DIRECTORY
RobotDefs USING [Instruction, MemoryIndex],
RobotEvaluator USING [AssignValueToSymbol, NewValueFromInteger, RopeToSymbolIndex, SymbolTable],
RobotHardware,
RobotOpCodes USING [DoOpCode],
Rope USING [ROPE];
RobotHardwareImpl:
CEDAR
PROGRAM
IMPORTS RobotEvaluator, RobotOpCodes
EXPORTS RobotHardware
~ {
OPEN RobotHardware;
ROPE: TYPE ~ Rope.ROPE;
nIndex: CARDINAL ~ LAST[MemoryIndex]+1;
Loc:
TYPE ~ {ac, i, stk, pc, hx, mx, hy, my, hdmg, mdmg, ctx, down, up, direct, fire, speed};
offset: INTEGER ~ LOOPHOLE[FIRST[Loc]];
hx: PUBLIC MemoryIndex ← Loc2Mem[hx];
mx: PUBLIC MemoryIndex ← Loc2Mem[mx];
hy: PUBLIC MemoryIndex ← Loc2Mem[hy];
my: PUBLIC MemoryIndex ← Loc2Mem[my];
hdmg: PUBLIC MemoryIndex ← Loc2Mem[hdmg];
mdmg: PUBLIC MemoryIndex ← Loc2Mem[mdmg];
direct: PUBLIC MemoryIndex ← Loc2Mem[direct];
fire: PUBLIC MemoryIndex ← Loc2Mem[fire];
speed:
PUBLIC MemoryIndex ← Loc2Mem[speed];
ProcessRobot:
PUBLIC
PROC [robot:
REF Memory]
RETURNS [addressWritten: MemoryMap] ~ {
CtxLoc:
PROC [loc: Loc]
RETURNS [MemoryIndex] ~
INLINE {
RETURN [(contextBase + Loc2Mem[loc] - Loc2Mem[ac]) MOD (nIndex)]
};
Addr:
PROC [val:
INTEGER]
RETURNS [MemoryIndex] ~
INLINE {
RETURN [LOOPHOLE[val, CARDINAL] MOD nIndex]
};
ac, ind, pc, addr, cont, value: INTEGER;
instruction: RobotDefs.Instruction;
contextBase: INTEGER ← robot[Loc2Mem[ctx]] MOD (nIndex);
ac ← CtxLoc[ac]; --Ac pointed to by context register
ind ← CtxLoc[i]; --Index pointed to by context register
pc ← Loc2Mem[pc] MOD nIndex; --Get the next instruction
instruction ← LOOPHOLE[robot[LOOPHOLE[robot[pc], CARDINAL] MOD nIndex]];
cont ← instruction.tag;
--Start by assuming #tag
Interpret immediate tags in range [-128 .. 127].
IF instruction.immediate AND cont > 127 THEN cont ← cont - 256;
addr ← -1; --And writes here do screwy things
Here, we need to dereference the instruction
IF instruction.indirect
AND instruction.immediate
AND ~instruction.indexed
THEN {
Since #tag^ useless, it is re-interpreted as a stack reference...
stkptr: MemoryIndex ← Addr[cont];
addr ← Addr[robot[stkptr]];
cont ← robot[addr];
robot[stkptr] ← robot[stkptr]+1;
}
ELSE {
IF instruction.indirect
THEN {
addr ← Addr[cont];
cont ← robot[addr];
};
IF instruction.indexed
THEN {
cont ← cont + robot[Addr[ind]];
addr ← -1;
};
IF ~instruction.immediate
THEN {
addr ← Addr[cont];
cont ← robot[addr];
};
};
Now, perform the operation using these references
addressWritten ← RobotOpCodes.DoOpCode[
op: instruction.opNum,
addr: addr,
cont: cont,
m: robot
];
[robot[ac], robot[ind], robot[pc], addr, cont, regs] ← RobotOpCodes.ProcessOpCode[
op: instruction.opNum,
lAc: robot[ac],
lInd: robot[ind],
lPc: robot[pc],
lAddr: addr,
lCont: cont
];
Identify which locations have been modified
IF regs.pc THEN addressWritten[pc] ← TRUE;
IF regs.ac THEN addressWritten[ac] ← TRUE;
IF regs.stk THEN addressWritten[Loc2Mem[stk]] ← TRUE;
IF regs.ind THEN addressWritten[ind] ← TRUE;
Tickle the up and down counters
IF (value←robot[Loc2Mem[up]])
IN MemoryIndex
AND robot[value]#0
THEN {
robot[value] ← robot[value]+1;
};
IF (value←robot[Loc2Mem[down]])
IN MemoryIndex
AND robot[value]#0
THEN {
robot[value] ← robot[value]-1;
};
};
InitialMemory:
PUBLIC PROC [code: Memory]
RETURNS [memory:
REF Memory] ~ {
memory ← NEW[Memory ← code];
FOR i: MemoryIndex
IN [Loc2Mem[
FIRST[Loc]] .. Loc2Mem[
LAST[Loc]]]
DO
memory[i] ← 0; --Zero register locations
ENDLOOP;
memory[Loc2Mem[pc]] ← Loc2Mem[LAST[Loc]]+1; --Start execution after last register
memory[Loc2Mem[stk]] ← nIndex-1; --Put stack at end of memory
memory[Loc2Mem[ctx]] ← Loc2Mem[ac]; --Start with accumulator at ac
memory[Loc2Mem[up]] ← -1; --No counters initially
memory[Loc2Mem[down]] ← -1; --No counters initially
};
InstallStandardSymbols:
PUBLIC
PROC [s: RobotEvaluator.SymbolTable] ~ {
Install:
PROC [loc: Loc, name:
ROPE] ~ {
OPEN RobotEvaluator;
AssignValueToSymbol[NewValueFromInteger[Loc2Mem[loc]], RopeToSymbolIndex[name, s], s];
};
Install[ac, "AC"];
Install[i, "I"];
Install[stk, "STK"];
Install[pc, "PC"];
Install[hx, "HX"];
Install[mx, "MX"];
Install[hy, "HY"];
Install[my, "MY"];
Install[hdmg, "HDMG"];
Install[mdmg, "MDMG"];
Install[ctx, "CONTEXT"];
Install[down, "DOWN"];
Install[up, "UP"];
Install[direct, "DIRECT"];
Install[fire, "FIRE"];
Install[speed, "SPEED"];
};
Loc2Mem:
PROC [loc: Loc]
RETURNS [MemoryIndex] ~
INLINE {
RETURN [LOOPHOLE[loc, INTEGER]-offset MOD nIndex]
};
Init:
PROC ~
TRUSTED {
};
Init[];
}.