RS6000MangerImpl.mesa
Copyright Ó 1990 by Xerox Corporation. All rights reserved.
Peter B. Kessler, April 18, 1990 10:50:58 pm PDT
Udagawa, September 13, 1991 6:48 pm PDT
DIRECTORY
TargetArchitecture,
RS6000Architecture,
BreakWorldArchitecture,
RS6000BreakWorldUtilities,
RS6000Manger;
RS6000MangerImpl: CEDAR PROGRAM
IMPORTS -- TargetArchitecture ,-- RS6000Architecture, BreakWorldArchitecture, RS6000BreakWorldUtilities, RS6000Manger
EXPORTS RS6000Manger
~ {
Procedures
Install: PUBLIC PROCEDURE [
address: BreakWorldArchitecture.Address,
manger: BreakWorldArchitecture.Address,
patchCode: BreakWorldArchitecture.Address]
RETURNS [] ~ {
IF address.IsNullAddress[] THEN {
ERROR RS6000Manger.CantInstall[
code: $NullAddress, message: "Install[null address]"];
};
IF manger.IsNullAddress[] THEN {
ERROR RS6000Manger.CantInstall[
code: $NullAddress, message: "Install[null manger]"];
};
IF patchCode.IsNullAddress[] THEN {
ERROR RS6000Manger.CantInstall[
code: $NullAddress, message: "Install[null patchCode]"];
};
{
instruction: RS6000Architecture.RS6000Instruction ~
RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[address: address];
SELECT TRUE FROM
RS6000Architecture.IsCallInstruction[instruction: instruction] => {
InstallCallManger[address: address, manger: manger, patchCode: patchCode];
};
RS6000Architecture.IsDelayedBranchInstruction[instruction: instruction] => {
InstallBranchManger[address: address, manger: manger, patchCode: patchCode];
};
RS6000Architecture.IsJmplO7Instruction[instruction: instruction] => {
InstallJmplO7Manger[address: address, manger: manger, patchCode: patchCode];
};
RS6000Architecture.IsJmplG0Instruction[instruction: instruction] => {
InstallJmplG0Manger[address: address, manger: manger, patchCode: patchCode];
};
RS6000Architecture.IsDelayedControlTransfer[instruction: instruction] => {
ERROR CantInstall[
code: $NotWithDelaySlot,
message: "Cannot install manger for instruction with that kind of delay slot"];
};
ENDCASE => {
InstallNormalManger[address: address, manger: manger, patchCode: patchCode];
};
};
};
InstallNormalManger: PROCEDURE [
address: BreakWorldArchitecture.Address,
manger: BreakWorldArchitecture.Address,
patchCode: BreakWorldArchitecture.Address]
RETURNS [] ~ {
errorCode: RS6000Manger.ErrorCode ← RS6000Manger.nullErrorCode;
errorMessage: RS6000Manger.ErrorMessage ← RS6000Manger.nullErrorMessage;
instructionAddress: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: address];
mangerRS6000Address: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: manger];
normalManger: RS6000Manger.NormalManger;
{
instruction: RS6000Architecture.RS6000Instruction ~
RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[address: address];
instructionAddress: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: address];
sheepAddress: RS6000Architecture.RS6000Address ~
RS6000Architecture.RS6000AddressFromDisplacement[
address: mangerRS6000Address, displacement: SheepOffset[]];
relocated: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.Relocate[
instruction: instruction,
from: instructionAddress,
to: sheepAddress
! RS6000Architecture.CantRelocate => {
errorCode ← $CantRelocate;
errorMessage ← "Cannot relocate instruction at breakpoint address";
GO TO Cannot;
}];
Is this the only transformation of the instruction that's required
normalManger.sheep ← relocated;
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: SheepOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: normalManger.sheep]];
EXITS
Cannot => {
ERROR CantInstall[code: errorCode, message: errorMessage];
};
};
{
nextInstructionAddress: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[
address: BreakWorldArchitecture.NextInstruction[pc: address]];
normalContinueAddress: RS6000Architecture.RS6000Address ~
RS6000Architecture.RS6000AddressFromDisplacement[
address: mangerRS6000Address, displacement: NormalContinueOffset[]];
normalManger.normalContinue ← RS6000Architecture.B[
pc: normalContinueAddress, to: nextInstructionAddress, abs: FALSE, link: FALSE];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: NormalContinueOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: normalManger.normalContinue]];
};
{
normalManger.normalNoop ← RS6000Architecture.Noop[];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: NormalNoopOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: normalManger.normalNoop]];
};
{
normalManger.tag ← RS6000Architecture.Liu[
rt: gpr3, upper: RS6000Architecture.High[ORD[RS6000Manger.MangerVariant.normal]]];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: TagOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: normalManger.tag]];
};
{
link the patch into the running code.
patchRS6000Address: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: patchCode];
instruction: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.B[
pc: instructionAddress, to: patchRS6000Address, abs: FALSE, link: FALSE];
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: instruction]];
This better be atomic. Else you have a race in smashed memory!
};
};
InstallBranchManger: PROCEDURE [
address: BreakWorldArchitecture.Address,
manger: BreakWorldArchitecture.Address,
patchCode: BreakWorldArchitecture.Address]
RETURNS [] ~ {
errorCode: RS6000Manger.ErrorCode ← RS6000Manger.nullErrorCode;
errorMessage: RS6000Manger.ErrorMessage ← RS6000Manger.nullErrorMessage;
instructionAddress: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: address];
mangerRS6000Address: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: manger];
branchManger: RS6000Manger.BranchManger;
branchDelayBreakWorldAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[
pc: address];
branchContinueBreakWorldAddress: BreakWorldArchitecture.Address ~
BreakWorldArchitecture.NextInstruction[pc: branchDelayBreakWorldAddress];
{
instruction: RS6000Architecture.RS6000Instruction ~
RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[address: address];
instructionAddress: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: address];
dctiAddress: RS6000Architecture.RS6000Address ~
RS6000Architecture.RS6000AddressFromDisplacement[
address: mangerRS6000Address, displacement: DctiOffset[]];
relocated: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.Relocate[
instruction: instruction,
from: instructionAddress,
to: dctiAddress
! RS6000Architecture.CantRelocate => {
errorCode ← $CantRelocate;
errorMessage ← "Cannot relocate instruction at breakpoint address";
GO TO Cannot;
}];
Is this the only transformation of the instruction that's required
branchManger.dcti ← relocated;
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: DctiOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: branchManger.dcti]];
EXITS
Cannot => {
ERROR CantInstall[code: errorCode, message: errorMessage];
};
};
{
branchDelayInstructionAddress: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[
address: branchDelayBreakWorldAddress];
branchDelayAddress: RS6000Architecture.RS6000Address ~
RS6000Architecture.RS6000AddressFromDisplacement[
address: mangerRS6000Address, displacement: BranchDelayOffset[]];
branchDelayInstruction: RS6000Architecture.RS6000Instruction ~
RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[
address: branchDelayBreakWorldAddress];
relocatedBranchDelayInstruction: RS6000Architecture.RS6000Instruction ~
RS6000Architecture.Relocate[
instruction: branchDelayInstruction,
from: branchDelayInstructionAddress,
to: branchDelayAddress
! RS6000Architecture.CantRelocate => {
errorCode ← $CantRelocate;
errorMessage ←
"Cannot relocate instruction in delay slot of breakpoint address";
GO TO Cannot;
}];
branchManger.branchDelay ← relocatedBranchDelayInstruction;
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: BranchDelayOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: branchManger.branchDelay]];
EXITS
Cannot => {
ERROR CantInstall[code: errorCode, message: errorMessage];
};
};
{
branchContinueInstructionAddress: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[
address: branchContinueBreakWorldAddress];
branchContinueAddress: RS6000Architecture.RS6000Address ~
RS6000Architecture.RS6000AddressFromDisplacement[
address: mangerRS6000Address, displacement: BranchContinueOffset[]];
branchManger.branchContinue ← RS6000Architecture.BAa[
pc: branchContinueAddress, to: branchContinueInstructionAddress];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: BranchContinueOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: branchManger.branchContinue]];
};
{
branchManger.tag ← RS6000Architecture.Sethi[
hi: ORD[RS6000Manger.MangerVariant.branch],
dest: RS6000Architecture.Register.global0];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: TagOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: branchManger.tag]];
};
{
link the patch into the running code.
patchRS6000Address: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: patchCode];
instruction: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.BAa[
pc: instructionAddress, to: patchRS6000Address];
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: instruction]];
This better be atomic. Else you have a race in smashed memory!
};
};
InstallCallManger: PROCEDURE [
address: BreakWorldArchitecture.Address,
manger: BreakWorldArchitecture.Address,
patchCode: BreakWorldArchitecture.Address]
RETURNS [] ~ {
callManger: RS6000Manger.CallManger;
instruction: RS6000Architecture.RS6000Instruction ~
RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[address: address];
instructionTargetAddress: TargetArchitecture.Address ~
BreakWorldArchitecture.TargetAddressFromBreakWorldAddress[address: address];
instructionAddress: RS6000Architecture.RS6000Address ~
RS6000Architecture.RS6000AddressFromTargetAddress[address: instructionTargetAddress];
instructionDisp30: RS6000Architecture.Disp30 ~ instruction.GetDisp30[];
byteDisplacement: TargetArchitecture.Displacement ~
instructionDisp30 * BYTES[RS6000Architecture.RS6000Instruction];
destination: TargetArchitecture.Address ~ TargetArchitecture.AddressFromDisplacement[
address: instructionTargetAddress, displacement: byteDisplacement];
mangerRS6000Address: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: manger];
{
callManger.callAddrHi ← RS6000Architecture.Sethi[
hi: RS6000Architecture.Hi[value: LOOPHOLE[destination]],
dest: RS6000Architecture.Register.global1];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: CallAddrHiOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: callManger.callAddrHi]];
};
{
callManger.callJmp ← RS6000Architecture.JmplConst[
source: RS6000Architecture.Register.global1,
constant: RS6000Architecture.Lo[value: LOOPHOLE[destination]],
dest: RS6000Architecture.Register.global0];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: CallJmpOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: callManger.callJmp]];
};
{
callManger.callNoop ← RS6000Architecture.Noop[];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: CallNoopOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: callManger.callNoop]];
};
{
callManger.tag ← RS6000Architecture.Sethi[
hi: ORD[RS6000Manger.MangerVariant.call],
dest: RS6000Architecture.Register.global0];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: TagOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: callManger.tag]];
};
{
link the patch into the running code.
patchRS6000Address: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: patchCode];
instruction: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.Call[
pc: instructionAddress, to: patchRS6000Address];
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: instruction]];
This better be atomic. Else you have a race in smashed memory!
};
};
InstallJmplO7Manger: PROCEDURE [
address: BreakWorldArchitecture.Address,
manger: BreakWorldArchitecture.Address,
patchCode: BreakWorldArchitecture.Address]
RETURNS [] ~ {
jmplO7Manger: RS6000Manger.JmplO7Manger;
instructionAddress: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: address];
mangerRS6000Address: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: manger];
{
instruction: RS6000Architecture.RS6000Instruction ~
RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[address: address];
jmplO7Manger.jmplO7Jmp ← RS6000Architecture.SetRd[
instruction: instruction, rd: RS6000Architecture.Register.global0];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: JmplO7JmpOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: jmplO7Manger.jmplO7Jmp]];
};
{
jmplO7Manger.jmplO7Noop ← RS6000Architecture.Noop[];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: JmplO7NoopOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: jmplO7Manger.jmplO7Noop]];
};
{
jmplO7Manger.jmplO7Pad ← RS6000Architecture.Noop[];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: JmplO7PadOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: jmplO7Manger.jmplO7Pad]];
};
{
jmplO7Manger.tag ← RS6000Architecture.Sethi[
hi: ORD[RS6000Manger.MangerVariant.jmplO7],
dest: RS6000Architecture.Register.global0];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: TagOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: jmplO7Manger.tag]];
};
{
link the patch into the running code.
patchRS6000Address: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: patchCode];
instruction: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.Call[
pc: instructionAddress, to: patchRS6000Address];
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: instruction]];
This better be atomic. Else you have a race in smashed memory!
};
};
InstallJmplG0Manger: PROCEDURE [
address: BreakWorldArchitecture.Address,
manger: BreakWorldArchitecture.Address,
patchCode: BreakWorldArchitecture.Address]
RETURNS [] ~ {
errorCode: RS6000Manger.ErrorCode ← RS6000Manger.nullErrorCode;
errorMessage: RS6000Manger.ErrorMessage ← RS6000Manger.nullErrorMessage;
instructionAddress: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: address];
mangerRS6000Address: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: manger];
jmplG0Manger: RS6000Manger.JmplG0Manger;
jmplG0DelayBreakWorldAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[
pc: address];
{
instruction: RS6000Architecture.RS6000Instruction ~
RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[address: address];
jmplG0Manger.jmplG0Jmp ← instruction;
Needs no relocation.
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: JmplG0JmpOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: jmplG0Manger.jmplG0Jmp]];
};
{
jmplG0DelayInstructionAddress: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[
address: jmplG0DelayBreakWorldAddress];
jmplG0DelayAddress: RS6000Architecture.RS6000Address ~
RS6000Architecture.RS6000AddressFromDisplacement[
address: mangerRS6000Address, displacement: JmplG0DelayOffset[]];
jmplG0DelayInstruction: RS6000Architecture.RS6000Instruction ~
RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[
address: jmplG0DelayBreakWorldAddress];
relocatedJmplG0DelayInstruction: RS6000Architecture.RS6000Instruction ~
RS6000Architecture.Relocate[
instruction: jmplG0DelayInstruction,
from: jmplG0DelayInstructionAddress,
to: jmplG0DelayAddress
! RS6000Architecture.CantRelocate => {
errorCode ← $CantRelocate;
errorMessage ←
"Cannot relocate instruction in delay slot of breakpoint address";
GO TO Cannot;
}];
jmplG0Manger.jmplG0Delay ← relocatedJmplG0DelayInstruction;
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: JmplG0DelayOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: jmplG0Manger.jmplG0Delay]];
EXITS
Cannot => {
ERROR CantInstall[code: errorCode, message: errorMessage];
};
};
{
jmplG0Manger.jmplG0Pad ← RS6000Architecture.Noop[];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: JmplG0PadOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: jmplG0Manger.jmplG0Pad]];
};
{
jmplG0Manger.tag ← RS6000Architecture.Sethi[
hi: ORD[RS6000Manger.MangerVariant.jmplG0],
dest: RS6000Architecture.Register.global0];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: TagOffset[],
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: jmplG0Manger.tag]];
};
{
link the patch into the running code.
patchRS6000Address: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: patchCode];
instruction: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.BAa[
pc: instructionAddress, to: patchRS6000Address];
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: instruction]];
This better be atomic. Else you have a race in smashed memory!
};
};
Uninstall: PUBLIC PROCEDURE [
address: BreakWorldArchitecture.Address,
manger: BreakWorldArchitecture.Address,
patchCode: BreakWorldArchitecture.Address] ~ {
tagInstruction: RS6000Architecture.RS6000Instruction ~
RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[
address: manger, displacement: TagOffset[]];
SELECT tagInstruction.GetImm22[] FROM
ORD[RS6000Manger.MangerVariant.normal] => {
UninstallNormal[address: address, manger: manger];
};
ORD[RS6000Manger.MangerVariant.branch] => {
UninstallBranch[address: address, manger: manger];
};
ORD[RS6000Manger.MangerVariant.call] => {
UninstallCall[address: address, manger: manger];
};
ORD[RS6000Manger.MangerVariant.jmplO7] => {
UninstallJmplO7[address: address, manger: manger];
};
ORD[RS6000Manger.MangerVariant.jmplG0] => {
UninstallJmplG0[address: address, manger: manger];
};
ENDCASE => {
ERROR CantUninstall[
code: $UnknownTag, message: "Can't decode manger"];
};
};
UninstallNormal: PROCEDURE [
address: BreakWorldArchitecture.Address,
manger: BreakWorldArchitecture.Address] ~ {
errorCode: RS6000Manger.ErrorCode ← RS6000Manger.nullErrorCode;
errorMessage: RS6000Manger.ErrorMessage ← RS6000Manger.nullErrorMessage;
{ -- extra scope to contain EXITS.
instruction: RS6000Architecture.RS6000Instruction ~
RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[
address: manger, displacement: SheepOffset[]];
mangerRS6000Address: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: manger];
sheepAddress: RS6000Architecture.RS6000Address ~
RS6000Architecture.RS6000AddressFromDisplacement[
address: mangerRS6000Address, displacement: SheepOffset[]];
instructionAddress: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: address];
unrelocated: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.Relocate[
instruction: instruction, from: sheepAddress, to: instructionAddress
! RS6000Architecture.CantRelocate => {
errorCode ← $CantRelocate;
errorMessage ← "Cannot unrelocate instruction to breakpoint address";
GO TO Cannot;
}];
Is this the only transformation of the instruction that's required?
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: unrelocated]];
This better be atomic. Else you have a race in smashed code!
EXITS
Cannot => {
ERROR CantUninstall[code: errorCode, message: errorMessage];
};
};
RETURN;
};
UninstallBranch: PROCEDURE [
address: BreakWorldArchitecture.Address,
manger: BreakWorldArchitecture.Address] ~ {
We don't need to replace the delay slot fortunately, since we wouldn't have time to.
errorCode: RS6000Manger.ErrorCode ← RS6000Manger.nullErrorCode;
errorMessage: RS6000Manger.ErrorMessage ← RS6000Manger.nullErrorMessage;
{ -- extra scope to contain EXITS.
instruction: RS6000Architecture.RS6000Instruction ~
RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[
address: manger, displacement: DctiOffset[]];
mangerRS6000Address: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: manger];
dctiAddress: RS6000Architecture.RS6000Address ~
RS6000Architecture.RS6000AddressFromDisplacement[
address: mangerRS6000Address, displacement: DctiOffset[]];
instructionAddress: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: address];
unrelocated: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.Relocate[
instruction: instruction, from: dctiAddress, to: instructionAddress
! RS6000Architecture.CantRelocate => {
errorCode ← $CantRelocate;
errorMessage ← "Cannot unrelocate instruction to breakpoint address";
GO TO Cannot;
}];
Is this the only transformation of the instruction that's required?
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: unrelocated]];
This better be atomic. Else you have a race in smashed code!
EXITS
Cannot => {
ERROR CantUninstall[code: errorCode, message: errorMessage];
};
};
RETURN;
};
UninstallCall: PROCEDURE [
address: BreakWorldArchitecture.Address,
manger: BreakWorldArchitecture.Address] ~ {
errorCode: RS6000Manger.ErrorCode ← RS6000Manger.nullErrorCode;
errorMessage: RS6000Manger.ErrorMessage ← RS6000Manger.nullErrorMessage;
callAddrHiInstruction: RS6000Architecture.RS6000Instruction ~
RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[
address: manger, displacement: CallAddrHiOffset[]];
callAddrHi: RS6000Architecture.Imm22 ~ callAddrHiInstruction.GetImm22[];
callAddrLoInstruction: RS6000Architecture.RS6000Instruction ~
RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[
address: manger, displacement: CallJmpOffset[]];
callAddrLo: RS6000Architecture.Simm13 ~ callAddrLoInstruction.GetSimm13[];
callAddr: RS6000Architecture.RS6000Address ~
LOOPHOLE[RS6000Architecture.HiLo[hi: callAddrHi, lo: callAddrLo]];
instructionAddress: RS6000Architecture.RS6000Address ~
RS6000BreakWorldUtilities.RS6000AddressFromBreakWorldAddress[address: address];
callInstruction: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.Call[
pc: instructionAddress, to: callAddr];
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: callInstruction]];
This better be atomic. Else you have a race in smashed code!
RETURN;
};
UninstallJmplO7: PROCEDURE [
address: BreakWorldArchitecture.Address,
manger: BreakWorldArchitecture.Address] ~ {
errorCode: RS6000Manger.ErrorCode ← RS6000Manger.nullErrorCode;
errorMessage: RS6000Manger.ErrorMessage ← RS6000Manger.nullErrorMessage;
jmplO7JmpInstruction: RS6000Architecture.RS6000Instruction ~
RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[
address: manger, displacement: JmplO7JmpOffset[]];
jmplO7Instruction: RS6000Architecture.RS6000Instruction ~ RS6000Architecture.SetRd[
instruction: jmplO7JmpInstruction, rd: RS6000Architecture.Register.out7];
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: jmplO7Instruction]];
This better be atomic. Else you have a race in smashed code!
RETURN;
};
UninstallJmplG0: PROCEDURE [
address: BreakWorldArchitecture.Address,
manger: BreakWorldArchitecture.Address] ~ {
errorCode: RS6000Manger.ErrorCode ← RS6000Manger.nullErrorCode;
errorMessage: RS6000Manger.ErrorMessage ← RS6000Manger.nullErrorMessage;
jmplG0JmpInstruction: RS6000Architecture.RS6000Instruction ~
RS6000BreakWorldUtilities.RS6000InstructionFromBreakWorldAddress[
address: manger, displacement: JmplG0JmpOffset[]];
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: RS6000Architecture.TargetInstructionFromRS6000Instruction[
instruction: jmplG0JmpInstruction]];
This better be atomic. Else you have a race in smashed code!
RETURN;
};
Manger offsets:
SheepOffset: PROCEDURE []
RETURNS [TargetArchitecture.Displacement] ~ TRUSTED {
offset: TargetArchitecture.Displacement ← TargetArchitecture.nullDisplacement;
manger: RS6000Manger.NormalManger;
mangerAddress: LONG POINTER TO RS6000Manger.NormalManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
sheepAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~
@manger.sheep;
sheepCard: CARD32 ~ LOOPHOLE[sheepAddress];
offset ← (sheepCard - mangerCard) * BYTES[UNIT];
RETURN [offset];
};
NormalContinueOffset: PROCEDURE []
RETURNS [TargetArchitecture.Displacement] ~ TRUSTED {
offset: TargetArchitecture.Displacement ← TargetArchitecture.nullDisplacement;
manger: RS6000Manger.NormalManger;
mangerAddress: LONG POINTER TO RS6000Manger.NormalManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
normalContinueAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~
@manger.normalContinue;
normalContinueCard: CARD32 ~ LOOPHOLE[normalContinueAddress];
offset ← (normalContinueCard - mangerCard) * BYTES[UNIT];
RETURN [offset];
};
NormalNoopOffset: PROCEDURE []
RETURNS [TargetArchitecture.Displacement] ~ TRUSTED {
offset: TargetArchitecture.Displacement ← TargetArchitecture.nullDisplacement;
manger: RS6000Manger.NormalManger;
mangerAddress: LONG POINTER TO RS6000Manger.NormalManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
normalNoopAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~
@manger.normalNoop;
normalNoopCard: CARD32 ~ LOOPHOLE[normalNoopAddress];
offset ← (normalNoopCard - mangerCard) * BYTES[UNIT];
RETURN [offset];
};
TagOffset: PROCEDURE []
RETURNS [TargetArchitecture.Displacement] ~ TRUSTED {
offset: TargetArchitecture.Displacement ← TargetArchitecture.nullDisplacement;
manger: RS6000Manger.NormalManger;
mangerAddress: LONG POINTER TO RS6000Manger.NormalManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
tagAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~
@manger.tag;
tagCard: CARD32 ~ LOOPHOLE[tagAddress];
offset ← (tagCard - mangerCard) * BYTES[UNIT];
RETURN [offset];
};
DctiOffset: PROCEDURE []
RETURNS [TargetArchitecture.Displacement] ~ TRUSTED {
offset: TargetArchitecture.Displacement ← TargetArchitecture.nullDisplacement;
manger: RS6000Manger.BranchManger;
mangerAddress: LONG POINTER TO RS6000Manger.BranchManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
dctiAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~
@manger.dcti;
dctiCard: CARD32 ~ LOOPHOLE[dctiAddress];
offset ← (dctiCard - mangerCard) * BYTES[UNIT];
RETURN [offset];
};
BranchDelayOffset: PROCEDURE []
RETURNS [TargetArchitecture.Displacement] ~ TRUSTED {
offset: TargetArchitecture.Displacement ← TargetArchitecture.nullDisplacement;
manger: RS6000Manger.BranchManger;
mangerAddress: LONG POINTER TO RS6000Manger.BranchManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
branchDelayAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~
@manger.branchDelay;
branchDelayCard: CARD32 ~ LOOPHOLE[branchDelayAddress];
offset ← (branchDelayCard - mangerCard) * BYTES[UNIT];
RETURN [offset];
};
BranchContinueOffset: PROCEDURE []
RETURNS [TargetArchitecture.Displacement] ~ TRUSTED {
offset: TargetArchitecture.Displacement ← TargetArchitecture.nullDisplacement;
manger: RS6000Manger.BranchManger;
mangerAddress: LONG POINTER TO RS6000Manger.BranchManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
branchContinueAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~
@manger.branchContinue;
branchContinueCard: CARD32 ~ LOOPHOLE[branchContinueAddress];
offset ← (branchContinueCard - mangerCard) * BYTES[UNIT];
RETURN [offset];
};
CallAddrHiOffset: PROCEDURE []
RETURNS [TargetArchitecture.Displacement] ~ TRUSTED {
offset: TargetArchitecture.Displacement ← TargetArchitecture.nullDisplacement;
manger: RS6000Manger.CallManger;
mangerAddress: LONG POINTER TO RS6000Manger.CallManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
callAddrHiAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~
@manger.callAddrHi;
callAddrHiCard: CARD32 ~ LOOPHOLE[callAddrHiAddress];
offset ← (callAddrHiCard - mangerCard) * BYTES[UNIT];
RETURN [offset];
};
CallJmpOffset: PROCEDURE []
RETURNS [TargetArchitecture.Displacement] ~ TRUSTED {
offset: TargetArchitecture.Displacement ← TargetArchitecture.nullDisplacement;
manger: RS6000Manger.CallManger;
mangerAddress: LONG POINTER TO RS6000Manger.CallManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
callJmpAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~
@manger.callJmp;
callJmpCard: CARD32 ~ LOOPHOLE[callJmpAddress];
offset ← (callJmpCard - mangerCard) * BYTES[UNIT];
RETURN [offset];
};
CallNoopOffset: PROCEDURE []
RETURNS [TargetArchitecture.Displacement] ~ TRUSTED {
offset: TargetArchitecture.Displacement ← TargetArchitecture.nullDisplacement;
manger: RS6000Manger.CallManger;
mangerAddress: LONG POINTER TO RS6000Manger.CallManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
callNoopAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~
@manger.callNoop;
callNoopCard: CARD32 ~ LOOPHOLE[callNoopAddress];
offset ← (callNoopCard - mangerCard) * BYTES[UNIT];
RETURN [offset];
};
JmplO7JmpOffset: PROCEDURE []
RETURNS [TargetArchitecture.Displacement] ~ TRUSTED {
offset: TargetArchitecture.Displacement ← TargetArchitecture.nullDisplacement;
manger: RS6000Manger.JmplO7Manger;
mangerAddress: LONG POINTER TO RS6000Manger.JmplO7Manger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
jmplO7JmpAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~
@manger.jmplO7Jmp;
jmplO7JmpCard: CARD32 ~ LOOPHOLE[jmplO7JmpAddress];
offset ← (jmplO7JmpCard - mangerCard) * BYTES[UNIT];
RETURN [offset];
};
JmplO7NoopOffset: PROCEDURE []
RETURNS [TargetArchitecture.Displacement] ~ TRUSTED {
offset: TargetArchitecture.Displacement ← TargetArchitecture.nullDisplacement;
manger: RS6000Manger.JmplO7Manger;
mangerAddress: LONG POINTER TO RS6000Manger.JmplO7Manger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
jmplO7NoopAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~
@manger.jmplO7Noop;
jmplO7NoopCard: CARD32 ~ LOOPHOLE[jmplO7NoopAddress];
offset ← (jmplO7NoopCard - mangerCard) * BYTES[UNIT];
RETURN [offset];
};
JmplO7PadOffset: PROCEDURE []
RETURNS [TargetArchitecture.Displacement] ~ TRUSTED {
offset: TargetArchitecture.Displacement ← TargetArchitecture.nullDisplacement;
manger: RS6000Manger.JmplO7Manger;
mangerAddress: LONG POINTER TO RS6000Manger.JmplO7Manger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
jmplO7PadAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~
@manger.jmplO7Pad;
jmplO7PadCard: CARD32 ~ LOOPHOLE[jmplO7PadAddress];
offset ← (jmplO7PadCard - mangerCard) * BYTES[UNIT];
RETURN [offset];
};
JmplG0JmpOffset: PROCEDURE []
RETURNS [TargetArchitecture.Displacement] ~ TRUSTED {
offset: TargetArchitecture.Displacement ← TargetArchitecture.nullDisplacement;
manger: RS6000Manger.JmplG0Manger;
mangerAddress: LONG POINTER TO RS6000Manger.JmplG0Manger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
jmplG0JmpAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~
@manger.jmplG0Jmp;
jmplG0JmpCard: CARD32 ~ LOOPHOLE[jmplG0JmpAddress];
offset ← (jmplG0JmpCard - mangerCard) * BYTES[UNIT];
RETURN [offset];
};
JmplG0DelayOffset: PROCEDURE []
RETURNS [TargetArchitecture.Displacement] ~ TRUSTED {
offset: TargetArchitecture.Displacement ← TargetArchitecture.nullDisplacement;
manger: RS6000Manger.JmplG0Manger;
mangerAddress: LONG POINTER TO RS6000Manger.JmplG0Manger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
jmplG0DelayAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~
@manger.jmplG0Delay;
jmplG0DelayCard: CARD32 ~ LOOPHOLE[jmplG0DelayAddress];
offset ← (jmplG0DelayCard - mangerCard) * BYTES[UNIT];
RETURN [offset];
};
JmplG0PadOffset: PROCEDURE []
RETURNS [TargetArchitecture.Displacement] ~ TRUSTED {
offset: TargetArchitecture.Displacement ← TargetArchitecture.nullDisplacement;
manger: RS6000Manger.JmplG0Manger;
mangerAddress: LONG POINTER TO RS6000Manger.JmplG0Manger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
jmplG0PadAddress: LONG POINTER TO RS6000Architecture.RS6000Instruction ~
@manger.jmplG0Pad;
jmplG0PadCard: CARD32 ~ LOOPHOLE[jmplG0PadAddress];
offset ← (jmplG0PadCard - mangerCard) * BYTES[UNIT];
RETURN [offset];
};
Errors
CantInstall: PUBLIC ERROR [
code: RS6000Manger.ErrorCode, message: RS6000Manger.ErrorMessage] ~ CODE;
CantUninstall: PUBLIC ERROR [
code: RS6000Manger.ErrorCode, message: RS6000Manger.ErrorMessage] ~ CODE;
}.