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];
}.