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, 1991 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 สฉ–(cedarcode) style•NewlineDelimiter ™codešœ™Kšœ ฯeœ7™BK™0K™'K™šฯk ˜ K˜K˜Kšœ˜Kšœ˜Kšœ ˜ —K˜—unitšะlnœžœž˜KšžœฯcœT˜vKšžœ ˜Kšœ˜head™ šฯnœžœž œ‚žœ˜ฉšžœžœ˜!šžœ˜K˜6—K˜—šžœžœ˜ šžœ˜Kšœ5˜5—K˜—šžœžœ˜#šžœ˜Kšœ8˜8—K˜—˜˜3KšœS˜S—K˜šžœžœž™™CKšœJ™JK™—™LKšœL™LK™—™EKšœL™LK™—™EKšœL™LK™—šœJ™Jšžœ ™Kšœ™KšœO™O—K™—šžœ™ KšœL˜LK™——K˜—K˜K˜—šกœž œ‚žœ˜ฎKšœ?˜?KšœH˜H˜6KšœO˜O—˜8KšœN˜N—Kšœ(˜(K˜˜šœ4˜4KšœS˜S—šœ7˜7KšœO˜O—šœ1˜1šœ1˜1Kšœ;˜;——šœN˜NK˜Kšœ˜Kšœ˜šœ&˜&K˜K˜CKšžœžœ˜ Kšœ˜—K™B—K˜Kšœ˜šœ'˜'Kšœ ˜ Kšœ˜šœG˜GKšœ"˜"——šž˜˜ Kšžœ5˜:K˜——K˜—˜šœ;˜;šœ=˜=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šœ&˜&K˜K˜EKšžœžœ˜ 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˜—K˜—…—:œฃ