diff --git a/CHANGES.txt b/CHANGES.txt index 20f1f96..b442cf4 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,6 +4,9 @@ the program counter to overflow to $10000. It now wraps around to $0000 as it should. Thanks to Gábor Lénárt for reporting it. + - Fixed BRK on 65C02 so it clears the decimal flag. On NMOS 6502, the + decimal flag is unaffected on BRK. On 65C02, it is always cleared. + 0.17 (2013-10-26) - Added support for Python 3.2 and 3.3 based on work by David Beazley. diff --git a/py65/devices/mpu65c02.py b/py65/devices/mpu65c02.py index a77aaa7..ee0b000 100644 --- a/py65/devices/mpu65c02.py +++ b/py65/devices/mpu65c02.py @@ -68,6 +68,21 @@ class MPU(mpu6502.MPU): # instructions + @instruction(name="BRK", mode="imp", cycles=7) + def inst_0x00(self): + # pc has already been increased one + pc = (self.pc + 1) & self.addrMask + self.stPushWord(pc) + + self.p |= self.BREAK + self.stPush(self.p | self.BREAK | self.UNUSED) + + self.p |= self.INTERRUPT + self.pc = self.WordAt(self.IrqTo) + + # 65C02 clears decimal flag, NMOS 6502 does not + self.p &= ~self.DECIMAL + @instruction(name="RMB0", mode="zpg", cycles=5) def inst_0x07(self): self.opRMB(self.ZeroPageAddr, 0xFE) diff --git a/py65/tests/devices/test_mpu6502.py b/py65/tests/devices/test_mpu6502.py index e740957..1f77227 100644 --- a/py65/tests/devices/test_mpu6502.py +++ b/py65/tests/devices/test_mpu6502.py @@ -1919,7 +1919,7 @@ class Common6502Tests: def test_brk_pushes_pc_plus_2_and_status_then_sets_pc_to_irq_vector(self): mpu = self._make_mpu() - mpu.p = mpu.BREAK | mpu.UNUSED + mpu.p = mpu.UNUSED self._write(mpu.memory, 0xFFFE, (0xCD, 0xAB)) # $C000 BRK mpu.memory[0xC000] = 0x00 @@ -5661,6 +5661,28 @@ class MPUTests(unittest.TestCase, Common6502Tests): mpu = self._make_mpu() self.assertTrue("6502" in repr(mpu)) + # BRK + + def test_brk_preserves_decimal_flag_when_it_is_set(self): + mpu = self._make_mpu() + mpu.p = mpu.DECIMAL + # $C000 BRK + mpu.memory[0xC000] = 0x00 + mpu.pc = 0xC000 + mpu.step() + self.assertEqual(mpu.BREAK, mpu.p & mpu.BREAK) + self.assertEqual(mpu.DECIMAL, mpu.p & mpu.DECIMAL) + + def test_brk_preserves_decimal_flag_when_it_is_clear(self): + mpu = self._make_mpu() + mpu.p = 0 + # $C000 BRK + mpu.memory[0xC000] = 0x00 + mpu.pc = 0xC000 + mpu.step() + self.assertEqual(mpu.BREAK, mpu.p & mpu.BREAK) + self.assertEqual(0, mpu.p & mpu.DECIMAL) + def _get_target_class(self): return py65.devices.mpu6502.MPU diff --git a/py65/tests/devices/test_mpu65c02.py b/py65/tests/devices/test_mpu65c02.py index 851d3b7..7133801 100644 --- a/py65/tests/devices/test_mpu65c02.py +++ b/py65/tests/devices/test_mpu65c02.py @@ -430,6 +430,18 @@ class MPUTests(unittest.TestCase, Common6502Tests): self.assertEqual(0x01, mpu.a) self.assertEqual(0x00, mpu.memory[0x0010 + mpu.x]) + # BRK + + def test_brk_clears_decimal_flag(self): + mpu = self._make_mpu() + mpu.p = mpu.DECIMAL + # $C000 BRK + mpu.memory[0xC000] = 0x00 + mpu.pc = 0xC000 + mpu.step() + self.assertEqual(mpu.BREAK, mpu.p & mpu.BREAK) + self.assertEqual(0, mpu.p & mpu.DECIMAL) + # EOR Zero Page, Indirect def test_eor_zp_ind_flips_bits_over_setting_z_flag(self):