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 _checkInterrupts(self): if self.iff1: self.halted = Bits.reset() self.iff1 = Bits.reset() self.iff2 = Bits.reset() self.ram[--self.SP] = Bits.limitTo8Bits(self.pc) self.ram[--self.SP] = self.pc >> 8 self.R += 1 if self.im == 0 or self.im == 1: self.PC = 0x0038
def xorA(cpu, opcode, logger): regInd = opcode & 7 cpu.A = cpu.A ^ cpu.regs[regInd] cpu.ZFlag = Bits.isZero(cpu.A) cpu.CFlag = Bits.reset() cpu.NFlag = Bits.reset() cpu.HFlag = Bits.reset() cpu.SFlag = Bits.signInTwosComp(cpu.A) cpu.PVFlag = Bits.isEvenParity(cpu.A) cpu.m_cycles, cpu.t_states = 1, 4 logger.info("XOR A")
def _or_hl(cpu, opcode, logger): cpu.A = cpu.A | cpu.ram[cpu.HL] cpu.HFlag = Bits.reset() cpu.CFlag = Bits.reset() cpu.NFlag = Bits.reset() cpu.ZFlag = Bits.isZero(cpu.A) cpu.SFlag = Bits.isNegative(cpu.A) cpu.PVFlag = Bits.isEvenParity(cpu.A) cpu.m_cycles, cpu.t_states = 2, 7 logger.info("OR (HL)")
def _checkInterrupts(self): if self.iff1 and self.generateInterrupt: self.generateInterrupt = False self.halted = Bits.reset() self.iff1 = Bits.reset() self.iff2 = Bits.reset() self.ram[--self.SP] = Bits.limitTo8Bits(self.pc) self.ram[--self.SP] = self.pc >> 8 self.R += 1 if self.im == 0 or self.im == 1: self.PC = 0x0038
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 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_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 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 _or(cpu, opcode, logger): regInd = opcode & 7 cpu.A = cpu.A | cpu.regs[regInd] cpu.HFlag = Bits.reset() cpu.CFlag = Bits.reset() cpu.NFlag = Bits.reset() cpu.ZFlag = Bits.isZero(cpu.A) cpu.SFlag = Bits.isNegative(cpu.A) cpu.PVFlag = Bits.isEvenParity(cpu.A) cpu.m_cycles, cpu.t_states = 1, 4 logger.info("OR {}".format(IndexToReg.translate8Bit(regInd)))
def _and_hl(cpu, opcode, logger): val = cpu.ram[cpu.HL] cpu.A = cpu.A & val 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, 7 logger.info("AND (HL)")
def xor_n(cpu, opcode, logger): n = cpu.ram[cpu.PC] old = cpu.A cpu.A = old ^ n cpu.ZFlag = Bits.isZero(cpu.A) cpu.CFlag = Bits.reset() cpu.NFlag = Bits.reset() cpu.HFlag = Bits.reset() cpu.SFlag = Bits.isNegative(cpu.A) cpu.PVFlag = Bits.isEvenParity(cpu.A) cpu.m_cycles, cpu.t_states = 2, 7 logger.info("XOR {:02X}".format(n))
def or_n(cpu, opcode, logger): n = cpu.ram[cpu.PC] old = cpu.A cpu.A = cpu.A | n cpu.SFlag = Bits.isNegative(cpu.A) cpu.ZFlag = Bits.isZero(cpu.A) cpu.HFlag = Bits.reset() cpu.PVFlag = Bits.overflow(old, cpu.A) cpu.NFlag = Bits.reset() cpu.CFlag = Bits.reset() cpu.m_cycles, cpu.t_states = 2, 7 logger.info("OR {:02X}".format(n))
def rrd(cpu, opcode, logger): low_a = cpu.A & 0x0F mem_hl = cpu.ram[cpu.HL] low_hl = mem_hl & 0x0F high_hl = (mem_hl & 0xF0) >> 4 cpu.A = (cpu.A & 0xF0) | low_hl mem_hl = (low_a << 4) | high_hl cpu.ram[cpu.HL] = mem_hl cpu.ZFlag = Bits.isZero(cpu.A) cpu.SFlag = Bits.isNegative(cpu.A) cpu.HFlag = Bits.reset() cpu.NFlag = Bits.reset() cpu.PVFlag = Bits.isEvenParity(cpu.A) cpu.m_cycles, cpu.t_states = 5, 18 logger.info("RRD")
def add_Hl_rr_c(cpu, opcode, logger): regInd = (opcode >> 4) & 3 val = cpu.Reg16(regInd) old = cpu.HL cpu.HL = cpu.HL + val + (1 if cpu.CFlag else 0) cpu.SFlag = Bits.signFlag(cpu.HL, bits=16) cpu.ZFlag = Bits.isZero(cpu.HL) cpu.HFlag = Bits.halfCarrySub16(old, cpu.HL) cpu.PVFlag = Bits.overflow(old, cpu.HL, bits=16) cpu.NFlag = Bits.reset() cpu.CFlag = Bits.set() if (Bits.getNthBit(old, 15) == 1 and Bits.getNthBit(cpu.HL, 15) == 0) else Bits.reset() cpu.m_cycles, cpu.t_states = 4, 15 logger.info("ADC HL, {}".format(IndexToReg.translate16Bit(regInd)))
def srl_r(cpu, opcode, logger): reg_idx = (opcode & 7) old_val = cpu.regs[reg_idx] cpu.regs[reg_idx] = (old_val >> 1) last_bit = Bits.getNthBit(old_val, 0) cpu.CFlag = Bits.set() if last_bit == 1 else Bits.reset() cpu.NFlag = Bits.reset() cpu.HFlag = Bits.reset() cpu.ZFlag = Bits.isZero(cpu.regs[reg_idx]) cpu.PVFlag = Bits.isEvenParity(cpu.regs[reg_idx]) cpu.SFlag = Bits.reset() cpu.m_cycles, cpu.t_states = 2, 8 logger.info("SRL {}".format(IndexToReg.translate8Bit(reg_idx)))
def test_add_a_d_with_C_flag_reset_correctly_caluclates_value(self): cpu = CPU(ROM(b'\x8a')) cpu.A = 0x22 cpu.D = 0x77 cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(0x99, cpu.A)
def test_add_a_c_with_C_flag_reset_correctly_caluclates_value(self): cpu = CPU(ROM(b'\x89')) cpu.A = 0x22 cpu.C = 0x88 cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(0xAA, cpu.A)
def test_sbc_a_d_sets_SFlag_when_result_is_below_zero(self): cpu = CPU(ROM('\x9a')) cpu.A = 0x40 cpu.D = 0x44 cpu.CFlag = Bits.reset() cpu.readOp() self.assertTrue(cpu.SFlag)
def test_add_a_d_with_C_flag_reset_correctly_caluclates_value(self): cpu = CPU(ROM('\x8a')) cpu.A = 0x22 cpu.D = 0x77 cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(0x99, cpu.A)
def test_sbc_a_e_sets_ZFlag_when_result_is_zero(self): cpu = CPU(ROM(b'\x9b')) cpu.A = 0x44 cpu.E = 0x44 cpu.CFlag = Bits.reset() cpu.readOp() self.assertTrue(cpu.ZFlag)
def test_sbc_a_c_without_c_calculates_results(self): cpu = CPU(ROM(b'\x99')) cpu.A = 0x40 cpu.C = 0x3f cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(1, cpu.A)
def test_sbc_a_e_sets_ZFlag_when_result_is_zero(self): cpu = CPU(ROM('\x9b')) cpu.A = 0x44 cpu.E = 0x44 cpu.CFlag = Bits.reset() cpu.readOp() self.assertTrue(cpu.ZFlag)
def test_add_a_l_with_C_flag_reset_correctly_caluclates_value(self): cpu = CPU(ROM(b'\x8d')) cpu.A = 0x22 cpu.L = 0x44 cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(0x66, cpu.A)
def test_add_HL_BC_with_C_flag_unset_takes_15_t_states(self): cpu = CPU(ROM('\xed\x4a')) cpu.HL = 0xCDCD cpu.BC = 0x1111 cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(15, cpu.t_states)
def test_adc_A_mem_HL_with_CFlag_reset_correctly_sets_A_register(self): cpu = CPU(ROM('\x8e\x05\x06\x07\x08')) cpu.HL = 0x03 cpu.A = 0x5 cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(12, cpu.A)
def test_adc_A_mem_HL_takes_7_t_states(self): cpu = CPU(ROM('\x8e\x05\x06\x07\x08')) cpu.HL = 0x03 cpu.A = 0x5 cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(7, cpu.t_states)
def test_add_a_b_with_C_flag_reset_correctly_calculates_value(self): cpu = CPU(ROM('\x88')) cpu.A = 0x22 cpu.B = 0x33 cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(0x55, cpu.A)
def test_add_a_c_with_C_flag_reset_correctly_caluclates_value(self): cpu = CPU(ROM('\x89')) cpu.A = 0x22 cpu.C = 0x88 cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(0xAA, cpu.A)
def test_add_HL_BC_with_C_flag_unset_correctly_calculates_value(self): cpu = CPU(ROM(b'\xed\x4a')) cpu.HL = 0xCDCD cpu.BC = 0x1111 cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(0XCDCD + 0x1111, cpu.HL)
def test_jp_nz_jumps_takes_3_m_cycles_if_jump_is_taken(self): rom = b'\x00' * 0x0480 + b'\x20\xFA' cpu = CPU(ROM(rom)) cpu.PC = 0x0480 cpu.ZFlag = Bits.reset() cpu.readOp() self.assertEqual(3, cpu.m_cycles)
def test_add_a_l_with_C_flag_reset_correctly_caluclates_value(self): cpu = CPU(ROM('\x8d')) cpu.A = 0x22 cpu.L = 0x44 cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(0x66, cpu.A)
def test_add_HL_BC_with_C_flag_unset_takes_15_t_states(self): cpu = CPU(ROM(b'\xed\x4a')) cpu.HL = 0xCDCD cpu.BC = 0x1111 cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(15, cpu.t_states)
def test_adc_A_mem_HL_with_CFlag_reset_correctly_sets_A_register(self): cpu = CPU(ROM(b'\x8e\x05\x06\x07\x08')) cpu.HL = 0x03 cpu.A = 0x5 cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(12, cpu.A)
def test_sbc_a_d_sets_SFlag_when_result_is_below_zero(self): cpu = CPU(ROM(b'\x9a')) cpu.A = 0x40 cpu.D = 0x44 cpu.CFlag = Bits.reset() cpu.readOp() self.assertTrue(cpu.SFlag)
def test_adc_A_mem_HL_takes_7_t_states(self): cpu = CPU(ROM(b'\x8e\x05\x06\x07\x08')) cpu.HL = 0x03 cpu.A = 0x5 cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(7, cpu.t_states)
def test_jp_nz_jumps_takes_3_m_cycles_if_jump_is_taken(self): rom = '\x00' * 0x0480+'\x20\xFA' cpu = CPU(ROM(rom)) cpu.PC = 0x0480 cpu.ZFlag = Bits.reset() cpu.readOp() self.assertEqual(3, cpu.m_cycles)
def test_add_HL_BC_with_C_flag_unset_correctly_calculates_value(self): cpu = CPU(ROM('\xed\x4a')) cpu.HL = 0xCDCD cpu.BC = 0x1111 cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(0XCDCD+0x1111, cpu.HL)
def test_add_a_b_with_C_flag_reset_correctly_calculates_value(self): cpu = CPU(ROM(b'\x88')) cpu.A = 0x22 cpu.B = 0x33 cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(0x55, cpu.A)
def test_sbc_a_c_without_c_calculates_results(self): cpu = CPU(ROM('\x99')) cpu.A = 0x40 cpu.C = 0x3f cpu.CFlag = Bits.reset() cpu.readOp() self.assertEquals(1, 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 ldir(cpu, opcode, logger): wasZero = cpu.BC == 0 while True: hl_mem = cpu.ram[cpu.HL] cpu.ram[cpu.DE] = hl_mem cpu.HL = cpu.HL + 1 cpu.DE = cpu.DE + 1 cpu.BC = cpu.BC - 1 if cpu.BC == 0: break cpu.NFlag = Bits.reset() cpu.HFlag = Bits.reset() cpu.PVFlag = Bits.reset() cpu.m_cycles, cpu.t_states = 4 if wasZero else 5, 16 if wasZero else 21 logger.info("LDIR")
def lddr(cpu, opcode, logger): isZero = cpu.BC == 0 while True: cpu.ram[cpu.DE] = cpu.ram[cpu.HL] cpu.HL = cpu.HL - 1 cpu.DE = cpu.DE - 1 cpu.BC = cpu.BC - 1 if cpu.BC == 0: cpu.NFlag = Bits.reset() cpu.HFlag = Bits.reset() cpu.PVFlag = Bits.reset() break cpu.m_cycles, cpu.t_states = 4 if isZero else 5, 16 if isZero else 21 logger.info("LDDR")
def test_bit_IY_plus_4_set_correctly_set_z_flag(self): ram = RAM() ram[0x2004] = 0b10111111 cpu = CPU(ROM(b'\xfd\xcb\x04\x76'), ram) cpu.ZFlag = Bits.reset() cpu.IY = 0x2000 cpu.readOp() self.assertTrue(cpu.ZFlag)
def test_bit_IY_plus_4_takes_20_t_states(self): ram = RAM() ram[0x2004] = 1 << 6 cpu = CPU(ROM(b'\xfd\xcb\x04\x76'), ram) cpu.ZFlag = Bits.reset() cpu.IY = 0x2000 cpu.readOp() self.assertEqual(20, cpu.t_states)
def bit_bit(cpu, opcode, logger): index = (opcode >> 8) & 255 bit = (opcode >> 3) & 7 cpu.ZFlag = cpu.ram[cpu.IY+index] & (1 << bit) != 0 cpu.HFlag = Bits.reset() cpu.m_cycles, cpu.t_states = 5, 20 logger.info("BIT {:X}, (IY+{:02X})".format(bit, index))
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 test_ret_cc_does_takes_11_t_states_if_cc_is_true(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.reset() cpu.readOp() self.assertEqual(11, cpu.t_states)
def test_ret_po_does_sets_PC_correctly_if_PVflag_is_reset(self): ram = RAM() ram[0x4000] = 0xB5 ram[0x4001] = 0x18 cpu = CPU(ROM(b'\x00' * 0x3535 + b'\xe0'), ram) cpu.PC = 0x3535 cpu.SP = 0x4000 cpu.PVFlag = Bits.reset() cpu.readOp() self.assertEqual(0x18b5, cpu.PC) self.assertEqual(0x4002, cpu.SP)
def test_call_cc_takes_10_t_cycles_if_condition_is_false(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.reset() cpu.readOp() self.assertEqual(10, cpu.t_states)
def reset(self): #Index registers self.ix = 0x00 self.iy = 0x00 self.sp = 0x00 self.pc = 0x00 #special registers self.i = 0x00 self.r = 0x00 self.w = 0x00 self.z = 0x00 self.halted = Bits.reset() self.iff1 = 0x00 self.iff2 = 0x00 self.im = 0 #B,C,D,E,H,L,none,A, F self.regs = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00] #B',C',D',E',H',L',none,A',F' self.regsPri = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00] self.tstates = 0 self.mcycles = 0
def test_bits_reset_returns_false(self): self.assertFalse(Bits.reset())
def test_jp_nc_takes_3_m_cycles_if_condition_is_met(self): cpu = CPU(ROM(b'\x30\x00')) cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(3, cpu.m_cycles)
def test_jp_nc_takes_12_t_states_if_condition_is_met(self): cpu = CPU(ROM(b'\x30\x00')) cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(12, cpu.t_states)
def test_add_a_a_with_C_flag_reset_correctly_sets_ZFlag(self): cpu = CPU(ROM(b'\x8f')) cpu.A = 0x00 cpu.CFlag = Bits.reset() cpu.readOp() self.assertTrue(cpu.ZFlag)