DIRECTORY Breakpoint, Rope, IO, UnixTypes, UnixSysCalls, TargetArchitecture, BreakWorldArchitecture, Shepherd, FakeCirio, SPARCArchitecture, CirioBreakpoint, Commander; BreakpointTesterImpl: CEDAR PROGRAM IMPORTS Breakpoint, IO, UnixSysCalls, BreakWorldArchitecture, Shepherd, FakeCirio, Commander, SPARCArchitecture ~ BEGIN Procedure: TYPE ~ PROCEDURE [] RETURNS []; aCleanWellLightedGlobalVariable: INT ¬ 0; ACleanWellLightedPlaceForBreakpointsName: Rope.ROPE ~ "_ACleanWellLightedPlaceForBreakpoints_P60"; ACleanWellLightedPlaceForBreakpoints: Procedure ~ { localBoolean: BOOLEAN ¬ FALSE; aCleanWellLightedGlobalVariable ¬ 1; IF NOT localBoolean THEN { aCleanWellLightedGlobalVariable ¬ aCleanWellLightedGlobalVariable + 2; }; IF localBoolean THEN { aCleanWellLightedGlobalVariable ¬ aCleanWellLightedGlobalVariable + 4; }; ADirectlyCalledProcedure[]; { indirectlyCalledProcedure: Procedure ¬ AnIndirectlyCalledProcedure; indirectlyCalledProcedure[]; }; IF aCleanWellLightedGlobalVariable # (1 + 2 + 8 + 16) THEN ERROR; }; ADirectlyCalledProcedure: Procedure ~ { aCleanWellLightedGlobalVariable ¬ aCleanWellLightedGlobalVariable + 8; }; AnIndirectlyCalledProcedure: Procedure ~ { aCleanWellLightedGlobalVariable ¬ aCleanWellLightedGlobalVariable + 16; }; TheNullProcedure: Procedure ~ { RETURN; }; TheNullProcedureName: Rope.ROPE ~ "_TheNullProcedure_P240"; TheNullBreakProcedure: Breakpoint.BreakProcedure ~ { RETURN; }; TheNullBreakProcedureName: Rope.ROPE ~ "_TheNullBreakProcedure_P300"; TheMinimalBreakProcedure: Breakpoint.BreakProcedure ~ TRUSTED { intRef: REF INT ~ NARROW[LOOPHOLE[breakData, REF ANY]]; intRef­ ¬ intRef­ + (checkInt - testInt); RETURN; }; TheMinimalBreakProcedureName: Rope.ROPE ~ "_TheMinimalBreakProcedure_P360"; stdout: IO.STREAM ¬ IO.noWhereStream; intRef: REF INT ¬ NEW[INT ¬ 0]; testInt: INT ~ 17; checkInt: INT ~ 42; TestSetBreakpoint: PROCEDURE [address: BreakWorldArchitecture.Address, proc: BreakWorldArchitecture.Address, clientData: CARD32] RETURNS [Breakpoint.Break] ~ { breakWorld: BreakWorldArchitecture.BreakWorld ~ BreakWorldArchitecture.BreakWorldFromBreakWorldAddress[address: address]; break: Breakpoint.Break; IF stdout # NIL THEN { stdout.PutF["Setting break at address 0x%08x (0x%08x), calling 0x%08x ... ", [cardinal[LOOPHOLE[ BreakWorldArchitecture.TargetAddressFromBreakWorldAddress[address: address]]]], [cardinal[LOOPHOLE[ BreakWorldArchitecture.PeekInstruction[pc: address]]]], [cardinal[LOOPHOLE[ BreakWorldArchitecture.TargetAddressFromBreakWorldAddress[address: proc]]]]]; }; break ¬ Breakpoint.SetBreakpoint[ address: address, clientData: NIL, breakProc: proc, breakData: clientData ! Breakpoint.CantSet => { stdout.PutRope[message]; }]; IF stdout # NIL THEN { stdout.PutF1["set. \nPatch PC 0x%08x\n", [cardinal[LOOPHOLE[ BreakWorldArchitecture.TargetAddressFromBreakWorldAddress[ address: Shepherd.CodeAddressFromPatch[ patch: Breakpoint.PatchFromBreak[break: break]]]]]]]; }; RETURN [break]; }; TestClearBreakpoint: PROCEDURE [break: Breakpoint.Break] RETURNS [] ~ { IF stdout # NIL THEN { stdout.PutRope["Clearing ... "]; }; Breakpoint.ClearBreakpoint[break: break ! Breakpoint.CantClear => { stdout.PutRope[message]; }]; IF stdout # NIL THEN { stdout.PutRope["cleared\n"]; }; }; BreakpointFlavorProc: Commander.CommandProc ~ { stdout ¬ cmd.out; TestBreakpointFlavors[]; stdout ¬ IO.noWhereStream; }; TestBreakpointFlavors: PROCEDURE [] RETURNS [] ~ { breakWorld: BreakWorldArchitecture.BreakWorld ~ BreakWorldArchitecture.CreateBreakWorld[ name: "SPARC", peekContents: FakeCirio.PeekContents, pokeContents: FakeCirio.PokeContents, getProcAddress: FakeCirio.GetProcAddress, getProcDataSegment: NIL, getPatchArea: FakeCirio.GetPatchArea, monitoredCall: FakeCirio.MonitoredCall, worldAccessData: NIL]; breakpointAddress: BreakWorldArchitecture.Address ~ FakeCirio.GetProcAddress[ breakWorld: breakWorld, procName: ACleanWellLightedPlaceForBreakpointsName]; breakProcedureAddress: BreakWorldArchitecture.Address ~ FakeCirio.GetProcAddress[ breakWorld: breakWorld, procName: TheMinimalBreakProcedureName]; break: Breakpoint.Break ¬ Breakpoint.nullBreak; { normalAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.AddressFromDisplacement[ address: breakpointAddress, displacement: 01CH]; instruction: TargetArchitecture.Instruction ~ BreakWorldArchitecture.PeekInstruction[ pc: normalAddress]; IF instruction # LOOPHOLE[090102001H] THEN { stdout.PutRope["Normal break, but not mov 0x1, %o0\n"]; ERROR; }; intRef­ ¬ testInt; break ¬ TestSetBreakpoint[address: normalAddress, proc: breakProcedureAddress, clientData: LOOPHOLE[intRef]]; ACleanWellLightedPlaceForBreakpoints[]; IF intRef­ = checkInt THEN { stdout.PutRope["\t\t\tNormal break seems to work\n"]; } ELSE { stdout.PutF1["\t\t\tNormal break DOES NOT WORK: intRef^ = %g\n", [integer[intRef­]]]; ERROR; }; TestClearBreakpoint[break: break]; }; { branchTakenAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.AddressFromDisplacement[ address: breakpointAddress, displacement: 02CH]; instruction: TargetArchitecture.Instruction ~ BreakWorldArchitecture.PeekInstruction[ pc: branchTakenAddress]; IF instruction # LOOPHOLE[012800005H] THEN { stdout.PutRope["Branch (taken) break, but not bne .+0x5\n"]; ERROR; }; intRef­ ¬ testInt; break ¬ TestSetBreakpoint[address: branchTakenAddress, proc: breakProcedureAddress, clientData: LOOPHOLE[intRef]]; ACleanWellLightedPlaceForBreakpoints[]; IF intRef­ = checkInt THEN { stdout.PutRope["\t\t\tBranch taken break seems to work\n"]; } ELSE { stdout.PutF1["\t\t\tBranch taken break DOES NOT WORK: intRef^ = %g\n", [integer[intRef­]]]; ERROR; }; TestClearBreakpoint[break: break]; }; { branchNotTakenAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.AddressFromDisplacement[ address: breakpointAddress, displacement: 048H]; instruction: TargetArchitecture.Instruction ~ BreakWorldArchitecture.PeekInstruction[ pc: branchNotTakenAddress]; IF instruction # LOOPHOLE[002800005H] THEN { stdout.PutRope["Branch not taken break, but not be .+0x5\n"]; ERROR; }; intRef­ ¬ testInt; break ¬ TestSetBreakpoint[address: branchNotTakenAddress, proc: breakProcedureAddress, clientData: LOOPHOLE[intRef]]; ACleanWellLightedPlaceForBreakpoints[]; IF intRef­ = checkInt THEN { stdout.PutRope["\t\t\tBranch not taken break seems to work\n"]; } ELSE { stdout.PutF1["\t\t\tBranch not taken break DOES NOT WORK: intRef^ = %g\n", [integer[intRef­]]]; ERROR; }; TestClearBreakpoint[break: break]; }; { callAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.AddressFromDisplacement[ address: breakpointAddress, displacement: 05CH]; instruction: TargetArchitecture.Instruction ~ BreakWorldArchitecture.PeekInstruction[ pc: callAddress]; IF instruction # LOOPHOLE[040000016H] THEN { stdout.PutRope["Call break, but not call .+0x16\n"]; ERROR; }; intRef­ ¬ testInt; break ¬ TestSetBreakpoint[address: callAddress, proc: breakProcedureAddress, clientData: LOOPHOLE[intRef]]; ACleanWellLightedPlaceForBreakpoints[]; IF intRef­ = checkInt THEN { stdout.PutRope["\t\t\tCall break seems to work\n"]; } ELSE { stdout.PutF1["\t\t\tCall break DOES NOT WORK: intRef^ = %g\n", [integer[intRef­]]]; ERROR; }; TestClearBreakpoint[break: break]; }; { jmplo7Address: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.AddressFromDisplacement[ address: breakpointAddress, displacement: 07CH]; instruction: TargetArchitecture.Instruction ~ BreakWorldArchitecture.PeekInstruction[ pc: jmplo7Address]; IF instruction # LOOPHOLE[09FC04000H] THEN { stdout.PutRope["Jmpl %o7 break, but not jmpl %g1, %o7\n"]; ERROR; }; intRef­ ¬ testInt; break ¬ TestSetBreakpoint[address: jmplo7Address, proc: breakProcedureAddress, clientData: LOOPHOLE[intRef]]; ACleanWellLightedPlaceForBreakpoints[]; IF intRef­ = checkInt THEN { stdout.PutRope["\t\t\tJmpl %%o7 break seems to work\n"]; } ELSE { stdout.PutF1["\t\t\tJmpl %%o7 break DOES NOT WORK: intRef^ = %g\n", [integer[intRef­]]]; ERROR; }; TestClearBreakpoint[break: break]; }; { jmplg0Address: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.AddressFromDisplacement[ address: breakpointAddress, displacement: 0ACH]; instruction: TargetArchitecture.Instruction ~ BreakWorldArchitecture.PeekInstruction[ pc: jmplg0Address]; IF instruction # LOOPHOLE[81C7E008H] THEN { stdout.PutRope["Jmpl %g0 break, but not jmpl %i7+8, %g0\n"]; ERROR; }; intRef­ ¬ testInt; break ¬ TestSetBreakpoint[address: jmplg0Address, proc: breakProcedureAddress, clientData: LOOPHOLE[intRef]]; ACleanWellLightedPlaceForBreakpoints[]; IF intRef­ = checkInt THEN { stdout.PutRope["\t\t\tJmpl %%g0 break seems to work\n"]; } ELSE { stdout.PutF1["\t\t\tJmpl %%g0 break DOES NOT WORK: intRef^ = %g\n", [integer[intRef­]]]; ERROR; }; TestClearBreakpoint[break: break]; }; { intRef­ ¬ testInt; ACleanWellLightedPlaceForBreakpoints[]; IF intRef­ # testInt THEN { stdout.PutF1["\t\t\tclearing DOES NOT WORK: intRef^ = %g\n", [integer[intRef­]]]; ERROR; } ELSE { stdout.PutRope["\t\t\tClearing seems to work\n"]; }; }; }; TimeBreakpointProc: Commander.CommandProc ~ { stdout ¬ cmd.out; TimeBreakpoint[]; stdout ¬ IO.noWhereStream; }; TimeBreakpoint: PROCEDURE [] RETURNS [] ~ { iterations: NAT ~ 1000000; nullUsec: CARD; maxiRegsUsec: CARD; regsUsec: CARD; miniRegsUsec: CARD; globalRegsUsec: CARD; nullRegsUsec: CARD; normalBreakUsec: CARD; fastBreakUsec: CARD; { nullUsec ¬ TimeProc[iterations: iterations, proc: TheNullProcedure]; }; { maxiRegsUsec ¬ TimeProc[iterations: iterations, proc: MaxiSaveRestoreProcedure]; }; { regsUsec ¬ TimeProc[iterations: iterations, proc: SaveRestoreProcedure]; }; { miniRegsUsec ¬ TimeProc[iterations: iterations, proc: MiniSaveRestoreProcedure]; }; { globalRegsUsec ¬ TimeProc[iterations: iterations, proc: GlobalsSaveRestoreProcedure]; }; { nullRegsUsec ¬ TimeProc[iterations: iterations, proc: NoneSaveRestoreProcedure]; }; { breakWorld: BreakWorldArchitecture.BreakWorld ~ BreakWorldArchitecture.CreateBreakWorld[ name: "SPARC", peekContents: FakeCirio.PeekContents, pokeContents: FakeCirio.PokeContents, getProcAddress: FakeCirio.GetProcAddress, getProcDataSegment: NIL, getPatchArea: FakeCirio.GetPatchArea, monitoredCall: FakeCirio.MonitoredCall, worldAccessData: NIL]; breakpointAddress: BreakWorldArchitecture.Address ~ FakeCirio.GetProcAddress[ breakWorld: breakWorld, procName: TheNullProcedureName]; breakProcedureAddress: BreakWorldArchitecture.Address ~ FakeCirio.GetProcAddress[ breakWorld: breakWorld, procName: TheNullBreakProcedureName]; break: Breakpoint.Break ¬ Breakpoint.nullBreak; break ¬ Breakpoint.SetBreakpoint[ address: breakpointAddress, clientData: NIL, breakProc: breakProcedureAddress, breakData: 0]; normalBreakUsec ¬ TimeProc[iterations: iterations, proc: TheNullProcedure]; Breakpoint.ClearBreakpoint[break: break]; break ¬ Breakpoint.SetBreakpoint[ address: breakpointAddress, clientData: NIL, breakProc: breakProcedureAddress, breakData: 0, damages: SPARCArchitecture.TargetRegisterClassFromSPARCRegisterClass[ SPARCArchitecture.RegisterClass.globalsAndIns]]; fastBreakUsec ¬ TimeProc[iterations: iterations, proc: TheNullProcedure]; Breakpoint.ClearBreakpoint[break: break]; }; stdout.PutF["%g null calls takes %g usec %g\n", [integer[iterations]], [cardinal[nullUsec]], [cardinal[nullUsec/iterations]]]; stdout.PutF["%g maxi save/restore registers takes %g usec %g\n", [integer[iterations]], [cardinal[maxiRegsUsec]], [cardinal[maxiRegsUsec/iterations]]]; stdout.PutF["%g regular save/restore registers takes %g usec %g\n", [integer[iterations]], [cardinal[regsUsec]], [cardinal[regsUsec/iterations]]]; stdout.PutF["%g mini save/restore registers takes %g usec %g\n", [integer[iterations]], [cardinal[miniRegsUsec]], [cardinal[miniRegsUsec/iterations]]]; stdout.PutF["%g globals save/restore registers takes %g usec %g\n", [integer[iterations]], [cardinal[globalRegsUsec]], [cardinal[globalRegsUsec/iterations]]]; stdout.PutF["%g null save/restore registers takes %g usec %g\n", [integer[iterations]], [cardinal[nullRegsUsec]], [cardinal[nullRegsUsec/iterations]]]; stdout.PutF["%g normal break calls takes %g usec %g\n", [integer[iterations]], [cardinal[normalBreakUsec]], [cardinal[normalBreakUsec/iterations]]]; stdout.PutF["%g fast break calls takes %g usec %g\n", [integer[iterations]], [cardinal[fastBreakUsec]], [cardinal[fastBreakUsec/iterations]]]; }; TimeProc: PROCEDURE [iterations: NAT, proc: Procedure] RETURNS [CARD] ~ TRUSTED { beforeRep: UnixTypes.TimeVal; before: UnixTypes.TimeValPtr ~ @beforeRep; afterRep: UnixTypes.TimeVal; after: UnixTypes.TimeValPtr ~ @afterRep; usec: CARD ¬ 0; IF UnixSysCalls.GetTimeOfDay[tp: before, tzp: NIL] = failure THEN { stdout.PutRope["couldn't get before time\n"]; }; THROUGH [1..iterations] DO { [] ¬ proc[]; } ENDLOOP; IF UnixSysCalls.GetTimeOfDay[tp: after, tzp: NIL] = failure THEN { stdout.PutRope["couldn't get after time\n"]; }; usec ¬ ((1000000 * after.sec) + after.usec) - ((1000000 * before.sec) + before.usec); RETURN [usec]; }; SaveRestoreProcedure: Procedure ~ TRUSTED { SaveArea: TYPE ~ LONG POINTER TO SaveAreaRep ¬ NIL; SaveAreaRep: TYPE ~ PACKED ARRAY [0 .. CirioBreakpoint.registerSaveArea) OF BYTE; saveAreaInstance: SaveAreaRep; saveArea: SaveArea ~ @saveAreaInstance; Save: PROCEDURE [saveArea: SaveArea] RETURNS [] ~ TRUSTED MACHINE CODE { "save_regs" }; Restore: PROCEDURE [saveArea: SaveArea] RETURNS [] ~ TRUSTED MACHINE CODE { "restore_regs" }; Save[saveArea: saveArea]; Restore[saveArea: saveArea]; RETURN; }; MiniSaveRestoreProcedure: Procedure ~ TRUSTED { SaveArea: TYPE ~ LONG POINTER TO SaveAreaRep ¬ NIL; SaveAreaRep: TYPE ~ PACKED ARRAY [0 .. CirioBreakpoint.registerSaveArea) OF BYTE; saveAreaInstance: SaveAreaRep; saveArea: SaveArea ~ @saveAreaInstance; Save: PROCEDURE [saveArea: SaveArea] RETURNS [] ~ TRUSTED MACHINE CODE { "save_regs_mini" }; Restore: PROCEDURE [saveArea: SaveArea] RETURNS [] ~ TRUSTED MACHINE CODE { "restore_regs_mini" }; Save[saveArea: saveArea]; Restore[saveArea: saveArea]; RETURN; }; MaxiSaveRestoreProcedure: Procedure ~ TRUSTED { SaveArea: TYPE ~ LONG POINTER TO SaveAreaRep ¬ NIL; SaveAreaRep: TYPE ~ PACKED ARRAY [0 .. CirioBreakpoint.registerSaveArea) OF BYTE; saveAreaInstance: SaveAreaRep; saveArea: SaveArea ~ @saveAreaInstance; Save: PROCEDURE [saveArea: SaveArea] RETURNS [] ~ TRUSTED MACHINE CODE { "save_regs_maxi" }; Restore: PROCEDURE [saveArea: SaveArea] RETURNS [] ~ TRUSTED MACHINE CODE { "restore_regs_maxi" }; Save[saveArea: saveArea]; Restore[saveArea: saveArea]; RETURN; }; GlobalsSaveRestoreProcedure: Procedure ~ TRUSTED { SaveArea: TYPE ~ LONG POINTER TO SaveAreaRep ¬ NIL; SaveAreaRep: TYPE ~ PACKED ARRAY [0 .. CirioBreakpoint.registerSaveArea) OF BYTE; saveAreaInstance: SaveAreaRep; saveArea: SaveArea ~ @saveAreaInstance; Save: PROCEDURE [saveArea: SaveArea] RETURNS [] ~ TRUSTED MACHINE CODE { "save_regs_globals" }; Restore: PROCEDURE [saveArea: SaveArea] RETURNS [] ~ TRUSTED MACHINE CODE { "restore_regs_globals" }; Save[saveArea: saveArea]; Restore[saveArea: saveArea]; RETURN; }; NoneSaveRestoreProcedure: Procedure ~ TRUSTED { SaveArea: TYPE ~ LONG POINTER TO SaveAreaRep ¬ NIL; SaveAreaRep: TYPE ~ PACKED ARRAY [0 .. CirioBreakpoint.registerSaveArea) OF BYTE; saveAreaInstance: SaveAreaRep; saveArea: SaveArea ~ @saveAreaInstance; Save: PROCEDURE [saveArea: SaveArea] RETURNS [] ~ TRUSTED MACHINE CODE { "save_regs_none" }; Restore: PROCEDURE [saveArea: SaveArea] RETURNS [] ~ TRUSTED MACHINE CODE { "restore_regs_none" }; Save[saveArea: saveArea]; Restore[saveArea: saveArea]; RETURN; }; Commander.Register[ key: "TimeBreakpoints", proc: TimeBreakpointProc, doc: "time the breakpoint operations"]; Commander.Register[ key: "TestBreakpointFlavors", proc: BreakpointFlavorProc, doc: "test different flavor breakpoints"]; END. δ BreakpointTesterImpl.mesa Copyright Σ 1989, 1990, 1991, 1992 by Xerox Corporation. All rights reserved. Peter B. Kessler, April 16, 1990 3:06 pm PDT Laurie Horton, October 10, 1991 10:23 pm PDT Michael Plass, February 24, 1992 4:21 pm PST Willie-s, May 15, 1992 4:36 pm PDT This is just for testing the breakpoint implementation. An address in text space where we can set a breakpoint. Null Proc. Break Proc. global data. Set/Clear/Hit a breakpoint. Running it. Registration Κ d–(cedarcode) style•NewlineDelimiter ™™Jšœ ΟeœC™NJ™,J™,J™,J™"Icode˜—J™7˜šΟk ˜ K˜ K˜Kšžœ˜K˜ K˜ K˜K˜K˜ K˜ K˜K˜K˜ K˜——KšΟnœžœž˜#šžœ˜Kšœ žœY˜g—šœž˜˜Kšœ žœž œžœ˜*——head™7Kšœ!žœ˜)K˜šŸ(œžœ˜6K˜,K˜—šŸ$œ˜3Kšœžœžœ˜K˜K˜$šžœžœžœ˜K˜FK˜—šžœžœ˜K˜FK˜—K˜˜K˜CK˜K˜K˜—Kšžœ4žœžœ˜AK˜K˜—šŸœ˜'K˜FK˜K˜—šŸœ˜*K˜GK˜K˜——™ šŸœ˜Kšžœ˜K˜KšŸœžœ˜;K˜——™ šŸœ˜4Kšžœ˜K˜KšŸœžœ!˜EK˜—šŸœžœ˜?Kš œžœžœžœžœ žœžœ˜7K˜K˜)Kšžœ˜K˜KšŸœžœ$˜KK˜——™ Kšœžœžœžœ˜%K˜š œžœžœžœžœ˜Kšœ žœ˜Kšœ žœ˜K˜——™šŸœž œ]žœžœ˜Ÿ˜0K˜I—K˜K˜šžœ žœžœ˜˜Lšœ žœ˜K˜O—šœ žœ˜K˜7—šœ žœ˜K˜M——K˜—˜!Kšœžœ(˜I˜K˜K˜——šžœ žœžœ˜šœ4žœ˜=˜:˜'K˜5———K˜—Kšžœ ˜K˜—K˜šŸœž œžœ˜Gšžœ žœžœ˜K˜ K˜—˜'˜K˜K˜——šžœ žœžœ˜K˜K˜—K˜K˜——™ šŸœ˜/K˜K˜Kšœ žœ˜K˜K˜—šŸœž œžœ˜2˜0˜(K˜K˜&K˜&K˜*Kšœžœ˜K˜&K˜'Kšœžœ˜——˜MK˜L—˜QK˜@—K˜/K˜˜˜0˜/K˜0——˜UK˜K˜—šžœžœ žœ˜,K˜8Kšžœ˜K˜—K˜˜2Kšœ)žœ ˜;—K˜'šžœ˜šžœ˜K˜5K˜—šžœ˜˜BK˜—Kšžœ˜K˜——K˜"K˜—˜˜5˜/K˜0——˜UK˜K˜—šžœžœ žœ˜,K˜K˜—Kšžœ˜K˜—šžœ˜K˜1K˜——K˜—K˜K˜—šŸœ˜-K˜K˜Kšœ žœ˜K˜K˜—šŸœž œžœ˜+Kšœ žœ ˜K˜Kšœ žœ˜Kšœžœ˜Kšœ žœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜K˜˜K˜DK˜—˜K˜PK˜—˜K˜HK˜—˜K˜PK˜—˜K˜UK˜—˜K˜PK˜—˜˜0˜(K˜K˜&K˜&K˜*Kšœžœ˜K˜&K˜'Kšœžœ˜——˜MK˜8—˜QK˜=—K˜/K˜˜!Kšœ(žœ˜-K˜0—K˜KK˜)K˜˜!Kšœ(žœ˜-K˜0˜EK˜0——K˜IK˜)K˜—˜0K˜N—˜AK˜V—˜DK˜N—˜AK˜V—˜DK˜Z—˜AK˜V—˜8K˜4K˜(—˜6K˜2K˜&—K˜K˜—š Ÿœž œžœžœžœžœ˜QK˜K˜*K˜K˜(Kšœžœ˜K˜šžœ,žœ žœ˜CK˜-K˜—šžœžœ˜K˜ Kšœžœ˜ —šžœ+žœ žœ˜BK˜,K˜—K˜UKšžœ˜K˜K˜—šŸœžœ˜+š œ žœžœžœžœžœ˜4Kš œ žœžœžœ)žœžœ˜Q—˜K˜'—š Ÿœž œžœžœžœžœ˜HK˜ K˜—š Ÿœž œžœžœžœžœ˜KK˜K˜—K˜K˜Kšžœ˜K˜—K˜šŸœžœ˜/š œ žœžœžœžœžœ˜4Kš œ žœžœžœ)žœžœ˜Q—˜K˜'—š Ÿœž œžœžœžœžœ˜HK˜K˜——š Ÿœž œžœžœžœžœ˜K˜K˜—K˜K˜Kšžœ˜K˜—K˜šŸœžœ˜/š œ žœžœžœžœžœ˜4Kš œ žœžœžœ)žœžœ˜Q—˜K˜'—Kš Ÿœž œžœžœžœžœ˜HK˜K˜š Ÿœž œžœžœžœžœ˜KK˜K˜—K˜K˜Kšžœ˜K˜—K˜šŸœžœ˜2š œ žœžœžœžœžœ˜4Kš œ žœžœžœ)žœžœ˜Q—˜K˜'—Kš Ÿœž œžœžœžœžœ˜HK˜K˜š Ÿœž œžœžœžœžœ˜KK˜K˜—K˜K˜Kšžœ˜K˜—K˜šŸœžœ˜/š œ žœžœžœžœžœ˜4Kš œ žœžœžœ)žœžœ˜Q—˜K˜'—š Ÿœž œžœžœžœžœ˜HK˜K˜—š Ÿœž œžœžœžœžœ˜KK˜K˜—K˜K˜Kšžœ˜K˜——™ ˜K˜2K˜'K˜—˜K˜:K˜*K˜——Kšžœ˜—…—=κM2