/** * Base class for all SamInstructions. Defines common features such * as shortcut variables and methods, toString(), name, cpu/mem access, * and an abstract exec(). All instructions must be associated first so they * can get a CPU/Memory. */ public abstract class SamInstruction implements Instruction, java.io.Serializable { protected final String name = this.getClass().getName(); public String toString() { return name; } protected SymbolTable symTable; protected Processor cpu = null; protected Memory mem = null; protected Video video = null; public void setSystem(Sys sys) { cpu = sys.cpu(); mem = sys.mem(); video = sys.video(); symTable = cpu.getProgram().getTable(); } // This is required to remove the references to the processor, memory, and video // before they are stored, and then to restore them private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { Processor cpuLocal = cpu; cpu = null; Memory memLocal = mem; mem = null; Video videoLocal = video; video = null; out.defaultWriteObject(); cpu = cpuLocal; mem = memLocal; video = videoLocal; } public void setTable(SymbolTable st) { symTable = st; } /*--------------------------------- Convenience -----------------------------------------------*/ /* Frequently used things that are hard to type are shortened here: */ /*---------------------------------------------------------------------------------------------*/ protected float popFloat() throws SystemException { return Float.intBitsToFloat(mem.pop()); } protected void pushFloat(float fl) throws SystemException { mem.push(FLOAT, Float.floatToIntBits(fl)); } public final static byte PC = Processor.PC, HP = Processor.HP, SP = Processor.SP, HALT = Processor.HALT, FBR = Processor.FBR; public final static byte MA = Memory.MA, INT = Memory.INT, FLOAT = Memory.FLOAT, PA = Memory.PA, CH = Memory.CH; /*--------------------------------------------------------------------------------------------*/ public abstract void exec() throws SystemException; } /* Abstract classes for each operand type */ abstract class SamIntInstruction extends SamInstruction { protected int op; public String toString() { return name + " " + op; } public void setOperand(int operand) { op = operand; } } abstract class SamFloatInstruction extends SamInstruction { protected float op; public String toString() { return name + " " + op; } public void setOperand(float operand) { op = operand; } } abstract class SamCharInstruction extends SamInstruction { protected char op; public String toString() { return name + " " + '\'' + op + '\''; } public void setOperand(char operand) { op = operand; } } abstract class SamStringInstruction extends SamInstruction { protected String op; public String toString() { return name + " " + '\"' + op + '\"'; } public void setOperand(String operand) { op = operand; } } /* Common print method for all jump instructions - resolve integer to label */ abstract class JumpOperandInstruction extends SamIntInstruction { public String toString() { String label = null; if (symTable != null) label = symTable.resolveSymbol(op); return name + " " + ((label == null) ? Integer.toString(op) : label); } } /*================================== Instructions==========================*/ /*------------------ Converters--------------- FTOI - float to integer truncate FTOIR - float to integer round ITOR - integer to float -------------------------------------------*/ class FTOI extends SamInstruction { public void exec() throws SystemException { mem.push(new Float(popFloat()).intValue()); cpu.inc(PC); } } class FTOIR extends SamInstruction { public void exec() throws SystemException { mem.push(Math.round(popFloat())); cpu.inc(PC); } } class ITOF extends SamInstruction { public void exec() throws SystemException { pushFloat(new Integer(mem.pop()).floatValue()); cpu.inc(PC); } } /* Push INT/FLOAT/CHAR */ class PUSHIMM extends SamIntInstruction { public void exec() throws SystemException { mem.push(op); cpu.inc(PC); } } class PUSHIMMF extends SamFloatInstruction { public void exec() throws SystemException { pushFloat(op); cpu.inc(PC); } } class PUSHIMMCH extends SamCharInstruction { public void exec() throws SystemException { mem.push(CH, (int)op); cpu.inc(PC); } } /* Store a string on the heap. Push its address. */ class PUSHIMMSTR extends SamStringInstruction { public void exec() throws SystemException { final int size = op.length(); mem.malloc(size); //allocate int addr = mem.getMem(cpu.get(SP) - 1); //get address for (int a = 0; a < size; a++) //store mem.setMem(addr + 1 + a, CH, op.charAt(a)); cpu.inc(PC); }; } /* Push the SP/FBR registers */ class PUSHSP extends SamInstruction { public void exec() throws SystemException { mem.push(MA, cpu.get(SP)); cpu.inc(PC); } } class PUSHFBR extends SamInstruction { public void exec() throws SystemException { mem.push(MA, cpu.get(FBR)); cpu.inc(PC); } } /* Pop the SP/FBR registers */ class POPSP extends SamInstruction { public void exec() throws SystemException { cpu.set(SP, mem.pop()); cpu.inc(PC); } } class POPFBR extends SamInstruction { public void exec() throws SystemException { cpu.set(FBR, mem.pop()); cpu.inc(PC); } } /* More stack manipulation - duplicate a stack value. Swap two values. This preserves type */ class DUP extends SamInstruction { public void exec() throws SystemException { byte type = mem.getType(cpu.get(SP) - 1); int value = mem.pop(); mem.push(type, value); mem.push(type, value); cpu.inc(PC); } } class SWAP extends SamInstruction { public void exec() throws SystemException { byte hightype = mem.getType(cpu.get(SP) - 1); int high = mem.pop(); byte lowtype = mem.getType(cpu.get(SP) - 1); int low = mem.pop(); mem.push(hightype, high); mem.push(lowtype, low); cpu.inc(PC); } } /* Stack/Heap allocation */ class ADDSP extends SamIntInstruction { public void exec() throws SystemException { cpu.set(SP, cpu.get(SP) + op); cpu.inc(PC); } } class MALLOC extends SamInstruction { public void exec() throws SystemException { mem.malloc(mem.pop()); cpu.inc(PC); } } /* PUSHIND/STOREIND - absolute store/retrieve */ class PUSHIND extends SamInstruction { public void exec() throws SystemException { int address = mem.pop(); mem.push(mem.getType(address), mem.getMem(address)); cpu.inc(PC); } } class STOREIND extends SamInstruction { public void exec() throws SystemException { byte type = mem.getType(cpu.get(SP) - 1); int value = mem.pop(); mem.setMem(mem.pop(), type, value); cpu.inc(PC); } } /* PUSHOFF/STOREOFF - relative store/retrieve */ class PUSHOFF extends SamIntInstruction { public void exec() throws SystemException { int address = cpu.get(FBR) + op; mem.push(mem.getType(address), mem.getMem(address)); cpu.inc(PC); } } class STOREOFF extends SamIntInstruction { public void exec() throws SystemException { byte type = mem.getType(cpu.get(SP) - 1); int value = mem.pop(); mem.setMem(cpu.get(FBR) + op, type, value); cpu.inc(PC); } } /* Simple Algebra */ class ADD extends SamInstruction { public void exec() throws SystemException { byte firsttype = mem.getType(cpu.get(SP) - 2); mem.push(firsttype, mem.pop() + mem.pop()); cpu.inc(PC); } } class ADDF extends SamInstruction { public void exec() throws SystemException { pushFloat(popFloat() + popFloat()); cpu.inc(PC); } } class SUB extends SamInstruction { public void exec() throws SystemException { byte firsttype = mem.getType(cpu.get(SP) - 2); mem.push(firsttype, -mem.pop() + mem.pop()); cpu.inc(PC); } } class SUBF extends SamInstruction { public void exec() throws SystemException { pushFloat(-popFloat() + popFloat()); cpu.inc(PC); } } class TIMES extends SamInstruction { public void exec() throws SystemException { mem.push(mem.pop() * mem.pop()); cpu.inc(PC); } } class TIMESF extends SamInstruction { public void exec() throws SystemException { pushFloat(popFloat() * popFloat()); cpu.inc(PC); } } class DIV extends SamInstruction { public void exec() throws SystemException { mem.push((int) ((double)1 / (double)mem.pop() * (double)mem.pop())); cpu.inc(PC); } } class DIVF extends SamInstruction { public void exec() throws SystemException { pushFloat((float) ((double)1 / (double)popFloat() * (double)popFloat())); cpu.inc(PC); } } class MOD extends SamInstruction { public void exec() throws SystemException { long v1 = mem.pop(); long v2 = mem.pop(); mem.push((int) (v2 % v1)); cpu.inc(PC); } } /* Shifts */ class LSHIFT extends SamIntInstruction { public void exec() throws SystemException { mem.push(mem.pop() << op); cpu.inc(PC); } } class RSHIFT extends SamIntInstruction { public void exec() throws SystemException { mem.push(mem.pop() >> op); cpu.inc(PC); } } /* Logic */ class AND extends SamInstruction { public void exec() throws SystemException { mem.push(mem.pop() == 0 | mem.pop() == 0 ? 0 : 1); cpu.inc(PC); } } class NAND extends SamInstruction { public void exec() throws SystemException { mem.push(mem.pop() == 0 | mem.pop() == 0 ? 1 : 0); cpu.inc(PC); } } class NOT extends ISNIL { } class OR extends SamInstruction { public void exec() throws SystemException { mem.push(mem.pop() != 0 | mem.pop() != 0 ? 1 : 0); cpu.inc(PC); } } class NOR extends SamInstruction { public void exec() throws SystemException { mem.push(mem.pop() != 0 | mem.pop() != 0 ? 0 : 1); cpu.inc(PC); } } class XOR extends SamInstruction { public void exec() throws SystemException { boolean one = (mem.pop() == 0) ? false : true; boolean two = (mem.pop() == 0) ? false : true; mem.push((one && !two) || (two && !one) ? 1 : 0); cpu.inc(PC); } } /* Bitwise Logic */ class BITNOT extends SamInstruction { public void exec() throws SystemException { mem.push(~mem.pop()); cpu.inc(PC); } } class BITOR extends SamInstruction { public void exec() throws SystemException { mem.push(mem.pop() | mem.pop()); cpu.inc(PC); } } class BITNOR extends SamInstruction { public void exec() throws SystemException { mem.push(~(mem.pop() | mem.pop())); cpu.inc(PC); } } class BITXOR extends SamInstruction { public void exec() throws SystemException { mem.push(mem.pop() ^ mem.pop()); cpu.inc(PC); } } class BITAND extends SamInstruction { public void exec() throws SystemException { mem.push(mem.pop() & mem.pop()); cpu.inc(PC); } } class BITNAND extends SamInstruction { public void exec() throws SystemException { mem.push(~(mem.pop() & mem.pop())); cpu.inc(PC); } } /* Comparison */ class CMP extends SamInstruction { public void exec() throws SystemException { int high = mem.pop(), low = mem.pop(); mem.push(high > low ? 1 : high < low ? -1 : 0); cpu.inc(PC); } } class CMPF extends SamInstruction { public void exec() throws SystemException { float high = Float.intBitsToFloat(mem.pop()), low = Float.intBitsToFloat(mem.pop()); mem.push(high > low ? 1 : high < low ? -1 : 0); cpu.inc(PC); } } class ISNIL extends SamInstruction { public void exec() throws SystemException { mem.push(mem.pop() == 0 ? 1 : 0); cpu.inc(PC); } } class ISPOS extends SamInstruction { public void exec() throws SystemException { mem.push(mem.pop() > 0 ? 1 : 0); cpu.inc(PC); } } class ISNEG extends SamInstruction { public void exec() throws SystemException { mem.push(mem.pop() < 0 ? 1 : 0); cpu.inc(PC); } } class GREATER extends SamInstruction { public void exec() throws SystemException { mem.push(mem.pop() < mem.pop() ? 1 : 0); cpu.inc(PC); } } class LESS extends SamInstruction { public void exec() throws SystemException { mem.push(mem.pop() > mem.pop() ? 1 : 0); cpu.inc(PC); } } class EQUAL extends SamInstruction { public void exec() throws SystemException { mem.push(mem.pop() == mem.pop() ? 1 : 0); cpu.inc(PC); } } /* Jumps */ class JUMP extends JumpOperandInstruction { public void exec() throws SystemException { cpu.set(PC, op); } } class JUMPC extends JumpOperandInstruction { public void exec() throws SystemException { if (mem.pop() != 0) cpu.set(PC, op); else cpu.inc(PC); } } class JUMPIND extends SamInstruction { public void exec() throws SystemException { cpu.set(PC, mem.pop()); } } class JSR extends JumpOperandInstruction { public void exec() throws SystemException { mem.push(PA, cpu.get(PC) + 1); cpu.set(PC, op); } } class JSRIND extends SamInstruction { public void exec() throws SystemException { int top = mem.pop(); mem.push(PA, cpu.get(PC) + 1); cpu.set(PC, top); } } class BRANCH extends SamInstruction { public void exec() throws SystemException { int top = mem.pop(); cpu.set(PC, cpu.get(PC) + top + 1); } } /* LINK - create a new stack frame */ class LINK extends SamInstruction { public void exec() throws SystemException { mem.push(MA, cpu.get(FBR)); cpu.set(FBR, cpu.get(SP) - 1); cpu.inc(PC); } } /* FSET - create a new stack frame */ class FSET extends SamIntInstruction { public void exec() throws SystemException { cpu.set(FBR, cpu.get(SP) - ( op + 1 ) ); cpu.inc(PC); } } /* Input/Output - READ/WRITE */ class READ extends SamInstruction { public void exec() throws SystemException { if (video != null) mem.push(video.readInt()); else mem.push(0); cpu.inc(PC); } } class READF extends SamInstruction { public void exec() throws SystemException { if (video != null) pushFloat(video.readFloat()); else pushFloat(0); cpu.inc(PC); } } class READCH extends SamInstruction { public void exec() throws SystemException { if (video != null) mem.push(CH, (int)video.readChar()); else mem.push(CH, 0); cpu.inc(PC); } } class READSTR extends SamInstruction { public void exec() throws SystemException { String str = (video != null) ? video.readString() : ""; final int size = str.length(); mem.malloc(size); int addr = mem.getMem(cpu.get(SP) - 1); for (int a = 0; a < size; a++) mem.setMem(addr + 1 + a, CH, str.charAt(a)); cpu.inc(PC); }; } class WRITE extends SamInstruction { public void exec() throws SystemException { if (video != null) video.writeInt(mem.pop()); else mem.pop(); cpu.inc(PC); } } class WRITEF extends SamInstruction { public void exec() throws SystemException { if (video != null) video.writeFloat(popFloat()); else mem.pop(); cpu.inc(PC); } } class WRITECH extends SamInstruction { public void exec() throws SystemException { if (video != null) video.writeChar((char)mem.pop()); else mem.pop(); cpu.inc(PC); } } class WRITESTR extends SamInstruction { public void exec() throws SystemException { String str = ""; int addr = mem.pop(); final int size = mem.getMem(addr); for (int a = 1; a < size; a++) str += (char)mem.getMem(addr + a); if (video != null) video.writeString(str); cpu.inc(PC); }; } /* Stop Execution */ class STOP extends SamInstruction { public void exec() throws SystemException { cpu.set(HALT, 1); } }