DIRECTORY TargetArchitecture, SPARCArchitecture, BreakWorldArchitecture, SPARCBreakWorldUtilities, SPARCManger; SPARCMangerImpl: CEDAR PROGRAM IMPORTS TargetArchitecture, SPARCArchitecture, BreakWorldArchitecture, SPARCBreakWorldUtilities, SPARCManger EXPORTS SPARCManger ~ { Install: PUBLIC PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { IF address.IsNullAddress[] THEN { ERROR SPARCManger.CantInstall[ code: $NullAddress, message: "Install[null address]"]; }; IF manger.IsNullAddress[] THEN { ERROR SPARCManger.CantInstall[ code: $NullAddress, message: "Install[null manger]"]; }; IF patchCode.IsNullAddress[] THEN { ERROR SPARCManger.CantInstall[ code: $NullAddress, message: "Install[null patchCode]"]; }; { instruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[address: address]; SELECT TRUE FROM SPARCArchitecture.IsCallInstruction[instruction: instruction] => { InstallCallManger[address: address, manger: manger, patchCode: patchCode]; }; SPARCArchitecture.IsDelayedBranchInstruction[instruction: instruction] => { InstallBranchManger[address: address, manger: manger, patchCode: patchCode]; }; SPARCArchitecture.IsJmplO7Instruction[instruction: instruction] => { InstallJmplO7Manger[address: address, manger: manger, patchCode: patchCode]; }; SPARCArchitecture.IsJmplG0Instruction[instruction: instruction] => { InstallJmplG0Manger[address: address, manger: manger, patchCode: patchCode]; }; SPARCArchitecture.IsDelayedControlTransfer[instruction: instruction] => { ERROR CantInstall[ code: $NotWithDelaySlot, message: "Cannot install manger for instruction with that kind of delay slot"]; }; ENDCASE => { InstallNormalManger[address: address, manger: manger, patchCode: patchCode]; }; }; }; InstallNormalManger: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { errorCode: SPARCManger.ErrorCode ฌ SPARCManger.nullErrorCode; errorMessage: SPARCManger.ErrorMessage ฌ SPARCManger.nullErrorMessage; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address]; mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger]; normalManger: SPARCManger.NormalManger; { instruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[address: address]; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address]; sheepAddress: SPARCArchitecture.SPARCAddress ~ SPARCArchitecture.SPARCAddressFromDisplacement[ address: mangerSPARCAddress, displacement: SheepOffset[]]; relocated: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Relocate[ instruction: instruction, from: instructionAddress, to: sheepAddress ! SPARCArchitecture.CantRelocate => { errorCode ฌ $CantRelocate; errorMessage ฌ "Cannot relocate instruction at breakpoint address"; GO TO Cannot; }]; normalManger.sheep ฌ relocated; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: SheepOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: normalManger.sheep]]; EXITS Cannot => { ERROR CantInstall[code: errorCode, message: errorMessage]; }; }; { nextInstructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[ address: BreakWorldArchitecture.NextInstruction[pc: address]]; normalContinueAddress: SPARCArchitecture.SPARCAddress ~ SPARCArchitecture.SPARCAddressFromDisplacement[ address: mangerSPARCAddress, displacement: NormalContinueOffset[]]; normalManger.normalContinue ฌ SPARCArchitecture.BAa[ pc: normalContinueAddress, to: nextInstructionAddress]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: NormalContinueOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: normalManger.normalContinue]]; }; { normalManger.normalNoop ฌ SPARCArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: NormalNoopOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: normalManger.normalNoop]]; }; { normalManger.tag ฌ SPARCArchitecture.Sethi[ hi: ORD[SPARCManger.MangerVariant.normal], dest: SPARCArchitecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: TagOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: normalManger.tag]]; }; { patchSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: patchCode]; instruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.BAa[ pc: instructionAddress, to: patchSPARCAddress]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: instruction]]; }; }; InstallBranchManger: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { errorCode: SPARCManger.ErrorCode ฌ SPARCManger.nullErrorCode; errorMessage: SPARCManger.ErrorMessage ฌ SPARCManger.nullErrorMessage; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address]; mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger]; branchManger: SPARCManger.BranchManger; branchDelayBreakWorldAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[ pc: address]; branchContinueBreakWorldAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[pc: branchDelayBreakWorldAddress]; { instruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[address: address]; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address]; dctiAddress: SPARCArchitecture.SPARCAddress ~ SPARCArchitecture.SPARCAddressFromDisplacement[ address: mangerSPARCAddress, displacement: DctiOffset[]]; relocated: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Relocate[ instruction: instruction, from: instructionAddress, to: dctiAddress ! SPARCArchitecture.CantRelocate => { errorCode ฌ $CantRelocate; errorMessage ฌ "Cannot relocate instruction at breakpoint address"; GO TO Cannot; }]; branchManger.dcti ฌ relocated; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: DctiOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: branchManger.dcti]]; EXITS Cannot => { ERROR CantInstall[code: errorCode, message: errorMessage]; }; }; { branchDelayInstructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[ address: branchDelayBreakWorldAddress]; branchDelayAddress: SPARCArchitecture.SPARCAddress ~ SPARCArchitecture.SPARCAddressFromDisplacement[ address: mangerSPARCAddress, displacement: BranchDelayOffset[]]; branchDelayInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[ address: branchDelayBreakWorldAddress]; relocatedBranchDelayInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Relocate[ instruction: branchDelayInstruction, from: branchDelayInstructionAddress, to: branchDelayAddress ! SPARCArchitecture.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: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: branchManger.branchDelay]]; EXITS Cannot => { ERROR CantInstall[code: errorCode, message: errorMessage]; }; }; { branchContinueInstructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[ address: branchContinueBreakWorldAddress]; branchContinueAddress: SPARCArchitecture.SPARCAddress ~ SPARCArchitecture.SPARCAddressFromDisplacement[ address: mangerSPARCAddress, displacement: BranchContinueOffset[]]; branchManger.branchContinue ฌ SPARCArchitecture.BAa[ pc: branchContinueAddress, to: branchContinueInstructionAddress]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: BranchContinueOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: branchManger.branchContinue]]; }; { branchManger.tag ฌ SPARCArchitecture.Sethi[ hi: ORD[SPARCManger.MangerVariant.branch], dest: SPARCArchitecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: TagOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: branchManger.tag]]; }; { patchSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: patchCode]; instruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.BAa[ pc: instructionAddress, to: patchSPARCAddress]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: instruction]]; }; }; InstallCallManger: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { callManger: SPARCManger.CallManger; instruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[address: address]; instructionTargetAddress: TargetArchitecture.Address ~ BreakWorldArchitecture.TargetAddressFromBreakWorldAddress[address: address]; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCArchitecture.SPARCAddressFromTargetAddress[address: instructionTargetAddress]; instructionDisp30: SPARCArchitecture.Disp30 ~ instruction.GetDisp30[]; byteDisplacement: TargetArchitecture.Displacement ~ instructionDisp30 * BYTES[SPARCArchitecture.SPARCInstruction]; destination: TargetArchitecture.Address ~ TargetArchitecture.AddressFromDisplacement[ address: instructionTargetAddress, displacement: byteDisplacement]; mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger]; { callManger.callAddrHi ฌ SPARCArchitecture.Sethi[ hi: SPARCArchitecture.Hi[value: LOOPHOLE[destination]], dest: SPARCArchitecture.Register.global1]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: CallAddrHiOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: callManger.callAddrHi]]; }; { callManger.callJmp ฌ SPARCArchitecture.JmplConst[ source: SPARCArchitecture.Register.global1, constant: SPARCArchitecture.Lo[value: LOOPHOLE[destination]], dest: SPARCArchitecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: CallJmpOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: callManger.callJmp]]; }; { callManger.callNoop ฌ SPARCArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: CallNoopOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: callManger.callNoop]]; }; { callManger.tag ฌ SPARCArchitecture.Sethi[ hi: ORD[SPARCManger.MangerVariant.call], dest: SPARCArchitecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: TagOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: callManger.tag]]; }; { patchSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: patchCode]; instruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Call[ pc: instructionAddress, to: patchSPARCAddress]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: instruction]]; }; }; InstallJmplO7Manger: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { jmplO7Manger: SPARCManger.JmplO7Manger; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address]; mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger]; { instruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[address: address]; jmplO7Manger.jmplO7Jmp ฌ SPARCArchitecture.SetRd[ instruction: instruction, rd: SPARCArchitecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: JmplO7JmpOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplO7Manger.jmplO7Jmp]]; }; { jmplO7Manger.jmplO7Noop ฌ SPARCArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: JmplO7NoopOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplO7Manger.jmplO7Noop]]; }; { jmplO7Manger.jmplO7Pad ฌ SPARCArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: JmplO7PadOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplO7Manger.jmplO7Pad]]; }; { jmplO7Manger.tag ฌ SPARCArchitecture.Sethi[ hi: ORD[SPARCManger.MangerVariant.jmplO7], dest: SPARCArchitecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: TagOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplO7Manger.tag]]; }; { patchSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: patchCode]; instruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Call[ pc: instructionAddress, to: patchSPARCAddress]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: instruction]]; }; }; InstallJmplG0Manger: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { errorCode: SPARCManger.ErrorCode ฌ SPARCManger.nullErrorCode; errorMessage: SPARCManger.ErrorMessage ฌ SPARCManger.nullErrorMessage; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address]; mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger]; jmplG0Manger: SPARCManger.JmplG0Manger; jmplG0DelayBreakWorldAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[ pc: address]; { instruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[address: address]; jmplG0Manger.jmplG0Jmp ฌ instruction; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: JmplG0JmpOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplG0Manger.jmplG0Jmp]]; }; { jmplG0DelayInstructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[ address: jmplG0DelayBreakWorldAddress]; jmplG0DelayAddress: SPARCArchitecture.SPARCAddress ~ SPARCArchitecture.SPARCAddressFromDisplacement[ address: mangerSPARCAddress, displacement: JmplG0DelayOffset[]]; jmplG0DelayInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[ address: jmplG0DelayBreakWorldAddress]; relocatedJmplG0DelayInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Relocate[ instruction: jmplG0DelayInstruction, from: jmplG0DelayInstructionAddress, to: jmplG0DelayAddress ! SPARCArchitecture.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: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplG0Manger.jmplG0Delay]]; EXITS Cannot => { ERROR CantInstall[code: errorCode, message: errorMessage]; }; }; { jmplG0Manger.jmplG0Pad ฌ SPARCArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: JmplG0PadOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplG0Manger.jmplG0Pad]]; }; { jmplG0Manger.tag ฌ SPARCArchitecture.Sethi[ hi: ORD[SPARCManger.MangerVariant.jmplG0], dest: SPARCArchitecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: TagOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplG0Manger.tag]]; }; { patchSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: patchCode]; instruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.BAa[ pc: instructionAddress, to: patchSPARCAddress]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: instruction]]; }; }; Uninstall: PUBLIC PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] ~ { tagInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[ address: manger, displacement: TagOffset[]]; SELECT tagInstruction.GetImm22[] FROM ORD[SPARCManger.MangerVariant.normal] => { UninstallNormal[address: address, manger: manger]; }; ORD[SPARCManger.MangerVariant.branch] => { UninstallBranch[address: address, manger: manger]; }; ORD[SPARCManger.MangerVariant.call] => { UninstallCall[address: address, manger: manger]; }; ORD[SPARCManger.MangerVariant.jmplO7] => { UninstallJmplO7[address: address, manger: manger]; }; ORD[SPARCManger.MangerVariant.jmplG0] => { UninstallJmplG0[address: address, manger: manger]; }; ENDCASE => { ERROR CantUninstall[ code: $UnknownTag, message: "Can't decode manger"]; }; }; UninstallNormal: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address] ~ { errorCode: SPARCManger.ErrorCode ฌ SPARCManger.nullErrorCode; errorMessage: SPARCManger.ErrorMessage ฌ SPARCManger.nullErrorMessage; { -- extra scope to contain EXITS. instruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[ address: manger, displacement: SheepOffset[]]; mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger]; sheepAddress: SPARCArchitecture.SPARCAddress ~ SPARCArchitecture.SPARCAddressFromDisplacement[ address: mangerSPARCAddress, displacement: SheepOffset[]]; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address]; unrelocated: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Relocate[ instruction: instruction, from: sheepAddress, to: instructionAddress ! SPARCArchitecture.CantRelocate => { errorCode ฌ $CantRelocate; errorMessage ฌ "Cannot unrelocate instruction to breakpoint address"; GO TO Cannot; }]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: unrelocated]]; EXITS Cannot => { ERROR CantUninstall[code: errorCode, message: errorMessage]; }; }; RETURN; }; UninstallBranch: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address] ~ { errorCode: SPARCManger.ErrorCode ฌ SPARCManger.nullErrorCode; errorMessage: SPARCManger.ErrorMessage ฌ SPARCManger.nullErrorMessage; { -- extra scope to contain EXITS. instruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[ address: manger, displacement: DctiOffset[]]; mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger]; dctiAddress: SPARCArchitecture.SPARCAddress ~ SPARCArchitecture.SPARCAddressFromDisplacement[ address: mangerSPARCAddress, displacement: DctiOffset[]]; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address]; unrelocated: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Relocate[ instruction: instruction, from: dctiAddress, to: instructionAddress ! SPARCArchitecture.CantRelocate => { errorCode ฌ $CantRelocate; errorMessage ฌ "Cannot unrelocate instruction to breakpoint address"; GO TO Cannot; }]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: unrelocated]]; EXITS Cannot => { ERROR CantUninstall[code: errorCode, message: errorMessage]; }; }; RETURN; }; UninstallCall: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address] ~ { errorCode: SPARCManger.ErrorCode ฌ SPARCManger.nullErrorCode; errorMessage: SPARCManger.ErrorMessage ฌ SPARCManger.nullErrorMessage; callAddrHiInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[ address: manger, displacement: CallAddrHiOffset[]]; callAddrHi: SPARCArchitecture.Imm22 ~ callAddrHiInstruction.GetImm22[]; callAddrLoInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[ address: manger, displacement: CallJmpOffset[]]; callAddrLo: SPARCArchitecture.Simm13 ~ callAddrLoInstruction.GetSimm13[]; callAddr: SPARCArchitecture.SPARCAddress ~ LOOPHOLE[SPARCArchitecture.HiLo[hi: callAddrHi, lo: callAddrLo]]; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address]; callInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Call[ pc: instructionAddress, to: callAddr]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: callInstruction]]; RETURN; }; UninstallJmplO7: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address] ~ { errorCode: SPARCManger.ErrorCode ฌ SPARCManger.nullErrorCode; errorMessage: SPARCManger.ErrorMessage ฌ SPARCManger.nullErrorMessage; jmplO7JmpInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[ address: manger, displacement: JmplO7JmpOffset[]]; jmplO7Instruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.SetRd[ instruction: jmplO7JmpInstruction, rd: SPARCArchitecture.Register.out7]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplO7Instruction]]; RETURN; }; UninstallJmplG0: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address] ~ { errorCode: SPARCManger.ErrorCode ฌ SPARCManger.nullErrorCode; errorMessage: SPARCManger.ErrorMessage ฌ SPARCManger.nullErrorMessage; jmplG0JmpInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[ address: manger, displacement: JmplG0JmpOffset[]]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplG0JmpInstruction]]; RETURN; }; SheepOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement ฌ TargetArchitecture.nullDisplacement; manger: SPARCManger.NormalManger; mangerAddress: LONG POINTER TO SPARCManger.NormalManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; sheepAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @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: SPARCManger.NormalManger; mangerAddress: LONG POINTER TO SPARCManger.NormalManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; normalContinueAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @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: SPARCManger.NormalManger; mangerAddress: LONG POINTER TO SPARCManger.NormalManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; normalNoopAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @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: SPARCManger.NormalManger; mangerAddress: LONG POINTER TO SPARCManger.NormalManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; tagAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @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: SPARCManger.BranchManger; mangerAddress: LONG POINTER TO SPARCManger.BranchManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; dctiAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @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: SPARCManger.BranchManger; mangerAddress: LONG POINTER TO SPARCManger.BranchManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; branchDelayAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @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: SPARCManger.BranchManger; mangerAddress: LONG POINTER TO SPARCManger.BranchManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; branchContinueAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @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: SPARCManger.CallManger; mangerAddress: LONG POINTER TO SPARCManger.CallManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; callAddrHiAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @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: SPARCManger.CallManger; mangerAddress: LONG POINTER TO SPARCManger.CallManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; callJmpAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @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: SPARCManger.CallManger; mangerAddress: LONG POINTER TO SPARCManger.CallManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; callNoopAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @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: SPARCManger.JmplO7Manger; mangerAddress: LONG POINTER TO SPARCManger.JmplO7Manger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jmplO7JmpAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @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: SPARCManger.JmplO7Manger; mangerAddress: LONG POINTER TO SPARCManger.JmplO7Manger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jmplO7NoopAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @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: SPARCManger.JmplO7Manger; mangerAddress: LONG POINTER TO SPARCManger.JmplO7Manger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jmplO7PadAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @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: SPARCManger.JmplG0Manger; mangerAddress: LONG POINTER TO SPARCManger.JmplG0Manger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jmplG0JmpAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @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: SPARCManger.JmplG0Manger; mangerAddress: LONG POINTER TO SPARCManger.JmplG0Manger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jmplG0DelayAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @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: SPARCManger.JmplG0Manger; mangerAddress: LONG POINTER TO SPARCManger.JmplG0Manger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jmplG0PadAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @manger.jmplG0Pad; jmplG0PadCard: CARD32 ~ LOOPHOLE[jmplG0PadAddress]; offset ฌ (jmplG0PadCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; CantInstall: PUBLIC ERROR [ code: SPARCManger.ErrorCode, message: SPARCManger.ErrorMessage] ~ CODE; CantUninstall: PUBLIC ERROR [ code: SPARCManger.ErrorCode, message: SPARCManger.ErrorMessage] ~ CODE; }. ` SPARCMangerImpl.mesa Copyright ำ 1990, 1991 by Xerox Corporation. All rights reserved. Peter B. Kessler, April 18, 1990 10:50:58 pm PDT Procedures 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! 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! link the patch into the running code. This better be atomic. Else you have a race in smashed memory! link the patch into the running code. This better be atomic. Else you have a race in smashed memory! Needs no relocation. link the patch into the running code. This better be atomic. Else you have a race in smashed memory! Is this the only transformation of the instruction that's required? This better be atomic. Else you have a race in smashed code! We don't need to replace the delay slot fortunately, since we wouldn't have time to. Is this the only transformation of the instruction that's required? This better be atomic. Else you have a race in smashed code! This better be atomic. Else you have a race in smashed code! This better be atomic. Else you have a race in smashed code! This better be atomic. Else you have a race in smashed code! Manger offsets: Errors ส™•NewlineDelimiter –(cedarcode) style™codešœ™Kšœ ฯeœ7™BK™0K™šฯk ˜ K˜K˜Kšœ˜Kšœ˜Kšœ ˜ —K˜—unitšะlnœžœž˜Kšžœe˜lKšžœ ˜Kšœ˜head™ šฯnœžœž œ‚žœ˜ฉšžœžœ˜!šžœ˜K˜6—K˜—šžœžœ˜ šžœ˜Kšœ5˜5—K˜—šžœžœ˜#šžœ˜Kšœ8˜8—K˜—˜˜1KšœQ˜Q—K˜šžœžœž˜˜BKšœJ˜JK˜—˜KKšœL˜LK˜—˜DKšœL˜LK˜—˜DKšœL˜LK˜—šœI˜Išžœ ˜Kšœ˜KšœO˜O—K˜—šžœ˜ KšœL˜LK˜——K˜—K˜K˜—š œž œ‚žœ˜ฎKšœ=˜=KšœF˜F˜4KšœM˜M—˜5KšœL˜L—Kšœ'˜'K˜˜šœ2˜2KšœQ˜Q—šœ5˜5KšœM˜M—šœ/˜/šœ/˜/Kšœ:˜:——šœK˜KK˜Kšœ˜Kšœ˜šœ%˜%K˜K˜CKšžœžœ˜ Kšœ˜—K™B—K˜Kšœ˜šœ'˜'Kšœ ˜ Kšœ˜šœE˜EKšœ"˜"——šž˜˜ Kšžœ5˜:K˜——K˜—˜šœ9˜9šœ;˜;Kšœ>˜>——šœ8˜8šœ/˜/KšœC˜C——K˜šœ4˜4Kšœ7˜7—šœ'˜'Kšœ ˜ Kšœ&˜&šœE˜EKšœ+˜+——K˜—˜Kšœ3˜3šœ'˜'Kšœ ˜ Kšœ"˜"šœE˜EKšœ'˜'——K˜—˜šœ+˜+Kšœžœ$˜+Kšœ*˜*—šœ'˜'Kšœ ˜ Kšœ˜šœE˜EKšœ ˜ ——K˜—˜Kšœ%™%šœ4˜4KšœO˜O—šœH˜HKšœ/˜/—K˜šœ'˜'Kšœ ˜ šœE˜EKšœ˜—K™?—Kšœ˜—Kšœ˜K˜—š œž œ‚žœ˜ฎKšœ=˜=KšœF˜F˜4KšœM˜M—˜5KšœL˜L—Kšœ'˜'šœf˜fKšœ ˜ —šœB˜BKšœI˜I—K˜˜šœ2˜2KšœQ˜Q—šœ5˜5KšœM˜M—šœ.˜.šœ/˜/Kšœ9˜9——šœK˜KK˜Kšœ˜Kšœ˜šœ%˜%K˜K˜CKšžœžœ˜ Kšœ˜—K™B—K˜Kšœ˜šœ'˜'Kšœ ˜ Kšœ˜šœE˜EKšœ!˜!——šž˜˜ Kšžœ5˜:K˜——K˜—˜šœ@˜@šœ;˜;Kšœ'˜'——šœ5˜5šœ/˜/Kšœ@˜@——šœ=˜=šœ?˜?Kšœ'˜'——šœF˜Fšœ˜Kšœ$˜$Kšœ%˜%Kšœ˜šœ%˜%K˜˜K˜B—Kšžœžœ˜ Kšœ˜———K˜Kšœ;˜;šœ'˜'Kšœ ˜ Kšœ#˜#šœE˜EKšœ(˜(——šž˜˜ Kšžœ5˜:K˜——K˜—˜šœC˜Cšœ;˜;Kšœ*˜*——šœ8˜8šœ/˜/KšœC˜C——K˜šœ4˜4KšœA˜A—šœ'˜'Kšœ ˜ Kšœ&˜&šœE˜EKšœ+˜+——K˜—˜šœ+˜+Kšœžœ$˜+Kšœ*˜*—šœ'˜'Kšœ ˜ Kšœ˜šœE˜EKšœ ˜ ——K˜—˜Kšœ%™%šœ4˜4KšœO˜O—šœH˜HKšœ/˜/—K˜šœ'˜'Kšœ ˜ šœE˜EKšœ˜—K™?—Kšœ˜—K˜K˜—š œž œ‚žœ˜ฌKšœ#˜#šœ2˜2KšœQ˜Q—šœ7˜7KšœL˜L—šœ5˜5KšœS˜S—K˜Fšœ4˜4Kšœžœ%˜>—šœU˜UKšœC˜C—˜5KšœL˜L—K˜˜šœ0˜0Kšœ žœ˜8Kšœ*˜*—šœ'˜'Kšœ ˜ Kšœ"˜"šœE˜EKšœ%˜%——K˜—˜šœ1˜1Kšœ+˜+Kšœ&žœ˜>Kšœ*˜*—šœ'˜'Kšœ ˜ Kšœ˜šœE˜EKšœ"˜"——K˜—˜Kšœ/˜/šœ'˜'Kšœ ˜ Kšœ ˜ šœE˜EKšœ#˜#——K˜—˜šœ)˜)Kšœžœ"˜)Kšœ*˜*—šœ'˜'Kšœ ˜ Kšœ˜šœE˜EKšœ˜——K˜—˜Kšœ%™%šœ4˜4KšœO˜O—šœI˜IKšœ/˜/—K˜šœ'˜'Kšœ ˜ šœE˜EKšœ˜—K™?—Kšœ˜—K˜K˜—š œž œ‚žœ˜ฎKšœ'˜'šœ5˜5KšœM˜M—˜5KšœL˜L—K˜˜šœ2˜2KšœQ˜Q—K˜šœ1˜1KšœB˜B—šœ'˜'Kšœ ˜ Kšœ!˜!šœE˜EKšœ&˜&——K˜—˜Kšœ3˜3šœ'˜'Kšœ ˜ Kšœ"˜"šœE˜EKšœ'˜'——K˜—˜Kšœ2˜2šœ'˜'Kšœ ˜ Kšœ!˜!šœE˜EKšœ&˜&——K˜—˜šœ+˜+Kšœžœ$˜+Kšœ*˜*—šœ'˜'Kšœ ˜ Kšœ˜šœE˜EKšœ ˜ ——K˜—˜Kšœ%™%šœ4˜4KšœO˜O—šœI˜IKšœ/˜/—K˜šœ'˜'Kšœ ˜ šœE˜EKšœ˜—K™?—Kšœ˜—K˜K˜—š œž œ‚žœ˜ฎKšœ=˜=KšœF˜Fšœ5˜5KšœM˜M—˜5KšœL˜L—Kšœ'˜'šœf˜fKšœ ˜ ——˜˜šœ2˜2KšœQ˜Q—K˜šœ%˜%K™—šœ'˜'Kšœ ˜ Kšœ!˜!šœE˜EKšœ&˜&——K˜—˜šœ@˜@šœ;˜;Kšœ'˜'——šœ5˜5šœ/˜/Kšœ@˜@——šœ=˜=šœ?˜?Kšœ'˜'——šœF˜Fšœ˜Kšœ$˜$Kšœ%˜%Kšœ˜šœ%˜%K˜˜K˜B—Kšžœžœ˜ Kšœ˜———K˜Kšœ;˜;šœ'˜'Kšœ ˜ Kšœ#˜#šœE˜EKšœ(˜(——šž˜˜ Kšžœ5˜:K˜——K˜—˜Kšœ2˜2šœ'˜'Kšœ ˜ Kšœ!˜!šœE˜EKšœ&˜&——K˜—˜šœ+˜+Kšœžœ$˜+Kšœ*˜*—šœ'˜'Kšœ ˜ Kšœ˜šœE˜EKšœ ˜ ——K˜—˜Kšœ%™%šœ4˜4KšœO˜O—šœH˜HKšœ/˜/—K˜šœ'˜'Kšœ ˜ šœE˜EKšœ˜—K™?—Kšœ˜—K˜K˜—š  œžœž œ„˜Ÿšœ5˜5šœ?˜?Kšœ,˜,——K˜šžœž˜%šžœ'˜*K˜2K˜—šžœ'˜*K˜2K˜—šžœ%˜(K˜0K˜—šžœ'˜*K˜2K˜—šžœ'˜*Kšœ2˜2K˜—šžœ˜ šžœ˜Kšœ3˜3—Kšœ˜——K˜K˜—š œž œX˜rK˜=KšœF˜Fšœฯc ˜"šœ2˜2šœ?˜?Kšœ.˜.——˜5KšœL˜L—šœ/˜/šœ/˜/Kšœ:˜:——šœ5˜5KšœM˜M—šœM˜MKšœD˜Dšœ%˜%K˜K˜EKšžœžœ˜ Kšœ˜—K™C—K˜šœ'˜'Kšœ ˜ šœE˜EKšœ˜—K™=—šž˜˜ Kšžœ7˜