diff --git a/src/py65/devices/mpu65c02.py b/src/py65/devices/mpu65c02.py index 59dfac9..e8d1124 100644 --- a/src/py65/devices/mpu65c02.py +++ b/src/py65/devices/mpu65c02.py @@ -28,6 +28,10 @@ class MPU(NMOS6502): address = x() self.memory[address] &= mask + def opSMB(self, x, mask): + address = x() + self.memory[address] |= mask + def opSTZ(self, x): self.memory[x()] = 0x00 @@ -135,11 +139,21 @@ class MPU(NMOS6502): self.opRMB(self.ZeroPageAddr, 0x7F) self.pc += 1 + @instruction(name="SMB0", mode="zpg", cycles=5) + def inst_0x87(self): + self.opSMB(self.ZeroPageAddr, 0x01) + self.pc += 1 + @instruction(name="STA", mode="zpi", cycles=5) def inst_0x92(self): self.opSTA(self.ZeroPageIndirectAddr) self.pc += 1 + @instruction(name="SMB1", mode="zpg", cycles=5) + def inst_0x97(self): + self.opSMB(self.ZeroPageAddr, 0x02) + self.pc += 1 + @instruction(name="STZ", mode="abs", cycles=4) def inst_0x9c(self): self.opSTZ(self.AbsoluteAddr) @@ -150,15 +164,45 @@ class MPU(NMOS6502): self.opSTZ(self.AbsoluteXAddr) self.pc += 2 + @instruction(name="SMB2", mode="zpg", cycles=5) + def inst_0xa7(self): + self.opSMB(self.ZeroPageAddr, 0x04) + self.pc += 1 + @instruction(name="LDA", mode="zpi", cycles=5) def inst_0xb2(self): self.opLDA(self.ZeroPageIndirectAddr) self.pc += 1 + @instruction(name="SMB3", mode="zpg", cycles=5) + def inst_0xb7(self): + self.opSMB(self.ZeroPageAddr, 0x08) + self.pc += 1 + + @instruction(name="SMB4", mode="zpg", cycles=5) + def inst_0xc7(self): + self.opSMB(self.ZeroPageAddr, 0x10) + self.pc += 1 + + @instruction(name="SMB5", mode="zpg", cycles=5) + def inst_0xd7(self): + self.opSMB(self.ZeroPageAddr, 0x20) + self.pc += 1 + @instruction(name="PHX", mode="imp", cycles=3) def inst_0xda(self): self.stPush(self.x) + @instruction(name="SMB6", mode="zpg", cycles=5) + def inst_0xe7(self): + self.opSMB(self.ZeroPageAddr, 0x40) + self.pc += 1 + + @instruction(name="SMB7", mode="zpg", cycles=5) + def inst_0xf7(self): + self.opSMB(self.ZeroPageAddr, 0x80) + self.pc += 1 + @instruction(name="PLX", mode="imp", cycles=4) def inst_0xfa(self): self.x = self.stPop() diff --git a/src/py65/tests/devices/test_mpu65c02.py b/src/py65/tests/devices/test_mpu65c02.py index 5e3707c..c79de34 100644 --- a/src/py65/tests/devices/test_mpu65c02.py +++ b/src/py65/tests/devices/test_mpu65c02.py @@ -469,6 +469,174 @@ class MPUTests(unittest.TestCase, Common6502Tests): self.assertEquals(0x00, mpu.a) self.assertEquals(flags, mpu.flags) + # SMB0 + + def test_smb0_sets_bit_0_without_affecting_other_bits(self): + mpu = self._make_mpu() + mpu.memory[0x0043] = int('00000000',2) + self._write(mpu.memory, 0x0000, (0x87, 0x43)) #=> SMB0 $43 + mpu.step() + self.assertEquals(0x0002, mpu.pc) + self.assertEquals(5, mpu.processorCycles) + expected = int('00000001', 2) + self.assertEquals(expected, mpu.memory[0x0043]) + + def test_smb0_does_not_affect_status_register(self): + mpu = self._make_mpu() + mpu.memory[0x0043] = int('00000000',2) + self._write(mpu.memory, 0x0000, (0x87, 0x43)) #=> SMB0 $43 + expected = int('11001100', 2) + mpu.flags = expected + mpu.step() + self.assertEquals(expected, mpu.flags) + + # SMB1 + + def test_smb1_sets_bit_1_without_affecting_other_bits(self): + mpu = self._make_mpu() + mpu.memory[0x0043] = int('00000000',2) + self._write(mpu.memory, 0x0000, (0x97, 0x43)) #=> SMB1 $43 + mpu.step() + self.assertEquals(0x0002, mpu.pc) + self.assertEquals(5, mpu.processorCycles) + expected = int('00000010', 2) + self.assertEquals(expected, mpu.memory[0x0043]) + + def test_smb1_does_not_affect_status_register(self): + mpu = self._make_mpu() + mpu.memory[0x0043] = int('00000000',2) + self._write(mpu.memory, 0x0000, (0x97, 0x43)) #=> SMB1 $43 + expected = int('11001100', 2) + mpu.flags = expected + mpu.step() + self.assertEquals(expected, mpu.flags) + + # SMB2 + + def test_smb2_sets_bit_2_without_affecting_other_bits(self): + mpu = self._make_mpu() + mpu.memory[0x0043] = int('00000000',2) + self._write(mpu.memory, 0x0000, (0xA7, 0x43)) #=> SMB2 $43 + mpu.step() + self.assertEquals(0x0002, mpu.pc) + self.assertEquals(5, mpu.processorCycles) + expected = int('00000100', 2) + self.assertEquals(expected, mpu.memory[0x0043]) + + def test_smb2_does_not_affect_status_register(self): + mpu = self._make_mpu() + mpu.memory[0x0043] = int('00000000',2) + self._write(mpu.memory, 0x0000, (0xA7, 0x43)) #=> SMB2 $43 + expected = int('11001100', 2) + mpu.flags = expected + mpu.step() + self.assertEquals(expected, mpu.flags) + + # SMB3 + + def test_smb3_sets_bit_3_without_affecting_other_bits(self): + mpu = self._make_mpu() + mpu.memory[0x0043] = int('00000000',2) + self._write(mpu.memory, 0x0000, (0xB7, 0x43)) #=> SMB3 $43 + mpu.step() + self.assertEquals(0x0002, mpu.pc) + self.assertEquals(5, mpu.processorCycles) + expected = int('00001000', 2) + self.assertEquals(expected, mpu.memory[0x0043]) + + def test_smb3_does_not_affect_status_register(self): + mpu = self._make_mpu() + mpu.memory[0x0043] = int('00000000',2) + self._write(mpu.memory, 0x0000, (0xB7, 0x43)) #=> SMB3 $43 + expected = int('11001100', 2) + mpu.flags = expected + mpu.step() + self.assertEquals(expected, mpu.flags) + + # SMB4 + + def test_smb4_sets_bit_4_without_affecting_other_bits(self): + mpu = self._make_mpu() + mpu.memory[0x0043] = int('00000000',2) + self._write(mpu.memory, 0x0000, (0xC7, 0x43)) #=> SMB4 $43 + mpu.step() + self.assertEquals(0x0002, mpu.pc) + self.assertEquals(5, mpu.processorCycles) + expected = int('00010000', 2) + self.assertEquals(expected, mpu.memory[0x0043]) + + def test_smb4_does_not_affect_status_register(self): + mpu = self._make_mpu() + mpu.memory[0x0043] = int('00000000',2) + self._write(mpu.memory, 0x0000, (0xC7, 0x43)) #=> SMB4 $43 + expected = int('11001100', 2) + mpu.flags = expected + mpu.step() + self.assertEquals(expected, mpu.flags) + + # SMB5 + + def test_smb5_sets_bit_5_without_affecting_other_bits(self): + mpu = self._make_mpu() + mpu.memory[0x0043] = int('00000000',2) + self._write(mpu.memory, 0x0000, (0xD7, 0x43)) #=> SMB5 $43 + mpu.step() + self.assertEquals(0x0002, mpu.pc) + self.assertEquals(5, mpu.processorCycles) + expected = int('00100000', 2) + self.assertEquals(expected, mpu.memory[0x0043]) + + def test_smb5_does_not_affect_status_register(self): + mpu = self._make_mpu() + mpu.memory[0x0043] = int('00000000',2) + self._write(mpu.memory, 0x0000, (0xD7, 0x43)) #=> SMB5 $43 + expected = int('11001100', 2) + mpu.flags = expected + mpu.step() + self.assertEquals(expected, mpu.flags) + + # SMB6 + + def test_smb6_sets_bit_6_without_affecting_other_bits(self): + mpu = self._make_mpu() + mpu.memory[0x0043] = int('00000000',2) + self._write(mpu.memory, 0x0000, (0xE7, 0x43)) #=> SMB6 $43 + mpu.step() + self.assertEquals(0x0002, mpu.pc) + self.assertEquals(5, mpu.processorCycles) + expected = int('01000000', 2) + self.assertEquals(expected, mpu.memory[0x0043]) + + def test_smb6_does_not_affect_status_register(self): + mpu = self._make_mpu() + mpu.memory[0x0043] = int('00000000',2) + self._write(mpu.memory, 0x0000, (0xE7, 0x43)) #=> SMB6 $43 + expected = int('11001100', 2) + mpu.flags = expected + mpu.step() + self.assertEquals(expected, mpu.flags) + + # SMB7 + + def test_smb7_sets_bit_7_without_affecting_other_bits(self): + mpu = self._make_mpu() + mpu.memory[0x0043] = int('00000000',2) + self._write(mpu.memory, 0x0000, (0xF7, 0x43)) #=> SMB7 $43 + mpu.step() + self.assertEquals(0x0002, mpu.pc) + self.assertEquals(5, mpu.processorCycles) + expected = int('10000000', 2) + self.assertEquals(expected, mpu.memory[0x0043]) + + def test_smb7_does_not_affect_status_register(self): + mpu = self._make_mpu() + mpu.memory[0x0043] = int('00000000',2) + self._write(mpu.memory, 0x0000, (0xF7, 0x43)) #=> SMB7 $43 + expected = int('11001100', 2) + mpu.flags = expected + mpu.step() + self.assertEquals(expected, mpu.flags) + # SBC Zero Page, Indirect def test_sbc_zp_indirect_all_zeros_and_no_borrow_is_zero(self):