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!
};
};
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];
};