<<>> <> <> <> <> <<>> DIRECTORY TargetArchitecture, MIPSArchitecture, BreakWorldArchitecture, MIPSBreakWorldUtilities, MIPSManger; MIPSMangerImpl: CEDAR PROGRAM IMPORTS MIPSArchitecture, BreakWorldArchitecture, MIPSBreakWorldUtilities, MIPSManger EXPORTS MIPSManger ~ { <> Install: PUBLIC PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { IF address.IsNullAddress[] THEN { ERROR MIPSManger.CantInstall[ code: $NullAddress, message: "Install[null address]"]; }; IF manger.IsNullAddress[] THEN { ERROR MIPSManger.CantInstall[ code: $NullAddress, message: "Install[null manger]"]; }; IF patchCode.IsNullAddress[] THEN { ERROR MIPSManger.CantInstall[ code: $NullAddress, message: "Install[null patchCode]"]; }; { instruction: MIPSArchitecture.MIPSInstruction ~ MIPSBreakWorldUtilities.MIPSInstructionFromBreakWorldAddress[address: address]; SELECT TRUE FROM MIPSArchitecture.IsBranchInstruction[instruction: instruction] => { InstallBranchManger[address: address, manger: manger, patchCode: patchCode]; }; MIPSArchitecture.IsCallInstruction[instruction: instruction] => { InstallCallManger[address: address, manger: manger, patchCode: patchCode]; }; MIPSArchitecture.IsJumpInstruction[instruction: instruction] => { InstallJumpManger[address: address, manger: manger, patchCode: patchCode]; }; MIPSArchitecture.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: MIPSManger.ErrorCode _ MIPSManger.nullErrorCode; errorMessage: MIPSManger.ErrorMessage _ MIPSManger.nullErrorMessage; instructionAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: address]; nextAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[pc: address]; nextInstructionAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: nextAddress]; continueAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[pc: nextAddress]; continueInstructionAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: continueAddress]; mangerMIPSAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: manger]; normalManger: MIPSManger.NormalManger; { instruction: MIPSArchitecture.MIPSInstruction ~ MIPSBreakWorldUtilities.MIPSInstructionFromBreakWorldAddress[address: address]; sheep1Address: MIPSArchitecture.MIPSAddress ~ MIPSArchitecture.MIPSAddressFromDisplacement[ address: mangerMIPSAddress, displacement: Sheep1Offset[]]; relocated: MIPSArchitecture.MIPSInstruction ~ MIPSArchitecture.Relocate[ instruction: instruction, from: instructionAddress, to: sheep1Address ! MIPSArchitecture.CantRelocate => { errorCode _ $CantRelocate; errorMessage _ "Cannot relocate instruction at breakpoint address"; GO TO Cannot; }]; <> normalManger.sheep1 _ relocated; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: Sheep1Offset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: normalManger.sheep1]]; EXITS Cannot => { ERROR CantInstall[code: errorCode, message: errorMessage]; }; }; { instruction: MIPSArchitecture.MIPSInstruction ~ MIPSBreakWorldUtilities.MIPSInstructionFromBreakWorldAddress[address: nextAddress]; sheep2Address: MIPSArchitecture.MIPSAddress ~ MIPSArchitecture.MIPSAddressFromDisplacement[ address: mangerMIPSAddress, displacement: Sheep2Offset[]]; relocated: MIPSArchitecture.MIPSInstruction ~ MIPSArchitecture.Relocate[ instruction: instruction, from: instructionAddress, to: sheep2Address ! MIPSArchitecture.CantRelocate => { errorCode _ $CantRelocate; errorMessage _ "Cannot relocate instruction at breakpoint address"; GO TO Cannot; }]; <> normalManger.sheep2 _ relocated; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: Sheep2Offset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: normalManger.sheep2]]; EXITS Cannot => { ERROR CantInstall[code: errorCode, message: errorMessage]; }; }; { normalContinueAddress: MIPSArchitecture.MIPSAddress ~ MIPSArchitecture.MIPSAddressFromDisplacement[ address: mangerMIPSAddress, displacement: NormalContinueOffset[]]; normalManger.normalContinue _ MIPSArchitecture.J[ pc: normalContinueAddress, to: continueInstructionAddress]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: NormalContinueOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: normalManger.normalContinue]]; }; { normalManger.normalNoop _ MIPSArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: NormalNoopOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: normalManger.normalNoop]]; }; { normalManger.tag _ MIPSArchitecture.LUI[ hi: ORD[MIPSManger.MangerVariant.normal], dest: MIPSArchitecture.Register.r0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: TagOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: normalManger.tag]]; }; { BreakWorldArchitecture.PokeContents[ address: manger, displacement: TagOffset[]+4, contents: LOOPHOLE[instructionAddress]]; }; { <> patchMIPSAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: patchCode]; instruction: MIPSArchitecture.MIPSInstruction ~ MIPSArchitecture.J[ pc: instructionAddress, to: patchMIPSAddress]; nextInstruction: MIPSArchitecture.MIPSInstruction ~ MIPSArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: instruction]]; BreakWorldArchitecture.PokeInstruction[ pc: nextAddress, instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: nextInstruction]]; }; }; InstallBranchManger: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { errorCode: MIPSManger.ErrorCode _ MIPSManger.nullErrorCode; errorMessage: MIPSManger.ErrorMessage _ MIPSManger.nullErrorMessage; instructionAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: address]; nextAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[pc: address]; nextInstructionAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: nextAddress]; continueAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[pc: nextAddress]; continueInstructionAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: continueAddress]; mangerMIPSAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: manger]; branchManger: MIPSManger.BranchManger; branchDelayBreakWorldAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[pc: address]; branchContinueBreakWorldAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[pc: branchDelayBreakWorldAddress]; { instruction: MIPSArchitecture.MIPSInstruction ~ MIPSBreakWorldUtilities.MIPSInstructionFromBreakWorldAddress[address: address]; branchBAddress: MIPSArchitecture.MIPSAddress ~ MIPSArchitecture.MIPSAddressFromDisplacement[ address: mangerMIPSAddress, displacement: BranchBOffset[]]; relocated: MIPSArchitecture.MIPSInstruction ~ MIPSArchitecture.Relocate[ instruction: instruction, from: instructionAddress, to: branchBAddress ! MIPSArchitecture.CantRelocate => { errorCode _ $CantRelocate; errorMessage _ "Cannot relocate instruction at breakpoint address"; GO TO Cannot; }]; <> branchManger.branchB _ relocated; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: BranchBOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: branchManger.branchB]]; EXITS Cannot => { ERROR CantInstall[code: errorCode, message: errorMessage]; }; }; { branchDelayInstructionAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[ address: branchDelayBreakWorldAddress]; branchDelayAddress: MIPSArchitecture.MIPSAddress ~ MIPSArchitecture.MIPSAddressFromDisplacement[ address: mangerMIPSAddress, displacement: BranchDelayOffset[]]; branchDelayInstruction: MIPSArchitecture.MIPSInstruction ~ MIPSBreakWorldUtilities.MIPSInstructionFromBreakWorldAddress[ address: branchDelayBreakWorldAddress]; relocatedBranchDelayInstruction: MIPSArchitecture.MIPSInstruction ~ MIPSArchitecture.Relocate[ instruction: branchDelayInstruction, from: branchDelayInstructionAddress, to: branchDelayAddress ! MIPSArchitecture.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: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: branchManger.branchDelay]]; EXITS Cannot => { ERROR CantInstall[code: errorCode, message: errorMessage]; }; }; { branchContinueInstructionAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[ address: branchContinueBreakWorldAddress]; branchContinueAddress: MIPSArchitecture.MIPSAddress ~ MIPSArchitecture.MIPSAddressFromDisplacement[ address: mangerMIPSAddress, displacement: BranchContinueOffset[]]; branchManger.branchContinue _ MIPSArchitecture.J[ pc: branchContinueAddress, to: branchContinueInstructionAddress]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: BranchContinueOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: branchManger.branchContinue]]; }; { branchManger.branchNoop _ MIPSArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: BranchNoopOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: branchManger.branchNoop]]; }; { branchManger.tag _ MIPSArchitecture.LUI[ hi: ORD[MIPSManger.MangerVariant.branch], dest: MIPSArchitecture.Register.r0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: TagOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: branchManger.tag]]; }; { BreakWorldArchitecture.PokeContents[ address: manger, displacement: TagOffset[]+4, contents: LOOPHOLE[instructionAddress]]; }; { <> patchMIPSAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: patchCode]; instruction: MIPSArchitecture.MIPSInstruction ~ MIPSArchitecture.J[ pc: instructionAddress, to: patchMIPSAddress]; nextInstruction: MIPSArchitecture.MIPSInstruction ~ MIPSArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: instruction]]; BreakWorldArchitecture.PokeInstruction[ pc: nextAddress, instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: nextInstruction]]; }; }; InstallCallManger: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { callManger: MIPSManger.CallManger; instruction: MIPSArchitecture.MIPSInstruction ~ MIPSBreakWorldUtilities.MIPSInstructionFromBreakWorldAddress[address: address]; instructionTargetAddress: TargetArchitecture.Address ~ BreakWorldArchitecture.TargetAddressFromBreakWorldAddress[address: address]; instructionAddress: MIPSArchitecture.MIPSAddress ~ MIPSArchitecture.MIPSAddressFromTargetAddress[address: instructionTargetAddress]; mangerMIPSAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: manger]; { addressFormat: MIPSArchitecture.AddressFormat ~ [ high: MIPSArchitecture.GetHighOrderBits[instructionAddress], target: MIPSArchitecture.GetDisp26[instruction], tag: 0]; callTargetAddress: MIPSArchitecture.MIPSAddress ~ LOOPHOLE[addressFormat]; callManger.callJ _ MIPSArchitecture.J[ pc: mangerMIPSAddress, to: callTargetAddress]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: CallJOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: callManger.callJ]]; }; { callManger.callNoop _ MIPSArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: CallNoopOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: callManger.callNoop]]; }; { callManger.dummy1 _ MIPSArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: Dummy1Offset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: callManger.dummy1]]; }; { callManger.dummy2 _ MIPSArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: Dummy2Offset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: callManger.dummy2]]; }; { callManger.tag _ MIPSArchitecture.LUI[ hi: ORD[MIPSManger.MangerVariant.call], dest: MIPSArchitecture.Register.r0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: TagOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: callManger.tag]]; }; { BreakWorldArchitecture.PokeContents[ address: manger, displacement: TagOffset[]+4, contents: LOOPHOLE[instructionAddress]]; }; { <> patchMIPSAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: patchCode]; instruction: MIPSArchitecture.MIPSInstruction ~ MIPSArchitecture.JAL[ pc: instructionAddress, to: patchMIPSAddress]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: instruction]]; }; }; InstallJumpManger: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { errorCode: MIPSManger.ErrorCode _ MIPSManger.nullErrorCode; errorMessage: MIPSManger.ErrorMessage _ MIPSManger.nullErrorMessage; instructionAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: address]; mangerMIPSAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: manger]; jumpManger: MIPSManger.JumpManger; jumpDelayBreakWorldAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[pc: address]; { instruction: MIPSArchitecture.MIPSInstruction ~ MIPSBreakWorldUtilities.MIPSInstructionFromBreakWorldAddress[address: address]; jumpJAddress: MIPSArchitecture.MIPSAddress ~ MIPSArchitecture.MIPSAddressFromDisplacement[ address: mangerMIPSAddress, displacement: JumpJOffset[]]; relocatedInstruction: MIPSArchitecture.MIPSInstruction ~ MIPSArchitecture.Relocate[ instruction: instruction, from: instructionAddress, to: jumpJAddress ! MIPSArchitecture.CantRelocate => { errorCode _ $CantRelocate; errorMessage _ "Cannot relocate instruction in delay slot of breakpoint address"; GO TO Cannot; }]; jumpManger.jumpJ _ relocatedInstruction; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: JumpJOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: jumpManger.jumpJ]]; EXITS Cannot => { ERROR CantInstall[code: errorCode, message: errorMessage]; }; }; { jumpManger.jumpNoop _ MIPSArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: JumpNoopOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: jumpManger.jumpNoop]]; }; { jumpManger.dummy1 _ MIPSArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: Dummy1Offset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: jumpManger.dummy1]]; }; { jumpManger.dummy2 _ MIPSArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: Dummy2Offset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: jumpManger.dummy2]]; }; { jumpManger.tag _ MIPSArchitecture.LUI[ hi: ORD[MIPSManger.MangerVariant.jump], dest: MIPSArchitecture.Register.r0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: TagOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: jumpManger.tag]]; }; { BreakWorldArchitecture.PokeContents[ address: manger, displacement: TagOffset[]+4, contents: LOOPHOLE[instructionAddress]]; }; { <> patchMIPSAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: patchCode]; instruction: MIPSArchitecture.MIPSInstruction ~ MIPSArchitecture.J[ pc: instructionAddress, to: patchMIPSAddress]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: instruction]]; }; }; Uninstall: PUBLIC PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] ~ { tagInstruction: MIPSArchitecture.MIPSInstruction ~ MIPSBreakWorldUtilities.MIPSInstructionFromBreakWorldAddress[ address: manger, displacement: TagOffset[]]; SELECT tagInstruction.GetImm16[] FROM ORD[MIPSManger.MangerVariant.normal] => { UninstallNormal[address: address, manger: manger]; }; ORD[MIPSManger.MangerVariant.branch] => { UninstallBranch[address: address, manger: manger]; }; ORD[MIPSManger.MangerVariant.call] => { UninstallCall[address: address, manger: manger]; }; ORD[MIPSManger.MangerVariant.jump] => { UninstallJump[address: address, manger: manger]; }; ENDCASE => { ERROR CantUninstall[ code: $UnknownTag, message: "Can't decode manger"]; }; }; UninstallNormal: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address] ~ { errorCode: MIPSManger.ErrorCode _ MIPSManger.nullErrorCode; errorMessage: MIPSManger.ErrorMessage _ MIPSManger.nullErrorMessage; { -- extra scope to contain EXITS. instruction: MIPSArchitecture.MIPSInstruction ~ MIPSBreakWorldUtilities.MIPSInstructionFromBreakWorldAddress[ address: manger, displacement: Sheep1Offset[]]; mangerMIPSAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: manger]; sheep1Address: MIPSArchitecture.MIPSAddress ~ MIPSArchitecture.MIPSAddressFromDisplacement[ address: mangerMIPSAddress, displacement: Sheep1Offset[]]; instructionAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: address]; unrelocated: MIPSArchitecture.MIPSInstruction ~ MIPSArchitecture.Relocate[ instruction: instruction, from: sheep1Address, to: instructionAddress ! MIPSArchitecture.CantRelocate => { errorCode _ $CantRelocate; errorMessage _ "Cannot unrelocate instruction to breakpoint address"; GO TO Cannot; }]; <> BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: unrelocated]]; <> EXITS Cannot => { ERROR CantUninstall[code: errorCode, message: errorMessage]; }; }; RETURN; }; UninstallBranch: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address] ~ { <> errorCode: MIPSManger.ErrorCode _ MIPSManger.nullErrorCode; errorMessage: MIPSManger.ErrorMessage _ MIPSManger.nullErrorMessage; { -- extra scope to contain EXITS. instruction: MIPSArchitecture.MIPSInstruction ~ MIPSBreakWorldUtilities.MIPSInstructionFromBreakWorldAddress[ address: manger, displacement: BranchBOffset[]]; mangerMIPSAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: manger]; branchBAddress: MIPSArchitecture.MIPSAddress ~ MIPSArchitecture.MIPSAddressFromDisplacement[ address: mangerMIPSAddress, displacement: BranchBOffset[]]; instructionAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: address]; unrelocated: MIPSArchitecture.MIPSInstruction ~ MIPSArchitecture.Relocate[ instruction: instruction, from: branchBAddress, to: instructionAddress ! MIPSArchitecture.CantRelocate => { errorCode _ $CantRelocate; errorMessage _ "Cannot unrelocate instruction to breakpoint address"; GO TO Cannot; }]; <> BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: unrelocated]]; <> EXITS Cannot => { ERROR CantUninstall[code: errorCode, message: errorMessage]; }; }; RETURN; }; UninstallCall: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address] ~ { errorCode: MIPSManger.ErrorCode _ MIPSManger.nullErrorCode; errorMessage: MIPSManger.ErrorMessage _ MIPSManger.nullErrorMessage; callJAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[ address: manger, displacement: CallJOffset[]]; callJInstruction: MIPSArchitecture.MIPSInstruction ~ MIPSBreakWorldUtilities.MIPSInstructionFromBreakWorldAddress[ address: manger, displacement: CallJOffset[]]; callAddr: MIPSArchitecture.MIPSAddress ~ LOOPHOLE[MIPSArchitecture.AddressFormat[ high: MIPSArchitecture.GetHighOrderBits[callJAddress], target: MIPSArchitecture.GetDisp26[callJInstruction], tag: 0]]; instructionAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: address]; callInstruction: MIPSArchitecture.MIPSInstruction ~ MIPSArchitecture.JAL[ pc: instructionAddress, to: callAddr]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: callInstruction]]; RETURN; }; UninstallJump: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address] ~ { errorCode: MIPSManger.ErrorCode _ MIPSManger.nullErrorCode; errorMessage: MIPSManger.ErrorMessage _ MIPSManger.nullErrorMessage; { -- extra scope to contain EXITS. instructionAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: address]; jumpJInstruction: MIPSArchitecture.MIPSInstruction ~ MIPSBreakWorldUtilities.MIPSInstructionFromBreakWorldAddress[ address: manger, displacement: JumpJOffset[]]; mangerMIPSAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: manger]; jumpJAddress: MIPSArchitecture.MIPSAddress ~ MIPSArchitecture.MIPSAddressFromDisplacement[ address: mangerMIPSAddress, displacement: JumpJOffset[]]; unrelocated: MIPSArchitecture.MIPSInstruction ~ MIPSArchitecture.Relocate[ instruction: jumpJInstruction, from: jumpJAddress, to: instructionAddress ! MIPSArchitecture.CantRelocate => { errorCode _ $CantRelocate; errorMessage _ "Cannot unrelocate instruction to breakpoint address"; GO TO Cannot; }]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: unrelocated]]; EXITS Cannot => { ERROR CantUninstall[code: errorCode, message: errorMessage]; }; }; RETURN; }; <> Sheep1Offset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: MIPSManger.NormalManger; mangerAddress: LONG POINTER TO MIPSManger.NormalManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; sheep1Address: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @manger.sheep1; sheep1Card: CARD32 ~ LOOPHOLE[sheep1Address]; offset _ (sheep1Card - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; Sheep2Offset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: MIPSManger.NormalManger; mangerAddress: LONG POINTER TO MIPSManger.NormalManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; sheep2Address: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @manger.sheep2; sheep2Card: CARD32 ~ LOOPHOLE[sheep2Address]; offset _ (sheep2Card - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; NormalContinueOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: MIPSManger.NormalManger; mangerAddress: LONG POINTER TO MIPSManger.NormalManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; normalContinueAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @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: MIPSManger.NormalManger; mangerAddress: LONG POINTER TO MIPSManger.NormalManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; normalNoopAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @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: MIPSManger.NormalManger; mangerAddress: LONG POINTER TO MIPSManger.NormalManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; tagAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @manger.tag; tagCard: CARD32 ~ LOOPHOLE[tagAddress]; offset _ (tagCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; BranchBOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: MIPSManger.BranchManger; mangerAddress: LONG POINTER TO MIPSManger.BranchManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; branchBAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @manger.branchB; branchBCard: CARD32 ~ LOOPHOLE[branchBAddress]; offset _ (branchBCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; BranchDelayOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: MIPSManger.BranchManger; mangerAddress: LONG POINTER TO MIPSManger.BranchManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; branchDelayAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @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: MIPSManger.BranchManger; mangerAddress: LONG POINTER TO MIPSManger.BranchManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; branchContinueAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @manger.branchContinue; branchContinueCard: CARD32 ~ LOOPHOLE[branchContinueAddress]; offset _ (branchContinueCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; BranchNoopOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: MIPSManger.BranchManger; mangerAddress: LONG POINTER TO MIPSManger.BranchManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; branchNoopAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @manger.branchNoop; branchNoopCard: CARD32 ~ LOOPHOLE[branchNoopAddress]; offset _ (branchNoopCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; CallJOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: MIPSManger.CallManger; mangerAddress: LONG POINTER TO MIPSManger.CallManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; callJAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @manger.callJ; callJCard: CARD32 ~ LOOPHOLE[callJAddress]; offset _ (callJCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; CallNoopOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: MIPSManger.CallManger; mangerAddress: LONG POINTER TO MIPSManger.CallManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; callNoopAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @manger.callNoop; callNoopCard: CARD32 ~ LOOPHOLE[callNoopAddress]; offset _ (callNoopCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; JumpJOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: MIPSManger.JumpManger; mangerAddress: LONG POINTER TO MIPSManger.JumpManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jumpJAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @manger.jumpJ; jumpJCard: CARD32 ~ LOOPHOLE[jumpJAddress]; offset _ (jumpJCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; JumpNoopOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: MIPSManger.JumpManger; mangerAddress: LONG POINTER TO MIPSManger.JumpManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jumpNoopAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @manger.jumpNoop; jumpNoopCard: CARD32 ~ LOOPHOLE[jumpNoopAddress]; offset _ (jumpNoopCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; Dummy1Offset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: MIPSManger.JumpManger; mangerAddress: LONG POINTER TO MIPSManger.JumpManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; dummy1Address: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @manger.dummy1; dummy1Card: CARD32 ~ LOOPHOLE[dummy1Address]; offset _ (dummy1Card - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; Dummy2Offset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: MIPSManger.JumpManger; mangerAddress: LONG POINTER TO MIPSManger.JumpManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; dummy2Address: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @manger.dummy2; dummy2Card: CARD32 ~ LOOPHOLE[dummy2Address]; offset _ (dummy2Card - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; <> CantInstall: PUBLIC ERROR [ code: MIPSManger.ErrorCode, message: MIPSManger.ErrorMessage] ~ CODE; CantUninstall: PUBLIC ERROR [ code: MIPSManger.ErrorCode, message: MIPSManger.ErrorMessage] ~ CODE; }.