From d7e353f3d9fc4ccfe39ebef79529e1bc3b6ec940 Mon Sep 17 00:00:00 2001 From: Mike Naberezny Date: Sat, 21 Nov 2009 16:17:26 -0800 Subject: [PATCH] Applied patch by Ed Spittles that fixes the behavior of the BREAK and UNUSED flags in the processor status register. Closes #16. --- CHANGES.txt | 7 ++++ src/py65/devices/mpu6502.py | 12 +++---- src/py65/tests/devices/test_mpu6502.py | 48 ++++++++++++++++---------- 3 files changed, 42 insertions(+), 25 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 1156055..56a53af 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,6 +4,13 @@ - We no longer bundle ez_setup to bootstrap setuptools installation. + - Restoring the processor status register from interrupt now correctly + set the BREAK and UNUSED flags to be high. Thanks to Ed Spittles + for reporting this. + + - The BREAK and UNUSED bits in the processor status register are + now always high. Patch by Ed Spittles. + 0.7 (2009-09-03) - When using the monitor, the nonblocking character input at diff --git a/src/py65/devices/mpu6502.py b/src/py65/devices/mpu6502.py index 566e8a8..ab613e1 100644 --- a/src/py65/devices/mpu6502.py +++ b/src/py65/devices/mpu6502.py @@ -11,7 +11,7 @@ class MPU: NEGATIVE = 128 OVERFLOW = 64 UNUSED = 32 - BREAK = 16 + BREAK = 16 # there is no BREAK flag, but this position indicates BREAK DECIMAL = 8 INTERRUPT = 4 ZERO = 2 @@ -62,7 +62,7 @@ class MPU: self.a = 0 self.x = 0 self.y = 0 - self.p = 0 + self.p = self.p = self.BREAK | self.UNUSED self.processorCycles = 0 # Helpers for addressing modes @@ -465,7 +465,7 @@ class MPU: self.stPushWord(pc) self.p |= self.BREAK - self.stPush(self.p) + self.stPush(self.p | self.BREAK | self.UNUSED) self.p |= self.INTERRUPT self.pc = self.WordAt(self.IrqTo) @@ -487,7 +487,7 @@ class MPU: @instruction(name="PHP", mode="imp", cycles=3) def inst_0x08(self): - self.stPush(self.p) + self.stPush(self.p | self.BREAK | self.UNUSED) @instruction(name="ORA", mode="imm", cycles=2) def inst_0x09(self): @@ -573,7 +573,7 @@ class MPU: @instruction(name="PLP", mode="imp", cycles=4) def inst_0x28(self): - self.p = self.stPop() + self.p = (self.stPop() | self.BREAK | self.UNUSED) @instruction(name="AND", mode="imm", cycles=2) def inst_0x29(self): @@ -639,7 +639,7 @@ class MPU: @instruction(name="RTI", mode="imp", cycles=6) def inst_0x40(self): - self.p = self.stPop() + self.p = (self.stPop() | self.BREAK | self.UNUSED) self.pc = self.stPopWord() @instruction(name="EOR", mode="inx", cycles=6) diff --git a/src/py65/tests/devices/test_mpu6502.py b/src/py65/tests/devices/test_mpu6502.py index f9c0abf..5dc5958 100644 --- a/src/py65/tests/devices/test_mpu6502.py +++ b/src/py65/tests/devices/test_mpu6502.py @@ -15,7 +15,7 @@ class Common6502Tests: self.assertEquals(0, mpu.a) self.assertEquals(0, mpu.x) self.assertEquals(0, mpu.y) - self.assertEquals(0, mpu.p) + self.assertEquals(mpu.BREAK | mpu.UNUSED, mpu.p) # ADC Absolute @@ -1676,19 +1676,19 @@ class Common6502Tests: def test_brk_pushes_pc_plus_2_and_status_then_sets_pc_to_irq_vector(self): mpu = self._make_mpu() - mpu.p = 0x00 + mpu.p = mpu.BREAK | mpu.UNUSED self._write(mpu.memory, 0xFFFE, (0xCD, 0xAB)) mpu.memory[0xC000] = 0x00 #=> BRK mpu.pc = 0xC000 mpu.step() self.assertEquals(0xABCD, mpu.pc) - self.assertEquals(0xC0, mpu.memory[0x1FF]) # PCH - self.assertEquals(0x02, mpu.memory[0x1FE]) # PCL - self.assertEquals(mpu.BREAK, mpu.memory[0x1FD]) # Status (P) - self.assertEquals(0xFC, mpu.sp) + self.assertEquals(0xC0, mpu.memory[0x1FF]) # PCH + self.assertEquals(0x02, mpu.memory[0x1FE]) # PCL + self.assertEquals(mpu.BREAK | mpu.UNUSED, mpu.memory[0x1FD]) # Status (P) + self.assertEquals(0xFC, mpu.sp) - self.assertEquals(mpu.BREAK | mpu.INTERRUPT, mpu.p) + self.assertEquals(mpu.BREAK | mpu.UNUSED | mpu.INTERRUPT, mpu.p) # BVC @@ -3281,14 +3281,14 @@ class Common6502Tests: # PHP def test_php_pushes_processor_status_and_updates_sp(self): - mpu = self._make_mpu() - flags = (mpu.NEGATIVE | mpu.OVERFLOW | mpu.DECIMAL | mpu.ZERO | mpu.CARRY) - mpu.p = flags - mpu.memory[0x0000] = 0x08 #=> PHP - mpu.step() - self.assertEquals(0x0001, mpu.pc) - self.assertEquals(flags, mpu.memory[0x1FF]) - self.assertEquals(0xFE, mpu.sp) + for flags in range(0x100): + mpu = self._make_mpu() + mpu.p = flags | mpu.BREAK | mpu.UNUSED + mpu.memory[0x0000] = 0x08 #=> PHP + mpu.step() + self.assertEquals(0x0001, mpu.pc) + self.assertEquals((flags | mpu.BREAK | mpu.UNUSED), mpu.memory[0x1FF]) + self.assertEquals(0xFE, mpu.sp) # PLA @@ -3307,11 +3307,11 @@ class Common6502Tests: def test_plp_pulls_top_byte_from_stack_into_flags_and_updates_sp(self): mpu = self._make_mpu() mpu.memory[0x0000] = 0x28 #=> PLP - mpu.memory[0x01FF] = 0xAB + mpu.memory[0x01FF] = 0xBA # must have BREAK and UNUSED set mpu.sp = 0xFE mpu.step() self.assertEquals(0x0001, mpu.pc) - self.assertEquals(0xAB, mpu.p) + self.assertEquals(0xBA, mpu.p) self.assertEquals(0xFF, mpu.sp) # ROL Accumulator @@ -3896,14 +3896,24 @@ class Common6502Tests: def test_rti_restores_status_register_and_program_counter_and_updates_sp(self): mpu = self._make_mpu() mpu.memory[0x0000] = 0x40 #=> RTI - self._write(mpu.memory, 0x01FD, (0xAB, 0x03, 0xC0)) # Status (P), PCL, PCH + self._write(mpu.memory, 0x01FD, (0xFC, 0x03, 0xC0)) # Status (P), PCL, PCH mpu.sp = 0xFC mpu.step() self.assertEquals(0xC003, mpu.pc) - self.assertEquals(0xAB, mpu.p) + self.assertEquals(0xFC, mpu.p) self.assertEquals(0xFF, mpu.sp) + def test_rti_forces_break_and_unused_flags_high(self): + mpu = self._make_mpu() + mpu.memory[0x0000] = 0x40 #=> RTI + self._write(mpu.memory, 0x01FD, (0x00, 0x03, 0xC0)) # Status (P), PCL, PCH + mpu.sp = 0xFC + + mpu.step() + self.assertEquals(mpu.BREAK, mpu.p & mpu.BREAK) + self.assertEquals(mpu.UNUSED, mpu.p & mpu.UNUSED) + # RTS def test_rts_restores_program_counter_and_increments_then_updates_sp(self):