SPARCMangerImpl.mesa
Copyright Ó 1990 by Xerox Corporation. All rights reserved.
Peter B. Kessler, April 18, 1990 10:50:58 pm PDT
DIRECTORY
TargetArchitecture,
SPARCArchitecture,
BreakWorldArchitecture,
SPARCBreakWorldUtilities,
SPARCManger;
SPARCMangerImpl: CEDAR PROGRAM
IMPORTS TargetArchitecture, SPARCArchitecture, BreakWorldArchitecture, SPARCBreakWorldUtilities, SPARCManger
EXPORTS SPARCManger
~ {
Procedures
Install: PUBLIC PROCEDURE [
address: BreakWorldArchitecture.Address,
manger: BreakWorldArchitecture.Address,
patchCode: BreakWorldArchitecture.Address]
RETURNS [] ~ {
IF address.IsNullAddress[] THEN {
ERROR SPARCManger.CantInstall[
code: $NullAddress, message: "Install[null address]"];
};
IF manger.IsNullAddress[] THEN {
ERROR SPARCManger.CantInstall[
code: $NullAddress, message: "Install[null manger]"];
};
IF patchCode.IsNullAddress[] THEN {
ERROR SPARCManger.CantInstall[
code: $NullAddress, message: "Install[null patchCode]"];
};
{
instruction: SPARCArchitecture.SPARCInstruction ~
SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[address: address];
SELECT TRUE FROM
SPARCArchitecture.IsCallInstruction[instruction: instruction] => {
InstallCallManger[address: address, manger: manger, patchCode: patchCode];
};
SPARCArchitecture.IsDelayedBranchInstruction[instruction: instruction] => {
InstallBranchManger[address: address, manger: manger, patchCode: patchCode];
};
SPARCArchitecture.IsJmplO7Instruction[instruction: instruction] => {
InstallJmplO7Manger[address: address, manger: manger, patchCode: patchCode];
};
SPARCArchitecture.IsJmplG0Instruction[instruction: instruction] => {
InstallJmplG0Manger[address: address, manger: manger, patchCode: patchCode];
};
SPARCArchitecture.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: SPARCManger.ErrorCode ← SPARCManger.nullErrorCode;
errorMessage: SPARCManger.ErrorMessage ← SPARCManger.nullErrorMessage;
instructionAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address];
mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger];
normalManger: SPARCManger.NormalManger;
{
instruction: SPARCArchitecture.SPARCInstruction ~
SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[address: address];
instructionAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address];
sheepAddress: SPARCArchitecture.SPARCAddress ~
SPARCArchitecture.SPARCAddressFromDisplacement[
address: mangerSPARCAddress, displacement: SheepOffset[]];
relocated: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Relocate[
instruction: instruction,
from: instructionAddress,
to: sheepAddress
! SPARCArchitecture.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: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: normalManger.sheep]];
EXITS
Cannot => {
ERROR CantInstall[code: errorCode, message: errorMessage];
};
};
{
nextInstructionAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[
address: BreakWorldArchitecture.NextInstruction[pc: address]];
normalContinueAddress: SPARCArchitecture.SPARCAddress ~
SPARCArchitecture.SPARCAddressFromDisplacement[
address: mangerSPARCAddress, displacement: NormalContinueOffset[]];
normalManger.normalContinue ← SPARCArchitecture.BAa[
pc: normalContinueAddress, to: nextInstructionAddress];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: NormalContinueOffset[],
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: normalManger.normalContinue]];
};
{
normalManger.normalNoop ← SPARCArchitecture.Noop[];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: NormalNoopOffset[],
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: normalManger.normalNoop]];
};
{
normalManger.tag ← SPARCArchitecture.Sethi[
hi: ORD[SPARCManger.MangerVariant.normal],
dest: SPARCArchitecture.Register.global0];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: TagOffset[],
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: normalManger.tag]];
};
{
link the patch into the running code.
patchSPARCAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: patchCode];
instruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.BAa[
pc: instructionAddress, to: patchSPARCAddress];
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
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: SPARCManger.ErrorCode ← SPARCManger.nullErrorCode;
errorMessage: SPARCManger.ErrorMessage ← SPARCManger.nullErrorMessage;
instructionAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address];
mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger];
branchManger: SPARCManger.BranchManger;
branchDelayBreakWorldAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[
pc: address];
branchContinueBreakWorldAddress: BreakWorldArchitecture.Address ~
BreakWorldArchitecture.NextInstruction[pc: branchDelayBreakWorldAddress];
{
instruction: SPARCArchitecture.SPARCInstruction ~
SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[address: address];
instructionAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address];
dctiAddress: SPARCArchitecture.SPARCAddress ~
SPARCArchitecture.SPARCAddressFromDisplacement[
address: mangerSPARCAddress, displacement: DctiOffset[]];
relocated: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Relocate[
instruction: instruction,
from: instructionAddress,
to: dctiAddress
! SPARCArchitecture.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: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: branchManger.dcti]];
EXITS
Cannot => {
ERROR CantInstall[code: errorCode, message: errorMessage];
};
};
{
branchDelayInstructionAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[
address: branchDelayBreakWorldAddress];
branchDelayAddress: SPARCArchitecture.SPARCAddress ~
SPARCArchitecture.SPARCAddressFromDisplacement[
address: mangerSPARCAddress, displacement: BranchDelayOffset[]];
branchDelayInstruction: SPARCArchitecture.SPARCInstruction ~
SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[
address: branchDelayBreakWorldAddress];
relocatedBranchDelayInstruction: SPARCArchitecture.SPARCInstruction ~
SPARCArchitecture.Relocate[
instruction: branchDelayInstruction,
from: branchDelayInstructionAddress,
to: branchDelayAddress
! SPARCArchitecture.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: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: branchManger.branchDelay]];
EXITS
Cannot => {
ERROR CantInstall[code: errorCode, message: errorMessage];
};
};
{
branchContinueInstructionAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[
address: branchContinueBreakWorldAddress];
branchContinueAddress: SPARCArchitecture.SPARCAddress ~
SPARCArchitecture.SPARCAddressFromDisplacement[
address: mangerSPARCAddress, displacement: BranchContinueOffset[]];
branchManger.branchContinue ← SPARCArchitecture.BAa[
pc: branchContinueAddress, to: branchContinueInstructionAddress];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: BranchContinueOffset[],
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: branchManger.branchContinue]];
};
{
branchManger.tag ← SPARCArchitecture.Sethi[
hi: ORD[SPARCManger.MangerVariant.branch],
dest: SPARCArchitecture.Register.global0];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: TagOffset[],
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: branchManger.tag]];
};
{
link the patch into the running code.
patchSPARCAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: patchCode];
instruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.BAa[
pc: instructionAddress, to: patchSPARCAddress];
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
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: SPARCManger.CallManger;
instruction: SPARCArchitecture.SPARCInstruction ~
SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[address: address];
instructionTargetAddress: TargetArchitecture.Address ~
BreakWorldArchitecture.TargetAddressFromBreakWorldAddress[address: address];
instructionAddress: SPARCArchitecture.SPARCAddress ~
SPARCArchitecture.SPARCAddressFromTargetAddress[address: instructionTargetAddress];
instructionDisp30: SPARCArchitecture.Disp30 ~ instruction.GetDisp30[];
byteDisplacement: TargetArchitecture.Displacement ~
instructionDisp30 * BYTES[SPARCArchitecture.SPARCInstruction];
destination: TargetArchitecture.Address ~ TargetArchitecture.AddressFromDisplacement[
address: instructionTargetAddress, displacement: byteDisplacement];
mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger];
{
callManger.callAddrHi ← SPARCArchitecture.Sethi[
hi: SPARCArchitecture.Hi[value: LOOPHOLE[destination]],
dest: SPARCArchitecture.Register.global1];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: CallAddrHiOffset[],
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: callManger.callAddrHi]];
};
{
callManger.callJmp ← SPARCArchitecture.JmplConst[
source: SPARCArchitecture.Register.global1,
constant: SPARCArchitecture.Lo[value: LOOPHOLE[destination]],
dest: SPARCArchitecture.Register.global0];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: CallJmpOffset[],
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: callManger.callJmp]];
};
{
callManger.callNoop ← SPARCArchitecture.Noop[];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: CallNoopOffset[],
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: callManger.callNoop]];
};
{
callManger.tag ← SPARCArchitecture.Sethi[
hi: ORD[SPARCManger.MangerVariant.call],
dest: SPARCArchitecture.Register.global0];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: TagOffset[],
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: callManger.tag]];
};
{
link the patch into the running code.
patchSPARCAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: patchCode];
instruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Call[
pc: instructionAddress, to: patchSPARCAddress];
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
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: SPARCManger.JmplO7Manger;
instructionAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address];
mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger];
{
instruction: SPARCArchitecture.SPARCInstruction ~
SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[address: address];
jmplO7Manger.jmplO7Jmp ← SPARCArchitecture.SetRd[
instruction: instruction, rd: SPARCArchitecture.Register.global0];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: JmplO7JmpOffset[],
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: jmplO7Manger.jmplO7Jmp]];
};
{
jmplO7Manger.jmplO7Noop ← SPARCArchitecture.Noop[];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: JmplO7NoopOffset[],
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: jmplO7Manger.jmplO7Noop]];
};
{
jmplO7Manger.jmplO7Pad ← SPARCArchitecture.Noop[];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: JmplO7PadOffset[],
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: jmplO7Manger.jmplO7Pad]];
};
{
jmplO7Manger.tag ← SPARCArchitecture.Sethi[
hi: ORD[SPARCManger.MangerVariant.jmplO7],
dest: SPARCArchitecture.Register.global0];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: TagOffset[],
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: jmplO7Manger.tag]];
};
{
link the patch into the running code.
patchSPARCAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: patchCode];
instruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Call[
pc: instructionAddress, to: patchSPARCAddress];
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
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: SPARCManger.ErrorCode ← SPARCManger.nullErrorCode;
errorMessage: SPARCManger.ErrorMessage ← SPARCManger.nullErrorMessage;
instructionAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address];
mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger];
jmplG0Manger: SPARCManger.JmplG0Manger;
jmplG0DelayBreakWorldAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[
pc: address];
{
instruction: SPARCArchitecture.SPARCInstruction ~
SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[address: address];
jmplG0Manger.jmplG0Jmp ← instruction;
Needs no relocation.
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: JmplG0JmpOffset[],
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: jmplG0Manger.jmplG0Jmp]];
};
{
jmplG0DelayInstructionAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[
address: jmplG0DelayBreakWorldAddress];
jmplG0DelayAddress: SPARCArchitecture.SPARCAddress ~
SPARCArchitecture.SPARCAddressFromDisplacement[
address: mangerSPARCAddress, displacement: JmplG0DelayOffset[]];
jmplG0DelayInstruction: SPARCArchitecture.SPARCInstruction ~
SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[
address: jmplG0DelayBreakWorldAddress];
relocatedJmplG0DelayInstruction: SPARCArchitecture.SPARCInstruction ~
SPARCArchitecture.Relocate[
instruction: jmplG0DelayInstruction,
from: jmplG0DelayInstructionAddress,
to: jmplG0DelayAddress
! SPARCArchitecture.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: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: jmplG0Manger.jmplG0Delay]];
EXITS
Cannot => {
ERROR CantInstall[code: errorCode, message: errorMessage];
};
};
{
jmplG0Manger.jmplG0Pad ← SPARCArchitecture.Noop[];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: JmplG0PadOffset[],
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: jmplG0Manger.jmplG0Pad]];
};
{
jmplG0Manger.tag ← SPARCArchitecture.Sethi[
hi: ORD[SPARCManger.MangerVariant.jmplG0],
dest: SPARCArchitecture.Register.global0];
BreakWorldArchitecture.PokeInstruction[
pc: manger,
displacement: TagOffset[],
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: jmplG0Manger.tag]];
};
{
link the patch into the running code.
patchSPARCAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: patchCode];
instruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.BAa[
pc: instructionAddress, to: patchSPARCAddress];
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
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: SPARCArchitecture.SPARCInstruction ~
SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[
address: manger, displacement: TagOffset[]];
SELECT tagInstruction.GetImm22[] FROM
ORD[SPARCManger.MangerVariant.normal] => {
UninstallNormal[address: address, manger: manger];
};
ORD[SPARCManger.MangerVariant.branch] => {
UninstallBranch[address: address, manger: manger];
};
ORD[SPARCManger.MangerVariant.call] => {
UninstallCall[address: address, manger: manger];
};
ORD[SPARCManger.MangerVariant.jmplO7] => {
UninstallJmplO7[address: address, manger: manger];
};
ORD[SPARCManger.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: SPARCManger.ErrorCode ← SPARCManger.nullErrorCode;
errorMessage: SPARCManger.ErrorMessage ← SPARCManger.nullErrorMessage;
{ -- extra scope to contain EXITS.
instruction: SPARCArchitecture.SPARCInstruction ~
SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[
address: manger, displacement: SheepOffset[]];
mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger];
sheepAddress: SPARCArchitecture.SPARCAddress ~
SPARCArchitecture.SPARCAddressFromDisplacement[
address: mangerSPARCAddress, displacement: SheepOffset[]];
instructionAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address];
unrelocated: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Relocate[
instruction: instruction, from: sheepAddress, to: instructionAddress
! SPARCArchitecture.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: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
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: SPARCManger.ErrorCode ← SPARCManger.nullErrorCode;
errorMessage: SPARCManger.ErrorMessage ← SPARCManger.nullErrorMessage;
{ -- extra scope to contain EXITS.
instruction: SPARCArchitecture.SPARCInstruction ~
SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[
address: manger, displacement: DctiOffset[]];
mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger];
dctiAddress: SPARCArchitecture.SPARCAddress ~
SPARCArchitecture.SPARCAddressFromDisplacement[
address: mangerSPARCAddress, displacement: DctiOffset[]];
instructionAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address];
unrelocated: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Relocate[
instruction: instruction, from: dctiAddress, to: instructionAddress
! SPARCArchitecture.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: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
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: SPARCManger.ErrorCode ← SPARCManger.nullErrorCode;
errorMessage: SPARCManger.ErrorMessage ← SPARCManger.nullErrorMessage;
callAddrHiInstruction: SPARCArchitecture.SPARCInstruction ~
SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[
address: manger, displacement: CallAddrHiOffset[]];
callAddrHi: SPARCArchitecture.Imm22 ~ callAddrHiInstruction.GetImm22[];
callAddrLoInstruction: SPARCArchitecture.SPARCInstruction ~
SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[
address: manger, displacement: CallJmpOffset[]];
callAddrLo: SPARCArchitecture.Simm13 ~ callAddrLoInstruction.GetSimm13[];
callAddr: SPARCArchitecture.SPARCAddress ~
LOOPHOLE[SPARCArchitecture.HiLo[hi: callAddrHi, lo: callAddrLo]];
instructionAddress: SPARCArchitecture.SPARCAddress ~
SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address];
callInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Call[
pc: instructionAddress, to: callAddr];
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: callInstruction]];
This better be atomic. Else you have a race in smashed code!
RETURN;
};
UninstallJmplO7: PROCEDURE [
address: BreakWorldArchitecture.Address,
manger: BreakWorldArchitecture.Address] ~ {
errorCode: SPARCManger.ErrorCode ← SPARCManger.nullErrorCode;
errorMessage: SPARCManger.ErrorMessage ← SPARCManger.nullErrorMessage;
jmplO7JmpInstruction: SPARCArchitecture.SPARCInstruction ~
SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[
address: manger, displacement: JmplO7JmpOffset[]];
jmplO7Instruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.SetRd[
instruction: jmplO7JmpInstruction, rd: SPARCArchitecture.Register.out7];
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
instruction: jmplO7Instruction]];
This better be atomic. Else you have a race in smashed code!
RETURN;
};
UninstallJmplG0: PROCEDURE [
address: BreakWorldArchitecture.Address,
manger: BreakWorldArchitecture.Address] ~ {
errorCode: SPARCManger.ErrorCode ← SPARCManger.nullErrorCode;
errorMessage: SPARCManger.ErrorMessage ← SPARCManger.nullErrorMessage;
jmplG0JmpInstruction: SPARCArchitecture.SPARCInstruction ~
SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[
address: manger, displacement: JmplG0JmpOffset[]];
BreakWorldArchitecture.PokeInstruction[
pc: address,
instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[
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: SPARCManger.NormalManger;
mangerAddress: LONG POINTER TO SPARCManger.NormalManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
sheepAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~
@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: SPARCManger.NormalManger;
mangerAddress: LONG POINTER TO SPARCManger.NormalManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
normalContinueAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~
@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: SPARCManger.NormalManger;
mangerAddress: LONG POINTER TO SPARCManger.NormalManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
normalNoopAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~
@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: SPARCManger.NormalManger;
mangerAddress: LONG POINTER TO SPARCManger.NormalManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
tagAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~
@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: SPARCManger.BranchManger;
mangerAddress: LONG POINTER TO SPARCManger.BranchManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
dctiAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~
@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: SPARCManger.BranchManger;
mangerAddress: LONG POINTER TO SPARCManger.BranchManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
branchDelayAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~
@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: SPARCManger.BranchManger;
mangerAddress: LONG POINTER TO SPARCManger.BranchManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
branchContinueAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~
@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: SPARCManger.CallManger;
mangerAddress: LONG POINTER TO SPARCManger.CallManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
callAddrHiAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~
@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: SPARCManger.CallManger;
mangerAddress: LONG POINTER TO SPARCManger.CallManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
callJmpAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~
@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: SPARCManger.CallManger;
mangerAddress: LONG POINTER TO SPARCManger.CallManger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
callNoopAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~
@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: SPARCManger.JmplO7Manger;
mangerAddress: LONG POINTER TO SPARCManger.JmplO7Manger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
jmplO7JmpAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~
@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: SPARCManger.JmplO7Manger;
mangerAddress: LONG POINTER TO SPARCManger.JmplO7Manger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
jmplO7NoopAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~
@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: SPARCManger.JmplO7Manger;
mangerAddress: LONG POINTER TO SPARCManger.JmplO7Manger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
jmplO7PadAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~
@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: SPARCManger.JmplG0Manger;
mangerAddress: LONG POINTER TO SPARCManger.JmplG0Manger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
jmplG0JmpAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~
@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: SPARCManger.JmplG0Manger;
mangerAddress: LONG POINTER TO SPARCManger.JmplG0Manger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
jmplG0DelayAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~
@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: SPARCManger.JmplG0Manger;
mangerAddress: LONG POINTER TO SPARCManger.JmplG0Manger ~ @manger;
mangerCard: CARD32 ~ LOOPHOLE[mangerAddress];
jmplG0PadAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~
@manger.jmplG0Pad;
jmplG0PadCard: CARD32 ~ LOOPHOLE[jmplG0PadAddress];
offset ← (jmplG0PadCard - mangerCard) * BYTES[UNIT];
RETURN [offset];
};
Errors
CantInstall: PUBLIC ERROR [
code: SPARCManger.ErrorCode, message: SPARCManger.ErrorMessage] ~ CODE;
CantUninstall: PUBLIC ERROR [
code: SPARCManger.ErrorCode, message: SPARCManger.ErrorMessage] ~ CODE;
}.