public SICEvent(Instruction inst, int PC) { this.instruction = inst; this.Continue = true; this.PC = PC; this.Ex = null; this.Message = null; }
public SICEvent(Instruction inst, int PC, Exception ex, string message) { this.instruction = inst; this.Continue = false; this.PC = PC; this.Ex = ex; this.Message = message; }
public bool Step() { this.devicewrite = false; current = getInstruction(); SICEvent instEvent = new SICEvent(current, ProgramCounter); PreInstructionHook(instEvent); if (!instEvent.Continue) return false; current.addrof = ProgramCounter; IncrementPC(current); if (current.twobyte) { DoTwoBye(current); lastInstruction = current; instEvent = new SICEvent(lastInstruction, ProgramCounter); PostInstructionHook(instEvent); if (!instEvent.Continue) return false; return true; } int calcaddr, memval; calcaddr = GetAddress(current); current.calculatedaddr = calcaddr; try { memval = GetData(current); } catch (IndexOutOfRangeException ex) { throw new IndexOutOfRangeException(string.Format("Error: Instruction at 0x{0:X3} references memory that's out of range (0x{1:X3}).", current.addrof, calcaddr), ex); } try { switch ((OpCode)current.opcode) { case OpCode.ADD: RegisterA += memval; break; case OpCode.SUB: RegisterA -= memval; break; case OpCode.MUL: RegisterA *= memval; break; case OpCode.DIV: RegisterA /= memval; break; case OpCode.COMP: Comp(RegisterA, memval); break; case OpCode.J: ProgramCounter = calcaddr; break; case OpCode.JLT: if (StatusWord == -1) ProgramCounter = calcaddr; break; case OpCode.JGT: if (StatusWord == 1) ProgramCounter = calcaddr; break; case OpCode.JEQ: if (StatusWord == 0) ProgramCounter = calcaddr; break; case OpCode.STA: StoreInt(calcaddr, RegisterA); break; case OpCode.STB: StoreInt(calcaddr, RegisterB); break; case OpCode.STL: StoreInt(calcaddr, RegisterL); break; case OpCode.STS: StoreInt(calcaddr, RegisterS); break; case OpCode.STT: StoreInt(calcaddr, RegisterT); break; case OpCode.STX: StoreInt(calcaddr, RegisterX); break; case OpCode.LDB: RegisterB = memval; break; case OpCode.LDX: RegisterX = memval; break; case OpCode.LDA: RegisterA = memval; break; case OpCode.LDL: RegisterL = memval; break; case OpCode.LDS: RegisterS = memval; break; case OpCode.LDT: RegisterT = memval; break; case OpCode.TIX: RegisterX++; Comp(RegisterX, memval); break; case OpCode.JSUB: RegisterL = ProgramCounter; ProgramCounter = calcaddr; break; case OpCode.RSUB: ProgramCounter = RegisterL; break; case OpCode.LDCH: byte[] regA = BitConverter.GetBytes(RegisterA); byte[] memChar = BitConverter.GetBytes(memval); byte[] newVal = { memChar[2], regA[1], regA[2], regA[3] }; RegisterA = BitConverter.ToInt32(newVal, 0); break; case OpCode.STCH: byte[] regiA = BitConverter.GetBytes(RegisterA); memory[calcaddr] = regiA[0]; MemoryChangedHook(calcaddr, 1); break; case OpCode.RD: case OpCode.TD: case OpCode.WD: devicewrite = true; if (!DoDevice(current.opcode, memval)) { ProgramCounter -= 3; return false; } break; case OpCode.AND: RegisterA = RegisterA & memval; break; case OpCode.OR: RegisterA = RegisterA | memval; break; default: int location = ProgramCounter; if (current.extended) location -= 4; else location -= 3; throw new ArgumentException(string.Format("Error: Instruction at 0x{0} not a recognized opcode.", !current.extended ? location.ToString("X3") : location.ToString("X4"))); } } catch (IndexOutOfRangeException ex) { throw new IndexOutOfRangeException(string.Format("Error: Instruction at 0x{0:X3} references memory that's out of range (0x{1:X3}).", ProgramCounter - 3, calcaddr), ex); } lastInstruction = current; instEvent = new SICEvent(lastInstruction, ProgramCounter); PostInstructionHook(instEvent); if (!instEvent.Continue) return false; return true; }
public void IncrementPC(Instruction current) { if (current.twobyte) ProgramCounter += 2; else if (current.extended) ProgramCounter += 4; else ProgramCounter += 3; }
public int GetData(Instruction current) { int address = GetAddress(current); int memval; if (current.immediate && !current.indirect) { if (!current.pcrel) { // Immediate mode combined with an addressing mode gets you the address as data. See Beck, p61 memval = current.address; if (current.extended) { if ((memval & 0x80000) > 0) memval = unchecked((int)((memval & 0xFFFFF) + 0xFFF00000)); } else { if ((memval & 0x800) > 0) memval = unchecked((int)((memval & 0xFFF) + 0xFFFFF000)); } } else if (current.baserel) memval = RegisterB + current.address; else memval = ProgramCounter + current.address; } else { memval = GetMemoryValue(address); } return memval; }
public int GetAddress(Instruction current) { int calcaddr; if (current.baserel) calcaddr = RegisterB + current.address; else if (current.extended) calcaddr = current.address; else calcaddr = ProgramCounter + current.address; if (!current.immediate && current.indirect) { calcaddr = GetMemoryValue(calcaddr); } if (current.indexed) { calcaddr += RegisterX; } return calcaddr; }
public void DoTwoBye(Instruction current) { Register r1 = current.r1; Register r2 = current.r2; switch (current.opcode) { case OpCode.ADDR: SetRegisterValue(r2, (GetRegisterValue(r2) + GetRegisterValue(r1))); break; case OpCode.CLEAR: SetRegisterValue(r1, 0); break; case OpCode.COMPR: Comp(GetRegisterValue(r1), GetRegisterValue(r2)); break; case OpCode.DIVR: SetRegisterValue(r2, (GetRegisterValue(r2) / GetRegisterValue(r1))); break; case OpCode.MULR: SetRegisterValue(r2, (GetRegisterValue(r2) * GetRegisterValue(r1))); break; case OpCode.RMO: SetRegisterValue(r2, GetRegisterValue(r1)); break; case OpCode.SUBR: SetRegisterValue(r2, (GetRegisterValue(r2) - GetRegisterValue(r1))); break; case OpCode.TIXR: RegisterX++; Comp(RegisterX, GetRegisterValue(r1)); break; case OpCode.SHIFTL: uint lshift = (uint)GetRegisterValue(r1); for (int i = 0; i < ((int)r2) + 1; i++) { lshift = lshift << 1; if ((lshift & 0x01000000) > 0) lshift = (lshift | 0x01); lshift = lshift & 0x00FFFFFF; } SetRegisterValue(r1, (int)lshift); break; case OpCode.SHIFTR: uint rshift = (uint)GetRegisterValue(r1); for (int i = 0; i < ((int)r2) + 1; i++) { bool ones = (rshift & 0x1) > 0; rshift = rshift >> 1; if (ones) rshift = (rshift | 0x800000); } SetRegisterValue(r1, (int)rshift); break; } }