static void CPU_InvalidInstruction(object sender, InvalidInstructionEventArgs e) { Console.Write("Invalid instruction executed: 0x" + e.Instruction.ToString("X4") + " at 0x" + e.Address.ToString("X4") + "\n>"); e.ContinueExecution = false; CPU.IsRunning = false; }
private void CpuOnInvalidInstruction(object sender, InvalidInstructionEventArgs invalidInstructionEventArgs) { InvalidInstruction(invalidInstructionEventArgs); if (breakOnInvalidInstructionToolStripMenuItem.Checked) { invalidInstructionEventArgs.ContinueExecution = false; CPU.IsRunning = false; } }
void InvalidInstruction(InvalidInstructionEventArgs eventArgs) { if (InvokeRequired) Invoke(new InvalidInstructionDelegate(InvalidInstruction), eventArgs); else { pictureBox1.Visible = true; invalidInstructionLabel.Text = "Invalid instruction at 0x" + eventArgs.Address.ToString("X4") + ": 0x" + eventArgs.Instruction.ToString("X4"); invalidInstructionLabel.Visible = true; if (breakOnInvalidInstructionToolStripMenuItem.Checked) ResetLayout(); } }
public void Execute(int CyclesToExecute) { if (!IsRunning && CyclesToExecute != -1) return; int oldCycles = Cycles; if (CyclesToExecute == -1) Cycles = 1; else Cycles += CyclesToExecute; while (Cycles > 0) { if (IsOnFire) Memory[Random.Next(0xFFFF)] = (ushort)Random.Next(0xFFFF); if (!InterruptQueueEnabled && InterruptQueue.Count > 0 && IA != 0) { Memory[--SP] = PC; Memory[--SP] = A; PC = IA; A = InterruptQueue.Dequeue(); InterruptQueueEnabled = true; } if (BreakpointHit != null) { foreach (var breakpoint in Breakpoints) { if (breakpoint.Address == PC) { if (breakpointHandled || (CyclesToExecute == -1)) { breakpointHandled = false; } else { var bea = new BreakpointEventArgs(breakpoint); BreakpointHit(this, bea); if (!bea.ContinueExecution) { breakpointHandled = true; return; } } break; } } } ushort PCBeforeExecution = PC; ushort instruction = Memory[PC++]; byte opcode = (byte)(instruction & 0x1F); byte valueB = (byte)((instruction & 0x3E0) >> 5); byte valueA = (byte)((instruction & 0xFC00) >> 10); ushort opA = 0, opB = 0; opA = Get(valueA); if (opcode != 0) { ushort pc_old = PC, sp_old = SP; opB = Get(valueB); PC = pc_old; SP = sp_old; } short opB_s = (short)opB; short opA_s = (short)opA; Cycles--; unchecked { switch (opcode) { case 0x00: // (nonbasic) switch (valueB) { case 0x01: // JSR a Cycles -= 2; Memory[--SP] = PC; PC = opA; break; case 0x08: // INT a Cycles -= 3; FireInterrupt(opA); break; case 0x09: // IAG a Set(valueA, IA); break; case 0x0A: // IAS a IA = opA; break; case 0x0B: // RFI a A = Memory[SP++]; PC = Memory[SP++]; InterruptQueueEnabled = false; break; case 0x0C: // IAQ a Cycles--; InterruptQueueEnabled = opA != 0; break; case 0x10: // HWN a Cycles--; Set(valueA, (ushort)Devices.Count); break; case 0x11: // HWQ a Cycles -= 3; if (opA < Devices.Count) { Device d = Devices[opA]; A = (ushort)(d.DeviceID & 0xFFFF); B = (ushort)((d.DeviceID & 0xFFFF0000) >> 16); C = d.Version; X = (ushort)(d.ManufacturerID & 0xFFFF); Y = (ushort)((d.ManufacturerID & 0xFFFF0000) >> 16); } break; case 0x12: // HWI a Cycles -= 3; if (opA < Devices.Count) Cycles -= Devices[opA].DoInterrupt(); break; default: if (InvalidInstruction != null) { var eventArgs = new InvalidInstructionEventArgs(instruction, PCBeforeExecution); PC = PCBeforeExecution; InvalidInstruction(this, eventArgs); if (!eventArgs.ContinueExecution) return; } break; } break; case 0x01: // SET b, a Set(valueB, opA); break; case 0x02: // ADD b, a Cycles--; if (opB + opA > 0xFFFF) EX = 0x0001; else EX = 0; Set(valueB, (ushort)(opB + opA)); break; case 0x03: // SUB b, a Cycles--; if (opB - opA < 0) EX = 0xFFFF; else EX = 0; Set(valueB, (ushort)(opB - opA)); break; case 0x04: // MUL b, a Cycles--; EX = (ushort)(((opB * opA) >> 16) & 0xffff); Set(valueB, (ushort)(opB * opA)); break; case 0x05: // MLI b, a Cycles--; EX = (ushort)(((opB_s * opA_s) >> 16) & 0xffff); Set(valueB, (ushort)(opB_s * opA_s)); break; case 0x06: // DIV b, a Cycles -= 2; if (opA == 0) { EX = 0; Set(valueB, 0); } else { EX = (ushort)(((opB << 16) / opA) & 0xffff); Set(valueB, (ushort)(opB / opA)); } break; case 0x07: // DVI b, a Cycles -= 2; if (opA_s == 0) { EX = 0; Set(valueB, 0); } else { EX = (ushort)(((opB_s << 16) / opA_s) & 0xffff); Set(valueB, (ushort)(opB_s / opA_s)); } break; case 0x08: // MOD b, a Cycles -= 2; if (opA == 0) Set(valueB, 0); else Set(valueB, (ushort)(opB % opA)); break; case 0x09: // MDI b, a Cycles -= 2; if (opA_s == 0) Set(valueB, 0); else Set(valueB, (ushort)(opB_s % opA_s)); break; case 0x0A: // AND b, a Set(valueB, (ushort)(opB & opA)); break; case 0x0B: // BOR b, a Set(valueB, (ushort)(opB | opA)); break; case 0x0C: // XOR b, a Set(valueB, (ushort)(opB ^ opA)); break; case 0x0D: // SHR b, a EX = (ushort)(((opB << 16) >> opA) & 0xffff); Set(valueB, (ushort)(opB >> opA)); break; case 0x0E: // ASR b, a EX = (ushort)(((opB_s << 16) >> opA) & 0xffff); Set(valueB, (ushort)(opB_s >> opA)); break; case 0x0F: // SHL b, a EX = (ushort)(((opB << opA) >> 16) & 0xffff); Set(valueB, (ushort)(opB << opA)); break; case 0x10: // IFB b, a Cycles -= 2; Get(valueB); if (!((ushort)(opB & opA) != 0)) SkipIfChain(); break; case 0x11: // IFC b, a Cycles -= 2; Get(valueB); if (!((ushort)(opB & opA) == 0)) SkipIfChain(); break; case 0x12: // IFE b, a Cycles -= 2; Get(valueB); if (!(opB == opA)) SkipIfChain(); break; case 0x13: // IFN b, a Cycles -= 2; Get(valueB); if (!(opB != opA)) SkipIfChain(); break; case 0x14: // IFG b, a Cycles -= 2; Get(valueB); if (!(opB > opA)) SkipIfChain(); break; case 0x15: // IFA b, a Cycles -= 2; Get(valueB); if (!(opB_s > opA_s)) SkipIfChain(); break; case 0x16: // IFL b, a Cycles -= 2; Get(valueB); if (!(opB < opA)) SkipIfChain(); break; case 0x17: // IFU b, a Cycles -= 2; Get(valueB); if (!(opB_s < opA_s)) SkipIfChain(); break; case 0x1A: // ADX b, a Cycles -= 2; uint resADX = (uint)(opB + opA + (short)EX); EX = (ushort)((resADX >> 16) & 0xFFFF); Set(valueB, (ushort)resADX); break; case 0x1B: // SBX b, a Cycles -= 2; uint resSBX = (uint)(opB - opA + (short)EX); EX = (ushort)((resSBX >> 16) & 0xFFFF); Set(valueB, (ushort)resSBX); break; case 0x1E: // STI b, a Cycles--; Set(valueB, opA); I++; J++; break; case 0x1F: // STD b, a Cycles--; Set(valueB, opA); I--; J--; break; default: // According to spec, should take zero cycles // For sanity, all NOPs take one cycle if (InvalidInstruction != null) { var eventArgs = new InvalidInstructionEventArgs(instruction, PCBeforeExecution); PC = PCBeforeExecution; InvalidInstruction(this, eventArgs); if (!eventArgs.ContinueExecution) return; } break; } } if (!IsRunning && CyclesToExecute != -1) return; } if (CyclesToExecute == -1) { TotalCycles += -(Cycles - 1); Cycles = oldCycles; } else TotalCycles += CyclesToExecute; }