def cpl(cpu, opcode, logger): old = cpu.A new = ~old cpu.A = new cpu.HFlag = Bits.set() cpu.NFlag = Bits.set() cpu.m_cycles, cpu.t_states = 1, 4 logger.info("CPL")
def test_ed43nn_does_not_affect_flags(self): cpu = CPU(ROM(b'\xed\x43\x00\x10')) cpu.CFlag = Bits.set() cpu.ZFlag = Bits.reset() cpu.SFlag = Bits.set() cpu.HFlag = Bits.reset() cpu.readOp() self.assertTrue(cpu.CFlag) self.assertFalse(cpu.ZFlag) self.assertTrue(cpu.SFlag) self.assertFalse(cpu.HFlag)
def test_ld_nn_a_does_not_affect_flags(self): cpu = CPU(ROM(b'\x32\xb2\x29')) cpu.HFlag = Bits.reset() cpu.ZFlag = Bits.set() cpu.PVFlag = Bits.reset() cpu.SFlag = Bits.set() self.assertFalse(cpu.HFlag) self.assertTrue(cpu.ZFlag) self.assertFalse(cpu.PVFlag) self.assertTrue(cpu.SFlag)
def test_add_a_e_with_C_flag_set_correctly_caluclates_value(self): cpu = CPU(ROM('\x8b')) cpu.A = 0x22 cpu.E = 0x66 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(0x89, cpu.A)
def test_add_a_d_with_C_flag_set_correctly_caluclates_value(self): cpu = CPU(ROM('\x8a')) cpu.A = 0x22 cpu.D = 0x77 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(0x9a, cpu.A)
def test_add_a_b_with_C_flag_set_correctly_calculates_value(self): cpu = CPU(ROM('\x88')) cpu.A = 0x12 cpu.B = 0x12 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(0x25, cpu.A)
def test_add_HL_SP_with_C_flag_set_correctly_calculates_value(self): cpu = CPU(ROM('\xed\x7a')) cpu.HL = 0x1111 cpu.SP = 0x2222 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(0x1111+0x2222+0x1, cpu.HL)
def test_add_HL_DE_with_C_flag_set_correctly_calculates_value(self): cpu = CPU(ROM('\xed\x5a')) cpu.HL = 0xCDCD cpu.DE = 0x1111 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(0XCDCD+0x1111+0x1, cpu.HL)
def test_adc_A_mem_HL_with_CFlag_set_correctly_sets_A_register(self): cpu = CPU(ROM('\x8e\x15\x16\x17\x18')) cpu.HL = 0x03 cpu.A = 0x5 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(0x1c, cpu.A)
def test_add_a_b_with_C_flag_set_takes_4_t_states(self): cpu = CPU(ROM('\x88')) cpu.A = 0x12 cpu.B = 0x12 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(4, cpu.t_states)
def test_jp_nz_jumps_takes_7_t_states_if_jump_is_taken(self): rom = b'\x00' * 0x0480 + b'\x20\xFA' cpu = CPU(ROM(rom)) cpu.PC = 0x0480 cpu.ZFlag = Bits.set() cpu.readOp() self.assertEqual(7, cpu.t_states)
def test_add_a_b_with_C_flag_set_correctly_calculates_value(self): cpu = CPU(ROM(b'\x88')) cpu.A = 0x12 cpu.B = 0x12 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(0x25, cpu.A)
def rlca(cpu, opcode, logger): cflag = Bits.getNthBit(cpu.A, 7) cpu.A = Bits.setNthBit(cpu.A << 1, 0, cflag) cpu.CFlag = Bits.set() if cflag != 0 else Bits.reset() cpu.m_cycles, cpu.t_states = 1, 4 logger.info("RLCA")
def test_sbc_a_mem_hl_correctly_calculates_value(self): cpu = CPU(ROM(b'\x9e\x00\x00\x22')) cpu.A = 0x23 cpu.HL = 0x3 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(0, cpu.A)
def test_jp_nz_jumps_takes_7_t_states_if_jump_is_taken(self): rom = '\x00' * 0x0480+'\x20\xFA' cpu = CPU(ROM(rom)) cpu.PC = 0x0480 cpu.ZFlag = Bits.set() cpu.readOp() self.assertEqual(7, cpu.t_states)
def test_jp_nz_jumps_takes_2_m_cycles_if_jump_is_not_taken(self): rom = '\x00' * 0x0480+'\x20\xFA' cpu = CPU(ROM(rom)) cpu.PC = 0x0480 cpu.ZFlag = Bits.set() cpu.readOp() self.assertEqual(2, cpu.m_cycles)
def test_add_HL_SP_with_C_flag_set_correctly_calculates_value(self): cpu = CPU(ROM(b'\xed\x7a')) cpu.HL = 0x1111 cpu.SP = 0x2222 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(0x1111 + 0x2222 + 0x1, cpu.HL)
def test_sbc_a_b_correctly_calculates_result(self): cpu = CPU(ROM('\x98')) cpu.A = 0x40 cpu.B = 0x3f cpu.CFlag = Bits.set() cpu.readOp() self.assertEquals(0, cpu.A)
def test_add_a_e_with_C_flag_set_correctly_caluclates_value(self): cpu = CPU(ROM(b'\x8b')) cpu.A = 0x22 cpu.E = 0x66 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(0x89, cpu.A)
def test_sbc_a_b_correctly_calculates_result(self): cpu = CPU(ROM(b'\x98')) cpu.A = 0x40 cpu.B = 0x3f cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(0, cpu.A)
def test_jr_z_jumps_if_ZFlag_is_set(self): rom = '\x00' * 0x0300+'\x28\x03' cpu = CPU(ROM(rom)) cpu.PC = 0x0300 cpu.ZFlag = Bits.set() cpu.readOp() self.assertEqual(0x0305, cpu.PC)
def test_add_iy_rr_resets_n_flag(self): cpu = CPU(ROM('\xfd\x39')) cpu.IY = 0x1001 cpu.SP = 0x0880 cpu.NFlag = Bits.set() cpu.readOp() self.assertFalse(cpu.NFlag)
def test_sbc_a_mem_hl_correctly_calculates_value(self): cpu = CPU(ROM('\x9e\x00\x00\x22')) cpu.A = 0x23 cpu.HL = 0x3 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(0, cpu.A)
def test_add_a_d_with_C_flag_set_correctly_caluclates_value(self): cpu = CPU(ROM(b'\x8a')) cpu.A = 0x22 cpu.D = 0x77 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(0x9a, cpu.A)
def test_add_HL_DE_with_C_flag_set_correctly_calculates_value(self): cpu = CPU(ROM(b'\xed\x5a')) cpu.HL = 0xCDCD cpu.DE = 0x1111 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(0XCDCD + 0x1111 + 0x1, cpu.HL)
def test_add_iy_rr_resets_n_flag(self): cpu = CPU(ROM(b'\xfd\x39')) cpu.IY = 0x1001 cpu.SP = 0x0880 cpu.NFlag = Bits.set() cpu.readOp() self.assertFalse(cpu.NFlag)
def test_adc_A_mem_HL_with_CFlag_set_correctly_sets_A_register(self): cpu = CPU(ROM(b'\x8e\x15\x16\x17\x18')) cpu.HL = 0x03 cpu.A = 0x5 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(0x1d, cpu.A)
def test_add_a_b_with_C_flag_set_takes_4_t_states(self): cpu = CPU(ROM(b'\x88')) cpu.A = 0x12 cpu.B = 0x12 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(4, cpu.t_states)
def test_jr_z_does_not_change_the_z_flag(self): cpu = CPU(ROM('\x28\x00\x28\x00')) cpu.ZFlag = Bits.reset() cpu.readOp() self.assertFalse(cpu.ZFlag) cpu.ZFlag = Bits.set() cpu.readOp() self.assertTrue(cpu.ZFlag)
def rra(cpu, opcode, logger): cflag = Bits.getNthBit(cpu.A, 0) cpu.A = Bits.setNthBit((cpu.A >> 1), 7, cpu.CFlag) cpu.CFlag = Bits.set() if cflag == 1 else Bits.reset() cpu.HFlag = Bits.reset() cpu.NFlag = Bits.reset() cpu.m_cycles, cpu.t_states = 1, 4 logger.info("RRA")
def test_ret_cc_does_takes_5_t_states_if_cc_is_false(self): ram = RAM() ram[0x4000] = 0xB5 ram[0x4001] = 0x18 cpu = CPU(ROM(b'\x00' * 0x3535 + b'\xf0'), ram) cpu.PC = 0x3535 cpu.SP = 0x4000 cpu.SFlag = Bits.set() cpu.readOp() self.assertEqual(5, cpu.t_states)
def test_ret_cc_does_takes_5_t_states_if_cc_is_false(self): ram = RAM() ram[0x4000] = 0xB5 ram[0x4001] = 0x18 cpu = CPU(ROM('\x00'*0x3535+'\xf0'), ram) cpu.PC = 0x3535 cpu.SP = 0x4000 cpu.SFlag = Bits.set() cpu.readOp() self.assertEqual(5, cpu.t_states)
def dec_at_hl(cpu, opcode, logger): old_val = cpu.ram[cpu.HL] new_val = old_val - 1 cpu.ram[cpu.HL] = new_val cpu.ZFlag = Bits.isZero(new_val) cpu.SFlag = Bits.isNegative(new_val) cpu.NFlag = Bits.set() cpu.PVFlag = Bits.halfCarrySub(old_val, new_val) cpu.m_cycles, cpu.t_states = 3, 11 logger.info("DEC (HL)")
def test_ret_c_does_sets_PC_correctly_if_Cflag_is_set(self): ram = RAM() ram[0x4000] = 0xB5 ram[0x4001] = 0x18 cpu = CPU(ROM(b'\x00' * 0x3535 + b'\xd8'), ram) cpu.PC = 0x3535 cpu.SP = 0x4000 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(0x18b5, cpu.PC) self.assertEqual(0x4002, cpu.SP)
def test_call_cc_takes_17_t_states_if_condition_is_true(self): ram = RAM() rom = ROM(b'\x00' * 0x1A47 + b'\xDC\x35\x21') cpu = CPU(rom, ram) cpu.PC = 0x1A47 cpu.SP = 0x3002 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(17, cpu.t_states)
def dec_at_ix_d(cpu, opcode, logger): d = cpu.ram[cpu.PC] old_val = cpu.ram[cpu.IX+d] new_val = old_val - 1 cpu.ram[cpu.IX+d] = new_val cpu.ZFlag = Bits.isZero(new_val) cpu.SFlag = Bits.isNegative(new_val) cpu.NFlag = Bits.set() cpu.PVFlag = Bits.halfCarrySub(old_val, new_val) cpu.m_cycles, cpu.t_states = 6, 23 logger.info("DEC (IX+{:02X})".format(d))
def test_ret_c_does_sets_PC_correctly_if_Cflag_is_set(self): ram = RAM() ram[0x4000] = 0xB5 ram[0x4001] = 0x18 cpu = CPU(ROM('\x00'*0x3535+'\xd8'), ram) cpu.PC = 0x3535 cpu.SP = 0x4000 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(0x18b5, cpu.PC) self.assertEqual(0x4002, cpu.SP)
def neg(cpu, opcode, logger): old = cpu.A cpu.A = 0 - cpu.A cpu.NFlag = Bits.reset() cpu.ZFlag = Bits.isZero(cpu.A) cpu.SFlag = Bits.isNegative(cpu.A) cpu.PVFlag = Bits.set() if old == 0x80 else Bits.reset() cpu.CFlag = Bits.isZero(old) cpu.HFlag = Bits.halfCarrySub(0x0, old) cpu.m_cycles, cpu.t_states = 2, 8 logger.info("NEG")
def ldar(cpu, opcode, logger): cpu.A = cpu.R cpu.SFlag = Bits.isNegative(cpu.R) cpu.ZFlag = Bits.isZero(cpu.R) cpu.HFlag = Bits.reset() cpu.PVFlag = Bits.set() if cpu.iff2 == 1 else Bits.reset() cpu.NFlag = Bits.reset() cpu.m_cycles, cpu.t_states = 2, 9 logger.info("LD A, R")
def cp_hl(cpu, opcode, logger): value = cpu.A - cpu.ram[cpu.HL] cpu.ZFlag = Bits.isZero(value) cpu.CFlag = Bits.carryFlag(value) cpu.NFlag = Bits.set() cpu.HFlag = Bits.halfCarrySub(cpu.A, value) cpu.SFlag = Bits.signFlag(value) cpu.PVFlag = Bits.overflow(value, cpu.A) cpu.m_cycles, cpu.t_states = 1, 7 logger.info("CP (HL)")
def cp(cpu, opcode, logger): regInd = opcode & 7 value = cpu.A - cpu.regs[regInd] cpu.ZFlag = Bits.isZero(value) cpu.CFlag = Bits.carryFlag(value) cpu.NFlag = Bits.set() cpu.HFlag = Bits.halfCarrySub(cpu.A, value) cpu.SFlag = Bits.signFlag(value) cpu.PVFlag = Bits.overflow(value, cpu.A) cpu.m_cycles, cpu.t_states = 1, 4 logger.info("CP {}".format(IndexToReg.translate8Bit(regInd)))
def sub_n(cpu, opcode, logger): n = cpu.ram[cpu.PC] value = cpu.A - n cpu.NFlag = Bits.set() cpu.ZFlag = Bits.isZero(value) cpu.HFlag = Bits.halfCarrySub(cpu.A, value) cpu.PVFlag = Bits.overflow(cpu.A, value) cpu.CFlag = Bits.carryFlag(value) cpu.A = value logger.info("SUB {:02X}".format(n))
def _and(cpu, opcode, logger): regInd = opcode & 7 cpu.A = cpu.A & cpu.regs[regInd] cpu.HFlag = Bits.set() cpu.CFlag = Bits.reset() cpu.NFlag = Bits.reset() cpu.ZFlag = Bits.isZero(cpu.A) cpu.SFlag = Bits.signInTwosComp(cpu.A) cpu.PVFlag = Bits.isEvenParity(cpu.A) cpu.m_cycles, cpu.t_states = 1, 4 logger.info("AND A")
def ret_cc(cpu, opcode, logger): cond = (opcode >> 3) & 7 cond_name = '' jump = None if cond == 0: cond_name = 'NZ' jump = cpu.ZFlag == Bits.reset() if cond == 1: cond_name = 'Z' jump = cpu.ZFlag == Bits.set() if cond == 2: cond_name = 'NC' jump = cpu.CFlag == Bits.reset() if cond == 3: cond_name = 'C' jump = cpu.CFlag == Bits.set() if cond == 4: cond_name = 'PO' jump = cpu.PVFlag == Bits.reset() if cond == 5: cond_name = 'PE' jump = cpu.PVFlag == Bits.set() if cond == 6: cond_name = 'P' jump = cpu.SFlag == Bits.reset() if cond == 7: cond_name = 'M' jump = cpu.SFlag == Bits.set() if jump: low = cpu.ram[cpu.SP] high = cpu.ram[cpu.SP+1] addr = (high << 8) + low cpu.SP += 2 cpu.PC = addr cpu.m_cycles, cpu.t_states = 2, 6 cpu.m_cycles, cpu.t_states = 1, 5 logger.info("RET {}".format(cond_name))
def dec8b(cpu, opcode, logger): reg_index = (opcode >> 3) & 7 old_val = cpu.regs[reg_index] cpu.regs[reg_index] = cpu.regs[reg_index] - 1 cpu.ZFlag = Bits.isZero(cpu.regs[reg_index]) cpu.SFlag = Bits.isNegative(cpu.regs[reg_index]) cpu.NFlag = Bits.set() cpu.PVFlag = Bits.halfCarrySub(old_val, cpu.regs[reg_index]) cpu.HFlag = Bits.halfCarrySub(old_val, cpu.regs[reg_index]) cpu.m_cycles, cpu.t_states = 1, 4 logger.info("DEC {}".format(IndexToReg.translate8Bit(reg_index)))
def dec_mem_at_iy(cpu, opcode, logger): displacement = cpu.ram[cpu.PC] addr = cpu.IY + displacement value = cpu.ram[addr] new_value = value - 1 cpu.ram[addr] = new_value cpu.NFlag = Bits.set() cpu.SFlag = Bits.isNegative(new_value) cpu.ZFlag = Bits.isZero(new_value) cpu.PVFlag = True if value == 0x80 else False cpu.HFlag = Bits.halfCarrySub(value, new_value) logger.info("DEC (IY+{:2X})".format(displacement))
def test_jp_nc_takes_7_t_states_if_condition_is_not_met(self): cpu = CPU(ROM(b'\x30\x00')) cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(7, cpu.t_states)
def test_add_a_a_with_C_flag_set_correctly_resets_ZFlag(self): cpu = CPU(ROM(b'\x8f')) cpu.A = 0x00 cpu.CFlag = Bits.set() cpu.readOp() self.assertFalse(cpu.ZFlag)
def test_adc_A_n_correctly_calculates_values(self): cpu = CPU(ROM(b'\xce\x02')) cpu.A = 0x02 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(0x05, cpu.A)
def test_bits_set_returns_true(self): self.assertTrue(Bits.set())