Tokens
TokenInfo: TYPE ~ REF TokenInfoRec;
TokenInfoRec:
TYPE ~
RECORD [
type: ATOM,
code: LIST OF PrincOps.op,
size: CARDINAL
];
SizeNeeded:
PROC [x: XTree]
RETURNS [size:
CARDINAL ← 11] ~ {
Given an expression, tell how many bytes will be needed for the procedure which implements them
AddSize:
ET.EnumerateProc ~
TRUSTED {
token: Token;
WITH narrowX: x
SELECT
FROM
constant => token ← $Constant;
fcn => token ← $Proc;
id => token ← narrowX.op;
unX => token ← narrowX.op;
binX => token ← narrowX.op;
trinX => token ← narrowX.op;
ENDCASE => ERROR;
size ← size + GetTokenInfo[token].size;
};
[] ← ET.EnumDescendants[x, AddSize];
};
GetTokenInfo:
PROC [token: Token]
RETURNS [tokenInfo: TokenInfo] ~ {
FOR tokens:
LIST
OF TokenInfo ← definedTokens, tokens.rest
WHILE tokens#
NIL
DO
IF tokens.first.type = token THEN RETURN [tokens.first];
ENDLOOP;
ERROR IllegalToken[];
};
AddToken:
PROC [token: Token, code:
LIST
OF PrincOps.op]
RETURNS [] ~ {
size: CARDINAL ← 0;
tokenInfo: TokenInfo;
See how much space this takes
FOR ops:
LIST
OF PrincOps.op ← code, ops.rest
WHILE ops#
NIL
DO
size ← size+1;
ENDLOOP;
tokenInfo ← NEW[TokenInfoRec ← [token, code, size]];
definedTokens ← CONS[tokenInfo, definedTokens];
};
InitTokens:
PROC ~ {
AddToken[$Name, LIST[PrincOps]];
AddToken[$Add, LIST[zMISC, aFADD]]; --Floating Arithmetic
AddToken[$Subtract, LIST[zMISC, aFSUB]];
AddToken[$Multiply, LIST[zMISC, aFMUL]];
AddToken[$Divide, LIST[zMISC, aFDIV]];
AddToken[$Id1, LIST[zLLDB, arg1]];
AddToken[$Id2, LIST[zLLDB, arg2]];
AddToken[$Id3, LIST[zLLDB, arg3]];
AddToken[$Id4, LIST[zLLDB, arg4]];
AddToken[$Id5, LIST[zLLDB, arg5]];
AddToken[$Negate, LIST[zLINI, zXOR]]; --Flip the sign bit
AddToken[$Constant, LIST[zLIW, 0, 0, zLIW, 0, 0, zSLDB, 0, zLLDB, 0]]; --Handled manually
AddToken[$If, LIST[zSLDB, temp1, zSLDB, temp2, zLI1, zAND, zLI1, zJEQ4, zLLDB, temp1, zJ3, zLLDB, temp2]];
AddToken[$Proc, LIST[zLIW, 0, 0, zSFC]]; --Handled manually
AddToken[$max, LIST[zSLDB, temp1, zSLDB, temp2, zLLDB, temp2, zLLDB, temp2, zLLDB, temp1, zMISC, aFCOMP, zLI0, zJGEB, 6, zPOP, zPOP, zLLDB, temp1]];
AddToken[$min, LIST[zSLDB, temp1, zSLDB, temp2, zLLDB, temp2, zLLDB, temp2, zLLDB, temp1, zMISC, aFCOMP, zLI0, zJLEB, 6, zPOP, zPOP, zLLDB, temp1]];
REMEMBER: When a BOOLEAN is on the stack in this interpreter, only the least significant bit matters!!! Bit set is TRUE.
AddToken[$GT, LIST[zMISC, aFCOMP, zINC, zLIN1, zSHIFT]];
AddToken[$LT, LIST[zMISC, aFCOMP, zLIN1, zSHIFT]];
AddToken[$EQ, LIST[zMISC, aFCOMP, zINC]];
AddToken[$GE, LIST[zMISC, aFCOMP, zLIN1, zSHIFT, zINC]];
AddToken[$LE, LIST[zMISC, aFCOMP, zNEG, zLIN1, zSHIFT, zINC]];
AddToken[$NE, LIST[zMISC, aFCOMP]];
AddToken[$not, LIST[zINC]];
AddToken[$or, LIST[zOR]];
AddToken[$and, LIST[zAND]];
AddToken[$xor, LIST[zXOR]];
};
Procedure-twiddling
ProcBase:
TYPE ~
LONG
POINTER;
ProcInfo: TYPE ~ REF ProcInfoRec;
ProcInfoRec:
TYPE ~
RECORD [
proc: ANYPROC,
inUse: BOOLEAN ← FALSE,
size: CARDINAL
];
ProcList:
TYPE ~
LIST
OF ProcInfo;
FindProcedure:
UNSAFE
PROC [length:
CARDINAL]
RETURNS [proc:
ANYPROC, procBase: ProcBase] ~
UNCHECKED {
FOR procs: ProcList ← procList, procs.rest
WHILE procs#
NIL
DO
IF ~procs.first.inUse
AND length<procs.first.size
THEN {
procs.first.inUse ← TRUE;
RETURN [procs.first.proc, BaseOfProc[procs.first.proc]];
};
ENDLOOP;
ERROR NoProcedureAvailable[];
};
FreeProcedureUnderLock:
PROC [proc:
ANYPROC] ~ {
Procedure assumes the caller has already got a lock on the monitor
IF proc=NIL THEN RETURN;
FOR procs: ProcList ← procList, procs.rest
WHILE procs#
NIL
DO
IF procs.first.proc=proc THEN {procs.first.inUse ← FALSE; RETURN};
ENDLOOP;
};
BaseOfProc:
UNSAFE
PROC [proc:
ANYPROC]
RETURNS [procBase: ProcBase] ~
UNCHECKED {
gf: PrincOps.GlobalFrameHandle ← PrincOpsUtils.GlobalFrame[proc];
codeBase: LONG POINTER TO PrincOps.CSegPrefix ← LOOPHOLE[PrincOpsUtils.Codebase[gf]];
offset: PrincOps.BytePC ← codeBase^.entry[PrincOpsUtils.GlobalFrameAndEntryPoint[proc].ep].initialpc;
procBase ← LOOPHOLE[codeBase + offset];
};
SetFrameSize:
UNSAFE
PROC [proc:
ANYPROC, size:
CARDINAL] ~
UNCHECKED {
fsi: FrameSizeIndex ← PrincOpsUtils.MakeFsi[size];
gf: PrincOps.GlobalFrameHandle ← PrincOpsUtils.GlobalFrame[proc];
codeBase: LONG POINTER TO PrincOps.CSegPrefix ← LOOPHOLE[PrincOpsUtils.Codebase[gf]];
where: LONG POINTER TO PrincOps.EntryInfo ← @(codeBase^.entry[PrincOpsUtils.GlobalFrameAndEntryPoint[proc].ep].info);
page: VM.PageNumber ← VM.PageNumberForAddress[where];
VM.MakeReadWrite[[page, 1]];
where^.framesize ← fsi;
VM.MakeReadOnly[[page, 1]];
};
PullArgsOffStack:
UNSAFE
PROC [procBase: ProcBase]
RETURNS [codePos:
CARDINAL ← 0] ~
UNCHECKED {
codePos ← AppendOpsToProc[procBase, codePos, LIST[zSLDB, arg5, zSLDB, arg4, zSLDB, arg3, zSLDB, arg2, zSLDB, arg1]]; --Kluge for now pull 5 REALs off stack
};
AppendFcn: UNSAFE PROC [procBase: ProcBase, oldCodePos: CARDINAL, token: Token] RETURNS [codePos: CARDINAL] ~ UNCHECKED {
code: LIST OF PrincOps.op ← GetTokenInfo[token].code;
codePos ← AppendOpsToProc[procBase, oldCodePos, code];
};
AppendPushConstant: UNSAFE PROC [procBase: ProcBase, oldCodePos: CARDINAL, constant: REAL] RETURNS [codePos: CARDINAL] ~ UNCHECKED {
opList: LIST OF PrincOps.op ← LIST[
zLIW,
HiB[LoW[constant]],
LoB[LoW[constant]],
zLIW,
HiB[HiW[constant]],
LoB[HiW[constant]]
];
codePos ← AppendOpsToProc[procBase, oldCodePos, opList];
};
AppendProcCall: UNSAFE PROC [procBase: ProcBase, oldCodePos: CARDINAL, proc: ANYPROC] RETURNS [codePos: CARDINAL] ~ UNCHECKED {
opList: LIST OF PrincOps.op ← LIST[
zLIW, --Push the link to the procedure
HiB[proc],
LoB[proc],
zKFCB, --check for assignment of nested procs out of scope
sProcCheck,
zSFC --If we still exist, call the procedure
];
codePos ← AppendOpsToProc[procBase, oldCodePos, opList];
};
AppendReturn:
UNSAFE
PROC [procBase: ProcBase, oldCodePos:
CARDINAL] ~
UNCHECKED {
[] ← AppendOpsToProc[procBase, oldCodePos, LIST[zRET]];
};
AppendOpsToProc:
UNSAFE
PROC [procBase: ProcBase, oldCodePos:
CARDINAL, opList:
LIST
OF PrincOps.op]
RETURNS [codePos:
CARDINAL] ~
UNCHECKED {
WhichByte: TYPE ~ {even, odd};
codePos ← oldCodePos;
Go through the ops given, placing them in the code at the current location pointer
FOR ops:
LIST
OF PrincOps.op ← opList, ops.rest
WHILE ops#
NIL
DO
offset: CARDINAL ← codePos/2;
which: WhichByte ← IF offset*2=codePos THEN even ELSE odd;
code: LONG POINTER TO PrincOps.InstWord ← LOOPHOLE[procBase+offset];
page: VM.PageNumber ← VM.PageNumberForAddress[code];
VM.MakeReadWrite[[page, 1]];
SELECT which
FROM
even => code^.evenbyte ← LOOPHOLE[ops.first];
odd => code^.oddbyte ← LOOPHOLE[ops.first];
ENDCASE;
VM.MakeReadOnly[[page, 1]];
codePos ← codePos + 1;
ENDLOOP;
};
RegisterP:
PROC [proc:
ANYPROC, size:
CARDINAL] ~ {
procInfo: ProcInfo ← NEW[ProcInfoRec ← [proc: proc, inUse: FALSE, size: size]];
procList ← CONS[procInfo, procList];
};
InitProcs:
PROC ~ {
RegisterP[P1000, 1000]; RegisterP[P1001, 1000]; RegisterP[P602, 600]; RegisterP[P603, 600]; RegisterP[P604, 600];
RegisterP[P605, 600]; RegisterP[P606, 600]; RegisterP[P607, 600]; RegisterP[P608, 600]; RegisterP[P609, 600];
RegisterP[P410, 400]; RegisterP[P411, 400]; RegisterP[P412, 400]; RegisterP[P413, 400]; RegisterP[P414, 400];
RegisterP[P415, 400]; RegisterP[P416, 400]; RegisterP[P417, 400]; RegisterP[P418, 400]; RegisterP[P419, 400];
RegisterP[P220, 200]; RegisterP[P221, 200]; RegisterP[P222, 200]; RegisterP[P223, 200]; RegisterP[P224, 200];
RegisterP[P225, 200]; RegisterP[P226, 200]; RegisterP[P227, 200]; RegisterP[P228, 200]; RegisterP[P229, 200];
RegisterP[P130, 100]; RegisterP[P131, 100]; RegisterP[P132, 100]; RegisterP[P133, 100]; RegisterP[P134, 100];
RegisterP[P135, 100]; RegisterP[P136, 100]; RegisterP[P137, 100]; RegisterP[P138, 100]; RegisterP[P139, 100];
RegisterP[Pf40, 50]; RegisterP[Pf41, 50]; RegisterP[Pf42, 50]; RegisterP[Pf43, 50]; RegisterP[Pf44, 50];
RegisterP[Pf45, 50]; RegisterP[Pf46, 50]; RegisterP[Pf47, 50]; RegisterP[Pf48, 50]; RegisterP[Pf49, 50];
};
LoW:
PROC [r:
REAL]
RETURNS [
UNSPECIFIED] ~ {
card: LONG CARDINAL ← LOOPHOLE[r];
cardinal: CARDINAL ← card - 10000H*(card/10000H);
RETURN[LOOPHOLE[cardinal]];
};
HiW:
PROC [r:
REAL]
RETURNS [
UNSPECIFIED] ~ {
card: LONG CARDINAL ← LOOPHOLE[r];
cardinal: CARDINAL ← card/10000H;
RETURN[LOOPHOLE[cardinal]];
};
LoB:
PROC [u:
UNSPECIFIED]
RETURNS [PrincOps.op] ~ {
card: CARDINAL ← LOOPHOLE[u];
RETURN[LOOPHOLE[card - 100H*(card/100H)]];
};
HiB:
PROC [u:
UNSPECIFIED]
RETURNS [PrincOps.op] ~ {
card: CARDINAL ← LOOPHOLE[u];
RETURN[LOOPHOLE[card/100H]];
};
Recyclable Procedures
Some frame location definitions
arg1: PrincOps.op = 4;
arg2: PrincOps.op = 6;
arg3: PrincOps.op = 8;
arg4: PrincOps.op = 10;
arg5: PrincOps.op = 12;
temp1: PrincOps.op = 14;
temp2: PrincOps.op = 16;
procTemp: PrincOps.op = 18;
MC25:
PROC ~
TRUSTED
MACHINE
CODE {
zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP;
};
MC50: PROC ~ INLINE {MC25[]; MC25[]};
MC100: PROC ~ INLINE {MC25[]; MC25[]; MC25[]; MC25[]};
MC200: PROC ~ INLINE {MC25[]; MC25[]; MC25[]; MC25[]; MC25[]; MC25[]; MC25[]; MC25[]};
MC400: PROC ~ INLINE {MC200[]; MC200[]};
MC600: PROC ~ INLINE {MC200[]; MC200[]; MC200[]};
MC1000:
PROC ~
INLINE {MC200[]; MC200[]; MC200[]; MC200[]; MC200[]};
P1000: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC1000};
P1001: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC1000};
P602: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC600};
P603: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC600};
P604: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC600};
P605: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC600};
P606: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC600};
P607: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC600};
P608: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC600};
P609: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC600};
P410: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P411: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P412: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P413: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P414: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P415: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P416: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P417: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P418: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P419: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P220: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P221: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P222: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P223: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P224: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P225: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P226: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P227: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P228: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P229: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P130: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
P131: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
P132: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
P133: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
P134: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
P135: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
P136: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
P137: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
P138: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
P139: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
Pf40: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
Pf41: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
Pf42: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
Pf43: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
Pf44: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
Pf45: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
Pf46: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
Pf47: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
Pf48: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
Pf49: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
}.