diff options
| -rw-r--r-- | cpu/cpu.go | 12 | ||||
| -rw-r--r-- | cpu/instructions.go | 5 | ||||
| -rw-r--r-- | cpu/opcodes.go | 13 | ||||
| -rw-r--r-- | tests/cpu_test.go | 36 |
4 files changed, 65 insertions, 1 deletions
@@ -16,6 +16,7 @@ type CPU struct { Bus Bus Cycles uint64 + Jammed bool extraCycles int } @@ -65,9 +66,13 @@ func (c *CPU) Reset() { c.Status = FlagU | FlagI c.PC = c.read16(vectorReset) c.Cycles = 7 + c.Jammed = false } func (c *CPU) IRQ() { + if c.Jammed { + return + } if c.flag(FlagI) { return } @@ -76,6 +81,9 @@ func (c *CPU) IRQ() { } func (c *CPU) NMI() { + if c.Jammed { + return + } c.interrupt(vectorNMI, false) c.Cycles += 7 } @@ -94,6 +102,10 @@ func (c *CPU) interrupt(vector uint16, brk bool) { } func (c *CPU) Step() int { + if c.Jammed { + c.Cycles++ + return 1 + } before := c.Cycles opcode := c.read(c.PC) diff --git a/cpu/instructions.go b/cpu/instructions.go index b390f5c..b74a2db 100644 --- a/cpu/instructions.go +++ b/cpu/instructions.go @@ -221,3 +221,8 @@ func iscExec(c *CPU, op operand) { c.writeOperand(op, v) c.addWithCarry(^v) } + +func jamExec(c *CPU, op operand) { + c.Jammed = true + c.PC-- +} diff --git a/cpu/opcodes.go b/cpu/opcodes.go index 00b1563..13f9612 100644 --- a/cpu/opcodes.go +++ b/cpu/opcodes.go @@ -235,6 +235,19 @@ func init() { def(0xDC, "NOP", ModeAbsoluteX, 4, true, nopExec) def(0xFC, "NOP", ModeAbsoluteX, 4, true, nopExec) + def(0x02, "JAM", ModeImplied, 2, false, jamExec) + def(0x12, "JAM", ModeImplied, 2, false, jamExec) + def(0x22, "JAM", ModeImplied, 2, false, jamExec) + def(0x32, "JAM", ModeImplied, 2, false, jamExec) + def(0x42, "JAM", ModeImplied, 2, false, jamExec) + def(0x52, "JAM", ModeImplied, 2, false, jamExec) + def(0x62, "JAM", ModeImplied, 2, false, jamExec) + def(0x72, "JAM", ModeImplied, 2, false, jamExec) + def(0x92, "JAM", ModeImplied, 2, false, jamExec) + def(0xB2, "JAM", ModeImplied, 2, false, jamExec) + def(0xD2, "JAM", ModeImplied, 2, false, jamExec) + def(0xF2, "JAM", ModeImplied, 2, false, jamExec) + def(0xEB, "SBC", ModeImmediate, 2, false, sbcExec) def(0xA7, "LAX", ModeZeroPage, 3, false, laxExec) diff --git a/tests/cpu_test.go b/tests/cpu_test.go index 87743b1..269f9ee 100644 --- a/tests/cpu_test.go +++ b/tests/cpu_test.go @@ -232,6 +232,40 @@ func TestUnimplementedOpcodePanics(t *testing.T) { t.Fatalf("expected panic for illegal opcode") } }() - c, _ := newTestCPU([]uint8{0x02}) + c, _ := newTestCPU([]uint8{0x8B}) c.Step() } + +func TestJamStopsCPU(t *testing.T) { + c, _ := newTestCPU([]uint8{0xA9, 0x42, 0x02, 0xEA}) + c.Step() + c.Step() + if !c.Jammed { + t.Fatal("Jammed = false, want true") + } + if c.PC != 0x8002 { + t.Fatalf("PC = 0x%04X, want 0x8002", c.PC) + } + for i := 0; i < 3; i++ { + if cycles := c.Step(); cycles != 1 { + t.Fatalf("cycles = %d, want 1", cycles) + } + } + if c.PC != 0x8002 || c.A != 0x42 { + t.Fatalf("PC = 0x%04X, A = 0x%02X; want 0x8002, 0x42", c.PC, c.A) + } +} + +func TestJammedIgnoresInterruptsUntilReset(t *testing.T) { + c, bus := newTestCPU([]uint8{0x02}) + bus.mem[0xFFFA], bus.mem[0xFFFB] = 0x00, 0x90 + c.Step() + c.NMI() + if c.PC != 0x8000 { + t.Fatalf("PC after NMI = 0x%04X, want 0x8000", c.PC) + } + c.Reset() + if c.Jammed { + t.Fatal("Jammed = true after Reset, want false") + } +} |