DIRECTORY TargetArchitecture, RS6000Architecture, BreakWorldArchitecture, RS6000BreakWorldUtilities, RS6000Manger; RS6000MangerImpl: CEDAR PROGRAM IMPORTS -- TargetArchitecture ,-- RS6000Architecture, BreakWorldArchitecture, RS6000BreakWorldUtilities, RS6000Manger EXPORTS RS6000Manger ~ { Install: PUBLIC PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { IF address.IsNullAddress[] THEN { ERROR RS6000Manger.CantInstall[ code: $NullAddress, message: "Install[null address]"]; }; IF manger.IsNullAddress[] THEN { ERROR RS6000Manger.CantInstall[ code: $NullAddress, message: "Install[null manger]"]; }; IF patchCode.IsNullAddress[] THEN { ERROR RS6000Manger.CantInstall[ code: $NullAddress, message: "Install[null patchCode]"]; }; { instruction: RS6000Architecture.RS6000Instruction ~ RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[address: address]; InstallNormalManger[address: address, manger: manger, patchCode: patchCode]; }; }; InstallNormalManger: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { errorCode: RS6000Manger.ErrorCode _ RS6000Manger.nullErrorCode; errorMessage: RS6000Manger.ErrorMessage _ RS6000Manger.nullErrorMessage; instructionAddress: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: address]; mangerRS6000Address: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: manger]; normalManger: RS6000Manger.NormalManger; { instruction: RS6000Architecture.RS6000Instruction ~ RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[address: address]; instructionAddress: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: address]; sheepAddress: RS6000Architecture.RS6000Address ~ RS6000Architecture.RS6000AddressFromDisplacement[ address: mangerRS6000Address, displacement: SheepOffset[]]; relocated: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.Relocate[ instruction: instruction, from: instructionAddress, to: sheepAddress ! RS6000Architecture.CantRelocate => { errorCode _ $CantRelocate; errorMessage _ "Cannot relocate instruction at breakpoint address"; GO TO Cannot; }]; normalManger.sheep _ relocated; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: SheepOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: normalManger.sheep]]; EXITS Cannot => { ERROR CantInstall[code: errorCode, message: errorMessage]; }; }; { nextInstructionAddress: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[ address: BreakWorldArchitecture.NextInstruction[pc: address]]; normalContinueAddress: RS6000Architecture.RS6000Address ~ RS6000Architecture.RS6000AddressFromDisplacement[ address: mangerRS6000Address, displacement: NormalContinueOffset[]]; normalManger.normalContinue _ RS6000Architecture.B[ pc: normalContinueAddress, to: nextInstructionAddress, abs: FALSE, link: FALSE]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: NormalContinueOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: normalManger.normalContinue]]; }; { normalManger.normalNoop _ RS6000Architecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: NormalNoopOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: normalManger.normalNoop]]; }; { normalManger.tag _ RS6000Architecture.Liu[ rt: gpr3, upper: RS6000Architecture.High[ORD[RS6000Manger.MangerVariant.normal]]]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: TagOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: normalManger.tag]]; }; { patchRS6000Address: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: patchCode]; instruction: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.B[ pc: instructionAddress, to: patchRS6000Address, abs: FALSE, link: FALSE]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: instruction]]; }; }; Uninstall: PUBLIC PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] ~ { tagInstruction: RS6000Architecture.RS6000Instruction ~ RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[ address: manger, displacement: TagOffset[]]; UninstallNormal[address: address, manger: manger]; }; UninstallNormal: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address] ~ { errorCode: RS6000Manger.ErrorCode _ RS6000Manger.nullErrorCode; errorMessage: RS6000Manger.ErrorMessage _ RS6000Manger.nullErrorMessage; { -- extra scope to contain EXITS. instruction: RS6000Architecture.RS6000Instruction ~ RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[ address: manger, displacement: SheepOffset[]]; mangerRS6000Address: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: manger]; sheepAddress: RS6000Architecture.RS6000Address ~ RS6000Architecture.RS6000AddressFromDisplacement[ address: mangerRS6000Address, displacement: SheepOffset[]]; instructionAddress: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: address]; unrelocated: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.Relocate[ instruction: instruction, from: sheepAddress, to: instructionAddress ! RS6000Architecture.CantRelocate => { errorCode _ $CantRelocate; errorMessage _ "Cannot unrelocate instruction to breakpoint address"; GO TO Cannot; }]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: unrelocated]]; EXITS Cannot => { ERROR CantUninstall[code: errorCode, message: errorMessage]; }; }; RETURN; }; SheepOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: RS6000Manger.NormalManger; mangerAddress: LONG POINTER TO RS6000Manger.NormalManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; sheepAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~ @manger.sheep; sheepCard: CARD32 ~ LOOPHOLE[sheepAddress]; offset _ (sheepCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; NormalContinueOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: RS6000Manger.NormalManger; mangerAddress: LONG POINTER TO RS6000Manger.NormalManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; normalContinueAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~ @manger.normalContinue; normalContinueCard: CARD32 ~ LOOPHOLE[normalContinueAddress]; offset _ (normalContinueCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; NormalNoopOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: RS6000Manger.NormalManger; mangerAddress: LONG POINTER TO RS6000Manger.NormalManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; normalNoopAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~ @manger.normalNoop; normalNoopCard: CARD32 ~ LOOPHOLE[normalNoopAddress]; offset _ (normalNoopCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; TagOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: RS6000Manger.NormalManger; mangerAddress: LONG POINTER TO RS6000Manger.NormalManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; tagAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~ @manger.tag; tagCard: CARD32 ~ LOOPHOLE[tagAddress]; offset _ (tagCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; DctiOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: RS6000Manger.BranchManger; mangerAddress: LONG POINTER TO RS6000Manger.BranchManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; dctiAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~ @manger.dcti; dctiCard: CARD32 ~ LOOPHOLE[dctiAddress]; offset _ (dctiCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; BranchDelayOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: RS6000Manger.BranchManger; mangerAddress: LONG POINTER TO RS6000Manger.BranchManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; branchDelayAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~ @manger.branchDelay; branchDelayCard: CARD32 ~ LOOPHOLE[branchDelayAddress]; offset _ (branchDelayCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; BranchContinueOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: RS6000Manger.BranchManger; mangerAddress: LONG POINTER TO RS6000Manger.BranchManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; branchContinueAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~ @manger.branchContinue; branchContinueCard: CARD32 ~ LOOPHOLE[branchContinueAddress]; offset _ (branchContinueCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; CallAddrHiOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: RS6000Manger.CallManger; mangerAddress: LONG POINTER TO RS6000Manger.CallManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; callAddrHiAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~ @manger.callAddrHi; callAddrHiCard: CARD32 ~ LOOPHOLE[callAddrHiAddress]; offset _ (callAddrHiCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; CallJmpOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: RS6000Manger.CallManger; mangerAddress: LONG POINTER TO RS6000Manger.CallManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; callJmpAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~ @manger.callJmp; callJmpCard: CARD32 ~ LOOPHOLE[callJmpAddress]; offset _ (callJmpCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; CallNoopOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: RS6000Manger.CallManger; mangerAddress: LONG POINTER TO RS6000Manger.CallManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; callNoopAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~ @manger.callNoop; callNoopCard: CARD32 ~ LOOPHOLE[callNoopAddress]; offset _ (callNoopCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; JmplO7JmpOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: RS6000Manger.JmplO7Manger; mangerAddress: LONG POINTER TO RS6000Manger.JmplO7Manger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jmplO7JmpAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~ @manger.jmplO7Jmp; jmplO7JmpCard: CARD32 ~ LOOPHOLE[jmplO7JmpAddress]; offset _ (jmplO7JmpCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; JmplO7NoopOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: RS6000Manger.JmplO7Manger; mangerAddress: LONG POINTER TO RS6000Manger.JmplO7Manger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jmplO7NoopAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~ @manger.jmplO7Noop; jmplO7NoopCard: CARD32 ~ LOOPHOLE[jmplO7NoopAddress]; offset _ (jmplO7NoopCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; JmplO7PadOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: RS6000Manger.JmplO7Manger; mangerAddress: LONG POINTER TO RS6000Manger.JmplO7Manger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jmplO7PadAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~ @manger.jmplO7Pad; jmplO7PadCard: CARD32 ~ LOOPHOLE[jmplO7PadAddress]; offset _ (jmplO7PadCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; JmplG0JmpOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: RS6000Manger.JmplG0Manger; mangerAddress: LONG POINTER TO RS6000Manger.JmplG0Manger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jmplG0JmpAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~ @manger.jmplG0Jmp; jmplG0JmpCard: CARD32 ~ LOOPHOLE[jmplG0JmpAddress]; offset _ (jmplG0JmpCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; JmplG0DelayOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: RS6000Manger.JmplG0Manger; mangerAddress: LONG POINTER TO RS6000Manger.JmplG0Manger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jmplG0DelayAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~ @manger.jmplG0Delay; jmplG0DelayCard: CARD32 ~ LOOPHOLE[jmplG0DelayAddress]; offset _ (jmplG0DelayCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; JmplG0PadOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: RS6000Manger.JmplG0Manger; mangerAddress: LONG POINTER TO RS6000Manger.JmplG0Manger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jmplG0PadAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~ @manger.jmplG0Pad; jmplG0PadCard: CARD32 ~ LOOPHOLE[jmplG0PadAddress]; offset _ (jmplG0PadCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; CantInstall: PUBLIC ERROR [ code: RS6000Manger.ErrorCode, message: RS6000Manger.ErrorMessage] ~ CODE; CantUninstall: PUBLIC ERROR [ code: RS6000Manger.ErrorCode, message: RS6000Manger.ErrorMessage] ~ CODE; }. Mฮ RS6000MangerImpl.mesa Copyright ำ 1990 by Xerox Corporation. All rights reserved. Peter B. Kessler, April 18, 1990 10:50:58 pm PDT Udagawa, September 13, 1991 6:48 pm PDT Procedures SELECT TRUE FROM RS6000Architecture.IsCallInstruction[instruction: instruction] => { InstallCallManger[address: address, manger: manger, patchCode: patchCode]; }; RS6000Architecture.IsDelayedBranchInstruction[instruction: instruction] => { InstallBranchManger[address: address, manger: manger, patchCode: patchCode]; }; RS6000Architecture.IsJmplO7Instruction[instruction: instruction] => { InstallJmplO7Manger[address: address, manger: manger, patchCode: patchCode]; }; RS6000Architecture.IsJmplG0Instruction[instruction: instruction] => { InstallJmplG0Manger[address: address, manger: manger, patchCode: patchCode]; }; RS6000Architecture.IsDelayedControlTransfer[instruction: instruction] => { ERROR CantInstall[ code: $NotWithDelaySlot, message: "Cannot install manger for instruction with that kind of delay slot"]; }; ENDCASE => { }; Is this the only transformation of the instruction that's required link the patch into the running code. This better be atomic. Else you have a race in smashed memory! InstallBranchManger: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { errorCode: RS6000Manger.ErrorCode _ RS6000Manger.nullErrorCode; errorMessage: RS6000Manger.ErrorMessage _ RS6000Manger.nullErrorMessage; instructionAddress: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: address]; mangerRS6000Address: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: manger]; branchManger: RS6000Manger.BranchManger; branchDelayBreakWorldAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[ pc: address]; branchContinueBreakWorldAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[pc: branchDelayBreakWorldAddress]; { instruction: RS6000Architecture.RS6000Instruction ~ RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[address: address]; instructionAddress: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: address]; dctiAddress: RS6000Architecture.RS6000Address ~ RS6000Architecture.RS6000AddressFromDisplacement[ address: mangerRS6000Address, displacement: DctiOffset[]]; relocated: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.Relocate[ instruction: instruction, from: instructionAddress, to: dctiAddress ! RS6000Architecture.CantRelocate => { errorCode _ $CantRelocate; errorMessage _ "Cannot relocate instruction at breakpoint address"; GO TO Cannot; }]; Is this the only transformation of the instruction that's required branchManger.dcti _ relocated; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: DctiOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: branchManger.dcti]]; EXITS Cannot => { ERROR CantInstall[code: errorCode, message: errorMessage]; }; }; { branchDelayInstructionAddress: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[ address: branchDelayBreakWorldAddress]; branchDelayAddress: RS6000Architecture.RS6000Address ~ RS6000Architecture.RS6000AddressFromDisplacement[ address: mangerRS6000Address, displacement: BranchDelayOffset[]]; branchDelayInstruction: RS6000Architecture.RS6000Instruction ~ RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[ address: branchDelayBreakWorldAddress]; relocatedBranchDelayInstruction: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.Relocate[ instruction: branchDelayInstruction, from: branchDelayInstructionAddress, to: branchDelayAddress ! RS6000Architecture.CantRelocate => { errorCode _ $CantRelocate; errorMessage _ "Cannot relocate instruction in delay slot of breakpoint address"; GO TO Cannot; }]; branchManger.branchDelay _ relocatedBranchDelayInstruction; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: BranchDelayOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: branchManger.branchDelay]]; EXITS Cannot => { ERROR CantInstall[code: errorCode, message: errorMessage]; }; }; { branchContinueInstructionAddress: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[ address: branchContinueBreakWorldAddress]; branchContinueAddress: RS6000Architecture.RS6000Address ~ RS6000Architecture.RS6000AddressFromDisplacement[ address: mangerRS6000Address, displacement: BranchContinueOffset[]]; branchManger.branchContinue _ RS6000Architecture.BAa[ pc: branchContinueAddress, to: branchContinueInstructionAddress]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: BranchContinueOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: branchManger.branchContinue]]; }; { branchManger.tag _ RS6000Architecture.Sethi[ hi: ORD[RS6000Manger.MangerVariant.branch], dest: RS6000Architecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: TagOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: branchManger.tag]]; }; { link the patch into the running code. patchRS6000Address: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: patchCode]; instruction: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.BAa[ pc: instructionAddress, to: patchRS6000Address]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: instruction]]; This better be atomic. Else you have a race in smashed memory! }; }; InstallCallManger: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { callManger: RS6000Manger.CallManger; instruction: RS6000Architecture.RS6000Instruction ~ RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[address: address]; instructionTargetAddress: TargetArchitecture.Address ~ BreakWorldArchitecture.TargetAddressFromBreakWorldAddress[address: address]; instructionAddress: RS6000Architecture.RS6000Address ~ RS6000Architecture.RS6000AddressFromTargetAddress[address: instructionTargetAddress]; instructionDisp30: RS6000Architecture.Disp30 ~ instruction.GetDisp30[]; byteDisplacement: TargetArchitecture.Displacement ~ instructionDisp30 * BYTES[RS6000Architecture.RS6000Instruction]; destination: TargetArchitecture.Address ~ TargetArchitecture.AddressFromDisplacement[ address: instructionTargetAddress, displacement: byteDisplacement]; mangerRS6000Address: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: manger]; { callManger.callAddrHi _ RS6000Architecture.Sethi[ hi: RS6000Architecture.Hi[value: LOOPHOLE[destination]], dest: RS6000Architecture.Register.global1]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: CallAddrHiOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: callManger.callAddrHi]]; }; { callManger.callJmp _ RS6000Architecture.JmplConst[ source: RS6000Architecture.Register.global1, constant: RS6000Architecture.Lo[value: LOOPHOLE[destination]], dest: RS6000Architecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: CallJmpOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: callManger.callJmp]]; }; { callManger.callNoop _ RS6000Architecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: CallNoopOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: callManger.callNoop]]; }; { callManger.tag _ RS6000Architecture.Sethi[ hi: ORD[RS6000Manger.MangerVariant.call], dest: RS6000Architecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: TagOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: callManger.tag]]; }; { link the patch into the running code. patchRS6000Address: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: patchCode]; instruction: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.Call[ pc: instructionAddress, to: patchRS6000Address]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: instruction]]; This better be atomic. Else you have a race in smashed memory! }; }; InstallJmplO7Manger: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { jmplO7Manger: RS6000Manger.JmplO7Manger; instructionAddress: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: address]; mangerRS6000Address: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: manger]; { instruction: RS6000Architecture.RS6000Instruction ~ RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[address: address]; jmplO7Manger.jmplO7Jmp _ RS6000Architecture.SetRd[ instruction: instruction, rd: RS6000Architecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: JmplO7JmpOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: jmplO7Manger.jmplO7Jmp]]; }; { jmplO7Manger.jmplO7Noop _ RS6000Architecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: JmplO7NoopOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: jmplO7Manger.jmplO7Noop]]; }; { jmplO7Manger.jmplO7Pad _ RS6000Architecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: JmplO7PadOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: jmplO7Manger.jmplO7Pad]]; }; { jmplO7Manger.tag _ RS6000Architecture.Sethi[ hi: ORD[RS6000Manger.MangerVariant.jmplO7], dest: RS6000Architecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: TagOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: jmplO7Manger.tag]]; }; { link the patch into the running code. patchRS6000Address: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: patchCode]; instruction: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.Call[ pc: instructionAddress, to: patchRS6000Address]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: instruction]]; This better be atomic. Else you have a race in smashed memory! }; }; InstallJmplG0Manger: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { errorCode: RS6000Manger.ErrorCode _ RS6000Manger.nullErrorCode; errorMessage: RS6000Manger.ErrorMessage _ RS6000Manger.nullErrorMessage; instructionAddress: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: address]; mangerRS6000Address: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: manger]; jmplG0Manger: RS6000Manger.JmplG0Manger; jmplG0DelayBreakWorldAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[ pc: address]; { instruction: RS6000Architecture.RS6000Instruction ~ RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[address: address]; jmplG0Manger.jmplG0Jmp _ instruction; Needs no relocation. BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: JmplG0JmpOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: jmplG0Manger.jmplG0Jmp]]; }; { jmplG0DelayInstructionAddress: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[ address: jmplG0DelayBreakWorldAddress]; jmplG0DelayAddress: RS6000Architecture.RS6000Address ~ RS6000Architecture.RS6000AddressFromDisplacement[ address: mangerRS6000Address, displacement: JmplG0DelayOffset[]]; jmplG0DelayInstruction: RS6000Architecture.RS6000Instruction ~ RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[ address: jmplG0DelayBreakWorldAddress]; relocatedJmplG0DelayInstruction: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.Relocate[ instruction: jmplG0DelayInstruction, from: jmplG0DelayInstructionAddress, to: jmplG0DelayAddress ! RS6000Architecture.CantRelocate => { errorCode _ $CantRelocate; errorMessage _ "Cannot relocate instruction in delay slot of breakpoint address"; GO TO Cannot; }]; jmplG0Manger.jmplG0Delay _ relocatedJmplG0DelayInstruction; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: JmplG0DelayOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: jmplG0Manger.jmplG0Delay]]; EXITS Cannot => { ERROR CantInstall[code: errorCode, message: errorMessage]; }; }; { jmplG0Manger.jmplG0Pad _ RS6000Architecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: JmplG0PadOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: jmplG0Manger.jmplG0Pad]]; }; { jmplG0Manger.tag _ RS6000Architecture.Sethi[ hi: ORD[RS6000Manger.MangerVariant.jmplG0], dest: RS6000Architecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: TagOffset[], instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: jmplG0Manger.tag]]; }; { link the patch into the running code. patchRS6000Address: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: patchCode]; instruction: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.BAa[ pc: instructionAddress, to: patchRS6000Address]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: instruction]]; This better be atomic. Else you have a race in smashed memory! }; }; SELECT tagInstruction.GetImm22[] FROM ORD[RS6000Manger.MangerVariant.normal] => { }; ORD[RS6000Manger.MangerVariant.branch] => { UninstallBranch[address: address, manger: manger]; }; ORD[RS6000Manger.MangerVariant.call] => { UninstallCall[address: address, manger: manger]; }; ORD[RS6000Manger.MangerVariant.jmplO7] => { UninstallJmplO7[address: address, manger: manger]; }; ORD[RS6000Manger.MangerVariant.jmplG0] => { UninstallJmplG0[address: address, manger: manger]; }; ENDCASE => { ERROR CantUninstall[ code: $UnknownTag, message: "Can't decode manger"]; }; Is this the only transformation of the instruction that's required? This better be atomic. Else you have a race in smashed code! UninstallBranch: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address] ~ { We don't need to replace the delay slot fortunately, since we wouldn't have time to. errorCode: RS6000Manger.ErrorCode _ RS6000Manger.nullErrorCode; errorMessage: RS6000Manger.ErrorMessage _ RS6000Manger.nullErrorMessage; { -- extra scope to contain EXITS. instruction: RS6000Architecture.RS6000Instruction ~ RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[ address: manger, displacement: DctiOffset[]]; mangerRS6000Address: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: manger]; dctiAddress: RS6000Architecture.RS6000Address ~ RS6000Architecture.RS6000AddressFromDisplacement[ address: mangerRS6000Address, displacement: DctiOffset[]]; instructionAddress: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: address]; unrelocated: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.Relocate[ instruction: instruction, from: dctiAddress, to: instructionAddress ! RS6000Architecture.CantRelocate => { errorCode _ $CantRelocate; errorMessage _ "Cannot unrelocate instruction to breakpoint address"; GO TO Cannot; }]; Is this the only transformation of the instruction that's required? BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: unrelocated]]; This better be atomic. Else you have a race in smashed code! EXITS Cannot => { ERROR CantUninstall[code: errorCode, message: errorMessage]; }; }; RETURN; }; UninstallCall: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address] ~ { errorCode: RS6000Manger.ErrorCode _ RS6000Manger.nullErrorCode; errorMessage: RS6000Manger.ErrorMessage _ RS6000Manger.nullErrorMessage; callAddrHiInstruction: RS6000Architecture.RS6000Instruction ~ RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[ address: manger, displacement: CallAddrHiOffset[]]; callAddrHi: RS6000Architecture.Imm22 ~ callAddrHiInstruction.GetImm22[]; callAddrLoInstruction: RS6000Architecture.RS6000Instruction ~ RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[ address: manger, displacement: CallJmpOffset[]]; callAddrLo: RS6000Architecture.Simm13 ~ callAddrLoInstruction.GetSimm13[]; callAddr: RS6000Architecture.RS6000Address ~ LOOPHOLE[RS6000Architecture.HiLo[hi: callAddrHi, lo: callAddrLo]]; instructionAddress: RS6000Architecture.RS6000Address ~ RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: address]; callInstruction: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.Call[ pc: instructionAddress, to: callAddr]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: callInstruction]]; This better be atomic. Else you have a race in smashed code! RETURN; }; UninstallJmplO7: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address] ~ { errorCode: RS6000Manger.ErrorCode _ RS6000Manger.nullErrorCode; errorMessage: RS6000Manger.ErrorMessage _ RS6000Manger.nullErrorMessage; jmplO7JmpInstruction: RS6000Architecture.RS6000Instruction ~ RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[ address: manger, displacement: JmplO7JmpOffset[]]; jmplO7Instruction: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.SetRd[ instruction: jmplO7JmpInstruction, rd: RS6000Architecture.Register.out7]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: jmplO7Instruction]]; This better be atomic. Else you have a race in smashed code! RETURN; }; UninstallJmplG0: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address] ~ { errorCode: RS6000Manger.ErrorCode _ RS6000Manger.nullErrorCode; errorMessage: RS6000Manger.ErrorMessage _ RS6000Manger.nullErrorMessage; jmplG0JmpInstruction: RS6000Architecture.RS6000Instruction ~ RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[ address: manger, displacement: JmplG0JmpOffset[]]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[ instruction: jmplG0JmpInstruction]]; This better be atomic. Else you have a race in smashed code! RETURN; }; Manger offsets: Errors ส•NewlineDelimiter – "cedar" style™codešœ™K™˜>——šœ:˜:šœ1˜1KšœD˜D——K˜šœ3˜3Kšœ<œœ˜P—šœ'˜'Kšœ ˜ Kšœ&˜&šœG˜GKšœ+˜+——K˜—˜Kšœ4˜4šœ'˜'Kšœ ˜ Kšœ"˜"šœG˜GKšœ'˜'——K˜—˜šœ*˜*Kšœ)œ&˜R—šœ'˜'Kšœ ˜ Kšœ˜šœG˜GKšœ ˜ ——K˜—˜Kšœ%™%šœ7˜7KšœQ˜Q—šœI˜IKšœ5œœ˜I—K˜šœ'˜'Kšœ ˜ šœG˜GKšœ˜—K™?—Kšœ˜—Kšœ˜K˜—š œ œ‚œ™ฎKšœ?™?KšœH™H™6JšœO™O—™8JšœN™N—Kšœ(™(šœf™fKšœ ™ —šœB™BKšœI™I—K™™šœ4™4JšœS™S—šœ7™7JšœO™O—šœ0™0šœ1™1Kšœ:™:——šœN™NK™Kšœ™Kšœ™šœ&™&J™J™CJšœœ™ Kšœ™—K™B—K™Kšœ™šœ'™'Kšœ ™ Kšœ™šœG™GKšœ!™!——š™™ Kšœ5™:K™——K™—™šœB™Bšœ=™=Kšœ'™'——šœ7™7šœ1™1KšœA™A——šœ?™?šœA™AKšœ'™'——šœH™Hšœ™Kšœ$™$Kšœ%™%Kšœ™šœ&™&J™™J™B—Jšœœ™ Kšœ™———K™Kšœ;™;šœ'™'Kšœ ™ Kšœ#™#šœG™GKšœ(™(——š™™ Kšœ5™:K™——K™—™šœE™Ešœ=™=Kšœ*™*——šœ:™:šœ1™1KšœD™D——K™šœ5™5KšœA™A—šœ'™'Kšœ ™ Kšœ&™&šœG™GKšœ+™+——K™—™šœ,™,Kšœœ%™,Kšœ+™+—šœ'™'Kšœ ™ Kšœ™šœG™GKšœ ™ ——K™—™Kšœ%™%šœ7™7KšœQ™Q—šœK™KKšœ0™0—K™šœ'™'Kšœ ™ šœG™GKšœ™—K™?—Kšœ™—K™K˜—š œ œ‚œ™ฌKšœ$™$šœ4™4JšœS™S—šœ7™7KšœL™L—šœ7™7KšœU™U—K™Gšœ4™4Jšœœ'™@—šœU™UKšœC™C—™8KšœN™N—K™™šœ1™1Kšœ!œ™9Kšœ+™+—šœ'™'Kšœ ™ Kšœ"™"šœG™GKšœ%™%——K™—™šœ2™2Kšœ,™,Kšœ'œ™?Kšœ+™+—šœ'™'Kšœ ™ Kšœ™šœG™GKšœ"™"——K™—™Kšœ0™0šœ'™'Kšœ ™ Kšœ ™ šœG™GKšœ#™#——K™—™šœ*™*Kšœœ#™*Kšœ+™+—šœ'™'Kšœ ™ Kšœ™šœG™GKšœ™——K™—™Kšœ%™%šœ7™7KšœQ™Q—šœL™LKšœ0™0—K™šœ'™'Kšœ ™ šœG™GKšœ™—K™?—Kšœ™—K™K˜—š œ œ‚œ™ฎKšœ(™(šœ7™7JšœO™O—™8KšœN™N—K™™šœ4™4JšœS™S—K™šœ2™2KšœC™C—šœ'™'Kšœ ™ Kšœ!™!šœG™GKšœ&™&——K™—™Kšœ4™4šœ'™'Kšœ ™ Kšœ"™"šœG™GKšœ'™'——K™—™Kšœ3™3šœ'™'Kšœ ™ Kšœ!™!šœG™GKšœ&™&——K™—™šœ,™,Kšœœ%™,Kšœ+™+—šœ'™'Kšœ ™ Kšœ™šœG™GKšœ ™ ——K™—™Kšœ%™%šœ7™7KšœQ™Q—šœL™LKšœ0™0—K™šœ'™'Kšœ ™ šœG™GKšœ™—K™?—Kšœ™—K™K™—š œ œ‚œ™ฎKšœ?™?KšœH™Hšœ7™7JšœO™O—™8KšœN™N—Kšœ(™(šœf™fKšœ ™ ——™™šœ4™4JšœS™S—K™šœ%™%K™—šœ'™'Kšœ ™ Kšœ!™!šœG™GKšœ&™&——K™—™šœB™Bšœ=™=Kšœ'™'——šœ7™7šœ1™1KšœA™A——šœ?™?šœA™AKšœ'™'——šœH™Hšœ™Kšœ$™$Kšœ%™%Kšœ™šœ&™&J™™J™B—Jšœœ™ Kšœ™———K™Kšœ;™;šœ'™'Kšœ ™ Kšœ#™#šœG™GKšœ(™(——š™™ Kšœ5™:K™——K™—™Kšœ3™3šœ'™'Kšœ ™ Kšœ!™!šœG™GKšœ&™&——K™—™šœ,™,Kšœœ%™,Kšœ+™+—šœ'™'Kšœ ™ Kšœ™šœG™GKšœ ™ ——K™—™Kšœ%™%šœ7™7KšœQ™Q—šœK™KKšœ0™0—K™šœ'™'Kšœ ™ šœG™GKšœ™—K™?—Kšœ™—K™K˜—š  œœ œ„˜Ÿšœ7˜7šœA˜AKšœ,˜,——K˜šœ™%šœ(™+K˜2K™—šœ(™+K™2K™—šœ&™)K™0K™—šœ(™+K™2K™—šœ(™+Kšœ2™2K™—šœ™ šœ™Kšœ3™3—Kšœ™——K˜K˜—š œ œX˜rK˜?KšœH˜HšœŸ ˜"šœ4˜4šœA˜AKšœ.˜.——˜8KšœN˜N—šœ1˜1šœ1˜1Kšœ;˜;——šœ7˜7KšœO˜O—šœP˜PKšœD˜Dšœ&˜&J˜J˜EJšœœ˜ Kšœ˜—K™C—K˜šœ'˜'Kšœ ˜ šœG˜GKšœ˜—K™=—š˜˜ Kšœ7˜™>šœA™AKšœ3™3——KšœH™Hšœ>™>šœA™AKšœ0™0——KšœJ™Jšœ-™-Kšœ:™B—šœ7™7JšœO™O—šœP™PKšœ&™&—K™šœ'™'Kšœ ™ šœG™GKšœ™—K™=—Kšœ™Kšœ™K™—š œ œX™rKšœ?™?KšœH™Hšœ=™=šœA™AKšœ2™2——šœS™SKšœI™I—K™šœ'™'Kšœ ™ šœG™GKšœ!™!—K™=—Kšœ™Kšœ™K™—š œ œX™rKšœ?™?KšœH™Hšœ=™=šœA™AKšœ2™2——K™šœ'™'Kšœ ™ šœG™GKšœ$™$—K™=—Kšœ™Kšœ™K˜—™š  œ œœ%œ˜PKšœN˜NKšœ"˜"Kšœœœœ%˜CKšœ œœ˜-šœœœœ(˜EKšœ˜—Kšœ œœ˜+K˜Kšœ$œœ˜0K˜Kšœ ˜Kšœ˜—š œ œœ%œ˜YKšœN˜NKšœ"˜"Kšœœœœ%˜CKšœ œœ˜-šœœœœ(˜NKšœ˜—Kšœœœ˜=K˜Kšœ-œœ˜9K˜Kšœ ˜Kšœ˜—š œ œœ%œ˜UKšœN˜NKšœ"˜"Kšœœœœ%˜CKšœ œœ˜-šœœœœ(˜JKšœ˜—Kšœœœ˜5K˜Kšœ)œœ˜5K˜Kšœ ˜Kšœ˜—š  œ œœ%œ˜NKšœN˜NKšœ"˜"Kšœœœœ%˜CKšœ œœ˜-šœ œœœ(˜CKšœ ˜ —Kšœ œœ ˜'K˜Kšœ"œœ˜.Kšœ ˜Kšœ˜K˜—š  œ œœ%œ˜OKšœN˜NKšœ"˜"Kšœœœœ%˜CKšœ œœ˜-šœ œœœ(˜DKšœ ˜ —Kšœ œœ˜)K˜Kšœ#œœ˜/Kšœ ˜Kšœ˜—š œ œœ%œ˜VKšœN˜NKšœ"˜"Kšœœœœ%˜CKšœ œœ˜-šœœœœ(˜KKšœ˜—Kšœœœ˜7K˜Kšœ*œœ˜6Kšœ ˜Kšœ˜—š œ œœ%œ˜YKšœN˜NKšœ"˜"Kšœœœœ%˜CKšœ œœ˜-šœœœœ(˜NKšœ˜—Kšœœœ˜=K˜Kšœ-œœ˜9Kšœ ˜Kšœ˜K˜—š œ œœ%œ˜UKšœN˜NKšœ ˜ Kšœœœœ#˜AKšœ œœ˜-šœœœœ(˜JKšœ˜—Kšœœœ˜5K˜Kšœ)œœ˜5Kšœ ˜Kšœ˜—š  œ œœ%œ˜RKšœN˜NKšœ ˜ Kšœœœœ#˜AKšœ œœ˜-šœœœœ(˜GKšœ˜—Kšœ œœ˜/K˜Kšœ&œœ˜2Kšœ ˜Kšœ˜—š œ œœ%œ˜SKšœN˜NKšœ ˜ Kšœœœœ#˜AKšœ œœ˜-šœœœœ(˜HKšœ˜—Kšœœœ˜1K˜Kšœ'œœ˜3Kšœ ˜Kšœ˜K˜—š œ œœ%œ˜TKšœN˜NKšœ"˜"Kšœœœœ%˜CKšœ œœ˜-šœœœœ(˜IKšœ˜—Kšœœœ˜3K˜Kšœ(œœ˜4Kšœ ˜Kšœ˜—š œ œœ%œ˜UKšœN˜NKšœ"˜"Kšœœœœ%˜CKšœ œœ˜-šœœœœ(˜JKšœ˜—Kšœœœ˜5K˜Kšœ)œœ˜5Kšœ ˜Kšœ˜—š œ œœ%œ˜TKšœN˜NKšœ"˜"Kšœœœœ%˜CKšœ œœ˜-šœœœœ(˜IKšœ˜—Kšœœœ˜3K˜Kšœ(œœ˜4Kšœ ˜Kšœ˜K˜—š œ œœ%œ˜TKšœN˜NKšœ"˜"Kšœœœœ%˜CKšœ œœ˜-šœœœœ(˜IKšœ˜—Kšœœœ˜3K˜Kšœ(œœ˜4Kšœ ˜Kšœ˜—š œ œœ%œ˜VKšœN˜NKšœ"˜"Kšœœœœ%˜CKšœ œœ˜-šœœœœ(˜KKšœ˜—Kšœœœ˜7K˜Kšœ*œœ˜6Kšœ ˜Kšœ˜—š œ œœ%œ˜TKšœN˜NKšœ"˜"Kšœœœœ%˜CKšœ œœ˜-šœœœœ(˜IKšœ˜—Kšœœœ˜3K˜Kšœ(œœ˜4Kšœ ˜Kšœ˜K˜———™š  œœœGœ˜eK˜—š  œœœGœ˜gK˜——K˜—J˜—…—:œฃ