FILE: RandomCodeDragonOpsImpl.mesa
Last Edited by: Sturgis, January 20, 1986 3:40:56 pm PST
McCreight, December 13, 1985 2:22:31 pm PST
DIRECTORY
Basics USING[HighByte, LowByte],
DragOpsCross,
IO USING[card, int, PutF, rope, STREAM],
RandomCodeTypes USING[ArgSeqTypeCheck, GetArgsResultsOfProcedureType, GetLength, GetOrdinaryWordType, GetSeqTypeOfPointerType, GetWordTypeFromOffset, ResultSeqTypeCheck, SeqType, WordStorableAs, WordType],
RandomCodeTypedProgramGraphs USING[BasicNodeTypeCheck, CheckRelativeJump, GetFrameVarType, GetNextFrameVarType, GetNextOfNextStack, GetNextOfStack, GetNextStack, GetStack, GetTopOfNextStack, GetTopOfStack, GetTypeSet, OpDescriptor, OpDescriptorBody, OpKind, OpKindBody, OpTypeClass, PGNode, TooFar, TypeCheckEPNode, TypeCheckRETNode],
RandomCodeDragonOps USING[],
Rope USING[ROPE];
RandomCodeDragonOpsImpl: CEDAR PROGRAM IMPORTS Basics, IO, RandomCodeTypes, RandomCodeTypedProgramGraphs EXPORTS RandomCodeDragonOps =
BEGIN
OPEN RandomCodeTypes, RandomCodeTypedProgramGraphs;
Comment: May 2, 1984 4:45:38 pm PDT: At the moment we have no way of requesting PopWPushW or PopWWPushW, so I have not implemented them (using RR), but when I construct a way to request them, I will generate them. (reduce a dummy node will have to find these as a special case before doing a source or target reduction directly?)
DragonOpTable: ARRAY OpTypeClass OF REF DragonOpTableBody;
DragonOpTableBody: TYPE = RECORD[
SEQUENCE nOps: CARDINAL OF GetOpProc];
GetOpProc: TYPE = PROCEDURE[
class: OpTypeClass,
random: PROCEDURE RETURNS[CARDINAL],
selectLocalIndex: PROCEDURE RETURNS[CARDINAL],
selectRemoteIndex: PROCEDURE RETURNS[CARDINAL],
selectLocalRemoteIndices: PROCEDURE RETURNS[l,r: CARDINAL]]
RETURNS[OpDescriptor];
dragonOpPrelimTable: ARRAY OpTypeClass OF REF DragonOpPrelimTableBody;
DragonOpPrelimTableBody: TYPE = RECORD[
nOps: CARDINAL ← 0,
first: REF PrelimTableEntryBody];
PrelimTableEntryBody: TYPE = RECORD[
getProc: GetOpProc,
next: REF PrelimTableEntryBody];
RefODBOpKindDataBody: TYPE = REF ODBOpKindDataBody;
InitDragonOpTables: PROCEDURE =
BEGIN
FOR class: OpTypeClass IN OpTypeClass DO
dragonOpPrelimTable[class] ← NEW[DragonOpPrelimTableBody];
ENDLOOP;
END;
RegisterDragonOpBuilder: PROCEDURE[
class: OpTypeClass,
getProc: PROCEDURE[
class: OpTypeClass,
random: PROCEDURE RETURNS[CARDINAL],
selectLocalIndex: PROCEDURE RETURNS[CARDINAL],
selectRemoteIndex: PROCEDURE RETURNS[CARDINAL],
selectLocalRemoteIndices: PROCEDURE RETURNS[l,r: CARDINAL]]
RETURNS[OpDescriptor]] =
BEGIN
cell: REF PrelimTableEntryBody ←
NEW[PrelimTableEntryBody ← [getProc, dragonOpPrelimTable[class].first]];
dragonOpPrelimTable[class].nOps ← dragonOpPrelimTable[class].nOps + 1;
dragonOpPrelimTable[class].first ← cell;
END;
CloseDragonOpTables: PROCEDURE =
BEGIN
FOR class: OpTypeClass IN OpTypeClass DO
body: REF DragonOpTableBody ←
NEW[DragonOpTableBody[dragonOpPrelimTable[class].nOps]];
item: REF PrelimTableEntryBody ← dragonOpPrelimTable[class].first;
FOR I: CARDINAL IN [0..body.nOps) DO
body[I] ← item.getProc;
item ← item.next;
ENDLOOP;
DragonOpTable[class] ← body;
ENDLOOP;
END;
GetDragonOp: PUBLIC PROCEDURE[
class: OpTypeClass,
random: PROCEDURE RETURNS[CARDINAL],
selectLocalIndex: PROCEDURE RETURNS[CARDINAL],
selectRemoteIndex: PROCEDURE RETURNS[CARDINAL],
selectLocalRemoteIndices: PROCEDURE RETURNS[l,r: CARDINAL]]
RETURNS[OpDescriptor] =
BEGIN
body: REF DragonOpTableBody ← DragonOpTable[class];
IF body.nOps = 0 THEN RETURN[NIL];
RETURN[body[random[] MOD body.nOps][class, random, selectLocalIndex, selectRemoteIndex, selectLocalRemoteIndices]];
END;
assorted dragon op classes, this concept of class is unrelated to OpTypeClass, but is organized according to the Dragon ops document.
NoteNullOpInstallation: PROCEDURE[OpDescriptor, PGNode] = {NULL};
NullOpInstallationRelease: PROCEDURE[OpDescriptor, PGNode] = {NULL};
NullOpGetDummyOpShape: PROCEDURE[OpDescriptor] RETURNS[nArgs, nResults: CARDINAL] = {ERROR};
NullSetRelativeJump: PROCEDURE[OpDescriptor, INT];
following is tentative
OpName: TYPE = {JEBB, JEBBJ, JNEBB, JNEBBJ, RADD, RAND, RFU, ROR, RRX, RSUB, RUADD, RUSUB, RVADD, RVSUB, RXOR, EP, RET, JB, JDB, SFC, LRI0, LRI1, LRI2, LRI3, LRI4, LRI5, LRI6, LRI7, LRI8, LRI9, LRI10, LRI11, LRI12, LRI13, LRI14, LRI15, SRI0, SRI1, SRI2, SRI3, SRI4, SRI5, SRI6, SRI7, SRI8, SRI9, SRI10, SRI11, SRI12, SRI13, SRI14, SRI15, StopTrap};
RopeFromOpName: PROCEDURE[name: OpName] RETURNS[Rope.ROPE] =
BEGIN
RETURN[SELECT name FROM
JEBB => "JEBB",
JEBBJ => "JEBBJ",
JNEBB => "JNEBB",
JNEBBJ => "JNEBBJ",
RADD => "RADD",
RAND => "RAND",
RFU => "RFU",
ROR => "ROR",
RRX => "RRX",
RSUB => "RSUB",
RUADD => "RUADD",
RUSUB => "RUSUB",
RVADD => "RVADD",
RVSUB => "RVSUB",
RXOR => "RXOR",
EP => "EP",
RET => "RET",
JB => "JB",
JDB => "JDB",
SFC => "SFC",
LRI0 => "LRI0",
LRI1 => "LRI1",
LRI2 => "LRI2",
LRI3 => "LRI3",
LRI4 => "LRI4",
LRI5 => "LRI5",
LRI6 => "LRI6",
LRI7 => "LRI7",
LRI8 => "LRI8",
LRI9 => "LRI9",
LRI10 => "LRI10",
LRI11 => "LRI11",
LRI12 => "LRI12",
LRI13 => "LRI13",
LRI14 => "LRI14",
LRI15 => "LRI15",
SRI0 => "SRI0",
SRI1 => "SRI1",
SRI2 => "SRI2",
SRI3 => "SRI3",
SRI4 => "SRI4",
SRI5 => "SRI5",
SRI6 => "SRI6",
SRI7 => "SRI7",
SRI8 => "SRI8",
SRI9 => "SRI9",
SRI10 => "SRI10",
SRI11 => "SRI11",
SRI12 => "SRI12",
SRI13 => "SRI13",
SRI14 => "SRI14",
SRI15 => "SRI15",
StopTrap => "StopTrap",
ENDCASE => ERROR]
END;
ByteCodeFromOpName: PROCEDURE[name: OpName] RETURNS[[0..255]] =
BEGIN
RETURN[SELECT name FROM
JEBB => DragOpsCross.Inst[dJEBB].ORD,
JEBBJ => DragOpsCross.Inst[dJEBBJ].ORD,
JNEBB => DragOpsCross.Inst[dJNEBB].ORD,
JNEBBJ => DragOpsCross.Inst[dJNEBBJ].ORD,
RADD => DragOpsCross.Inst[dRADD].ORD,
RAND => DragOpsCross.Inst[dRAND].ORD,
RFU => DragOpsCross.Inst[dRFU].ORD,
ROR => DragOpsCross.Inst[dROR].ORD,
RRX => DragOpsCross.Inst[dRRX].ORD,
RSUB => DragOpsCross.Inst[dRSUB].ORD,
RUADD => DragOpsCross.Inst[dRUADD].ORD,
RUSUB => DragOpsCross.Inst[dRUSUB].ORD,
RVADD => DragOpsCross.Inst[dRVADD].ORD,
RVSUB => DragOpsCross.Inst[dRVSUB].ORD,
RXOR => DragOpsCross.Inst[dRXOR].ORD,
EP => DragOpsCross.Inst[dALS].ORD,
RET => DragOpsCross.Inst[dRET].ORD,
JB => DragOpsCross.Inst[dJB].ORD,
JDB => DragOpsCross.Inst[dJDB].ORD,
SFC => DragOpsCross.Inst[dSFC].ORD,
LRI0 => DragOpsCross.Inst[dLRI0].ORD,
LRI1 => DragOpsCross.Inst[dLRI1].ORD,
LRI2 => DragOpsCross.Inst[dLRI2].ORD,
LRI3 => DragOpsCross.Inst[dLRI3].ORD,
LRI4 => DragOpsCross.Inst[dLRI4].ORD,
LRI5 => DragOpsCross.Inst[dLRI5].ORD,
LRI6 => DragOpsCross.Inst[dLRI6].ORD,
LRI7 => DragOpsCross.Inst[dLRI7].ORD,
LRI8 => DragOpsCross.Inst[dLRI8].ORD,
LRI9 => DragOpsCross.Inst[dLRI9].ORD,
LRI10 => DragOpsCross.Inst[dLRI10].ORD,
LRI11 => DragOpsCross.Inst[dLRI11].ORD,
LRI12 => DragOpsCross.Inst[dLRI12].ORD,
LRI13 => DragOpsCross.Inst[dLRI13].ORD,
LRI14 => DragOpsCross.Inst[dLRI14].ORD,
LRI15 => DragOpsCross.Inst[dLRI15].ORD,
SRI0 => DragOpsCross.Inst[dSRI0].ORD,
SRI1 => DragOpsCross.Inst[dSRI1].ORD,
SRI2 => DragOpsCross.Inst[dSRI2].ORD,
SRI3 => DragOpsCross.Inst[dSRI3].ORD,
SRI4 => DragOpsCross.Inst[dSRI4].ORD,
SRI5 => DragOpsCross.Inst[dSRI5].ORD,
SRI6 => DragOpsCross.Inst[dSRI6].ORD,
SRI7 => DragOpsCross.Inst[dSRI7].ORD,
SRI8 => DragOpsCross.Inst[dSRI8].ORD,
SRI9 => DragOpsCross.Inst[dSRI9].ORD,
SRI10 => DragOpsCross.Inst[dSRI10].ORD,
SRI11 => DragOpsCross.Inst[dSRI11].ORD,
SRI12 => DragOpsCross.Inst[dSRI12].ORD,
SRI13 => DragOpsCross.Inst[dSRI13].ORD,
SRI14 => DragOpsCross.Inst[dSRI14].ORD,
SRI15 => DragOpsCross.Inst[dSRI15].ORD,
StopTrap => DragOpsCross.Inst[x377b].ORD,
ENDCASE => ERROR]
END;
RR ops
RROpKind: OpKind ← NEW[OpKindBody ← [
"RROp",
CopyRROp,
NoteNullOpInstallation,
NullOpInstallationRelease,
NullOpGetDummyOpShape,
GetRROpSize,
NullSetRelativeJump,
TypeCheckRROp,
PrintRROpDetails,
GenRROpBytes]];
RROpKindDataBody: TYPE = RECORD[
op: OpName,
purpose: Rope.ROPE,
c,a: [0..15],
aOpt, cOpt, bOpt, aux: BOOLEAN,
b: [0..15]];
RROps: ARRAY [0..11) OF OpName = [RADD, RAND, RFU, ROR, RRX, RSUB, RUADD, RUSUB, RVADD, RVSUB, RXOR];
CopyRROp: PROCEDURE[op: OpDescriptor] RETURNS[OpDescriptor] =
BEGIN
inData: REF RROpKindDataBody ← NARROW[op.data];
outData: REF RROpKindDataBody ← NEW[RROpKindDataBody ← inData^];
RETURN[NEW[OpDescriptorBody ← [RROpKind, outData]]];
END;
GetRROpForPopWW: GetOpProc = 
BEGIN
local: CARDINAL ← selectLocalIndex[];
kind: OpKind ← RROpKind;
data: REF RROpKindDataBody;
r1, r2: CARDINAL;
data ← NEW[RROpKindDataBody ← [
op: RROps[random[] MOD 11],
purpose: "PopWW",
c: 0,
a: 0,
aOpt: TRUE, cOpt: FALSE, bOpt: TRUE, aux: FALSE,
b: 0]];
SELECT r1 ← (random[] MOD 2) FROM
0 => {data.a ← 14; data.b ← 15};
1 => {data.a ← 15; data.b ← 14};
ENDCASE => ERROR;
IF local = LAST[CARDINAL] THEN
SELECT r2 ← (random[] MOD 2) FROM
0 => {data.c ← 12; data.cOpt ← TRUE};
1 => {data.c ← 13; data.cOpt ← TRUE};
ENDCASE => ERROR
ELSE
SELECT r2 ← (random[] MOD 3) FROM
0 => {data.c ← local; data.cOpt ← FALSE};
1 => {data.c ← 12; data.cOpt ← TRUE};
2 => {data.c ← 13; data.cOpt ← TRUE};
ENDCASE => ERROR;
RETURN[NEW[OpDescriptorBody ← [kind, data]]];
END;
GetRROpForPopWWPushW: GetOpProc = 
BEGIN
kind: OpKind ← RROpKind;
data: REF RROpKindDataBody;
r: CARDINAL;
data ← NEW[RROpKindDataBody ← [
op: RROps[random[] MOD 11],
purpose: "PopWWPushW",
c: 0,
a: 0,
aOpt: TRUE, cOpt: TRUE, bOpt: TRUE, aux: FALSE,
b: 0]];
SELECT r ← (random[] MOD 4) FROM
0 => {data.a ← 12; data.b ← 15; data.c ← 12};
1 => {data.a ← 15; data.b ← 12; data.c ← 12};
2 => {data.a ← 13; data.b ← 14; data.c ← 12};
3 => {data.a ← 14; data.b ← 13; data.c ← 12};
ENDCASE => ERROR;
RETURN[NEW[OpDescriptorBody ← [kind, data]]];
END;
GetRROpForPopW: GetOpProc = 
BEGIN
local1: CARDINAL ← selectLocalIndex[];
local2: CARDINAL ← selectLocalIndex[];
kind: OpKind ← RROpKind;
data: REF RROpKindDataBody;
r1, r2: CARDINAL;
data ← NEW[RROpKindDataBody ← [
op: RROps[random[] MOD 11],
purpose: "PopW",
c: 0,
a: 0,
aOpt: FALSE, cOpt: FALSE, bOpt: FALSE, aux: FALSE,
b: 0]];
IF local2 = LAST[CARDINAL] THEN
{data.c ← 12; data.cOpt ← TRUE}
ELSE
SELECT r1 ← (random[] MOD 2) FROM
0 => {data.c ← local2; data.cOpt ← FALSE};
1 => {data.c ← 12; data.cOpt ← TRUE};
ENDCASE => ERROR;
IF local1 = LAST[CARDINAL] THEN
SELECT r2 ← (random[] MOD 2) FROM
0 => {data.aOpt ← TRUE; data.a ← 12; data.bOpt ← TRUE; data.b ← 14};
1 => {data.aOpt ← TRUE; data.a ← 14; data.bOpt ← TRUE; data.b ← 12};
ENDCASE => ERROR
ELSE
SELECT r2 ← (random[] MOD 2) FROM
0 => {data.aOpt ← TRUE; data.a ← 14; data.b ← local1};
1 => {data.bOpt ← TRUE; data.a ← local1; data.b ← 14};
ENDCASE => ERROR;
RETURN[NEW[OpDescriptorBody ← [kind, data]]];
END;
GetRROpForPopWPushW: GetOpProc = 
BEGIN
local: CARDINAL ← selectLocalIndex[];
kind: OpKind ← RROpKind;
data: REF RROpKindDataBody;
r: CARDINAL;
data ← NEW[RROpKindDataBody ← [
op: RROps[random[] MOD 11],
purpose: "PopWPushW",
c: 0,
a: 0,
aOpt: TRUE, cOpt: FALSE, bOpt: TRUE, aux: FALSE,
b: 0]];
IF local = LAST[CARDINAL] THEN
{data.aOpt ← TRUE; data.a ← 12; data.bOpt ← TRUE; data.b ← 12}
ELSE
SELECT r ← (random[] MOD 2) FROM
0 => {data.aOpt ← FALSE; data.a ← local; data.bOpt ← TRUE; data.b ← 12};
1 => {data.aOpt ← TRUE; data.a ← 12; data.bOpt ← FALSE; data.b ← local};
ENDCASE => ERROR;
{data.cOpt ← TRUE; data.c ← 12};
RETURN[NEW[OpDescriptorBody ← [kind, data]]];
END;
GetRROpForPushW: GetOpProc = 
BEGIN
local1: CARDINAL ← selectLocalIndex[];
local2: CARDINAL ← selectLocalIndex[];
kind: OpKind ← RROpKind;
data: REF RROpKindDataBody;
IF local1 = LAST[CARDINAL] OR local2 = LAST[CARDINAL] THEN RETURN[NIL];
data ← NEW[RROpKindDataBody ← [
op: RROps[random[] MOD 11],
purpose: "PushW",
c: 15,
a: local1,
aOpt: FALSE, cOpt: TRUE, bOpt: FALSE, aux: FALSE,
b: local2]];
RETURN[NEW[OpDescriptorBody ← [kind, data]]];
END;
GetRROpForPushT: GetOpProc = 
BEGIN
local: CARDINAL ← selectLocalIndex[];
kind: OpKind ← RROpKind;
r: CARDINAL;
data: REF RROpKindDataBody;
IF local = LAST[CARDINAL] THEN RETURN[NIL];
data ← NEW[RROpKindDataBody ← [
op: SELECT (r ← random[] MOD 2) FROM
0 => RAND,
1 => ROR
ENDCASE => ERROR,
purpose: "PushT",
c: 15,
a: local,
aOpt: FALSE, cOpt: TRUE, bOpt: FALSE, aux: FALSE,
b: local]];
RETURN[NEW[OpDescriptorBody ← [kind, data]]];
END;
GetRROpForPopT: GetOpProc = 
BEGIN
local: CARDINAL ← selectLocalIndex[];
SelectLocal: PROCEDURE RETURNS[CARDINAL] = {RETURN[local]};
op: OpDescriptor;
data: REF RROpKindDataBody;
IF local = LAST[CARDINAL] THEN RETURN[NIL];
op ← GetRROpForStoreLocalT[class, random, SelectLocal, NIL, NIL];
data ← NARROW[op.data];
data.purpose ← "PopT";
RETURN[op];
END;
GetRROpForStoreLocalT: GetOpProc =
BEGIN
local: CARDINAL ← selectLocalIndex[];
kind: OpKind ← RROpKind;
r1, r2: CARDINAL;
data: REF RROpKindDataBody;
IF local = LAST[CARDINAL] THEN ERROR;
data ← NEW[RROpKindDataBody ← [
op: SELECT (r1 ← random[] MOD 2) FROM
0 => RAND,
1 => ROR
ENDCASE => ERROR,
purpose: "StoreLocalT",
c: local,
a: 0,
aOpt: TRUE, cOpt: FALSE, bOpt: TRUE, aux: FALSE,
b: 0]];
SELECT r2 ← (random[] MOD 2) FROM
0 => {data.a ← 14; data.b ← 12};
1 => {data.a ← 12; data.b ← 14};
ENDCASE => ERROR;
RETURN[NEW[OpDescriptorBody ← [kind, data]]];
END;
GetRROpSize: PROCEDURE[op: OpDescriptor] RETURNS[INT] = {RETURN[3]};
this test assumes only ordinary word types in the constant registers.
TypeCheckRROp: PROCEDURE[op: OpDescriptor, node: PGNode] =
BEGIN
opData: REF RROpKindDataBody ← NARROW[op.data];
mdt: CARDINAL ← 0; -- maxDepthTouched
aLocal: BOOLEANNOT opData.aOpt;
bLocal: BOOLEANNOT opData.bOpt;
cLocal: BOOLEANNOT opData.cOpt;
aType, bType, sType: WordType;
SE: INTEGER ← 0; -- initial value
IF opData.aux THEN ERROR; -- above local equations would be wrong
IF aLocal THEN aType ← GetFrameVarType[node, opData.a]
ELSE SELECT opData.a FROM
< 12 => aType ← GetOrdinaryWordType[GetTypeSet[node]];
12 => aType ← GetTopOfStack[node];
13 => aType ← GetNextOfStack[node];
14 => {aType ← GetTopOfStack[node]; SESE - 1};
15 => {aType ← GetNextOfStack[node]; SESE - 1};
ENDCASE => ERROR;
IF bLocal THEN bType ← GetFrameVarType[node, opData.b]
ELSE SELECT opData.b FROM
< 12 => bType ← GetOrdinaryWordType[GetTypeSet[node]];
12 => bType ← GetTopOfStack[node];
13 => bType ← GetNextOfStack[node];
14 => {bType ← GetTopOfStack[node]; SESE - 1};
15 => {bType ← GetNextOfStack[node]; SESE - 1};
ENDCASE => ERROR;
IF aType # bType THEN ERROR;
IF aLocal AND bLocal AND opData.a = opData.b AND (opData.op = RAND OR opData.op = ROR) THEN sType ← aType
ELSE IF NOT aLocal AND NOT bLocal AND (opData.op = RAND OR opData.op = ROR) AND
(opData.a = opData.b OR (opData.a = 12 AND opData.b = 14) OR (opData.a = 14 AND opData.b = 12) OR (opData.a = 13 AND opData.b = 15) OR (opData.a = 15 AND opData.b = 13)) THEN sType ← aType
ELSE sType ← GetOrdinaryWordType[GetTypeSet[node]];
IF NOT cLocal AND opData.c = 15 THEN SESE + 1;
IF SE = +1 THEN
BEGIN
IF cLocal THEN ERROR; -- we had better put something on top
IF opData.c # 14 AND opData.c # 15 THEN ERROR; -- again, nothing was put on top;
BasicNodeTypeCheck[node, 0, 1];
IF NOT WordStorableAs[sType, GetTopOfNextStack[node]] THEN ERROR;
END
ELSE IF cLocal THEN
BEGIN
BasicNodeTypeCheck[node, -SE, 0, opData.c];
IF NOT WordStorableAs[sType, GetNextFrameVarType[node, opData.c]] THEN ERROR;
END
ELSE IF opData.c < 12 THEN
ERROR -- we don't allow storing at constants
ELSE
BEGIN
SELECT opData.c FROM
12 => -- storing at old top of stack
SELECT SE FROM
0 => -- no stack size change
BEGIN
BasicNodeTypeCheck[node, 1, 1];
IF NOT WordStorableAs[sType, GetTopOfNextStack[node]] THEN ERROR;
END;
-1 => -- removing one from top of stack
BasicNodeTypeCheck[node, 1, 0];
-2 => -- removing two from top of stack
BasicNodeTypeCheck[node, 2, 0];
ENDCASE => ERROR;
13 => -- storing one down from old top
SELECT SE FROM
0 => -- no stack size change
BEGIN
BasicNodeTypeCheck[node, 2, 2];
IF NOT WordStorableAs[GetTopOfStack[node], GetTopOfNextStack[node]] THEN ERROR;
IF NOT WordStorableAs[sType, GetNextOfNextStack[node]] THEN ERROR;
END;
-1 => -- removing one from top of stack
BEGIN
BasicNodeTypeCheck[node, 2, 1];
IF NOT WordStorableAs[sType, GetTopOfNextStack[node]] THEN ERROR;
END;
-2 => -- removing two from top of stack
BasicNodeTypeCheck[node, 2, 0];
ENDCASE => ERROR;
ENDCASE => ERROR;
END;
END;
PrintRROpDetails: PROCEDURE[op: OpDescriptor, node: PGNode, on: IO.STREAM, nested: CARDINAL] =
BEGIN
opData: REF RROpKindDataBody ← NARROW[op.data];
FOR I: CARDINAL IN [0..nested) DO on.PutF[" "] ENDLOOP;
on.PutF["op: %g(%g), c: %g, a: %g, aOpt: %g, ",
IO.rope[RopeFromOpName[opData.op]],
IO.rope[opData.purpose],
IO.card[opData.c],
IO.card[opData.a],
IO.rope[IF opData.aOpt THEN "1" ELSE "0"]];
on.PutF["cOpt: %g, bOpt: %g, aux: %g, b: %g]",
IO.rope[IF opData.cOpt THEN "1" ELSE "0"],
IO.rope[IF opData.bOpt THEN "1" ELSE "0"],
IO.rope[IF opData.aux THEN "1" ELSE "0"],
IO.card[opData.b]];
on.PutF["\N"];
END;
GenRROpBytes: PROCEDURE[op: OpDescriptor, oneByte: PROC[[0..255]]] =
BEGIN
opData: REF RROpKindDataBody ← NARROW[op.data];
oneByte[ByteCodeFromOpName[opData.op]];
oneByte[
(IF opData.aOpt THEN 128 ELSE 0) +
(IF opData.cOpt THEN 64 ELSE 0) +
(IF opData.bOpt THEN 32 ELSE 0) +
(IF opData.aux THEN 16 ELSE 0) +
opData.b];
oneByte[opData.c*16+opData.a];
END;
JBB codes
JBBOpKind: OpKind ← NEW[OpKindBody ← [
"JBBOp",
CopyJBBOp,
NoteNullOpInstallation,
NullOpInstallationRelease,
NullOpGetDummyOpShape,
GetJBBOpSize,
SetJBBOpRelativeJump,
TypeCheckJBBOp,
PrintJBBOpDetails,
GenJBBOpBytes]];
JBBOpKindDataBody: TYPE = RECORD[
op: OpName,
purpose: Rope.ROPE,
dist: [-128..127],
lit: [0..255]];
JBBOps: ARRAY[0..4) OF OpName = [JEBB, JEBBJ, JNEBB, JNEBBJ];
CopyJBBOp: PROCEDURE[op: OpDescriptor] RETURNS[OpDescriptor] =
BEGIN
inData: REF JBBOpKindDataBody ← NARROW[op.data];
outData: REF JBBOpKindDataBody ← NEW[JBBOpKindDataBody ← inData^];
RETURN[NEW[OpDescriptorBody ← [JBBOpKind, outData]]];
END;
GetJBOpForTestX: GetOpProc =
BEGIN
kind: OpKind ← JBBOpKind;
r: CARDINAL;
data: REF JBBOpKindDataBody ← NEW[JBBOpKindDataBody ← [
op: SELECT (r ← random[] MOD 4) FROM
0 => JEBB,
1 => JEBBJ,
2 => JNEBB,
3 => JNEBBJ,
ENDCASE => ERROR,
purpose: "TestX",
dist: 0, -- this wil get filled in later, and if the actual jump doesn't fit, then the op will be replaced
lit: 0]]; -- always test for 0
RETURN[NEW[OpDescriptorBody ← [kind, data]]];
END;
GetJBBOpSize: PROCEDURE[op: OpDescriptor] RETURNS[INT] = {RETURN[3]};
SetJBBOpRelativeJump: PROCEDURE[op: OpDescriptor, deltaBytes: INT] =
BEGIN
delta: INT;
opData: REF JBBOpKindDataBody ← NARROW[op.data];
IF deltaBytes < -128 OR deltaBytes > 127 THEN SIGNAL TooFar[];
opData.dist ← deltaBytes;
delta ← 25;
delta ← opData.dist;
IF delta # deltaBytes THEN ERROR;
END;
TypeCheckJBBOp: PROCEDURE[op: OpDescriptor, node: PGNode] =
BEGIN
opData: REF JBBOpKindDataBody ← NARROW[op.data];
BasicNodeTypeCheck[node, 1, 0, LAST[CARDINAL], TRUE];
CheckRelativeJump[node, opData.dist];
note: we will accept any word type argument, and the op code will just look at the bits
END;
PrintJBBOpDetails: PROCEDURE[op: OpDescriptor, node: PGNode, on: IO.STREAM, nested: CARDINAL] =
BEGIN
opData: REF JBBOpKindDataBody ← NARROW[op.data];
FOR I: CARDINAL IN [0..nested) DO on.PutF[" "] ENDLOOP;
on.PutF["op: %g(%g), dist: %g, lit: %g]",
IO.rope[RopeFromOpName[opData.op]],
IO.rope[opData.purpose],
IO.int[opData.dist],
IO.int[opData.lit]];
on.PutF["\N"];
END;
GenJBBOpBytes: PROCEDURE[op: OpDescriptor, oneByte: PROC[[0..255]]] =
BEGIN
opData: REF JBBOpKindDataBody ← NARROW[op.data];
oneByte[ByteCodeFromOpName[opData.op]];
oneByte[(opData.lit + 256) MOD 256];
oneByte[opData.dist];
END;
OB format op codes
EPOpKind: OpKind ← NEW[OpKindBody ← [
"EPOp",
CopyOBOp,
NoteNullOpInstallation,
NullOpInstallationRelease,
NullOpGetDummyOpShape,
GetOBOpSize,
NullSetRelativeJump,
TypeCheckEPOp,
PrintOBOpDetails,
GenOBOpBytes]];
RETOpKind: OpKind ← NEW[OpKindBody ← [
"RETOp",
CopyOBOp,
NoteNullOpInstallation,
NullOpInstallationRelease,
NullOpGetDummyOpShape,
GetOBOpSize,
NullSetRelativeJump,
TypeCheckRETOp,
PrintOBOpDetails,
GenOBOpBytes]];
JBOpKind: OpKind ← NEW[OpKindBody ← [
"JBOp",
CopyOBOp,
NoteNullOpInstallation,
NullOpInstallationRelease,
NullOpGetDummyOpShape,
GetOBOpSize,
SetJBOpRelativeJump,
TypeCheckJBOp,
PrintOBOpDetails,
GenOBOpBytes]];
OBOpKindDataBody: TYPE = RECORD[
op: OpName,
purpose: Rope.ROPE,
lit: [0..255]];
OBOps: ARRAY[0..3) OF OpName = [EP, RET, JB];
CopyOBOp: PROCEDURE[op: OpDescriptor] RETURNS[OpDescriptor] =
BEGIN
inData: REF OBOpKindDataBody ← NARROW[op.data];
outData: REF OBOpKindDataBody ← NEW[OBOpKindDataBody ← inData^];
RETURN[NEW[OpDescriptorBody ← [op.kind, outData]]];
END;
GetEPOpForEntry: PUBLIC PROCEDURE[nArgs: CARDINAL] RETURNS[OpDescriptor] =
BEGIN
kind: OpKind ← EPOpKind;
data: REF OBOpKindDataBody ← NEW[OBOpKindDataBody ← [
op: EP,
purpose: "Entry",
lit: (257-nArgs) MOD 256]];
RETURN[NEW[OpDescriptorBody ← [kind, data]]];
END;
GetRetOpForReturn: PUBLIC PROCEDURE[nRetWords: CARDINAL] RETURNS[OpDescriptor] =
BEGIN
kind: OpKind ← RETOpKind;
data: REF OBOpKindDataBody ← NEW[OBOpKindDataBody ← [
op: EP,
purpose: "Return",
lit: (255 + nRetWords) MOD 256]];
RETURN[NEW[OpDescriptorBody ← [kind, data]]];
END;
GetJBOpForJump: PUBLIC PROCEDURE[deltaBytes: INTEGER] RETURNS[OpDescriptor] =
BEGIN
kind: OpKind ← JBOpKind;
data: REF OBOpKindDataBody ← NEW[OBOpKindDataBody ← [
op: JB,
purpose: "Jump",
lit: deltaBytes]];
RETURN[NEW[OpDescriptorBody ← [kind, data]]];
END;
GetOBOpSize: PROCEDURE[op: OpDescriptor] RETURNS[INT] = {RETURN[2]};
SetJBOpRelativeJump: PROCEDURE[op: OpDescriptor, deltaBytes: INT] =
BEGIN
opData: REF OBOpKindDataBody ← NARROW[op.data];
IF deltaBytes < -128 OR deltaBytes > 127 THEN SIGNAL TooFar[];
opData.lit ← (deltaBytes + 256) MOD 256;
END;
TypeCheckEPOp: PROCEDURE[op: OpDescriptor, node: PGNode] =
BEGIN
opData: REF OBOpKindDataBody ← NARROW[op.data];
TypeCheckEPNode[node, (257-opData.lit) MOD 256]
END;
TypeCheckRETOp: PROCEDURE[op: OpDescriptor, node: PGNode] = 
BEGIN
opData: REF OBOpKindDataBody ← NARROW[op.data];
TypeCheckRETNode[node, (opData.lit+1) MOD 256]
END;
TypeCheckJBOp: PROCEDURE[op: OpDescriptor, node: PGNode] = 
BEGIN
opData: REF OBOpKindDataBody ← NARROW[op.data];
BasicNodeTypeCheck[node, 0, 0, LAST[CARDINAL], FALSE, TRUE];
CheckRelativeJump[node, ((opData.lit+128) MOD 256) - 128];
END;
PrintOBOpDetails: PROCEDURE[op: OpDescriptor, node: PGNode, on: IO.STREAM, nested: CARDINAL] =
BEGIN
opData: REF OBOpKindDataBody ← NARROW[op.data];
FOR I: CARDINAL IN [0..nested) DO on.PutF[" "] ENDLOOP;
on.PutF["op: %g(%g), lit: %g]",
IO.rope[RopeFromOpName[opData.op]],
IO.rope[opData.purpose],
IO.card[opData.lit]];
on.PutF["\N"];
END;
GenOBOpBytes: PROCEDURE[op: OpDescriptor, oneByte: PROC[[0..255]]] =
BEGIN
opData: REF OBOpKindDataBody ← NARROW[op.data];
oneByte[ByteCodeFromOpName[opData.op]];
oneByte[opData.lit];
END;
LRB format op codes
SRInOpKind: OpKind ← NEW[OpKindBody ← [
"SRInOp",
CopyLRBOp,
NoteNullOpInstallation,
NullOpInstallationRelease,
NullOpGetDummyOpShape,
GetLRBOpSize,
NullSetRelativeJump,
TypeCheckSRInOp,
PrintLRBOpDetails,
GenLRBOpBytes]];
LRInOpKind: OpKind ← NEW[OpKindBody ← [
"LRInOp",
CopyLRBOp,
NoteNullOpInstallation,
NullOpInstallationRelease,
NullOpGetDummyOpShape,
GetLRBOpSize,
NullSetRelativeJump,
TypeCheckLRInOp,
PrintLRBOpDetails,
GenLRBOpBytes]];
LRBOpKindDataBody: TYPE = RECORD[
op: OpName,
purpose: Rope.ROPE,
reg: [0..15],
disp: [0..255]];
SRInOps: ARRAY[0..16) OF OpName = [SRI0, SRI1, SRI2, SRI3, SRI4, SRI5, SRI6, SRI7, SRI8, SRI9, SRI10, SRI11, SRI12, SRI13, SRI14, SRI15];
LRInOps: ARRAY[0..16) OF OpName = [LRI0, LRI1, LRI2, LRI3, LRI4, LRI5, LRI6, LRI7, LRI8, LRI9, LRI10, LRI11, LRI12, LRI13, LRI14, LRI15]; 
CopyLRBOp: PROCEDURE[op: OpDescriptor] RETURNS[OpDescriptor] =
BEGIN
inData: REF LRBOpKindDataBody ← NARROW[op.data];
outData: REF LRBOpKindDataBody ← NEW[LRBOpKindDataBody ← inData^];
RETURN[NEW[OpDescriptorBody ← [op.kind, outData]]];
END;
GetLRBOpForPushFIT: GetOpProc = 
BEGIN
local: CARDINAL;
remote: CARDINAL;
data: REF LRBOpKindDataBody;
kind: OpKind ← LRInOpKind;
[local, remote] ← selectLocalRemoteIndices[];
data ← NEW[LRBOpKindDataBody ← [
op: LRInOps[local],
purpose: "PushFIT",
reg: local,
disp: remote]];
RETURN[NEW[OpDescriptorBody ← [kind, data]]];
END;
GetLRBOpSize: PROCEDURE[op: OpDescriptor] RETURNS[INT] = {RETURN[2]};
TypeCheckSRInOp: PROCEDURE[op: OpDescriptor, node: PGNode] = 
BEGIN
opData: REF LRBOpKindDataBody ← NARROW[op.data];
remoteRecordType: SeqType ← GetSeqTypeOfPointerType[GetFrameVarType[node, opData.reg]];
IF SRInOps[opData.reg] # opData.op THEN ERROR;
BasicNodeTypeCheck[node, 1, 0];
IF NOT WordStorableAs[GetTopOfStack[node], GetWordTypeFromOffset[remoteRecordType, opData.disp]] THEN ERROR;
END;
TypeCheckLRInOp: PROCEDURE[op: OpDescriptor, node: PGNode] = 
BEGIN
opData: REF LRBOpKindDataBody ← NARROW[op.data];
remoteRecordType: SeqType ← GetSeqTypeOfPointerType[GetFrameVarType[node, opData.reg]];
IF LRInOps[opData.reg] # opData.op THEN ERROR;
BasicNodeTypeCheck[node, 0, 1];
IF NOT WordStorableAs[GetWordTypeFromOffset[remoteRecordType, opData.disp], GetTopOfNextStack[node]] THEN ERROR;
END;
PrintLRBOpDetails: PROCEDURE[op: OpDescriptor, node: PGNode, on: IO.STREAM, nested: CARDINAL] =
BEGIN
opData: REF LRBOpKindDataBody ← NARROW[op.data];
FOR I: CARDINAL IN [0..nested) DO on.PutF[" "] ENDLOOP;
on.PutF["op: %g(%g), reg: %g, disp: %g]",
IO.rope[RopeFromOpName[opData.op]],
IO.rope[opData.purpose],
IO.card[opData.reg],
IO.card[opData.disp]];
on.PutF["\N"];
END;
GenLRBOpBytes: PROCEDURE[op: OpDescriptor, oneByte: PROC[[0..255]]] =
BEGIN
opData: REF LRBOpKindDataBody ← NARROW[op.data];
oneByte[ByteCodeFromOpName[opData.op]];
oneByte[opData.disp];
END;
ODB format op codes
JDBOpKind: OpKind ← NEW[OpKindBody ← [
"JDBOp",
CopyODBOp,
NoteNullOpInstallation,
NullOpInstallationRelease,
NullOpGetDummyOpShape,
GetODBOpSize,
SetJDBOpRelativeJump,
TypeCheckJDBOp,
PrintODBOpDetails,
GenODBOpBytes]];
ODBOpKindDataBody: TYPE = RECORD[
op: OpName,
purpose: Rope.ROPE,
litt: [0..65535]];
ODBOps: ARRAY[0..1) OF OpName = [JDB];
CopyODBOp: PROCEDURE[op: OpDescriptor] RETURNS[OpDescriptor] =
BEGIN
inData: REF ODBOpKindDataBody ← NARROW[op.data];
outData: REF ODBOpKindDataBody ← NEW[ODBOpKindDataBody ← inData^];
RETURN[NEW[OpDescriptorBody ← [op.kind, outData]]];
END;
GetJDBOpForJump: PUBLIC PROCEDURE[deltaBytes: INTEGER] RETURNS[OpDescriptor] =
BEGIN
kind: OpKind ← JDBOpKind;
data: RefODBOpKindDataBody ← NEW[ODBOpKindDataBody ← [
op: JDB,
purpose: "Jump",
litt: deltaBytes+3267]];
RETURN[NEW[OpDescriptorBody ← [kind, data]]];
END;
GetODBOpSize: PROCEDURE[op: OpDescriptor] RETURNS[INT] = {RETURN[3]};
SetJDBOpRelativeJump: PROCEDURE[op: OpDescriptor, deltaBytes: INT] =
BEGIN
opData: RefODBOpKindDataBody ← NARROW[op.data];
IF deltaBytes < -32767 OR deltaBytes > 32768 THEN SIGNAL TooFar[];
opData.litt ← deltaBytes+3267;
END;
TypeCheckJDBOp: PROCEDURE[op: OpDescriptor, node: PGNode] = 
BEGIN
opData: RefODBOpKindDataBody ← NARROW[op.data];
litt: INT ← opData.litt; -- gets it into right mode
BasicNodeTypeCheck[node, 0, 0, LAST[CARDINAL], FALSE, TRUE];
CheckRelativeJump[node, litt-3267];
END;
PrintODBOpDetails: PROCEDURE[op: OpDescriptor, node: PGNode, on: IO.STREAM, nested: CARDINAL] =
BEGIN
opData: RefODBOpKindDataBody ← NARROW[op.data];
FOR I: CARDINAL IN [0..nested) DO on.PutF[" "] ENDLOOP;
on.PutF["op: %g(%g), lit: %g]",
IO.rope[RopeFromOpName[opData.op]],
IO.rope[opData.purpose],
IO.card[opData.litt]];
on.PutF["\N"];
END; 
GenODBOpBytes: PROCEDURE[op: OpDescriptor, oneByte: PROC[[0..255]]] =
BEGIN
opData: RefODBOpKindDataBody ← NARROW[op.data];
oneByte[ByteCodeFromOpName[opData.op]];
oneByte[Basics.HighByte[opData.litt]];
oneByte[Basics.LowByte[opData.litt]];
END;
OI format op codes
SFCOpKind: OpKind ← NEW[OpKindBody ← [
"SFCOp",
CopyOIOp,
NoteNullOpInstallation,
NullOpInstallationRelease,
NullOpGetDummyOpShape,
GetOIOpSize,
NullSetRelativeJump,
TypeCheckSFCOp,
PrintOIOpDetails,
GenOIOpBytes]];
StopTrapOpKind: OpKind ← NEW[OpKindBody ← [
"StopTrapOp",
CopyOIOp,
NoteNullOpInstallation,
NullOpInstallationRelease,
NullOpGetDummyOpShape,
GetOIOpSize,
NullSetRelativeJump,
TypeCheckStopTrapOp,
PrintOIOpDetails,
GenOIOpBytes]];
OIOpKindDataBody: TYPE = RECORD[
op: OpName,
purpose: Rope.ROPE];
OIOps: ARRAY[0..1) OF OpName = [SFC];
CopyOIOp: PROCEDURE[op: OpDescriptor] RETURNS[OpDescriptor] =
BEGIN
inData: REF OIOpKindDataBody ← NARROW[op.data];
outData: REF OIOpKindDataBody ← NEW[OIOpKindDataBody ← inData^];
RETURN[NEW[OpDescriptorBody ← [op.kind, outData]]];
END;
GetSFCOpForSFCall: PUBLIC PROCEDURE RETURNS[OpDescriptor] =
BEGIN
kind: OpKind ← SFCOpKind;
data: REF OIOpKindDataBody ← NEW[OIOpKindDataBody ← [
op: SFC,
purpose: "SFCall"]];
RETURN[NEW[OpDescriptorBody ← [kind, data]]];
END;
GetStopTrapOpForStop: PUBLIC PROCEDURE RETURNS[OpDescriptor] =
BEGIN
kind: OpKind ← StopTrapOpKind;
data: REF OIOpKindDataBody ← NEW[OIOpKindDataBody ← [
op: StopTrap,
purpose: "Stop"]];
RETURN[NEW[OpDescriptorBody ← [kind, data]]];
END;
GetOIOpSize: PROCEDURE[op: OpDescriptor] RETURNS[INT] = {RETURN[1]};
TypeCheckSFCOp: PROCEDURE[op: OpDescriptor, node: PGNode] = 
BEGIN
opData: REF OIOpKindDataBody ← NARROW[op.data];
proc: WordType ← GetTopOfStack[node];
args, results: SeqType;
IF proc.type # procedure THEN ERROR;
[args, results] ← GetArgsResultsOfProcedureType[proc];
BasicNodeTypeCheck[node, GetLength[args]+1, GetLength[results]];
ArgSeqTypeCheck[GetStack[node], args, TRUE];
ResultSeqTypeCheck[results, GetNextStack[node]]; 
END;
TypeCheckStopTrapOp: PROCEDURE[op: OpDescriptor, node: PGNode] = 
BEGIN
opData: REF OIOpKindDataBody ← NARROW[op.data]; 
END;
PrintOIOpDetails: PROCEDURE[op: OpDescriptor, node: PGNode, on: IO.STREAM, nested: CARDINAL] =
BEGIN
opData: REF OIOpKindDataBody ← NARROW[op.data];
FOR I: CARDINAL IN [0..nested) DO on.PutF[" "] ENDLOOP;
on.PutF["op: %g(%g)]",
IO.rope[RopeFromOpName[opData.op]],
IO.rope[opData.purpose]];
on.PutF["\N"];
END;
GenOIOpBytes: PROCEDURE[op: OpDescriptor, oneByte: PROC[[0..255]]] =
BEGIN
opData: REF OIOpKindDataBody ← NARROW[op.data];
oneByte[ByteCodeFromOpName[opData.op]];
END;
main code
note: need PushFIT and PopSIT, as they are called upon
InitDragonOpTables[];
RegisterDragonOpBuilder[PopWW, GetRROpForPopWW];
RegisterDragonOpBuilder[PopWWPushW, GetRROpForPopWWPushW];
RegisterDragonOpBuilder[PopW, GetRROpForPopW];
RegisterDragonOpBuilder[PopWPushW, GetRROpForPopWPushW];
RegisterDragonOpBuilder[PushW, GetRROpForPushW];
RegisterDragonOpBuilder[PushT, GetRROpForPushT];
RegisterDragonOpBuilder[PopT, GetRROpForPopT];
RegisterDragonOpBuilder[StoreLocalT, GetRROpForStoreLocalT];
RegisterDragonOpBuilder[TestX, GetJBOpForTestX];
RegisterDragonOpBuilder[PushFIT, GetLRBOpForPushFIT];
CloseDragonOpTables[];
END.
MODULE HISTORY
Initial by: Sturgis, May 1, 1984 2:23:24 pm PDT
RTE: May 17, 1984 11:59:49 am PDT: the alpha, beta, etc bytes are defined by DragOps to be from the low order bits to the high orderbits amongst a given number. I incorrectly generated the high order bits first.
RTE: May 17, 1984 4:46:47 pm PDT: GetEPOpForEntry and GetRetOpForReturn had off by one errors. The byte in the instruction had to be one less than the number of arguments (or return words).
RTE: May 17, 1984 5:40:07 pm PDT: JBBOpBytes had an error in the calulation of the displacement byte, I added 128, and should not have.
RTE: May 18, 1984 11:46:11 am PDT: still an addressing problem, this time with JB. Also, noticed that the previously fixed JBBOpBytes will be wrong for negative relative jumps, so fixed it. (May 18, 1984 11:56:35 am PDT) This fix used a lot of conditional range checks, changed to making appropriate use of MODs.
Change: December 16, 1985 2:51:58 pm PST: literal bytes now generated high byte first, rather than low byte first. Caused a change in only GenODBOpBytes.
Change: January 7, 1986 4:30:05 pm PST: Sturgis: changed the order of the two bytes following a JBB op code, as alphaS is now used to define the PC after the jump, rather than betaS.
Change: January 20, 1986 3:37:19 pm PST: Sturgis: changed the order of the two bytes following an RRm op code.