MIPSMangerImpl.mesa
Copyright Ó 1992 by Xerox Corporation. All rights reserved.
Katsuyuki Komatsu August 5, 1992 3:38 pm PDT
Jas, October 12, 1992 3:33 pm PDT
DIRECTORY
TargetArchitecture,
MIPSArchitecture,
BreakWorldArchitecture,
MIPSBreakWorldUtilities,
MIPSManger;
MIPSMangerImpl: CEDAR PROGRAM
IMPORTS MIPSArchitecture, BreakWorldArchitecture, MIPSBreakWorldUtilities, MIPSManger
EXPORTS MIPSManger
~ {
Procedures
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;
}];
Is this the only transformation of the instruction that's required
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;
}];
Is this the only transformation of the instruction that's required
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]];
};
{
link the patch into the running code.
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;
}];
Is this the only transformation of the instruction that's required
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]];
};
{
link the patch into the running code.
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]];
};
{
link the patch into the running code.
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]];
};
{
link the patch into the running code.
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;
}];
Is this the only transformation of the instruction that's required?
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[
instruction: unrelocated]];
This better be atomic. Else you have a race in smashed code!
EXITS
Cannot => {
ERROR CantUninstall[code: errorCode, message: errorMessage];
};
};
RETURN;
};
UninstallBranch: PROCEDURE [
address: BreakWorldArchitecture.Address,
manger: BreakWorldArchitecture.Address] ~ {
We don't need to replace the delay slot fortunately, since we wouldn't have time to.
errorCode: 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;
}];
Is this the only transformation of the instruction that's required?
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[
instruction: unrelocated]];
This better be atomic. Else you have a race in smashed code!
EXITS
Cannot => {
ERROR CantUninstall[code: errorCode, message: errorMessage];
};
};
RETURN;
};
UninstallCall: PROCEDURE [
address: BreakWorldArchitecture.Address,
manger: BreakWorldArchitecture.Address] ~ {
errorCode: 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;
};
Manger offsets:
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];
};
Errors
CantInstall: PUBLIC ERROR [
code: MIPSManger.ErrorCode, message: MIPSManger.ErrorMessage] ~ CODE;
CantUninstall: PUBLIC ERROR [
code: MIPSManger.ErrorCode, message: MIPSManger.ErrorMessage] ~ CODE;
}.