mirror of
https://github.com/mnaberez/py65.git
synced 2025-01-16 18:33:00 +00:00
Remove page wrap bug from indexed indirect (X) on 65C02
This commit is contained in:
parent
ec311c879e
commit
3c6c631945
@ -26,11 +26,14 @@ class MPU(mpu6502.MPU):
|
||||
|
||||
# addressing modes
|
||||
|
||||
def IndirectXAddr(self):
|
||||
return self.WordAt(self.ByteAt(self.pc) + self.x)
|
||||
|
||||
def ZeroPageIndirectAddr(self):
|
||||
return self.WordAt(255 & (self.ByteAt(self.pc)))
|
||||
return self.WordAt(self.ByteAt(self.pc))
|
||||
|
||||
def IndirectAbsXAddr(self):
|
||||
return (self.WordAt(self.pc) + self.x) & self.addrMask
|
||||
return self.addrMask & (self.WordAt(self.pc) + self.x)
|
||||
|
||||
def AccumulatorAddr(self):
|
||||
return self.a
|
||||
|
@ -5636,17 +5636,38 @@ class MPUTests(unittest.TestCase, Common6502Tests):
|
||||
mpu = self._make_mpu()
|
||||
self.assertTrue("6502" in repr(mpu))
|
||||
|
||||
# LDA Zero Page, X-Indexed
|
||||
# ADC Indirect, Indexed (X)
|
||||
|
||||
def test_lda_zp_x_indexed_page_wraps(self):
|
||||
def test_adc_ind_indexed_has_page_wrap_bug(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.a = 0x00
|
||||
mpu.a = 0x01
|
||||
mpu.x = 0xFF
|
||||
# $0000 LDA $80,X
|
||||
self._write(mpu.memory, 0x0000, (0xB5, 0x80))
|
||||
mpu.memory[0x007F] = 0x42
|
||||
# $0000 ADC ($80,X)
|
||||
# $007f Vector to $BBBB (read if page wrapped)
|
||||
# $017f Vector to $ABCD (read if no page wrap)
|
||||
self._write(mpu.memory, 0x0000, (0x61, 0x80))
|
||||
self._write(mpu.memory, 0x007f, (0xBB, 0xBB))
|
||||
self._write(mpu.memory, 0x017f, (0xCD, 0xAB))
|
||||
mpu.memory[0xABCD] = 0x01
|
||||
mpu.memory[0xBBBB] = 0x02
|
||||
mpu.step()
|
||||
self.assertEqual(0x03, mpu.a)
|
||||
|
||||
# AND Indirect, Indexed (X)
|
||||
|
||||
def test_and_ind_indexed_x_has_page_wrap_bug(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.a = 0x42
|
||||
mpu.x = 0xFF
|
||||
# $0000 AND ($80,X)
|
||||
# $007f Vector to $BBBB (read if page wrapped)
|
||||
# $017f Vector to $ABCD (read if no page wrap)
|
||||
self._write(mpu.memory, 0x0000, (0x21, 0x80))
|
||||
self._write(mpu.memory, 0x007f, (0xBB, 0xBB))
|
||||
self._write(mpu.memory, 0x017f, (0xCD, 0xAB))
|
||||
mpu.memory[0xABCD] = 0
|
||||
mpu.memory[0xBBBB] = 0xFF
|
||||
mpu.step()
|
||||
self.assertEqual(0x0002, mpu.pc)
|
||||
self.assertEqual(0x42, mpu.a)
|
||||
|
||||
# BRK
|
||||
@ -5671,9 +5692,75 @@ class MPUTests(unittest.TestCase, Common6502Tests):
|
||||
self.assertEqual(mpu.BREAK, mpu.p & mpu.BREAK)
|
||||
self.assertEqual(0, mpu.p & mpu.DECIMAL)
|
||||
|
||||
# CMP Indirect, Indexed (X)
|
||||
|
||||
def test_cmp_ind_x_has_page_wrap_bug(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.p = 0
|
||||
mpu.a = 0x42
|
||||
mpu.x = 0xFF
|
||||
# $0000 CMP ($80,X)
|
||||
# $007f Vector to $BBBB (read if page wrapped)
|
||||
# $017f Vector to $ABCD (read if no page wrap)
|
||||
self._write(mpu.memory, 0x0000, (0xC1, 0x80))
|
||||
self._write(mpu.memory, 0x007f, (0xBB, 0xBB))
|
||||
self._write(mpu.memory, 0x017f, (0xCD, 0xAB))
|
||||
mpu.memory[0xABCD] = 0x00
|
||||
mpu.memory[0xBBBB] = 0x42
|
||||
mpu.step()
|
||||
self.assertEqual(mpu.ZERO, mpu.p & mpu.ZERO)
|
||||
|
||||
# EOR Indirect, Indexed (X)
|
||||
|
||||
def test_eor_ind_x_has_page_wrap_bug(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.p = 0
|
||||
mpu.a = 0xAA
|
||||
mpu.x = 0xFF
|
||||
# $0000 EOR ($80,X)
|
||||
# $007f Vector to $BBBB (read if page wrapped)
|
||||
# $017f Vector to $ABCD (read if no page wrap)
|
||||
self._write(mpu.memory, 0x0000, (0x41, 0x80))
|
||||
self._write(mpu.memory, 0x007f, (0xBB, 0xBB))
|
||||
self._write(mpu.memory, 0x017f, (0xCD, 0xAB))
|
||||
mpu.memory[0xABCD] = 0x00
|
||||
mpu.memory[0xBBBB] = 0xFF
|
||||
mpu.step()
|
||||
self.assertEqual(0x55, mpu.a)
|
||||
|
||||
# LDA Indirect, Indexed (X)
|
||||
|
||||
def test_lda_ind_indexed_x_has_page_wrap_bug(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.a = 0x00
|
||||
mpu.x = 0xff
|
||||
# $0000 LDA ($80,X)
|
||||
# $007f Vector to $BBBB (read if page wrapped)
|
||||
# $017f Vector to $ABCD (read if no page wrap)
|
||||
self._write(mpu.memory, 0x0000, (0xA1, 0x80))
|
||||
self._write(mpu.memory, 0x007f, (0xBB, 0xBB))
|
||||
self._write(mpu.memory, 0x017f, (0xCD, 0xAB))
|
||||
mpu.memory[0xABCD] = 0x42
|
||||
mpu.memory[0xBBBB] = 0xEF
|
||||
mpu.step()
|
||||
self.assertEqual(0xEF, mpu.a)
|
||||
|
||||
# LDA Zero Page, X-Indexed
|
||||
|
||||
def test_lda_zp_x_has_page_wrap_bug(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.a = 0x00
|
||||
mpu.x = 0xFF
|
||||
# $0000 LDA $80,X
|
||||
self._write(mpu.memory, 0x0000, (0xB5, 0x80))
|
||||
mpu.memory[0x007F] = 0x42
|
||||
mpu.step()
|
||||
self.assertEqual(0x0002, mpu.pc)
|
||||
self.assertEqual(0x42, mpu.a)
|
||||
|
||||
# JMP Indirect
|
||||
|
||||
def test_jmp_jumps_to_address_with_page_wrap_bug(self):
|
||||
def test_jmp_indirect_has_page_wrap_bug(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.memory[0x00ff] = 0
|
||||
# $0000 JMP ($00)
|
||||
@ -5682,6 +5769,59 @@ class MPUTests(unittest.TestCase, Common6502Tests):
|
||||
self.assertEqual(0x6c00, mpu.pc)
|
||||
self.assertEqual(5, mpu.processorCycles)
|
||||
|
||||
# ORA Indirect, Indexed (X)
|
||||
|
||||
def test_ora_ind_indexed_x_has_page_wrap_bug(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.a = 0
|
||||
mpu.x = 0xFF
|
||||
# $0000 ORA ($80,X)
|
||||
# $007f Vector to $BBBB (read if page wrapped)
|
||||
# $017f Vector to $ABCD (read if no page wrap)
|
||||
self._write(mpu.memory, 0x0000, (0x01, 0x80))
|
||||
self._write(mpu.memory, 0x007f, (0xBB, 0xBB))
|
||||
self._write(mpu.memory, 0x017f, (0xCD, 0xAB))
|
||||
mpu.memory[0xABCD] = 0
|
||||
mpu.memory[0xBBBB] = 0x42
|
||||
mpu.step()
|
||||
self.assertEqual(0x42, mpu.a)
|
||||
|
||||
# SBC Indirect, Indexed (X)
|
||||
|
||||
def test_sbc_ind_x_has_page_wrap_bug(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.p = mpu.CARRY
|
||||
mpu.a = 0x03
|
||||
mpu.x = 0xFF
|
||||
# $0000 SBC ($80,X)
|
||||
# $007f Vector to $BBBB (read if page wrapped)
|
||||
# $017f Vector to $ABCD (read if no page wrap)
|
||||
self._write(mpu.memory, 0x0000, (0xE1, 0x80))
|
||||
self._write(mpu.memory, 0x007f, (0xBB, 0xBB))
|
||||
self._write(mpu.memory, 0x017f, (0xCD, 0xAB))
|
||||
mpu.memory[0xABCD] = 0x01
|
||||
mpu.memory[0xBBBB] = 0x02
|
||||
mpu.step()
|
||||
self.assertEqual(0x01, mpu.a)
|
||||
|
||||
# STA Indirect, Indexed (X)
|
||||
|
||||
def test_sta_ind_indexed_x_has_page_wrap_bug(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.a = 0x42
|
||||
mpu.x = 0xFF
|
||||
# $0000 STA ($80,X)
|
||||
# $007f Vector to $BBBB (read if page wrapped)
|
||||
# $017f Vector to $ABCD (read if no page wrap)
|
||||
self._write(mpu.memory, 0x0000, (0x81, 0x80))
|
||||
self._write(mpu.memory, 0x007f, (0xBB, 0xBB))
|
||||
self._write(mpu.memory, 0x017f, (0xCD, 0xAB))
|
||||
mpu.memory[0xABCD] = 0
|
||||
mpu.memory[0xBBBB] = 0
|
||||
mpu.step()
|
||||
self.assertEqual(0x00, mpu.memory[0xABCD])
|
||||
self.assertEqual(0x42, mpu.memory[0xBBBB])
|
||||
|
||||
# Test page wrapping
|
||||
|
||||
def test_zeropage_indexed_ind_wrap(self):
|
||||
@ -5694,34 +5834,6 @@ class MPUTests(unittest.TestCase, Common6502Tests):
|
||||
mpu.step()
|
||||
self.assertEqual(0x31, mpu.a)
|
||||
|
||||
def test_zeropage_indexed_wrap(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.x = 1
|
||||
# $0000 LDA $FF,X
|
||||
self._write(mpu.memory, 0, (0xb5, 0xff))
|
||||
mpu.step()
|
||||
self.assertEqual(0xb5, mpu.a)
|
||||
|
||||
def test_zeropage_ind_indexed_wrap(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.x = 0
|
||||
mpu.memory[0xa100] = 0x31
|
||||
mpu.memory[0xff] = 0
|
||||
# $0000 LDA ($FF,X)
|
||||
self._write(mpu.memory, 0, (0xa1, 0xff))
|
||||
mpu.step()
|
||||
self.assertEqual(0x31, mpu.a)
|
||||
|
||||
def test_zeropage_ind_indexed_index_wrap(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.x = 0xff
|
||||
mpu.memory[0xa100] = 0x31
|
||||
mpu.memory[0x00ff] = 0
|
||||
# $0000 LDA ($00,X)
|
||||
self._write(mpu.memory, 0, (0xa1, 0))
|
||||
mpu.step()
|
||||
self.assertEqual(0x31, mpu.a)
|
||||
|
||||
def _get_target_class(self):
|
||||
return py65.devices.mpu6502.MPU
|
||||
|
||||
|
@ -11,6 +11,23 @@ class MPUTests(unittest.TestCase, Common6502Tests):
|
||||
mpu = self._make_mpu()
|
||||
self.assertTrue('65C02' in repr(mpu))
|
||||
|
||||
# ADC Indirect, Indexed (X)
|
||||
|
||||
def test_adc_ind_indexed_has_page_wrap_bug(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.a = 0x01
|
||||
mpu.x = 0xFF
|
||||
# $0000 ADC ($80,X)
|
||||
# $007f Vector to $BBBB (read if page wrapped)
|
||||
# $017f Vector to $ABCD (read if no page wrap)
|
||||
self._write(mpu.memory, 0x0000, (0x61, 0x80))
|
||||
self._write(mpu.memory, 0x007f, (0xBB, 0xBB))
|
||||
self._write(mpu.memory, 0x017f, (0xCD, 0xAB))
|
||||
mpu.memory[0xABCD] = 0x01
|
||||
mpu.memory[0xBBBB] = 0x02
|
||||
mpu.step()
|
||||
self.assertEqual(0x02, mpu.a)
|
||||
|
||||
# ADC Zero Page, Indirect
|
||||
|
||||
def test_adc_bcd_off_zp_ind_carry_clear_in_accumulator_zeroes(self):
|
||||
@ -149,6 +166,23 @@ class MPUTests(unittest.TestCase, Common6502Tests):
|
||||
self.assertEqual(mpu.OVERFLOW, mpu.p & mpu.OVERFLOW)
|
||||
self.assertEqual(0, mpu.p & mpu.ZERO)
|
||||
|
||||
# AND Indirect, Indexed (X)
|
||||
|
||||
def test_and_ind_indexed_x_does_not_have_page_wrap_bug(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.a = 0x42
|
||||
mpu.x = 0xFF
|
||||
# $0000 AND ($80,X)
|
||||
# $007f Vector to $BBBB (read if page wrapped)
|
||||
# $017f Vector to $ABCD (read if no page wrap)
|
||||
self._write(mpu.memory, 0x0000, (0x21, 0x80))
|
||||
self._write(mpu.memory, 0x007f, (0xBB, 0xBB))
|
||||
self._write(mpu.memory, 0x017f, (0xCD, 0xAB))
|
||||
mpu.memory[0xABCD] = 0xFF
|
||||
mpu.memory[0xBBBB] = 0
|
||||
mpu.step()
|
||||
self.assertEqual(0x42, mpu.a)
|
||||
|
||||
# AND Zero Page, Indirect
|
||||
|
||||
def test_and_zp_ind_all_zeros_setting_zero_flag(self):
|
||||
@ -442,6 +476,42 @@ class MPUTests(unittest.TestCase, Common6502Tests):
|
||||
self.assertEqual(mpu.BREAK, mpu.p & mpu.BREAK)
|
||||
self.assertEqual(0, mpu.p & mpu.DECIMAL)
|
||||
|
||||
# CMP Indirect, Indexed (X)
|
||||
|
||||
def test_cmp_ind_x_has_page_wrap_bug(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.p = 0
|
||||
mpu.a = 0x42
|
||||
mpu.x = 0xFF
|
||||
# $0000 CMP ($80,X)
|
||||
# $007f Vector to $BBBB (read if page wrapped)
|
||||
# $017f Vector to $ABCD (read if no page wrap)
|
||||
self._write(mpu.memory, 0x0000, (0xC1, 0x80))
|
||||
self._write(mpu.memory, 0x007f, (0xBB, 0xBB))
|
||||
self._write(mpu.memory, 0x017f, (0xCD, 0xAB))
|
||||
mpu.memory[0xABCD] = 0x42
|
||||
mpu.memory[0xBBBB] = 0x00
|
||||
mpu.step()
|
||||
self.assertEqual(mpu.ZERO, mpu.p & mpu.ZERO)
|
||||
|
||||
# EOR Indirect, Indexed (X)
|
||||
|
||||
def test_eor_ind_x_does_not_have_page_wrap_bug(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.p = 0
|
||||
mpu.a = 0xAA
|
||||
mpu.x = 0xFF
|
||||
# $0000 EOR ($80,X)
|
||||
# $007f Vector to $BBBB (read if page wrapped)
|
||||
# $017f Vector to $ABCD (read if no page wrap)
|
||||
self._write(mpu.memory, 0x0000, (0x41, 0x80))
|
||||
self._write(mpu.memory, 0x007f, (0xBB, 0xBB))
|
||||
self._write(mpu.memory, 0x017f, (0xCD, 0xAB))
|
||||
mpu.memory[0xABCD] = 0xFF
|
||||
mpu.memory[0xBBBB] = 0x00
|
||||
mpu.step()
|
||||
self.assertEqual(0x55, mpu.a)
|
||||
|
||||
# EOR Zero Page, Indirect
|
||||
|
||||
def test_eor_zp_ind_flips_bits_over_setting_z_flag(self):
|
||||
@ -499,6 +569,23 @@ class MPUTests(unittest.TestCase, Common6502Tests):
|
||||
self.assertEqual(0x1234, mpu.pc)
|
||||
self.assertEqual(6, mpu.processorCycles)
|
||||
|
||||
# LDA Indirect, Indexed (X)
|
||||
|
||||
def test_lda_ind_indexed_x_does_not_have_page_wrap_bug(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.a = 0x00
|
||||
mpu.x = 0xff
|
||||
# $0000 LDA ($80,X)
|
||||
# $007f Vector to $BBBB (read if page wrapped)
|
||||
# $017f Vector to $ABCD (read if no page wrap)
|
||||
self._write(mpu.memory, 0x0000, (0xA1, 0x80))
|
||||
self._write(mpu.memory, 0x007f, (0xBB, 0xBB))
|
||||
self._write(mpu.memory, 0x017f, (0xCD, 0xAB))
|
||||
mpu.memory[0xABCD] = 0x42
|
||||
mpu.memory[0xBBBB] = 0xFF
|
||||
mpu.step()
|
||||
self.assertEqual(0x42, mpu.a)
|
||||
|
||||
# LDA Zero Page, Indirect
|
||||
|
||||
def test_lda_zp_ind_loads_a_sets_n_flag(self):
|
||||
@ -531,6 +618,23 @@ class MPUTests(unittest.TestCase, Common6502Tests):
|
||||
self.assertEqual(mpu.ZERO, mpu.p & mpu.ZERO)
|
||||
self.assertEqual(0, mpu.p & mpu.NEGATIVE)
|
||||
|
||||
# ORA Indirect, Indexed (X)
|
||||
|
||||
def test_ora_ind_indexed_x_does_not_have_page_wrap_bug(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.a = 0
|
||||
mpu.x = 0xFF
|
||||
# $0000 ORA ($80,X)
|
||||
# $007f Vector to $BBBB (read if page wrapped)
|
||||
# $017f Vector to $ABCD (read if no page wrap)
|
||||
self._write(mpu.memory, 0x0000, (0x01, 0x80))
|
||||
self._write(mpu.memory, 0x007f, (0xBB, 0xBB))
|
||||
self._write(mpu.memory, 0x017f, (0xCD, 0xAB))
|
||||
mpu.memory[0xABCD] = 0x42
|
||||
mpu.memory[0xBBBB] = 0
|
||||
mpu.step()
|
||||
self.assertEqual(0x42, mpu.a)
|
||||
|
||||
# ORA Zero Page, Indirect
|
||||
|
||||
def test_ora_zp_ind_zeroes_or_zeros_sets_z_flag(self):
|
||||
@ -806,6 +910,42 @@ class MPUTests(unittest.TestCase, Common6502Tests):
|
||||
mpu.step()
|
||||
self.assertEqual(expected, mpu.p)
|
||||
|
||||
# SBC Indirect, Indexed (X)
|
||||
|
||||
def test_sbc_ind_x_has_page_wrap_bug(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.p = mpu.CARRY
|
||||
mpu.a = 0x03
|
||||
mpu.x = 0xFF
|
||||
# $0000 SBC ($80,X)
|
||||
# $007f Vector to $BBBB (read if page wrapped)
|
||||
# $017f Vector to $ABCD (read if no page wrap)
|
||||
self._write(mpu.memory, 0x0000, (0xE1, 0x80))
|
||||
self._write(mpu.memory, 0x007f, (0xBB, 0xBB))
|
||||
self._write(mpu.memory, 0x017f, (0xCD, 0xAB))
|
||||
mpu.memory[0xABCD] = 0x01
|
||||
mpu.memory[0xBBBB] = 0x02
|
||||
mpu.step()
|
||||
self.assertEqual(0x02, mpu.a)
|
||||
|
||||
# STA Indirect, Indexed (X)
|
||||
|
||||
def test_sta_ind_indexed_x_does_not_have_page_wrap_bug(self):
|
||||
mpu = self._make_mpu()
|
||||
mpu.a = 0x42
|
||||
mpu.x = 0xFF
|
||||
# $0000 STA ($80,X)
|
||||
# $007f Vector to $BBBB (read if page wrapped)
|
||||
# $017f Vector to $ABCD (read if no page wrap)
|
||||
self._write(mpu.memory, 0x0000, (0x81, 0x80))
|
||||
self._write(mpu.memory, 0x007f, (0xBB, 0xBB))
|
||||
self._write(mpu.memory, 0x017f, (0xCD, 0xAB))
|
||||
mpu.memory[0xABCD] = 0
|
||||
mpu.memory[0xBBBB] = 0
|
||||
mpu.step()
|
||||
self.assertEqual(0x42, mpu.memory[0xABCD])
|
||||
self.assertEqual(0x00, mpu.memory[0xBBBB])
|
||||
|
||||
# STA Zero Page, Indirect
|
||||
|
||||
def test_sta_zp_ind_stores_a_leaves_a_and_n_flag_unchanged(self):
|
||||
|
Loading…
x
Reference in New Issue
Block a user