RESIDisp.mesa
Last Edited by: Sweet, March 7, 1985 3:05:08 pm PST
DIRECTORY
CedarMicrocode,
ListerUtils,
OpDebug,
RESInterpreter,
PrincOps;
RESIDisp: CEDAR PROGRAM
IMPORTS CedarMicrocode, OpDebug, RI: RESInterpreter
EXPORTS RESInterpreter = {
OPEN PrincOps;
Types and Global Data
Value: TYPE = RI.Value;
DValue: TYPE = RI.DValue;
Ptr1: TYPE = RI.Ptr1;
Ptr2: TYPE = RI.Ptr2;
LPtr1: TYPE = RI.LPtr1;
LPtr2: TYPE = RI.LPtr2;
LCB: TYPE = RI.LCB;
Machine: TYPE = RI.Machine;
Byte: TYPE = RI.Byte;
Bytes: TYPE = RI.Bytes;
Pair: TYPE = RI.Pair;
FieldDescriptor: TYPE = PrincOps.FieldDescriptor;
StrangeCode: PUBLIC SIGNAL = CODE;
Instruction execution
Execute: PUBLIC PROC [m: Machine] = TRUSTED {
hist: RI.OpHistory;
opData: ListerUtils.OpCodeArray;
IF m.traceOps THEN {
hist ← m.history;
opData ← OpDebug.OpData[]};
DO
savedPc: CARDINAL = m.pc;
savedSP: CARDINAL = m.sd;
op: Byte;
op ← RI.NextOpByte[m, TRUE];
IF m.countOps THEN m.opCount[op] ← m.opCount[op] + 1;
m.iCount ← m.iCount + 1;
IF m.traceOps THEN {
cb: LONG POINTER TO PACKED ARRAY [0..0) OF Byte = m.cb;
hi: RI.OpHistoryItem;
hi ← [pc: savedPc, gf: m.g, stkDepth: m.sd, stk: NULL, op: [op,0,0]];
FOR j: CARDINAL IN [0..m.sd) DO
hi.stk[j] ← m.stack[j];
ENDLOOP;
IF opData # NIL THEN SELECT opData[op].length FROM
2 => hi.op[1] ← cb[savedPc+1];
3 => {hi.op[2] ← cb[savedPc+2]; hi.op[1] ← cb[savedPc+1]};
ENDCASE;
hist.data[hist.tail] ← hi;
hist.tail ← (hist.tail+1) MOD RI.OpHistorySize;
IF hist.tail = hist.head THEN hist.head ← (hist.head+1) MOD RI.OpHistorySize};
SELECT op FROM
Most popular operations, avoiding an extra procedure call
zLI0, zLI1, zLI2, zLI3, zLI4, zLI5, zLI6 => {RI.Push[m, RI.VCard[op - zLI0]]};
zLIB => {RI.Push[m, RI.VCard[RI.NextOpByte[m]]]};
zLGDB => {
n: CARDINALRI.NextOpByte[m];
RI.Push2[m, RI.ReadDouble[m, LOOPHOLE[LONG[m.g+n]]]]};
zRFL => {
p: LPtr1 ← RI.LPtr1V[RI.Pop2[m]];
n: CARDINAL = RI.NextOpByte[m];
fd: FieldDescriptor ← LOOPHOLE[RI.NextOpByte[m]];
RI.Push[m, RI.ReadField[m, p+n, fd]]};
zRILPL => {
pr: Pair ← LOOPHOLE[RI.NextOpByte[m]];
p: LPtr1;
RI.DoubleReadLocal[m, PrincOps.localbase+pr.p1];
p ← RI.LPtr1V[LOOPHOLE[(m.l+PrincOps.localbase+pr.p1), Ptr2]^];
RI.Push[m, RI.Read[m, p+pr.p2]]};
Monitor stuff
zNOOP, zME, zMRE, zMXW, zMXD, zNOTIFY, zBCAST, zREQUEUE =>
RI.DoMonitorOps[m, op];
Loads & Stores of Locals
zLL0, zLL1, zLL2, zLL3, zLL4, zLL5, zLL6, zLL7 => {
n: CARDINAL ← op - zLL0;
p: POINTER TO Value = m.l+PrincOps.localbase+n;
RI.ReadLocal[m, n];
RI.Push[m, p^]};
zLLB => {
n: CARDINALRI.NextOpByte[m];
p: POINTER TO Value = m.l+n;
RI.ReadLocal[m, n];
RI.Push[m, p^]};
zLLDB => {
n: CARDINALRI.NextOpByte[m];
p: POINTER TO DValue = LOOPHOLE[m.l+n];
RI.DoubleReadLocal[m, n];
RI.Push2[m, p^]};
zSL0, zSL1, zSL2, zSL3, zSL4, zSL5, zSL6, zSL7 => {
n: CARDINAL ← op - zSL0;
p: POINTER TO Value = m.l+PrincOps.localbase+n;
RI.StoreLocal[m, n];
p^ ← RI.Pop[m]};
zSLB => {
n: CARDINALRI.NextOpByte[m];
p: POINTER TO Value = m.l+n;
RI.StoreLocal[m, n];
p^ ← RI.Pop[m]};
zSLDB => {
n: CARDINALRI.NextOpByte[m];
p: POINTER TO DValue = LOOPHOLE[m.l+n];
RI.DoubleStoreLocal[m, n];
p^ ← RI.Pop2[m]};
zPL0, zPL1, zPL2, zPL3 => {
n: CARDINAL ← op - zPL0;
p: POINTER TO Value = m.l+PrincOps.localbase+n;
RI.StoreLocal[m, n];
p^ ← RI.Top[m]};
Loads & Stores of Globals
zLG0, zLG1, zLG2, zLG3, zLG4, zLG5, zLG6, zLG7, zLGB, zLGDB, zSG0, zSG1, zSG2, zSG3, zSGB, zSGDB =>
RI.DoGlobalOps[m, op];
Loads of Constants
zLI0, zLI1, zLI2, zLI3, zLI4, zLI5, zLI6, zLIN1, zLINI, zLIB, zLIW, zLCO, zLINB, zLADRB, zGADRB =>
RI.DoLiteralOps[m, op];
Reads from pointer on stack
zR0, zR1, zR2, zR3, zR4, zRB, zRBL, zRD0, zRDB, zRDBL, zRF, zRFL =>
RI.DoReadOps[m, op];
Writes from pointer on stack
zWCDBL, zICDBL, zW0, zW1, zW2, zWB, zWBL, zWD0, zWDB, zWDBL, zWF, zWFL =>
RI.DoWriteOps[m, op];
Read and write string
zRSTR => {
n: CARDINALRI.NextOpByte[m];
i: CARDINALRI.CardV[RI.Pop[m]];
p: Ptr1 ← RI.Ptr1V[RI.Pop[m]];
fd: FieldDescriptor ←
IF (n+i) MOD 2 = 0 THEN [offset: 0, posn: 0, size: 8]
ELSE [offset: 0, posn: 8, size: 8];
RI.Push[m, RI.ReadField[m, LONG[p+(n+i)/2], fd]]};
zWSTR => {
n: CARDINALRI.NextOpByte[m];
i: CARDINALRI.CardV[RI.Pop[m]];
p: Ptr1 ← RI.Ptr1V[RI.Pop[m]];
v: Value ← RI.Pop[m];
fd: FieldDescriptor ←
IF (n+i) MOD 2 = 0 THEN [offset: 0, posn: 0, size: 8]
ELSE [offset: 0, posn: 8, size: 8];
RI.WriteField[m, LONG[p+(n+i)/2], fd, v]};
zRSTRL => {
n: CARDINALRI.NextOpByte[m];
i: CARDINALRI.CardV[RI.Pop[m]];
p: LPtr1 ← RI.LPtr1V[RI.Pop2[m]];
fd: FieldDescriptor ←
IF (n+i) MOD 2 = 0 THEN [offset: 0, posn: 0, size: 8]
ELSE [offset: 0, posn: 8, size: 8];
RI.Push[m, RI.ReadField[m, p+(n+i)/2, fd]]};
zWSTRL => {
n: CARDINALRI.NextOpByte[m];
i: CARDINALRI.CardV[RI.Pop[m]];
p: LPtr1 ← RI.LPtr1V[RI.Pop2[m]];
v: Value ← RI.Pop[m];
fd: FieldDescriptor ←
IF (n+i) MOD 2 = 0 THEN [offset: 0, posn: 0, size: 8]
ELSE [offset: 0, posn: 8, size: 8];
RI.WriteField[m, p+(n+i)/2, fd, v]};
Read indirect through locals
zRXLP, zRXLPL, zRXGPL, zRILP, zRILPL, zRIGP, zRIGPL, zRIL0 => RI.DoReadIndirectOps[m, op];
Write indirect through locals
zWXLP, zWXLPL, zWXGPL, zWILP, zWILPL, zWIGPL => RI.DoWriteIndirectOps[m, op];
Write Swapped
zWS0, zWSB, zWSDB, zWSF => RI.DoWriteSwappedOps[m, op];
zRFC => { -- read from code segment
n: CARDINALRI.NextOpByte[m];
fd: FieldDescriptor ← LOOPHOLE[RI.NextOpByte[m]];
p: LONG POINTER ← m.cb + n + RI.CardV[RI.Pop[m]];
RI.Push[m, RI.ReadField[m, p, fd]]};
Field descriptor on stack
zRFS => {
fd: FieldDescriptor ← LOOPHOLE[RI.Pop[m]];
p: Ptr1 ← RI.Ptr1V[RI.Pop[m]];
p ← p + fd.offset; fd.offset ← 0;
RI.Push[m, RI.ReadField[m, LONG[p], fd]]};
zRFSL => {
fd: FieldDescriptor ← LOOPHOLE[RI.Pop[m]];
p: LPtr1 ← RI.LPtr1V[RI.Pop2[m]];
p ← p + fd.offset; fd.offset ← 0;
RI.Push[m, RI.ReadField[m, p, fd]]};
zWFS => {
fd: FieldDescriptor ← LOOPHOLE[RI.Pop[m]];
p: Ptr1 ← RI.Ptr1V[RI.Pop[m]];
p ← p + fd.offset; fd.offset ← 0;
RI.WriteField[m, LONG[p], fd, RI.Pop[m]]};
zWFSL => {
fd: FieldDescriptor ← LOOPHOLE[RI.Pop[m]];
p: LPtr1 ← RI.LPtr1V[RI.Pop2[m]];
p ← p + fd.offset; fd.offset ← 0;
RI.WriteField[m, p, fd, RI.Pop[m]]};
Random stack operations
zLP => {
RI.Push2[m, RI.VLPtr1[LONG[RI.Ptr1V[RI.Pop[m]]]]]};
zPUSH => {
m.sd ← m.sd + 1};
zPOP => {
m.sd ← m.sd - 1};
zEXCH => {
t: Value ← m.stack[m.sd-1];
m.stack[m.sd-1] ← m.stack[m.sd-2];
m.stack[m.sd-2] ← t};
zDUP => {
m.stack[m.sd] ← m.stack[m.sd-1];
m.sd ← m.sd + 1};
zNILCK => {
IF RI.Ptr1V[m.stack[m.sd-1]] = NIL THEN RI.NilFault[m]};
zNILCKL => {
IF RI.Ptr1V[m.stack[m.sd-1]] = NIL AND RI.Ptr1V[m.stack[m.sd-2]] = NIL THEN RI.NilFault[m]};
zBNDCK => {
bound: CARDINALRI.CardV[RI.Pop[m]];
IF RI.CardV[m.stack[m.sd-1]] >= bound THEN RI.BoundsFault[m]};
zLINKB => {
delta: CARDINALRI.NextOpByte[m];
indirectLoc: CARDINALRI.CardV[m.stack[m.sd]];
StoreLocal[localbase];
(m.l + localbase)^ ← RI.VCard[indirectLoc - delta]};
Jumps
zJ2, zJ3, zJ4, zJ5, zJ6, zJ7, zJ8, zJ9 => {
alpha: INTEGER = op - zJ2 + 2;
RI.SetPc[m, savedPc + alpha]};
zJB => {
alpha: INTEGER = RI.SignedOpByte[m];
RI.SetPc[m, savedPc + alpha]};
zJW => {
alpha: RECORD [SELECT OVERLAID * FROM
int => [i: INTEGER],
pair => [bp: RI.Bytes],
ENDCASE];
alpha.bp.b1 ← RI.NextOpByte[m];
alpha.bp.b2 ← RI.NextOpByte[m];
RI.SetPc[m, savedPc + alpha.i]};
zJEQ2, zJEQ3, zJEQ4, zJEQ5, zJEQ6, zJEQ7, zJEQ8, zJEQ9 => {
alpha: INTEGER = op - zJEQ2 + 2;
op2: CARDINAL = RI.CardV[RI.Pop[m]];
op1: CARDINAL = RI.CardV[RI.Pop[m]];
IF op1 = op2 THEN RI.SetPc[m, savedPc + alpha]};
zJNE2, zJNE3, zJNE4, zJNE5, zJNE6, zJNE7, zJNE8, zJNE9 => {
alpha: INTEGER = op - zJNE2 + 2;
op2: CARDINAL = RI.CardV[RI.Pop[m]];
op1: CARDINAL = RI.CardV[RI.Pop[m]];
IF op1 # op2 THEN RI.SetPc[m, savedPc + alpha]};
zJLB, zJGEB, zJGB, zJLEB => RI.DoSignedJump[m, savedPc, op];
zJEQB, zJNEB, zJULB, zJUGEB, zJUGB, zJULEB => RI.DoUnsignedJump[m, savedPc, op];
zJZEQB => {
alpha: INTEGER = RI.SignedOpByte[m];
op1: CARDINAL = RI.CardV[RI.Pop[m]];
IF op1 = 0 THEN RI.SetPc[m, savedPc + alpha]};
zJZNEB => {
alpha: INTEGER = RI.SignedOpByte[m];
op1: CARDINAL = RI.CardV[RI.Pop[m]];
IF op1 # 0 THEN RI.SetPc[m, savedPc + alpha]};
zJIB => {
tab: RECORD [SELECT OVERLAID * FROM
bytes => [bp: Bytes],
ptr => [p: RI.LCB RELATIVE POINTER TO PACKED ARRAY [0..0) OF Byte],
ENDCASE];
delta: LONG POINTER TO PACKED ARRAY [0..0) OF Byte;
index, bound: CARDINAL;
tab.bp.b1 ← RI.NextOpByte[m];
tab.bp.b2 ← RI.NextOpByte[m];
delta ← @LOOPHOLE[m.cb, RI.LCB][tab.p];
bound ← RI.CardV[RI.Pop[m]];
index ← RI.CardV[RI.Pop[m]];
IF index < bound THEN {
alpha: Byte;
RI.ReadAtAddress[m, delta + index/2];
alpha ← delta[index];
RI.SetPc[m, savedPc + alpha]};
};
zJIW => {
tab: RECORD [SELECT OVERLAID * FROM
bytes => [bp: Bytes],
ptr => [p: RI.LCB RELATIVE POINTER TO ARRAY [0..0) OF INTEGER],
ENDCASE];
delta: LONG POINTER TO ARRAY [0..0) OF INTEGER;
index, bound: CARDINAL;
tab.bp.b1 ← RI.NextOpByte[m];
tab.bp.b2 ← RI.NextOpByte[m];
delta ← @LOOPHOLE[m.cb, RI.LCB][tab.p];
bound ← RI.CardV[RI.Pop[m]];
index ← RI.CardV[RI.Pop[m]];
IF index < bound THEN {
alpha: INTEGER;
RI.ReadAtAddress[m, delta + index];
alpha ← delta[index];
RI.SetPc[m, savedPc + alpha]};
};
Short arithmetic
zADD, zADD01, zSUB, zMUL, zDBL, zDIV, zLDIV, zNEG, zINC, zAND, zOR, zXOR, zSHIFT => RI.DoShortArithmetic[m, op];
Long arithmetic
zDADD => {
c2: LONG CARDINAL = RI.LCardV[RI.Pop2[m]];
c1: LONG CARDINAL = RI.LCardV[RI.Pop2[m]];
RI.Push2[m, RI.VLCard[c1+c2]]};
zDSUB => {
c2: LONG CARDINAL = RI.LCardV[RI.Pop2[m]];
c1: LONG CARDINAL = RI.LCardV[RI.Pop2[m]];
RI.Push2[m, RI.VLCard[c1-c2]]};
zDCOMP => {
c2: LONG INTEGER = RI.LIntV[RI.Pop2[m]];
c1: LONG INTEGER = RI.LIntV[RI.Pop2[m]];
Compare: PROC [x, y: LONG INTEGER] RETURNS [Value] = TRUSTED MACHINE CODE {
PrincOps.zDCOMP};
RI.Push[m, Compare[c1,c2]]};
zDUCOMP => {
c2: LONG CARDINAL = RI.LCardV[RI.Pop2[m]];
c1: LONG CARDINAL = RI.LCardV[RI.Pop2[m]];
UnsignedCompare: PROC [x, y: LONG CARDINAL] RETURNS [Value] = TRUSTED MACHINE CODE {
PrincOps.zDUCOMP};
RI.Push[m, UnsignedCompare[c1,c2]]};
Function call
zEFC0, zEFC1, zEFC2, zEFC3, zEFC4, zEFC5, zEFC6, zEFC7, zEFC8, zEFC9, zEFC10, zEFC11, zEFC12, zEFC13, zEFC14, zEFC15, zEFCB => {
lk: Byte = IF op = zEFCB THEN RI.NextOpByte[m] ELSE op-zEFC0;
RI.WriteAtAddress[m, LONG[@LOOPHOLE[m.l, FrameHandle].pc]];
LOOPHOLE[m.l, FrameHandle].pc ← [m.pc];
RI.Xfer[m: m, dst: RI.FetchLink[m, lk], src: [frame[RI.FH[m.l]]]]};
zLFC1, zLFC2, zLFC3, zLFC4, zLFC5, zLFC6, zLFC7, zLFC8, zLFC9, zLFC10, zLFC11, zLFC12, zLFC13, zLFC14, zLFC15, zLFC16, zLFCB => {
evi: CARDINAL = IF op = zLFCB THEN RI.NextOpByte[m] ELSE op-zLFC1+1;
ev: EntryVectorItem;
nlf: FrameHandle;
nPc: CARDINAL;
RI.WriteAtAddress[m, LONG[@LOOPHOLE[m.l, FrameHandle].pc]];
LOOPHOLE[m.l, FrameHandle].pc ← [m.pc];
RI.DoubleReadAtAddress[m, @LOOPHOLE[m.cb, LCB].entry[evi]];
ev ← LOOPHOLE[m.cb, LCB].entry[evi];
nPc ← ev.initialpc * 2;
IF nPc = 0 THEN RI.UnboundProcTrap[m, RI.MakeProcDesc[m, LOOPHOLE[m.g], evi]];
nlf ← RI.AllocFrame[ev.info.framesize];
RI.WriteAtAddress[m, LONG[@nlf.accesslink]];
nlf.accesslink ← LOOPHOLE[m.g];
RI.WriteAtAddress[m, LONG[@nlf.returnlink]];
nlf.returnlink ← [frame[RI.FH[m.l]]];
nlf.pc ← [nPc+1]; -- for interpreter display of lf
m.l ← LOOPHOLE[nlf]; RI.SetPc[m, nPc]};
zSFC => {
RI.WriteAtAddress[m, LONG[@LOOPHOLE[m.l, FrameHandle].pc]];
LOOPHOLE[m.l, FrameHandle].pc ← [m.pc];
RI.Xfer[m: m, dst: LOOPHOLE[RI.Pop[m]], src: [frame[RI.FH[m.l]]]]};
zRET => {
link: PrincOps.ControlLink = LOOPHOLE[m.l, FrameHandle].returnlink;
RI.ReadAtAddress[m, LONG[@LOOPHOLE[m.l, FrameHandle].returnlink]];
IF link = RI.MagicReturn THEN SIGNAL RI.FinishedExecution;
RI.Xfer[m: m, dst: link, src: NullLink, free: TRUE]};
zPORTO => {
port: PortHandle ← LOOPHOLE[RI.Pop[m]];
RI.WriteAtAddress[m, LONG[@LOOPHOLE[m.l, FrameHandle].pc]];
LOOPHOLE[m.l, FrameHandle].pc ← [m.pc];
RI.WriteAtAddress[m, LONG[@port.frame]];
port.frame ← RI.FH[m.l];
RI.Xfer[m: m, dst: port.dest, src: LOOPHOLE[port]]};
zPORTI => {
port: PortHandle ← LOOPHOLE[m.stack[m.sd+1]];
src: ControlLink ← LOOPHOLE[m.stack[m.sd]];
RI.WriteAtAddress[m, LONG[@port.frame]];
port.frame ← NIL;
IF src # NullLink THEN {
RI.WriteAtAddress[m, LONG[@port.dest]];
port.dest ← src};
};
zKFCB => {
alpha: CARDINALRI.NextOpByte[m];
link: ControlLink;
SELECT alpha FROM
sBLTEC, sBLTECL => { -- can't let these through as cb reg points to us
data, const: LPtr1;
equal: Value ← [1];
count: CARDINAL;
const ← m.cb + RI.CardV[RI.Pop[m]];
count ← RI.CardV[RI.Pop[m]];
IF alpha = sBLTEC THEN {
sp: Ptr1 ← RI.Ptr1V[RI.Pop[m]];
data ← sp}
ELSE data ← RI.LPtr1V[RI.Pop2[m]];
THROUGH [0..count) DO
IF RI.Read[m, data] # RI.Read[m, const] THEN GO TO false;
data ← data + SIZE[Value]; const ← const + SIZE[Value];
REPEAT
false => equal ← [0];
ENDLOOP;
RI.Push[m, equal]};
compiler doesn't generate the next two.
sBYTBLTEC, sBYTBLTECL => SIGNAL StrangeCode;
ENDCASE => {
RI.ReadAtAddress[m, LONG[@SD[alpha]]];
link ← SD[alpha];
RI.WriteAtAddress[m, LONG[@LOOPHOLE[m.l, FrameHandle].pc]];
LOOPHOLE[m.l, FrameHandle].pc ← [m.pc];
RI.Xfer[m: m, dst: link, src: [frame[RI.FH[m.l]]]]};
};
zDESCB => {
alpha: CARDINALRI.NextOpByte[m]/2; -- Alto compatibility, I believe
RI.Push[m, LOOPHOLE[RI.MakeProcDesc[m: m, gf: LOOPHOLE[m.g], entry: alpha]]]};
zDESCBS => {
alpha: CARDINALRI.NextOpByte[m]/2; -- Alto compatibility, I believe
gf: GlobalFrameHandle ← LOOPHOLE[RI.Pop[m]];
RI.Push[m, LOOPHOLE[RI.MakeProcDesc[m: m, gf: gf, entry: alpha]]]};
zDST => {
alpha: CARDINALRI.NextOpByte[m];
st: POINTER TO StateVector = LOOPHOLE[m.l + alpha];
FOR i: CARDINAL IN [0..MIN[m.sd+2, PrincOps.stackDepth]) DO
RI.StoreLocal[m, alpha +i];
st.stk[i] ← m.stack[i];
ENDLOOP;
RI.StoreLocal[m, alpha + PrincOps.stackDepth];
st.stkptr ← m.sd;
};
zLST => {
RI.LoadState[m, FALSE]};
zLSTF => {
RI.LoadState[m, TRUE]};
zALLOC => {RI.Push[m, LOOPHOLE[RI.AllocFrame[RI.CardV[RI.Pop[m]]]]]};
zFREE => {RI.FreeFrame[LOOPHOLE[RI.Pop[m]]]};
zLLKB => {
alpha: CARDINALRI.NextOpByte[m];
RI.Push[m, LOOPHOLE[RI.FetchLink[m, alpha]]]};
Block Transfer
zBLT => {
to: Ptr1 ← RI.Ptr1V[RI.Pop[m]];
nwords: CARDINALRI.CardV[RI.Pop[m]];
from: Ptr1 ← RI.Ptr1V[RI.Pop[m]];
THROUGH [0..nwords) DO
RI.Write[m, to, RI.Read[m, from]];
to ← to + SIZE[Value];
from ← from + SIZE[Value];
ENDLOOP;
};
zBLTL => {
to: LPtr1 ← RI.LPtr1V[RI.Pop2[m]];
nwords: CARDINALRI.CardV[RI.Pop[m]];
from: LPtr1 ← RI.LPtr1V[RI.Pop2[m]];
THROUGH [0..nwords) DO
RI.Write[m, to, RI.Read[m, from]];
to ← to + SIZE[Value];
from ← from + SIZE[Value];
ENDLOOP;
};
zBLTC => {
to: Ptr1 ← RI.Ptr1V[RI.Pop[m]];
nwords: CARDINALRI.CardV[RI.Pop[m]];
delta: CARDINALRI.CardV[RI.Pop[m]];
from: LPtr1 ← m.cb + delta;
THROUGH [0..nwords) DO
RI.Write[m, to, RI.Read[m, from]];
to ← to + SIZE[Value];
from ← from + SIZE[Value];
ENDLOOP;
};
zBLTCL => {
to: LPtr1 ← RI.LPtr1V[RI.Pop2[m]];
nwords: CARDINALRI.CardV[RI.Pop[m]];
delta: CARDINALRI.CardV[RI.Pop[m]];
from: LPtr1 ← m.cb + delta;
THROUGH [0..nwords) DO
RI.Write[m, to, RI.Read[m, from]];
to^ ← from^;
to ← to + SIZE[Value];
from ← from + SIZE[Value];
ENDLOOP;
};
zBITBLT => {
Punt memory reference statistics
DoBitBlt: PROC [Value] = TRUSTED MACHINE CODE {zBITBLT};
DoBitBlt[RI.Pop[m]]};
Random others
zIWDC => {
Why are we disabling interrupts
NULL}; --SIGNAL StrangeCode
zDWDC => {
Enabling interrupts is a little more socially acceptable
NULL}; --SIGNAL StrangeCode
zSTOP => {
I think this is ALTO only
SIGNAL StrangeCode};
zCATCH => {
Treat as a two byte NOOP
[] ← RI.NextOpByte[m]};
zMISC => DoMiscOp[m];
zSTARTIO => {
I think this is ALTO only
SIGNAL StrangeCode};
zJRAM => {
I think this is ALTO only
SIGNAL StrangeCode};
zWR => {
I think this is ALTO only
SIGNAL StrangeCode};
zRR => { -- legal values are 0-8, each returns an UNSPECIFIED
regVal: Value;
alpha: Byte = RI.NextOpByte[m];
SELECT alpha FROM -- ugly, but since alpha is in the instruction stream ...
0 => regVal ← RR0[];
1 => regVal ← RR1[];
2 => regVal ← RR2[];
3 => regVal ← RR3[];
4 => regVal ← RR4[];
5 => regVal ← RR5[];
6 => regVal ← RR6[];
7 => regVal ← RR7[];
8 => regVal ← RR8[];
ENDCASE => SIGNAL StrangeCode;
RI.Push[m, regVal]};
zBRK => {SIGNAL StrangeCode};
ENDCASE;
IF m.singleStep OR (LOOPHOLE[m.g, CARDINAL] = LOOPHOLE[m.breakGF, CARDINAL] AND m.pc = m.breakPC) THEN EXIT;
ENDLOOP;
};
Machine codes for read register
RR0: PROC RETURNS [Value] = TRUSTED MACHINE CODE {zRR, 0};
RR1: PROC RETURNS [Value] = TRUSTED MACHINE CODE {zRR, 1};
RR2: PROC RETURNS [Value] = TRUSTED MACHINE CODE {zRR, 2};
RR3: PROC RETURNS [Value] = TRUSTED MACHINE CODE {zRR, 3};
RR4: PROC RETURNS [Value] = TRUSTED MACHINE CODE {zRR, 4};
RR5: PROC RETURNS [Value] = TRUSTED MACHINE CODE {zRR, 5};
RR6: PROC RETURNS [Value] = TRUSTED MACHINE CODE {zRR, 6};
RR7: PROC RETURNS [Value] = TRUSTED MACHINE CODE {zRR, 7};
RR8: PROC RETURNS [Value] = TRUSTED MACHINE CODE {zRR, 8};
Machine codes for misc operations
aLocalZERO: CARDINAL = 103B; --?
DoASSOC: PROC [vp: CARDINAL, m: MapFlags] = TRUSTED MACHINE CODE {zMISC, aASSOC};
DoSETF: PROC [vp: CARDINAL, new: MapFlags] RETURNS [old: UNSPECIFIED] = TRUSTED MACHINE CODE {zMISC, aSETF};
DoLOADRAMJ: PROC [item: LONG POINTER, flag: BOOL] = TRUSTED MACHINE CODE {zMISC, aLOADRAMJ};
DoINPUT: PROC [device: CARDINAL] RETURNS [CARDINAL] = TRUSTED MACHINE CODE {zMISC, aINPUT};
DoOUTPUT: PROC [data, device: CARDINAL] = TRUSTED MACHINE CODE {zMISC, aOUTPUT};
DoCHKSUM: PROC [s: CARDINAL, count: CARDINAL, p: LONG POINTER] RETURNS [CARDINAL] = TRUSTED MACHINE CODE {zMISC, aCHKSUM};
DoSETMP: PROC [CARDINAL] = TRUSTED MACHINE CODE {zMISC, aSETMP};
DoRCLK: PROC RETURNS [LONG CARDINAL] = TRUSTED MACHINE CODE {zMISC, aRCLK};
DoRPRINTER: PROC RETURNS [CARDINAL] = TRUSTED MACHINE CODE {zMISC, aRPRINTER};
DoWPRINTER: PROC [CARDINAL] = TRUSTED MACHINE CODE {zMISC, aWPRINTER};
DoGETF: PROC [vp: CARDINAL] RETURNS [MapEntry] = TRUSTED MACHINE CODE {zMISC, aGETF};
DoFADD: PROC [REAL, REAL] RETURNS [REAL] = TRUSTED MACHINE CODE {zMISC, aFADD};
DoFSUB: PROC [REAL, REAL] RETURNS [REAL] = TRUSTED MACHINE CODE {zMISC, aFSUB};
DoFMUL: PROC [REAL, REAL] RETURNS [REAL] = TRUSTED MACHINE CODE {zMISC, aFMUL};
DoFDIV: PROC [REAL, REAL] RETURNS [REAL] = TRUSTED MACHINE CODE {zMISC, aFDIV};
DoFCOMP: PROC [x, y: REAL] RETURNS [INTEGER] = TRUSTED MACHINE CODE {zMISC, aFCOMP};
DoFIX: PROC [REAL] RETURNS [INT] = TRUSTED MACHINE CODE {zMISC, aFIX};
DoFLOAT: PROC [INT] RETURNS [REAL] = TRUSTED MACHINE CODE {zMISC, aFLOAT};
DoFIXI: PROC [REAL] RETURNS [INTEGER] = TRUSTED MACHINE CODE {zMISC, aFIXI};
DoFIXC: PROC [REAL] RETURNS [CARDINAL] = TRUSTED MACHINE CODE {zMISC, aFIXC};
DoFSTICKY: PROC [WORD] RETURNS [WORD] = TRUSTED MACHINE CODE {zMISC, aFSTICKY};
DoFREM: PROC [REAL, REAL] RETURNS [REAL] = TRUSTED MACHINE CODE {zMISC, aFREM};
DoROUND: PROC [REAL] RETURNS [INT] = TRUSTED MACHINE CODE {zMISC, aROUND};
DoROUNDI: PROC [REAL] RETURNS [INTEGER] = TRUSTED MACHINE CODE {zMISC, aROUNDI};
DoROUNDC: PROC [REAL] RETURNS [CARDINAL] = TRUSTED MACHINE CODE {zMISC, aROUNDC};
DoFSQRT: PROC [REAL] RETURNS [REAL] = TRUSTED MACHINE CODE {zMISC, aFSQRT};
DoFSC: PROC [REAL, INTEGER] RETURNS [REAL] = TRUSTED MACHINE CODE {zMISC, aFSC};
DoLocalZERO: PROC [count: CARDINAL] = TRUSTED MACHINE CODE {zMISC, aLocalZERO};
DoZERO: PROC [lp: LONG POINTER, count: CARDINAL] RETURNS [LONG POINTER] = TRUSTED MACHINE CODE {zMISC, aZERO};
DoVERSION: PROC RETURNS [LONG CARDINAL] = TRUSTED MACHINE CODE {zMISC, aVERSION};
MapFlags: TYPE = UNSPECIFIED;
MapEntry: TYPE = UNSPECIFIED;
DoMiscOp: PROC [m: Machine] = TRUSTED {
OPEN CM: CedarMicrocode;
alpha: Byte = RI.NextOpByte[m];
SELECT alpha FROM
aASSOC => {
p2: UNSPECIFIED = RI.Pop[m];
p1: UNSPECIFIED = RI.Pop[m];
DoASSOC[p1, p2]};
aSETF => {
p2: UNSPECIFIED = RI.Pop[m];
p1: UNSPECIFIED = RI.Pop[m];
RI.Push[m, LOOPHOLE[DoSETF[p1, p2]]]};
aLOADRAMJ => {
p2: UNSPECIFIED = RI.Pop[m];
p1: LONG POINTER = LOOPHOLE[RI.Pop2[m]];
DoLOADRAMJ[p1, p2]};
aINPUT => {
p1: UNSPECIFIED = RI.Pop[m];
RI.Push[m, LOOPHOLE[DoINPUT[p1]]]};
aOUTPUT => {
p2: UNSPECIFIED = RI.Pop[m];
p1: UNSPECIFIED = RI.Pop[m];
DoOUTPUT[p1, p2]};
aCHKSUM => {
p3: LONG POINTER = LOOPHOLE[RI.Pop2[m]];
p2: UNSPECIFIED = RI.Pop[m];
p1: UNSPECIFIED = RI.Pop[m];
RI.Push[m, LOOPHOLE[DoCHKSUM[p1, p2, p3]]]};
aSETMP => {
p1: UNSPECIFIED = RI.Pop[m];
DoSETMP[p1]};
aRCLK => {
RI.Push2[m, LOOPHOLE[DoRCLK[]]]};
aRPRINTER => {
RI.Push[m, LOOPHOLE[DoRPRINTER[]]]};
aWPRINTER => {
p1: UNSPECIFIED = RI.Pop[m];
DoWPRINTER[p1]};
aGETF => {
p1: UNSPECIFIED = RI.Pop[m];
RI.Push[m, LOOPHOLE[DoGETF[p1]]]};
aFADD, aFSUB, aFMUL, aFDIV, aFREM => {
p2: REAL = LOOPHOLE[RI.Pop2[m]];
p1: REAL = LOOPHOLE[RI.Pop2[m]];
res: REAL;
SELECT alpha FROM
aFADD =>
res ← DoFADD[p1, p2];
aFSUB =>
res ← DoFSUB[p1, p2];
aFMUL =>
res ← DoFMUL[p1, p2];
aFDIV =>
res ← DoFDIV[p1, p2];
aFREM =>
res ← DoFREM[p1, p2];
ENDCASE;
RI.Push2[m, LOOPHOLE[res]]};
aFIXI, aFIXC, aROUNDI, aROUNDC => {
par: REAL = LOOPHOLE[RI.Pop2[m]];
res: UNSPECIFIED;
SELECT alpha FROM
aFADD =>
res ← DoFIXI[par];
aFSUB =>
res ← DoFIXC[par];
aFMUL =>
res ← DoROUNDI[par];
aFDIV =>
res ← DoROUNDC[par];
ENDCASE;
RI.Push[m, LOOPHOLE[res]]};
aFCOMP => {
p2: REAL = LOOPHOLE[RI.Pop2[m]];
p1: REAL = LOOPHOLE[RI.Pop2[m]];
res: INTEGER = DoFCOMP[p1, p2];
RI.Push[m, LOOPHOLE[res]]};
aFSQRT => {
p1: REAL = LOOPHOLE[RI.Pop2[m]];
res: REAL;
res ← DoFSQRT[p1];
RI.Push2[m, LOOPHOLE[res]]};
aFLOAT => {
p1: INT = LOOPHOLE[RI.Pop2[m]];
res: REAL;
res ← DoFLOAT[p1];
RI.Push2[m, LOOPHOLE[res]]};
aFIX, aROUND => {
p1: REAL = LOOPHOLE[RI.Pop2[m]];
res: INT;
SELECT alpha FROM
aFIX => res ← DoFIX[p1];
aROUND => res ← DoROUND[p1];
ENDCASE;
RI.Push2[m, LOOPHOLE[res]]};
aFSTICKY => {
p1: UNSPECIFIED = RI.Pop[m];
RI.Push[m, LOOPHOLE[DoFSTICKY[p1]]]};
aFSC => {
p2: UNSPECIFIED = RI.Pop[m];
p1: REAL = LOOPHOLE[RI.Pop2[m]];
RI.Push2[m, LOOPHOLE[DoFSC[p1, p2]]]};
aLocalZERO => {
p1: UNSPECIFIED = RI.Pop[m];
DoLocalZERO[p1]};
aZERO => {
p2: UNSPECIFIED = RI.Pop[m];
p1: LONG POINTER = LOOPHOLE[RI.Pop2[m]];
RI.Push2[m, LOOPHOLE[DoZERO[p1, p2]]]};
aVERSION => {
RI.Push2[m, LOOPHOLE[DoVERSION[]]]};
CM.aRECLAIMEDREF => {
r: REF = LOOPHOLE[RI.Pop2[m]];
RI.Push2[m, LOOPHOLE[CM.RECLAIMEDREF[r]]];
};
CM.aENABLEMICROCODE => TRUSTED {
zct: LONG POINTER = LOOPHOLE[RI.Pop2[m]];
n: NAT = CM.ENABLEMICROCODE[zct];
RI.Push[m, LOOPHOLE[n]];
};
CM.aDISABLEMICROCODE => {
zct: LONG POINTER = LOOPHOLE[RI.Pop2[m]];
CM.DISABLEMICROCODE[zct];
};
CM.aCREATEREF => {
nhp: LONG POINTER = LOOPHOLE[RI.Pop2[m]];
CM.CREATEREF[nhp];
};
CM.aRECLAIMABLEREF => {
nhp: LONG POINTER = LOOPHOLE[RI.Pop2[m]];
cd: UNSPECIFIEDCM.RECLAIMABLEREF[nhp];
RI.Push[m, LOOPHOLE[cd]];
};
CM.aALLOCATEOBJECT => {
type: UNSPECIFIED = RI.Pop[m];
size: CARDINAL = RI.CardV[RI.Pop[m]];
r: REF = CM.ALLOCATE[size, type];
RI.Push2[m, LOOPHOLE[r]];
};
CM.aFREEOBJECT => {
nhp: LONG POINTER = LOOPHOLE[RI.Pop2[m]];
success: BOOL = CM.FREEPLEASE[nhp];
RI.Push[m, LOOPHOLE[success]];
};
CM.aRTMOVESTATUS => {
gcStateBank: CARDINAL = RI.CardV[RI.Pop[m]];
msOperation: CARDINAL = RI.CardV[RI.Pop[m]];
val: CARDINAL = CM.RTMOVESTATUS[msOperation, gcStateBank];
RI.Push[m, RI.VCard[val]];
};
CM.aGETCANONICALREFERENTTYPE => {
ref: REF = LOOPHOLE[RI.Pop2[m]];
type: UNSPECIFIED = CM.GETCANONICALREFERENTTYPE[ref];
RI.Push[m, type];
};
ENDCASE => ERROR StrangeCode};
}.
 alpha=240b Zero and Enable Event counters
 alpha=241b Read Event counters
 alpha=242b Stop Event counters
 alpha=243b Set PC Histogram Address
 alpha=244b Unused
 alpha=245b Unused
 alpha=246b Read/write muffler/manifold system
 alpha=247b Reset Ethernet hardware and tasks (PrincOps only)
 alpha=250B Reset 10MBEthernet hardware and tasks (PrincOps only)
 alpha=251B Get size of real and virtual memory
 alpha=252B Halt Dorado (for timed power-off)
 alpha=253B Set display field rate
 alpha=254b Reset disk hardware and task (PrincOps only)
 alpha=255b Set interval timer (PrincOps only)
 alpha=256b Stable Storage block input
 alpha=257b Stable Storage block output