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; }. Š MIPSMangerImpl.mesa Copyright ำ 1992, 1993 by Xerox Corporation. All rights reserved. Katsuyuki Komatsu August 5, 1992 3:38 pm PDT Jas, October 12, 1992 3:33 pm PDT Procedures Is this the only transformation of the instruction that's required Is this the only transformation of the instruction that's required link the patch into the running code. Is this the only transformation of the instruction that's required link the patch into the running code. link the patch into the running code. link the patch into the running code. 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! Manger offsets: Errors สา–"cedarcode" style•NewlineDelimiter ™codešœ™Kšœ ฯeœ7™BK™,K™!K™šฯk ˜ K˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ —K˜—unitšะlnœžœž˜KšžœN˜UKšžœ ˜Kšœ˜head™ šฯnœžœž œ‚žœ˜ฉšžœžœ˜!šžœ˜K˜6—K˜—šžœžœ˜ šžœ˜Kšœ5˜5—K˜—šžœžœ˜#šžœ˜Kšœ8˜8—K˜—˜˜/KšœO˜O—K˜šžœžœž˜˜CKšœL˜LK˜—˜AKšœJ˜JK˜—˜AKšœJ˜JK˜—šœH˜Hšžœ ˜Kšœ˜KšœO˜O—K˜—šžœ˜ KšœL˜LK˜——K˜—K˜K˜—š œž œ‚žœ˜ฎK˜;K˜Dšœ3˜3KšœK˜K—Kšœb˜bKšœ†˜†Kšœj˜jKšœŽ˜Ž˜2KšœJ˜J—Kšœ&˜&K˜˜šœ0˜0KšœO˜O—šœ.˜.šœ-˜-Kšœ:˜:——šœH˜HK˜Kšœ˜Kšœ˜šœ$˜$K˜K˜CKšžœžœ˜ Kšœ˜—K™B—K˜K˜ šœ'˜'Kšœ ˜ Kšœ˜šœC˜CKšœ#˜#——šž˜˜ Kšžœ5˜:K˜——K˜—˜šœ0˜0KšœS˜S—šœ.˜.šœ-˜-Kšœ:˜:——šœH˜HK˜Kšœ˜Kšœ˜šœ$˜$K˜K˜CKšžœžœ˜ Kšœ˜—K™B—K˜K˜ šœ'˜'Kšœ ˜ Kšœ˜šœC˜CKšœ#˜#——šž˜˜ Kšžœ5˜:K˜——K˜—˜šœ6˜6šœ-˜-KšœB˜B——K˜˜1Kšœ;˜;—šœ'˜'Kšœ ˜ Kšœ&˜&šœC˜CKšœ+˜+——K˜—˜K˜2šœ'˜'Kšœ ˜ Kšœ"˜"šœC˜CKšœ'˜'——K˜—˜šœ$žœ˜(Kšœžœ#˜*Kšœ$˜$—šœ'˜'Kšœ ˜ Kšœ˜šœC˜CKšœ ˜ ——K˜—˜šœ$˜$Kšœ˜Kšœ˜Kšœ žœ˜(—K˜—˜Kšœ%™%šœ1˜1KšœM˜M—šœC˜CKšœ.˜.—KšœL˜LK˜šœ'˜'Kšœ ˜ šœC˜CKšœ˜——šœ'˜'Kšœ˜šœC˜CKšœ˜——Kšœ˜—Kšœ˜K˜—š œž œ‚žœ˜ฎK˜;K˜D˜2KšœK˜K—Kšœb˜bKšœ†˜†Kšœj˜jKšœŽ˜Ž˜2KšœJ˜J—Kšœ&˜&Kšœs˜sšœB˜BKšœI˜I—K˜˜šœ0˜0KšœO˜O—šœ/˜/šœ-˜-Kšœ;˜;——šœH˜HK˜Kšœ˜Kšœ˜šœ$˜$K˜K˜CKšžœžœ˜ Kšœ˜—K™B—K˜K˜!šœ'˜'Kšœ ˜ Kšœ˜šœC˜CKšœ$˜$——šž˜˜ Kšžœ5˜:K˜——K˜—˜šœ>˜>šœ9˜9Kšœ'˜'——šœ3˜3šœ-˜-Kšœ?˜?——šœ;˜;šœ=˜=Kšœ'˜'——šœD˜Dšœ˜Kšœ$˜$Kšœ%˜%Kšœ˜šœ$˜$K˜˜K˜B—Kšžœžœ˜ Kšœ˜———K˜K˜;šœ'˜'Kšœ ˜ Kšœ#˜#šœC˜CKšœ(˜(——šž˜˜ Kšžœ5˜:K˜——K˜—˜šœA˜Ašœ9˜9Kšœ*˜*——šœ6˜6šœ-˜-KšœB˜B——K˜˜1KšœA˜A—šœ'˜'Kšœ ˜ Kšœ&˜&šœC˜CKšœ+˜+——K˜—˜K˜2šœ'˜'Kšœ ˜ Kšœ"˜"šœC˜CKšœ'˜'——K˜—˜šœ$žœ˜(Kšœžœ#˜*Kšœ$˜$—šœ'˜'Kšœ ˜ Kšœ˜šœC˜CKšœ ˜ ——K˜—˜šœ$˜$Kšœ˜Kšœ˜Kšœ žœ˜(—K˜—˜Kšœ%™%šœ1˜1KšœM˜M—šœC˜CKšœ.˜.—KšœL˜LK˜šœ'˜'Kšœ ˜ šœC˜CKšœ˜——šœ'˜'Kšœ˜šœC˜CKšœ˜——Kšœ˜—K˜K˜—š œž œ‚žœ˜ฌKšœ"˜"šœ0˜0KšœO˜O—šœ7˜7KšœL˜L—šœ3˜3KšœQ˜Q—˜2KšœJ˜J—K˜˜šœ1˜1Kšœ<˜