TestBreakpointFlavors:
PROCEDURE []
RETURNS [] ~ {
breakWorld: BreakWorldArchitecture.BreakWorld ~
BreakWorldArchitecture.CreateBreakWorld[
name: "SPARC",
peekContents: FakeCirio.PeekContents,
pokeContents: FakeCirio.PokeContents,
getProcAddress: FakeCirio.GetProcAddress,
getProcDataSegment: NIL,
getPatchArea: FakeCirio.GetPatchArea,
monitoredCall: FakeCirio.MonitoredCall,
worldAccessData: NIL];
breakpointAddress: BreakWorldArchitecture.Address ~ FakeCirio.GetProcAddress[
breakWorld: breakWorld, procName: ACleanWellLightedPlaceForBreakpointsName];
breakProcedureAddress: BreakWorldArchitecture.Address ~ FakeCirio.GetProcAddress[
breakWorld: breakWorld, procName: TheMinimalBreakProcedureName];
break: Breakpoint.Break ← Breakpoint.nullBreak;
{
normalAddress: BreakWorldArchitecture.Address ~
BreakWorldArchitecture.AddressFromDisplacement[
address: breakpointAddress, displacement: 01CH];
instruction: TargetArchitecture.Instruction ~ BreakWorldArchitecture.PeekInstruction[
pc: normalAddress];
IF instruction #
LOOPHOLE[090102001H]
THEN {
stdout.PutRope["Normal break, but not mov 0x1, %o0\n"];
ERROR;
};
intRef^ ← testInt;
break ← TestSetBreakpoint[address: normalAddress,
proc: breakProcedureAddress, clientData: LOOPHOLE[intRef]];
ACleanWellLightedPlaceForBreakpoints[];
IF intRef^ = checkInt
THEN {
stdout.PutF["\t\t\tNormal break seems to work\n"];
}
ELSE {
stdout.PutF["\t\t\tNormal break DOES NOT WORK: intRef^ = %g\n",
[integer[intRef^]]];
ERROR;
};
TestClearBreakpoint[break: break];
};
{
branchTakenAddress: BreakWorldArchitecture.Address ~
BreakWorldArchitecture.AddressFromDisplacement[
address: breakpointAddress, displacement: 02CH];
instruction: TargetArchitecture.Instruction ~ BreakWorldArchitecture.PeekInstruction[
pc: branchTakenAddress];
IF instruction #
LOOPHOLE[012800005H]
THEN {
stdout.PutRope["Branch (taken) break, but not bne .+0x5\n"];
ERROR;
};
intRef^ ← testInt;
break ← TestSetBreakpoint[address: branchTakenAddress,
proc: breakProcedureAddress, clientData: LOOPHOLE[intRef]];
ACleanWellLightedPlaceForBreakpoints[];
IF intRef^ = checkInt
THEN {
stdout.PutF["\t\t\tBranch taken break seems to work\n"];
}
ELSE {
stdout.PutF["\t\t\tBranch taken break DOES NOT WORK: intRef^ = %g\n",
[integer[intRef^]]];
ERROR;
};
TestClearBreakpoint[break: break];
};
{
branchNotTakenAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.AddressFromDisplacement[
address: breakpointAddress, displacement: 048H];
instruction: TargetArchitecture.Instruction ~ BreakWorldArchitecture.PeekInstruction[
pc: branchNotTakenAddress];
IF instruction #
LOOPHOLE[002800005H]
THEN {
stdout.PutRope["Branch not taken break, but not be .+0x5\n"];
ERROR;
};
intRef^ ← testInt;
break ← TestSetBreakpoint[address: branchNotTakenAddress,
proc: breakProcedureAddress, clientData: LOOPHOLE[intRef]];
ACleanWellLightedPlaceForBreakpoints[];
IF intRef^ = checkInt
THEN {
stdout.PutF["\t\t\tBranch not taken break seems to work\n"];
}
ELSE {
stdout.PutF["\t\t\tBranch not taken break DOES NOT WORK: intRef^ = %g\n",
[integer[intRef^]]];
ERROR;
};
TestClearBreakpoint[break: break];
};
{
callAddress: BreakWorldArchitecture.Address ~
BreakWorldArchitecture.AddressFromDisplacement[
address: breakpointAddress, displacement: 05CH];
instruction: TargetArchitecture.Instruction ~ BreakWorldArchitecture.PeekInstruction[
pc: callAddress];
IF instruction #
LOOPHOLE[040000016H]
THEN {
stdout.PutRope["Call break, but not call .+0x16\n"];
ERROR;
};
intRef^ ← testInt;
break ← TestSetBreakpoint[address: callAddress,
proc: breakProcedureAddress, clientData: LOOPHOLE[intRef]];
ACleanWellLightedPlaceForBreakpoints[];
IF intRef^ = checkInt
THEN {
stdout.PutF["\t\t\tCall break seems to work\n"];
}
ELSE {
stdout.PutF["\t\t\tCall break DOES NOT WORK: intRef^ = %g\n",
[integer[intRef^]]];
ERROR;
};
TestClearBreakpoint[break: break];
};
{
jmplo7Address: BreakWorldArchitecture.Address ~
BreakWorldArchitecture.AddressFromDisplacement[
address: breakpointAddress, displacement: 07CH];
instruction: TargetArchitecture.Instruction ~ BreakWorldArchitecture.PeekInstruction[
pc: jmplo7Address];
IF instruction #
LOOPHOLE[09FC04000H]
THEN {
stdout.PutRope["Jmpl %o7 break, but not jmpl %g1, %o7\n"];
ERROR;
};
intRef^ ← testInt;
break ← TestSetBreakpoint[address: jmplo7Address,
proc: breakProcedureAddress, clientData: LOOPHOLE[intRef]];
ACleanWellLightedPlaceForBreakpoints[];
IF intRef^ = checkInt
THEN {
stdout.PutF["\t\t\tJmpl %%o7 break seems to work\n"];
}
ELSE {
stdout.PutF["\t\t\tJmpl %%o7 break DOES NOT WORK: intRef^ = %g\n",
[integer[intRef^]]];
ERROR;
};
TestClearBreakpoint[break: break];
};
{
jmplg0Address: BreakWorldArchitecture.Address ~
BreakWorldArchitecture.AddressFromDisplacement[
address: breakpointAddress, displacement: 0ACH];
instruction: TargetArchitecture.Instruction ~ BreakWorldArchitecture.PeekInstruction[
pc: jmplg0Address];
IF instruction #
LOOPHOLE[81C7E008H]
THEN {
stdout.PutRope["Jmpl %g0 break, but not jmpl %i7+8, %g0\n"];
ERROR;
};
intRef^ ← testInt;
break ← TestSetBreakpoint[address: jmplg0Address,
proc: breakProcedureAddress, clientData: LOOPHOLE[intRef]];
ACleanWellLightedPlaceForBreakpoints[];
IF intRef^ = checkInt
THEN {
stdout.PutF["\t\t\tJmpl %%g0 break seems to work\n"];
}
ELSE {
stdout.PutF["\t\t\tJmpl %%g0 break DOES NOT WORK: intRef^ = %g\n",
[integer[intRef^]]];
ERROR;
};
TestClearBreakpoint[break: break];
};
{
intRef^ ← testInt;
ACleanWellLightedPlaceForBreakpoints[];
IF intRef^ # testInt
THEN {
stdout.PutF["\t\t\tclearing DOES NOT WORK: intRef^ = %g\n",
[integer[intRef^]]];
ERROR;
}
ELSE {
stdout.PutF["\t\t\tClearing seems to work\n"];
};
};
TimeBreakpoint:
PROCEDURE []
RETURNS [] ~ {
iterations: NAT ~ 1000000;
nullUsec: CARD;
maxiRegsUsec: CARD;
regsUsec: CARD;
miniRegsUsec: CARD;
globalRegsUsec: CARD;
nullRegsUsec: CARD;
normalBreakUsec: CARD;
fastBreakUsec: CARD;
{
nullUsec ← TimeProc[iterations: iterations, proc: TheNullProcedure];
};
{
maxiRegsUsec ← TimeProc[iterations: iterations, proc: MaxiSaveRestoreProcedure];
};
{
regsUsec ← TimeProc[iterations: iterations, proc: SaveRestoreProcedure];
};
{
miniRegsUsec ← TimeProc[iterations: iterations, proc: MiniSaveRestoreProcedure];
};
{
globalRegsUsec ← TimeProc[iterations: iterations, proc: GlobalsSaveRestoreProcedure];
};
{
nullRegsUsec ← TimeProc[iterations: iterations, proc: NoneSaveRestoreProcedure];
};
{
breakWorld: BreakWorldArchitecture.BreakWorld ~
BreakWorldArchitecture.CreateBreakWorld[
name: "SPARC",
peekContents: FakeCirio.PeekContents,
pokeContents: FakeCirio.PokeContents,
getProcAddress: FakeCirio.GetProcAddress,
getProcDataSegment: NIL,
getPatchArea: FakeCirio.GetPatchArea,
monitoredCall: FakeCirio.MonitoredCall,
worldAccessData: NIL];
breakpointAddress: BreakWorldArchitecture.Address ~ FakeCirio.GetProcAddress[
breakWorld: breakWorld, procName: TheNullProcedureName];
breakProcedureAddress: BreakWorldArchitecture.Address ~ FakeCirio.GetProcAddress[
breakWorld: breakWorld, procName: TheNullBreakProcedureName];
break: Breakpoint.Break ← Breakpoint.nullBreak;
break ← Breakpoint.SetBreakpoint[
address: breakpointAddress, clientData: NIL,
breakProc: breakProcedureAddress, breakData: 0];
normalBreakUsec ← TimeProc[iterations: iterations, proc: TheNullProcedure];
Breakpoint.ClearBreakpoint[break: break];
break ← Breakpoint.SetBreakpoint[
address: breakpointAddress, clientData: NIL,
breakProc: breakProcedureAddress, breakData: 0,
damages: SPARCArchitecture.TargetRegisterClassFromSPARCRegisterClass[
SPARCArchitecture.RegisterClass.globalsAndIns]];
fastBreakUsec ← TimeProc[iterations: iterations, proc: TheNullProcedure];
Breakpoint.ClearBreakpoint[break: break];
};
stdout.PutF["%g null calls takes %g usec %g\n",
[integer[iterations]], [cardinal[nullUsec]], [cardinal[nullUsec/iterations]]];
stdout.PutF["%g maxi save/restore registers takes %g usec %g\n",
[integer[iterations]], [cardinal[maxiRegsUsec]], [cardinal[maxiRegsUsec/iterations]]];
stdout.PutF["%g regular save/restore registers takes %g usec %g\n",
[integer[iterations]], [cardinal[regsUsec]], [cardinal[regsUsec/iterations]]];
stdout.PutF["%g mini save/restore registers takes %g usec %g\n",
[integer[iterations]], [cardinal[miniRegsUsec]], [cardinal[miniRegsUsec/iterations]]];
stdout.PutF["%g globals save/restore registers takes %g usec %g\n",
[integer[iterations]], [cardinal[globalRegsUsec]], [cardinal[globalRegsUsec/iterations]]];
stdout.PutF["%g null save/restore registers takes %g usec %g\n",
[integer[iterations]], [cardinal[nullRegsUsec]], [cardinal[nullRegsUsec/iterations]]];
stdout.PutF["%g normal break calls takes %g usec %g\n",
[integer[iterations]], [cardinal[normalBreakUsec]],
[cardinal[normalBreakUsec/iterations]]];
stdout.PutF["%g fast break calls takes %g usec %g\n",
[integer[iterations]], [cardinal[fastBreakUsec]],
[cardinal[fastBreakUsec/iterations]]];
};
TimeProc:
PROCEDURE [iterations:
NAT, proc: Procedure]
RETURNS [
CARD] ~
TRUSTED {
beforeRep: UnixTime.TimeVal;
before: UnixTime.TimeValPtr ~ @beforeRep;
afterRep: UnixTime.TimeVal;
after: UnixTime.TimeValPtr ~ @afterRep;
usec: CARD ← 0;
IF UnixSysCalls.GetTimeOfDay[tp: before, tzp:
NIL] = failure
THEN {
stdout.PutRope["couldn't get before time\n"];
};
THROUGH [1..iterations]
DO {
[] ← proc[];
} ENDLOOP;
IF UnixSysCalls.GetTimeOfDay[tp: after, tzp:
NIL] = failure
THEN {
stdout.PutRope["couldn't get after time\n"];
};
usec ← ((1000000 * after.sec) + after.usec) - ((1000000 * before.sec) + before.usec);
RETURN [usec];
};
SaveRestoreProcedure: Procedure ~
TRUSTED {
SaveArea:
TYPE ~
LONG
POINTER
TO SaveAreaRep ←
NIL;
SaveAreaRep: TYPE ~ PACKED ARRAY [0 .. SPARCBreakpoint.registerSaveArea) OF BYTE;
saveAreaInstance: SaveAreaRep;
saveArea: SaveArea ~ @saveAreaInstance;
Save:
PROCEDURE [saveArea: SaveArea]
RETURNS [] ~
TRUSTED
MACHINE
CODE {
"save←regs"
};
Restore:
PROCEDURE [saveArea: SaveArea]
RETURNS [] ~
TRUSTED
MACHINE
CODE {
"restore←regs"
};
Save[saveArea: saveArea];
Restore[saveArea: saveArea];
RETURN;
};
MiniSaveRestoreProcedure: Procedure ~
TRUSTED {
SaveArea:
TYPE ~
LONG
POINTER
TO SaveAreaRep ←
NIL;
SaveAreaRep: TYPE ~ PACKED ARRAY [0 .. SPARCBreakpoint.registerSaveArea) OF BYTE;
saveAreaInstance: SaveAreaRep;
saveArea: SaveArea ~ @saveAreaInstance;
Save:
PROCEDURE [saveArea: SaveArea]
RETURNS [] ~
TRUSTED
MACHINE
CODE {
"save←regs←mini"
};
Restore:
PROCEDURE [saveArea: SaveArea]
RETURNS [] ~
TRUSTED
MACHINE
CODE {
"restore←regs←mini"
};
Save[saveArea: saveArea];
Restore[saveArea: saveArea];
RETURN;
};
MaxiSaveRestoreProcedure: Procedure ~
TRUSTED {
SaveArea:
TYPE ~
LONG
POINTER
TO SaveAreaRep ←
NIL;
SaveAreaRep: TYPE ~ PACKED ARRAY [0 .. SPARCBreakpoint.registerSaveArea) OF BYTE;
saveAreaInstance: SaveAreaRep;
saveArea: SaveArea ~ @saveAreaInstance;
Save:
PROCEDURE [saveArea: SaveArea]
RETURNS [] ~
TRUSTED
MACHINE
CODE {
"save←regs←maxi"
};
Restore:
PROCEDURE [saveArea: SaveArea]
RETURNS [] ~
TRUSTED
MACHINE
CODE {
"restore←regs←maxi"
};
Save[saveArea: saveArea];
Restore[saveArea: saveArea];
RETURN;
};
GlobalsSaveRestoreProcedure: Procedure ~
TRUSTED {
SaveArea:
TYPE ~
LONG
POINTER
TO SaveAreaRep ←
NIL;
SaveAreaRep: TYPE ~ PACKED ARRAY [0 .. SPARCBreakpoint.registerSaveArea) OF BYTE;
saveAreaInstance: SaveAreaRep;
saveArea: SaveArea ~ @saveAreaInstance;
Save:
PROCEDURE [saveArea: SaveArea]
RETURNS [] ~
TRUSTED
MACHINE
CODE {
"save←regs←globals"
};
Restore:
PROCEDURE [saveArea: SaveArea]
RETURNS [] ~
TRUSTED
MACHINE
CODE {
"restore←regs←globals"
};
Save[saveArea: saveArea];
Restore[saveArea: saveArea];
RETURN;
};
NoneSaveRestoreProcedure: Procedure ~
TRUSTED {
SaveArea:
TYPE ~
LONG
POINTER
TO SaveAreaRep ←
NIL;
SaveAreaRep: TYPE ~ PACKED ARRAY [0 .. SPARCBreakpoint.registerSaveArea) OF BYTE;
saveAreaInstance: SaveAreaRep;
saveArea: SaveArea ~ @saveAreaInstance;
Save:
PROCEDURE [saveArea: SaveArea]
RETURNS [] ~
TRUSTED
MACHINE
CODE {
"save←regs←none"
};
Restore:
PROCEDURE [saveArea: SaveArea]
RETURNS [] ~
TRUSTED
MACHINE
CODE {
"restore←regs←none"
};
Save[saveArea: saveArea];
Restore[saveArea: saveArea];
RETURN;
};
}.