RobotOpCodesImpl.mesa
Created Monday, May 21, 1984 10:38 pm PDT
Last edited by Eric Nickell, July 6, 1985 11:21:02 am PDT
Last Edited by: Rumph, November 7, 1984 3:37:19 pm PST
DIRECTORY
RobotDefs USING [MemoryMap, MemoryMapRep],
RobotHardware USING [direct, fire, speed],
RobotOpCodes,
Rope USING [Equal, Fetch, Length, ROPE];
RobotOpCodesImpl:
CEDAR
PROGRAM
IMPORTS RobotHardware, Rope
EXPORTS RobotOpCodes
~ {
OPEN RobotOpCodes;
MemoryMap: TYPE ~ RobotDefs.MemoryMap;
OpCodeEntry:
TYPE ~
RECORD [
text: Rope.ROPE, --The actual name
hash: INT, --A quick comparison
proc: OpProc --The execution proc
];
OpProc: TYPE ~ PRIVATE PROC [addr, cont: INTEGER, m: REF Memory, mw: MemoryMap];
MaxOpCodes: INT ~ 32;
opCodeTable: ARRAY [0..MaxOpCodes) OF OpCodeEntry;
opCodesInTable:
INTEGER ← 0;
IsOpCode:
PUBLIC
PROC [r: Rope.
ROPE]
RETURNS [
BOOLEAN] ~ {
RETURN [OpCode[r]^>=0]; --OpCode returns -1 if not an opcode
};
Given a rope, return the opcode #, or -1 if the opcode doesn't exist
OpCode:
PUBLIC
PROC [r: Rope.
ROPE]
RETURNS [
REF
INTEGER] ~ {
hash: INT ← HashRope[r];
IF opCodesInTable=0 THEN RETURN [NEW[INTEGER ← -1]]; --Implies not there
FOR i:
INT
IN [0..opCodesInTable)
DO
IF hash=opCodeTable[i].hash AND Rope.Equal[r,opCodeTable[i].text] THEN RETURN[NEW[INTEGER ← i]];
ENDLOOP;
RETURN [NEW[INTEGER ← -1]]; --Implies not there
};
DoOpCode:
PUBLIC
PROC [op:
INT, addr, cont:
INTEGER, m:
REF Memory]
RETURNS [mw: MemoryMap] ~ {
mw ← NEW[RobotDefs.MemoryMapRep ← ALL[FALSE]];
Check for for illegal op => a noop
IF opCodeTable[op].proc=NIL THEN RETURN;
OK, call the proc for this opcode to get the work done...
opCodeTable[op].proc[addr, cont, m, mw];
IF ~mw[pc] THEN m[pc] ← m[pc]+1; --If nobody else modified it
};
HashRope:
PRIVATE
PROC [r: Rope.
ROPE]
RETURNS [
INT] ~ {
len: INTEGER ← Rope.Length[r];
RETURN [len + CharToInt[Rope.Fetch[r,0]] + CharToInt[Rope.Fetch[r,len-1]]];
};
CharToInt:
PRIVATE
PROC [c:
CHAR]
RETURNS [i:
INT] ~ {
RETURN [ORD[c]];
};
Install:
PRIVATE
PROC [r: Rope.
ROPE, proc: OpProc] ~ {
opCode: OpCodeEntry ← [
text: r,
hash: HashRope[r],
proc: proc
];
IF opCodesInTable >= MaxOpCodes THEN ERROR;
opCodeTable[opCodesInTable] ← opCode;
opCodesInTable ← opCodesInTable + 1;
};
ShiftLeft:
PRIVATE
PROC [shiftee, shifter:
INTEGER]
RETURNS [shifted:
INTEGER] ~ {
shifted ← shiftee;
SELECT
TRUE
FROM
shifter >=16 => RETURN [0];
shifter
IN [0..16) => {
THROUGH [1..shifter] DO shifted ← shifted*2 ENDLOOP;
RETURN[shifted];
};
shifter=0 => RETURN[shiftee];
shifter
IN (-16..0) => {
THROUGH [shifter..-1] DO shifted ← shifted/2 ENDLOOP;
RETURN[shifted];
};
shifter <=-16 => RETURN[0];
ENDCASE => ERROR;
};
Set:
PROC [mem:
REF Memory, memWrit: MemoryMap, loc: MemoryIndex, val:
INTEGER] ~ {
mem[loc] ← val;
memWrit[loc] ← TRUE;
};
RUN THIS SECTION ON START-UP
ac: INTEGER ~ 0;
i: INTEGER ~ 1;
stk: INTEGER ~ 2;
pc: INTEGER ~ 3;
fire: INTEGER ~ RobotHardware.fire;
direct: INTEGER ~ RobotHardware.direct;
speed: INTEGER ~ RobotHardware.speed;
Define the opcode procedures
LDAProc: OpProc ~ {Set[m,mw,ac,cont]};
STAProc: OpProc ~ {Set[m,mw,addr,m[ac]]};
BAZProc: OpProc ~ {IF m[ac]=0 THEN Set[m,mw,pc,cont]};
BALProc: OpProc ~ {IF m[ac]<0 THEN Set[m,mw,pc,cont]};
BAGProc: OpProc ~ {IF m[ac]>0 THEN Set[m,mw,pc,cont]};
BANProc: OpProc ~ {IF m[ac]#0 THEN Set[m,mw,pc,cont]};
LDIProc: OpProc ~ {Set[m,mw,i,cont]};
STIProc: OpProc ~ {Set[m,mw,addr,m[i]]};
BIZProc: OpProc ~ {IF m[i]=0 THEN Set[m,mw,pc,cont]};
BILProc: OpProc ~ {IF m[i]<0 THEN Set[m,mw,pc,cont]};
BIGProc: OpProc ~ {IF m[i]>0 THEN Set[m,mw,pc,cont]};
BINProc: OpProc ~ {IF m[i]#0 THEN Set[m,mw,pc,cont]};
JMPProc: OpProc ~ {Set[m,mw,pc,cont]};
LUPProc: OpProc ~ {Set[m,mw,i,m[i]-1]; IF m[i]>=0 THEN Set[m,mw,pc,cont]};
ADDProc: OpProc ~ {Set[m,mw,ac,m[ac]+cont]};
SUBProc: OpProc ~ {Set[m,mw,ac,m[ac]-cont]};
MULProc: OpProc ~ {Set[m,mw,ac,m[ac]*cont]};
SHFProc: OpProc ~ {Set[m,mw,ac,ShiftLeft[m[ac],cont]]};
FRMProc: OpProc ~ {Set[m,mw,ac,cont-m[ac]]};
FIRProc: OpProc ~ {Set[m,mw,fire,cont]};
TRNProc: OpProc ~ {Set[m,mw,direct,cont]};
SPDProc: OpProc ~ {Set[m,mw,speed,cont]};
Install the opcode procedures
Install ["LDA", LDAProc];
Install ["STA", STAProc];
Install ["BAZ", BAZProc];
Install ["BAL", BALProc];
Install ["BAG", BAGProc];
Install ["BAN", BANProc];
Install ["LDI", LDIProc];
Install ["STI", STIProc];
Install ["BIZ", BIZProc];
Install ["BIL", BILProc];
Install ["BIG", BIGProc];
Install ["BIN", BINProc];
Install ["JMP", JMPProc];
Install ["LUP", LUPProc];
Install ["ADD", ADDProc];
Install ["SUB", SUBProc];
Install ["MUL", MULProc];
Install ["SHF", SHFProc];
Install ["FRM", FRMProc];
Install ["FIR", FIRProc];
Install ["TRN", TRNProc];
Install ["SPD", SPDProc];
}.