import copy import logging from . util import * import sys class instruction(object): def __init__(self, opcode_args, n_operands, string, tstates=1): self.string = string self.super_op = 0 #op_args = [] #for i in opcode_args: ##super_op = i[0] >> 8 ##self.super_op = super_op ##op = i[0] & 255 #op_args.append((op, i[1])) #self.opcode_args = op_args self.opcode_args = opcode_args self.n_operands = n_operands # number bytes to read pos opcodeaa() self.tstates = tstates def __call__(self, f): return Instruction(self, f) class Instruction(object): def __init__(self, ins, executer): self.string = ins.string self.super_op = ins.super_op self.opcode_args = ins.opcode_args self.n_operands = ins.n_operands self.tstates = ins.tstates self.executer = executer def get_read_list(self, operands=()): return self.executer(*((self, self.registers, True, None) + self.args + tuple([operands[i] for i in self.operands]) )) def execute(self, data=None, operands=()): return self.executer(*((self, self.registers, False, data) + self.args + tuple([operands[i] for i in self.operands]) )) def assembler(self, operands=()): return self.string.format(*(self.args + tuple([operands[i] for i in self.operands]))) def __str__(self): s = "Instruction: " + self.string + "\n" s += "args: " + str(self.args) + "\n" s += "operand bytes: " + str(self.operands) + "\n" return s class InstructionSet(): def __init__(self, registers): self._registers = registers self._instructions = {} #0: [None] * 256} #keys of this are super_ops self._instructions2 = {} # Fill instruction lookup for i in dir(self): f = getattr(self, i) if f.__class__ == Instruction: print (i, ":") for o in f.opcode_args: print (o) ff = copy.copy(f) ff.registers = self._registers ff.args = o[1] if len(o) == 3: ff.tstates = o[2] #print "Tstates=", ff.tstates else: # print "missing tstates for " # tstates not specified so used instruction group number # so default... pass ff.operands = [] d = self._instructions2 opargs = o if type(o[0]) == type(0x4): if o[0] > 0xFF: opargs = ((o[0] >> 8, o[0] & 0xFF), o[1]) else: opargs = ((o[0], ), o[1]) for n, i in enumerate(opargs[0][:-1]): if i in d: d = d[i] elif i == "-": ff.operands.append(n) if len(d.keys()) == 0: d2 = {} for i in range(256): d[i] = d2 d = d2 else: d = d[0] else: d[i] = {} d = d[i] if opargs[0][-1] == "-": ff.operands.append(n+1) for i in range(256): d[i] = ff else: d[opargs[0][-1]] = ff self._instructions = self._instructions2 self._instruction_composer = [] self._composer_instruction = None self._composer_len = 1 def __getitem__(self, ins): if self.is_two_parter(ins): return self._instructions[ins] else: if ins in self._instructions[0]: return self._instructions[0][ins] raise AttributeError("Unknown opcode") def __lshift__(self, op): self._instruction_composer.append(op) q = self._instructions for i in self._instruction_composer: q = q[i] if isinstance(q, dict): return False, 0 else: ops = tuple(self._instruction_composer) self._instruction_composer = [] # print q, ops return q, ops def reset_composer(self): self._instruction_composer = [] def is_two_parter(self, ins): return ins in self._instructions #---------------------------------------------------------------------- #---------------------------------------------------------------------- # 8-bit Load Instructions #---------------------------------------------------------------------- @instruction([(0x7F, ("A", "A")), (0x78, ("A", "B")), (0x79, ("A", "C")), (0x7A, ("A", "D")), (0x7B, ("A", "E")), (0x7C, ("A", "H")), (0x7D, ("A", "L")), (0x47, ("B", "A")), (0x40, ("B", "B")), (0x41, ("B", "C")), (0x42, ("B", "D")), (0x43, ("B", "E")), (0x44, ("B", "H")), (0x45, ("B", "L")), (0x4F, ("C", "A")), (0x48, ("C", "B")), (0x49, ("C", "C")), (0x4A, ("C", "D")), (0x4B, ("C", "E")), (0x4C, ("C", "H")), (0x4D, ("C", "L")), (0x57, ("D", "A")), (0x50, ("D", "B")), (0x51, ("D", "C")), (0x52, ("D", "D")), (0x53, ("D", "E")), (0x54, ("D", "H")), (0x55, ("D", "L")), (0x5F, ("E", "A")), (0x58, ("E", "B")), (0x59, ("E", "C")), (0x5A, ("E", "D")), (0x5B, ("E", "E")), (0x5C, ("E", "H")), (0x5D, ("E", "L")), (0x67, ("H", "A")), (0x60, ("H", "B")), (0x61, ("H", "C")), (0x62, ("H", "D")), (0x63, ("H", "E")), (0x64, ("H", "H")), (0x65, ("H", "L")), (0x6F, ("L", "A")), (0x68, ("L", "B")), (0x69, ("L", "C")), (0x6A, ("L", "D")), (0x6B, ("L", "E")), (0x6C, ("L", "H")), (0x6D, ("L", "L")), (0xED47, ("I", "A"), 9), (0xED4F, ("R", "A"), 9), ], 0, "LD {0}, {1}", 4) def ld_r_r_(instruction, registers, get_reads, data, r, r_): if get_reads: return [] else: registers[r] = registers[r_] return [] @instruction([(0xED57, ('I', )), (0xED5F, ("R", ))], 0, "LD A, {0}", 9) def ld_a_ir(instruction, registers, get_reads, data, r): if get_reads: return [] else: if r == "R": # Add 2 to refresh. TODO: fix registers[r] += 2 registers.A = registers[r] registers.condition.S = registers[r] >> 7 registers.condition.Z = registers[r] == 0 registers.condition.H = 0 registers.condition.PV = registers.IFF2 registers.condition.N = 0 set_f5_f3_from_a(registers) return [] #@instruction([(0xED47, ("I", )), (0xED5F, ("R", )), (0x00, (), 30) ], #1, "LD {0}, {1}", 9) #def ld_a_ir(instruction, registers, get_reads, data, r): #if get_reads: #return [] #else: ##registers.A = registers[r] ##registers.condition.S = registers[r] >> 7 ##registers.condition.Z = registers[r] == 0 ##registers.condition.H = 0 ##registers.condition.PV = registers.IFF2 ##registers.condition.N = 0 ##set_f5_f3_from_a(registers) #return [] @instruction([([0x3E, '-'], ("A", )), ([0x06, '-'], ("B", )), ([0x0E, '-'], ("C", )), ([0x16, '-'], ("D", )), ([0x1E, '-'], ("E", )), ([0x26, '-'], ("H", )), ([0x2E, '-'], ("L", ))], 1, "LD {0}, {1:X}H", 7) def ld_r_n(instruction, registers, get_reads, data, r, n): if get_reads: return [] else: registers[r] = n return [] @instruction([(0x7E, ("A", )), (0x46, ("B", )), (0x4E, ("C", )), (0x56, ("D", )), (0x5E, ("E", )), (0x66, ("H", )), (0x6E, ("L", ))], 0, "LD {0}, (HL)", 7) def ld_r_hl(instruction, registers, get_reads, data, r): if get_reads: return [registers.H << 8 | registers.L] else: registers[r] = data[0] return [] @instruction([([0xDD, 0x7E, '-'], ("A", "IX")), ([0xDD, 0x46, '-'], ("B", "IX")), ([0xDD, 0x4E, '-'], ("C", "IX")), ([0xDD, 0x56, '-'], ("D", "IX")), ([0xDD, 0x5E, '-'], ("E", "IX")), ([0xDD, 0x66, '-'], ("H", "IX")), ([0xDD, 0x6E, '-'], ("L", "IX")), ([0xFD, 0x7E, '-'], ("A", "IY")), ([0xFD, 0x46, '-'], ("B", "IY")), ([0xFD, 0x4E, '-'], ("C", "IY")), ([0xFD, 0x56, '-'], ("D", "IY")), ([0xFD, 0x5E, '-'], ("E", "IY")), ([0xFD, 0x66, '-'], ("H", "IY")), ([0xFD, 0x6E, '-'], ("L", "IY"))], 1, "LD {0}, ({1}+{2:X}H)", 19) def ld_r_i_d(instruction, registers, get_reads, data, r, i, d): if get_reads: return [registers[i] + get_8bit_twos_comp(d)] else: registers[r] = data[0] return [] @instruction([(0x77, ("A", )), (0x70, ("B", )), (0x71, ("C", )), (0x72, ("D", )), (0x73, ("E", )), (0x74, ("H", )), (0x75, ("L", ))], 0, "LD (HL), {0}", 7) def ld_hl_r(instruction, registers, get_reads, data, r): if get_reads: return [] else: return [(registers.H << 8 | registers.L, registers[r])] @instruction([([0xDD, 0x77, '-'], ("A", "IX")), ([0xDD, 0x70, '-'], ("B", "IX")), ([0xDD, 0x71, '-'], ("C", "IX")), ([0xDD, 0x72, '-'], ("D", "IX")), ([0xDD, 0x73, '-'], ("E", "IX")), ([0xDD, 0x74, '-'], ("H", "IX")), ([0xDD, 0x75, '-'], ("L", "IX")), ([0xFD, 0x77, '-'], ("A", "IY")), ([0xFD, 0x70, '-'], ("B", "IY")), ([0xFD, 0x71, '-'], ("C", "IY")), ([0xFD, 0x72, '-'], ("D", "IY")), ([0xFD, 0x73, '-'], ("E", "IY")), ([0xFD, 0x74, '-'], ("H", "IY")), ([0xFD, 0x75, '-'], ("L", "IY"))], 1, "LD ({1}+{2:X}H), {0}", 19) def ld_i_d_r(instruction, registers, get_reads, data, r, i, d): if get_reads: return [] else: return [( registers[i] + get_8bit_twos_comp(d), registers[r])] @instruction([([0x36, '-'], ( ))], 1, "LD (HL), {0:X}H", 10) def ld_hl_n(instruction, registers, get_reads, data, n): if get_reads: return [] else: return [(registers.H << 8 | registers.L, n)] @instruction([([0xDD, 0x36, '-', '-'], ("IX", )), ([0xFD, 0x36, '-', '-'], ("IY", ))], 2, "LD ({0}+{1:X}H), {2:X}H", 19) def ld_i_d_n(instruction, registers, get_reads, data, i, d, n): if get_reads: return [] else: return [( registers[i] + get_8bit_twos_comp(d), n)] @instruction([(0x0A, ("B", "C")), (0x1A, ("D", "E"))], 0, "LD A, ({0}{1})", 7) def ld_a_rr(instruction, registers, get_reads, data, r, r2): if get_reads: return [registers[r] << 8 | registers[r2]] else: registers.A = data[0] return [] @instruction([([0x3A, '-', '-'], ())], 2, "LD A, ({1:x}{0:X}H)", 13) def ld_a_nn(instruction, registers, get_reads, data, n, n2): if get_reads: return [n2 << 8 | n] else: registers.A = data[0] return [] @instruction([(0x02, ("B", "C")), (0x12, ("D", "E"))], 0, "LD ({0}{1}), A", 7) def ld_rr_a(instruction, registers, get_reads, data, r, r2): if get_reads: return [] else: return [(registers[r] << 8 | registers[r2], registers.A)] @instruction([([0x32, '-', '-'], ())], 2, "LD ({1:x}{0:X}H), A", 13) def ld_nn_a(instruction, registers, get_reads, data, n, n2): if get_reads: return [] else: return [(n2 << 8 | n, registers.A)] #---------------------------------------------------------------------- # 16-bit Load instructions #---------------------------------------------------------------------- @instruction([([0x01, '-', '-'], ("B", "C")), ([0x11, '-', '-'], ("D", "E")), ([0x21, '-', '-'], ("H", "L"))], 2, "LD {0}{1}, {3:X}{2:X}H", 10) def ld_dd_nn(instruction, registers, get_reads, data, r, r2, n, n2): if get_reads: return [] else: registers[r] = n2 registers[r2] = n return [] @instruction([([0x31, '-', '-'], ("SP",), 10), ([0xDD, 0x21, '-', '-'], ("IX", )), ([0xFD, 0x21, '-', '-'], ("IY", ))], 2, "LD {0}, {2:X}{1:X}H", 14) def ld_D_nn(instruction, registers, get_reads, data, r, n, n2): if get_reads: return [] else: registers[r] = n2 << 8 | n return [] @instruction([([0xED, 0x4B, '-', '-'], ("B", "C" )), ([0xED, 0x5B, '-', '-'], ("D", "E" )), ([0xED, 0x6B, '-', '-'], ("H", "L" )), ([0x2A, '-', '-'], ("H", "L" ), 16), ], 2, "LD {0}{1}, ({3:X}{2:X}H)", 20) def ld_dd_nn_(instruction, registers, get_reads, data, r, r_, n, n_): if get_reads: return [n_ << 8 | n, (n_ << 8 | n) + 1] else: registers[r] = data[1] registers[r_] = data[0] return [] @instruction([([0xDD, 0x2A, '-', '-'], ("IX", )), ([0xFD, 0x2A, '-', '-'], ("IY", )), ([0xED, 0x7B, '-', '-'], ("SP", ))], 2, "LD {0}, ({2:X}{1:X}H)", 20) def ld_D_nn_(instruction, registers, get_reads, data, r, n, n2): if get_reads: return [n2 << 8 | n, (n2 << 8 | n) + 1] else: registers[r] = data[1] << 8 | data[0] return [] @instruction([([0xED, 0x73, '-', '-'], ("SP", )), ([0xDD, 0x22, '-', '-'], ("IX", )), ([0xFD, 0x22, '-', '-'], ("IY", ))], 2, "LD ({2:X}{1:X}H), {0}", 20) def ld_nn__D(instruction, registers, get_reads, data, r, n, n2): if get_reads: return [] else: ad = n2 << 8 | n return [(ad + 1, registers[r] >> 8), (ad, registers[r] & 255)] @instruction([([0xED, 0x63, '-', '-'], ("H", "L", )), ([0x22, '-', '-'], ("H", "L", ), 16), ([0xED, 0x43, '-', '-'], ("B", "C", )), ([0xED, 0x53, '-', '-'], ("D", "E", ))], 2, "LD ({3:X}{2:X}H), {0}{1}", 20) def ld_nn_D(instruction, registers, get_reads, data, r, r2, n, n2): if get_reads: return [] else: ad = n2 << 8 | n return [(ad + 1, registers[r]), (ad, registers[r2])] @instruction([(0xF9, ())], 0, "LD SP, HL", 6) def ld_sp_hl(instruction, registers, get_reads, data): if get_reads: return [] else: registers.SP = registers.H << 8 | registers.L return [] @instruction([(0xDDF9, ("IX", )), (0xFDF9, ("IY", ))], 0, "LD SP, {0}", 10) def ld_sp_i(instruction, registers, get_reads, data, i): if get_reads: return [] else: registers.SP = registers[i] return [] @instruction([(0xC5, ("B", "C" )), (0xD5, ("D", "E" )), (0xE5, ("H", "L" )), (0xF5, ("A", "F" ))], 0, "PUSH {0}{1}", 11) def push_qq(instruction, registers, get_reads, data, q, q2): if get_reads: return [] else: stack = registers.SP registers.SP -= 2 return [(stack - 1, registers[q]), (stack - 2, registers[q2])] @instruction([(0xDDE5, ("IX", )), (0xFDE5, ("IY", ))], 0, "PUSH {0}", 15) def push_i(instruction, registers, get_reads, data, i): if get_reads: return [] else: stack = registers.SP registers.SP -= 2 return [(stack - 1, registers[i] >> 8), (stack - 2, registers[i] & 255)] @instruction([(0xC1, ("B", "C" )), (0xD1, ("D", "E" )), (0xE1, ("H", "L" )), (0xF1, ("A", "F" ))], 0, "POP {0}{1}", 10) def pop_qq(instruction, registers, get_reads, data, q, q2): if get_reads: stack = registers.SP return [stack, stack + 1] else: registers.SP += 2 registers[q2] = data[0] registers[q] = data[1] return [] @instruction([(0xDDE1, ("IX", )), (0xFDE1, ("IY", ))], 0, "POP {0}", 14) def pop_i(instruction, registers, get_reads, data, i): if get_reads: stack = registers.SP return [stack, stack + 1] else: registers.SP += 2 registers[i] = data[1] << 8 | data[0] return [] #---------------------------------------------------------------------- # Exchange, Block Transfer, and Search Group #---------------------------------------------------------------------- @instruction([(0xEB, ())], 0, "EX DE, HL", 4) def ex_de_hl(instruction, registers, get_reads, data): if get_reads: return [] else: registers.D, registers.H = (registers.H, registers.D) registers.E, registers.L = (registers.L, registers.E) return [] @instruction([(0x08, ())], 0, "EX AF, AF'", 4) def ex_af_af_(instruction, registers, get_reads, data): if get_reads: return [] else: registers.A, registers.A_ = (registers.A_, registers.A) registers.F, registers.F_ = (registers.F_, registers.F) return [] @instruction([(0xD9, ())], 0, "EXX", 4) def exx(instruction, registers, get_reads, data): if get_reads: return [] else: registers.B, registers.B_ = (registers.B_, registers.B) registers.C, registers.C_ = (registers.C_, registers.C) registers.D, registers.D_ = (registers.D_, registers.D) registers.E, registers.E_ = (registers.E_, registers.E) registers.H, registers.H_ = (registers.H_, registers.H) registers.L, registers.L_ = (registers.L_, registers.L) return [] @instruction([(0xE3, ())], 0, "EX (SP), HL", 19) def ex_sp__hl(instruction, registers, get_reads, data): if get_reads: return [registers.SP, registers.SP + 1] else: h = registers.H l = registers.L registers.H = data[1] registers.L = data[0] return [(registers.SP, l), (registers.SP + 1, h)] @instruction([(0xDDE3, ("IX", )), (0xFDE3, ("IY", ))], 0, "EX (SP), {0}", 23) def ex_sp__i(instruction, registers, get_reads, data, i): if get_reads: return [registers.SP, registers.SP + 1] else: ix = registers[i] registers[i] = data[1] << 8 | data[0] return [(registers.SP, registers[i] & 255), (registers.SP + 1, registers[i] >> 8)] @instruction([(0xEDA0, ())], 0, "LDI", 16) def ldi(instruction, registers, get_reads, data): if get_reads: return [registers.H << 8 | registers.L] else: de_ = de = registers.D << 8 | registers.E hl = registers.H << 8 | registers.L bc = registers.B << 8 | registers.C hl += 1 if hl > 0xFFFF: hl = 0 registers.H = hl >> 8 registers.L = hl & 0xFF bc -= 1 if bc < 0: bc = 0xFFFF registers.B = bc >> 8 registers.C = bc & 0xFF de += 1 if de > 0xFFFF: de = 0 registers.D = de >> 8 registers.E = de & 0xFF registers.condition.H = 0 if bc != 0: registers.condition.PV = 1 else: registers.condition.PV = 0 registers.condition.N = 0 registers.condition.F3 = (registers.A + data[0]) & 0x08 registers.condition.F5 = (registers.A + data[0]) & 0x02 return [(de, data[0])] @instruction([(0xEDB0, ())], 0, "LDIR", 21) def ldir(instruction, registers, get_reads, data): if get_reads: return [registers.H << 8 | registers.L] else: de_ = de = registers.D << 8 | registers.E hl = registers.H << 8 | registers.L bc = registers.B << 8 | registers.C hl += 1 if hl > 0xFFFF: hl = 0 registers.H = hl >> 8 registers.L = hl & 0xFF bc -= 1 if bc < 0: bc = 0xFFFF registers.B = bc >> 8 registers.C = bc & 0xFF de += 1 if de > 0xFFFF: de = 0 registers.D = de >> 8 registers.E = de & 0xFF registers.condition.H = 0 if bc != 0: registers.PC -= 2 instruction.tstates = 21 else: instruction.tstates = 16 registers.condition.PV = 0 registers.condition.N = 0 registers.condition.F3 = (registers.A + data[0]) & 0x08 registers.condition.F5 = (registers.A + data[0]) & 0x02 return [(de, data[0])] @instruction([(0xEDA8, ())], 0, "LDD", 16) def ldd(instruction, registers, get_reads, data): if get_reads: return [registers.H << 8 | registers.L] else: de_ = de = registers.D << 8 | registers.E hl = registers.H << 8 | registers.L bc = registers.B << 8 | registers.C hl -= 1 if hl < 0: hl = 0xFFFF registers.H = hl >> 8 registers.L = hl & 0xFF bc -= 1 if bc < 0: bc = 0xFFFF registers.B = bc >> 8 registers.C = bc & 0xFF de -= 1 if de < 0: de = 0xFFFF registers.D = de >> 8 registers.E = de & 0xFF registers.condition.H = 0 if bc != 0: registers.condition.PV = 1 else: registers.condition.PV = 0 registers.condition.N = 0 registers.condition.F3 = (registers.A + data[0]) & 0x08 registers.condition.F5 = (registers.A + data[0]) & 0x02 return [(de, data[0])] @instruction([(0xEDB8, ())], 0, "LDDR", 16) def lddr(instruction, registers, get_reads, data): if get_reads: return [registers.H << 8 | registers.L] else: de_ = de = registers.D << 8 | registers.E hl = registers.H << 8 | registers.L bc = registers.B << 8 | registers.C hl -= 1 if hl < 0: hl = 0xFFFF registers.H = hl >> 8 registers.L = hl & 0xFF bc -= 1 if bc < 0: bc = 0xFFFF registers.B = bc >> 8 registers.C = bc & 0xFF de -= 1 if de < 0: de = 0xFFFF registers.D = de >> 8 registers.E = de & 0xFF registers.condition.H = 0 if bc != 0: registers.PC -= 2 instruction.tstates = 21 else: instruction.tstates = 16 registers.condition.PV = 0 registers.condition.N = 0 registers.condition.F3 = (registers.A + data[0]) & 0x08 registers.condition.F5 = (registers.A + data[0]) & 0x02 return [(de, data[0])] @instruction([(0xEDA1, ())], 0, "CPI", 16) def cpi(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: registers.HL = inc16(registers.HL) registers.BC = dec16(registers.BC) subtract8(registers.A, data[0], registers) registers.condition.PV = registers.BC != 0 # F3 is bit 3 of (A - (HL) - H), H # F5 is bit 1 of (A - (HL) - H), H a f5f3 = registers.A - data[0] - registers.H registers.condition.F5 = f5f3 & 0x01 registers.condition.F3 = f5f3 & 0x04 return [] @instruction([(0xEDB1, ())], 0, "CPIR", 16) def cpir(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: registers.HL = inc16(registers.HL) registers.BC = dec16(registers.BC) res = subtract8(registers.A, data[0], registers) if registers.BC != 0 and res != 0: registers.PC -= 2 instruction.tstates = 21 else: instruction.tstates = 16 registers.condition.PV = registers.BC != 0 return [] @instruction([(0xEDA9, ())], 0, "CPD", 16) def cpd(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: registers.HL = dec16(registers.HL) registers.BC = dec16(registers.BC) subtract8(registers.A, data[0], registers) registers.condition.PV = registers.BC != 0 return [] @instruction([(0xEDB9, ())], 0, "CPDR", 16) def cpdr(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: registers.HL = dec16(registers.HL) registers.BC = dec16(registers.BC) res = subtract8(registers.A, data[0], registers) if registers.BC != 0 and res != 0: registers.PC -= 2 instruction.tstates = 21 else: instruction.tstates = 16 registers.condition.PV = registers.BC != 0 return [] #---------------------------------------------------------------------- # 8-Bit Arithmetic Group #---------------------------------------------------------------------- #---- ADD ---- @instruction([(0x87, ("A",)), (0x80, ("B",)), (0x81, ("C",)), (0x82, ("D",)), (0x83, ("E",)), (0x84, ("H",)), (0x85, ("L",))], 0, "ADD A, {0}", 4) def add_a_r(instruction, registers, get_reads, data, r): if get_reads: return [] else: registers.A = add8(registers.A, registers[r], registers) return [] @instruction([([0xC6, '-'], ())], 1, "ADD A, {0:X}H", 7) def add_a_n(instruction, registers, get_reads, data, n): if get_reads: return [] else: registers.A = add8(registers.A, n, registers) return [] @instruction([(0x86, ())], 0, "ADD A, (HL)", 7) def add_a_hl_(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: registers.A = add8(registers.A, data[0], registers) return [] @instruction([([0xDD, 0x86, '-'], ("IX",)), ([0xFD, 0x86, '-'], ("IY",))], 1, "ADD A, ({0}+{1:X}H)", 19) def add_a_i_(instruction, registers, get_reads, data, i, d): if get_reads: return [registers[i] + get_8bit_twos_comp(d)] else: registers.A = add8(registers.A, data[0], registers) return [] #---- ADC ---- @instruction([(0x8f, ("A",)), (0x88, ("B",)), (0x89, ("C",)), (0x8A, ("D",)), (0x8B, ("E",)), (0x8C, ("H",)), (0x8D, ("L",))], 0, "ADC A, {0}", 4) def adc_a_r(instruction, registers, get_reads, data, r): if get_reads: return [] else: registers.A = add8(registers.A + registers.condition.C, registers[r], registers) return [] @instruction([([0xCE, '-'], ())], 1, "ADC A, {0:X}H", 7) def adc_a_n(instruction, registers, get_reads, data, n): if get_reads: return [] else: registers.A = add8(registers.A + registers.condition.C, n, registers) return [] @instruction([(0x8E, ())], 0, "ADC A, (HL)", 7) def adc_a_hl_(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: registers.A = add8(registers.A + registers.condition.C, data[0], registers) return [] @instruction([([0xDD, 0x8E, '-'], ("IX",)), ([0xFD, 0x8E, '-'], ("IY",))], 1, "ADC A, ({0}+{1:X}H)", 19) def adc_a_i_(instruction, registers, get_reads, data, i, d): if get_reads: return [registers[i] + get_8bit_twos_comp(d)] else: registers.A = add8(registers.A + registers.condition.C, data[0], registers) return [] #---- SUB ---- @instruction([(0x97, ("A",)), (0x90, ("B",)), (0x91, ("C",)), (0x92, ("D",)), (0x93, ("E",)), (0x94, ("H",)), (0x95, ("L",))], 0, "SUB A, {0}", 4) def sub_a_r(instruction, registers, get_reads, data, r): if get_reads: return [] else: registers.A = subtract8_check_overflow(registers.A, registers[r], registers) return [] @instruction([([0xD6, '-'], ())], 1, "SUB A, {0:X}H", 7) def sub_a_n(instruction, registers, get_reads, data, n): if get_reads: return [] else: registers.A = subtract8_check_overflow(registers.A, n, registers) return [] @instruction([(0x96, ())], 0, "SUB A, (HL)", 7) def sub_a_hl_(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: registers.A = subtract8_check_overflow(registers.A, data[0], registers) return [] @instruction([([0xDD, 0x96, '-'], ("IX",)), ([0xFD, 0x96, '-'], ("IY",))], 1, "SUB A, ({0}+{1:X}H)", 19) def sub_a_i_(instruction, registers, get_reads, data, i, d): if get_reads: return [registers[i] + get_8bit_twos_comp(d)] else: registers.A = subtract8_check_overflow(registers.A, data[0], registers) return [] #---- SBC ---- @instruction([(0x9f, ("A",)), (0x98, ("B",)), (0x99, ("C",)), (0x9A, ("D",)), (0x9B, ("E",)), (0x9C, ("H",)), (0x9D, ("L",))], 0, "SBC A, {0}", 4) def sbc_a_r(instruction, registers, get_reads, data, r): if get_reads: return [] else: registers.A = subtract8_check_overflow(registers.A - registers.condition.C, registers[r], registers) return [] @instruction([([0xDE, '-'], ())], 1, "SBC A, {0:X}H", 7) def sbc_a_n(instruction, registers, get_reads, data, n): if get_reads: return [] else: registers.A = subtract8_check_overflow(registers.A - registers.condition.C, n, registers) return [] @instruction([(0x9E, ())], 0, "SBC A, (HL)", 7) def sbc_a_hl_(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: registers.A = subtract8_check_overflow(registers.A - registers.condition.C, data[0], registers) return [] @instruction([([0xDD, 0x9E, '-'], ("IX",)), ([0xFD, 0x9E, '-'], ("IY",))], 1, "SBC A, ({0}+{1:X}H)", 19) def sbc_a_i_(instruction, registers, get_reads, data, i, d): if get_reads: return [registers[i] + get_8bit_twos_comp(d)] else: registers.A = subtract8_check_overflow(registers.A - registers.condition.C, data[0], registers) return [] #---- AND ---- @instruction([(0xa7, ("A",)), (0xa0, ("B",)), (0xa1, ("C",)), (0xa2, ("D",)), (0xa3, ("E",)), (0xa4, ("H",)), (0xa5, ("L",))], 0, "AND {0}", 4) def and_a_r(instruction, registers, get_reads, data, r): if get_reads: return [] else: a_and_n(registers, registers[r]) registers.condition.S = (registers.A >> 7) return [] @instruction([([0xe6, '-'], ())], 1, "AND {0:X}H", 7) def and_a_n(instruction, registers, get_reads, data, n): if get_reads: return [] else: a_and_n(registers, n) return [] @instruction([(0xa6, ())], 0, "AND (HL)", 7) def and_a_hl_(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: a_and_n(registers, data[0]) return [] @instruction([([0xDD, 0xA6, '-'], ("IX",)), ([0xFD, 0xA6, '-'], ("IY",))], 1, "AND ({0}+{1:X}H)", 19) def and_a_i_(instruction, registers, get_reads, data, i, d): if get_reads: return [registers[i] + get_8bit_twos_comp(d)] else: a_and_n(registers, data[0]) return [] #---- OR ---- @instruction([(0xb7, ("A",)), (0xb0, ("B",)), (0xb1, ("C",)), (0xb2, ("D",)), (0xb3, ("E",)), (0xb4, ("H",)), (0xb5, ("L",))], 0, "OR {0}", 4) def or_a_r(instruction, registers, get_reads, data, r): if get_reads: return [] else: a_or_n(registers, registers[r]) registers.condition.S = (registers.A >> 7) return [] @instruction([([0xf6, '-'], ())], 1, "OR {0:X}H", 7) def or_a_n(instruction, registers, get_reads, data, n): if get_reads: return [] else: a_or_n(registers, n) return [] @instruction([(0xb6, ())], 0, "OR (HL)", 7) def or_a_hl_(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: a_or_n(registers, data[0]) return [] @instruction([([0xDD, 0xB6, '-'], ("IX",)), ([0xFD, 0xB6, '-'], ("IY",))], 1, "OR ({0}+{1:X}H)", 19) def or_a_i_(instruction, registers, get_reads, data, i, d): if get_reads: return [registers[i] + get_8bit_twos_comp(d)] else: a_or_n(registers, data[0]) return [] #---- XOR ---- @instruction([(0xaf, ("A",)), (0xa8, ("B",)), (0xa9, ("C",)), (0xaa, ("D",)), (0xab, ("E",)), (0xac, ("H",)), (0xad, ("L",))], 0, "XOR {0}", 4) def xor_a_r(instruction, registers, get_reads, data, r): if get_reads: return [] else: a_xor_n(registers, registers[r]) registers.condition.S = (registers.A >> 7) return [] @instruction([([0xee, '-'], ())], 1, "XOR {0:X}H", 7) def xor_a_n(instruction, registers, get_reads, data, n): if get_reads: return [] else: a_xor_n(registers, n) return [] @instruction([(0xae, ())], 0, "XOR (HL)", 7) def xor_a_hl_(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: a_xor_n(registers, data[0]) return [] @instruction([([0xDD, 0xAE, '-'], ("IX",)), ([0xFD, 0xAE, '-'], ("IY",))], 1, "XOR ({0}+{1:X}H)", 19) def xor_a_i_(instruction, registers, get_reads, data, i, d): if get_reads: return [registers[i] + get_8bit_twos_comp(d)] else: a_xor_n(registers, data[0]) return [] #---- CP ---- @instruction([(0xbf, ("A",)), (0xb8, ("B",)), (0xb9, ("C",)), (0xba, ("D",)), (0xbb, ("E",)), (0xbc, ("H",)), (0xbd, ("L",))], 0, "CP {0}", 4) def cp_a_r(instruction, registers, get_reads, data, r): if get_reads: return [] else: subtract8_check_overflow(registers.A, registers[r], registers) set_f5_f3(registers, registers[r]) return [] @instruction([([0xfe, '-'], ())], 1, "CP {0:X}H", 7) def cp_a_n(instruction, registers, get_reads, data, n): if get_reads: return [] else: subtract8_check_overflow(registers.A, n, registers) set_f5_f3(registers, n) return [] @instruction([(0xbe, ())], 0, "CP (HL)", 7) def cp_a_hl_(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: subtract8_check_overflow(registers.A, data[0], registers) set_f5_f3(registers, data[0]) return [] @instruction([([0xDD, 0xBE, '-'], ("IX",)), ([0xFD, 0xBE, '-'], ("IY",))], 1, "CP ({0}+{1:X}H)", 19) def cp_a_i_(instruction, registers, get_reads, data, i, d): if get_reads: return [registers[i] + get_8bit_twos_comp(d)] else: subtract8_check_overflow(registers.A, data[0], registers) set_f5_f3(registers, data[0]) return [] #---- INC s ---- @instruction([(0x3c, ("A",)), (0x04, ("B",)), (0x0c, ("C",)), (0x14, ("D",)), (0x1c, ("E",)), (0x24, ("H",)), (0x2c, ("L",))], 0, "INC {0}", 4) def inc_r(instruction, registers, get_reads, data, r): if get_reads: return [] else: registers[r] = add8(registers[r], 1, registers, C=False ) return [] @instruction([(0x34, ())], 0, "INC (HL)", 11) def inc_hl_(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: new = add8(data[0], 1, registers, C=False ) return [(registers.HL, new)] @instruction([([0xDD, 0x34, '-'], ("IX",)), ([0xFD, 0x34, '-'], ("IY",))], 1, "INC ({0}+{1:X}H)", 23) def inc_i_(instruction, registers, get_reads, data, i, d): if get_reads: return [registers[i] + get_8bit_twos_comp(d)] else: new = add8(data[0], 1, registers, C=False ) return [(registers.HL, new)] #---- DEC s ---- @instruction([(0x3d, ("A",)), (0x05, ("B",)), (0x0d, ("C",)), (0x15, ("D",)), (0x1d, ("E",)), (0x25, ("H",)), (0x2d, ("L",))], 0, "DEC {0}", 4) def dec_r(instruction, registers, get_reads, data, r): if get_reads: return [] else: registers.condition.PV = registers[r] == 0x80 registers[r] = subtract8(registers[r], 1, registers, PV=False) return [] @instruction([(0x35, ())], 0, "DEC (HL)", 11) def dec_hl_(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: new = subtract8(data[0], 1, registers, PV=False) if data[0] == 0x80: registers.condition.PV = 1 else: registers.condition.PV = 0 return [(registers.HL, new)] @instruction([([0xDD, 0x35, '-'], ("IX",)), ([0xFD, 0x35, '-'], ("IY",))], 1, "DEC ({0}+{1:X}H)", 23) def dec_i_(instruction, registers, get_reads, data, i, d): if get_reads: return [registers[i] + get_8bit_twos_comp(d)] else: new = subtract8(data[0], 1, registers, PV=False) if data[0] == 0x80: registers.condition.PV = 1 else: registers.condition.PV = 0 return [(registers[i] + get_8bit_twos_comp(d), new)] #-------------------------------------------------------------------- # General-Purpose Arithmetic and CPU Control Groups #-------------------------------------------------------------------- @instruction([(0x27, ())], 0, "DAA", 4) def daa(instruction, registers, get_reads, data): if get_reads: return [] else: if registers.condition.N == 0: # add operation if registers.condition.C == 0: pass else: pass pass else: pass # TODO: implement DAA #raise Exception("DAA Not implemented ") return [] @instruction([(0x2F, ())], 0, "CPL", 4) def cpl(instruction, registers, get_reads, data): if get_reads: return [] else: registers.A = 0xFF ^ registers.A registers.condition.N = 1 registers.condition.H = 1 set_f5_f3_from_a(registers) return [] @instruction([(0xED44, ())], 0, "NEG", 8) def neg(instruction, registers, get_reads, data): if get_reads: return [] else: registers.A = subtract8_check_overflow(0, registers.A, registers) return [] @instruction([(0x3F, ())], 0, "CCF", 4) def ccf(instruction, registers, get_reads, data): if get_reads: return [] else: registers.condition.H = registers.condition.C registers.condition.N = 0 registers.condition.C = not registers.condition.C set_f5_f3_from_a(registers) return [] @instruction([(0x37, ())], 0, "SCF", 4) def scf(instruction, registers, get_reads, data): if get_reads: return [] else: registers.condition.H = 0 registers.condition.N = 0 registers.condition.C = 1 set_f5_f3_from_a(registers) return [] @instruction([(0x00, ())], 0, "NOP", 4) def nop(instruction, registers, get_reads, data): if get_reads: return [] else: return [] @instruction([(0x76, ())], 0, "HALT", 4) def halt(instruction, registers, get_reads, data): if get_reads: return [] else: registers.HALT = True registers.PC -= 1 return [] @instruction([(0xF3, ())], 0, "DI", 4) def di(instruction, registers, get_reads, data): if get_reads: return [] else: registers.IFF = False registers.IFF2 = False return [] @instruction([(0xFB, ())], 0, "EI", 4) def ei(instruction, registers, get_reads, data): if get_reads: return [] else: registers.IFF = True registers.IFF2 = True return [] @instruction([(0xED46, (0,)), (0xED56, (1,)), (0xED5E, (2,))], 0, "IM {}", 8) def im(instruction, registers, get_reads, data, mode): if get_reads: return [] else: registers.IM = mode return [] #-------------------------------------------------------------------- # 16-Bit Arithmetic Group #-------------------------------------------------------------------- @instruction([(0x39, ("SP",)), (0x09, ("BC",)), (0x19, ("DE",)),(0x29, ("HL",))], 0, "ADD HL, {0}", 11) def add16_hl(instruction, registers, get_reads, data, reg): if get_reads: return [] else: val = registers.HL + getattr(registers, reg) dummy_reg = registers.create() add8(registers.HL & 0xFF, getattr(registers, reg) & 0xFF, dummy_reg, PV=True) registers.condition.H = dummy_reg.condition.C add8(registers.HL >> 8, getattr(registers, reg) >> 8, dummy_reg, PV=True) registers.condition.F3 = dummy_reg.condition.F3 registers.condition.F5 = dummy_reg.condition.F5 registers.condition.N = 0 registers.condition.C = val > 0xFFFF registers.HL = val & 0xFFFF return [] @instruction([(0xED7A, ("SP",)), (0xED4A, ("BC",)), (0xED5A, ("DE",)),(0xED6A, ("HL",))], 0, "ADC HL, {0}", 15) def adc16_hl(instruction, registers, get_reads, data, reg): if get_reads: return [] else: registers.HL = add16(registers.HL + registers.condition.C, getattr(registers, reg), registers) return [] @instruction([(0xED72, ("SP",)), (0xED42, ("BC",)), (0xED52, ("DE",)),(0xED62, ("HL",))], 0, "SBC HL, {0}", 15) def sbc16_hl(instruction, registers, get_reads, data, reg): if get_reads: return [] else: a = registers.HL b = registers[reg] res = a - b if registers.condition.C: res -= 1 registers.condition.S = (res >> 15) & 0x01 registers.condition.N = 1 registers.condition.Z = (res == 0) registers.condition.F3 = res & 0x0800 registers.condition.F5 = res & 0x2000 if (b & 0xFFF) > (a & 0xFFF) - registers.condition.C : registers.condition.H = 1 else: registers.condition.H = 0 pvtest = get_16bit_twos_comp(a) - get_16bit_twos_comp(b) - registers.condition.C if pvtest < -32768 or pvtest > 32767: registers.condition.PV = 1 # overflow else: registers.condition.PV = 0 registers.condition.C = res > 0xFFFF or res < 0 registers.HL = res & 0xFFFF return [] @instruction([(0xDD39, ("IX", "SP",)), (0xDD09, ("IX", "BC",)), (0xDD19, ("IX", "DE",)),(0xDD29, ("IX", "IX",)), (0xFD39, ("IY", "SP",)), (0xFD09, ("IY", "BC",)), (0xFD19, ("IY", "DE",)),(0xFD29, ("IY", "IY",))], 0, "ADD {0}, {1}", 15) def add16_i_pp(instruction, registers, get_reads, data, i, r): if get_reads: return [] else: val = registers[i] + registers[r] if ((registers[i] & 0xFFF) + (registers[r] & 0xFFF)) > 0xFFF : registers.condition.H = 1 else: registers.condition.H = 0 registers.condition.N = 0 registers.condition.C = val > 0xFFFF set_f5_f3(registers, (registers[i] >>8)+(registers[r]>>8)) registers[i] = val & 0xFFFF return [] @instruction([(0x33, ("SP",)), (0x03, ("BC",)), (0x13, ("DE",)),(0x23, ("HL",)), (0xDD23, ("IX",), 10), (0xFD23, ("IY",), 10)], 0, "INC {0}", 6) def inc16_ss(instruction, registers, get_reads, data, s): if get_reads: return [] else: registers[s] = inc16(registers[s]) return [] @instruction([(0x3b, ("SP",)), (0x0b, ("BC",)), (0x1b, ("DE",)),(0x2b, ("HL",)), (0xDD2b, ("IX",), 10), (0xFD2b, ("IY",), 10)], 0, "DEC {0}", 6) def dec16_ss(instruction, registers, get_reads, data, s): if get_reads: return [] else: registers[s] = dec16(registers[s]) return [] #-------------------------------------------------------------------- # Rotate and Shift Group #-------------------------------------------------------------------- @instruction([(0x07, ())], 0, "RLCA", 4) def rlca(instruction, registers, get_reads, data): if get_reads: return [] else: c = registers.A >> 7 registers.A = ((registers.A << 1) | c) & 0xFF registers.condition.C = c registers.condition.H = 0 registers.condition.N = 0 set_f5_f3_from_a(registers) return [] @instruction([(0x17, ())], 0, "RLA", 4) def rla(instruction, registers, get_reads, data): if get_reads: return [] else: c = registers.A >> 7 pc = registers.condition.C registers.A = (registers.A << 1 | pc) & 0xFF registers.condition.C = c registers.condition.H = 0 registers.condition.N = 0 set_f5_f3_from_a(registers) return [] @instruction([(0x0F, ())], 0, "RRCA", 4) def rrca(instruction, registers, get_reads, data): if get_reads: return [] else: c = registers.A & 0x01 registers.A = (registers.A >> 1 | c << 7) & 0xFF registers.condition.C = c registers.condition.H = 0 registers.condition.N = 0 set_f5_f3_from_a(registers) return [] @instruction([(0x1F, ())], 0, "RRA", 4) def rra(instruction, registers, get_reads, data): if get_reads: return [] else: c = registers.A & 0x01 pc = registers.condition.C registers.A = (registers.A >> 1 | pc << 7) & 0xFF registers.condition.C = c registers.condition.H = 0 registers.condition.N = 0 set_f5_f3_from_a(registers) return [] # RLC m @instruction([(0xCB07, ("A", )), (0xCB00, ("B", )), (0xCB01, ("C", )), (0xCB02, ("D", )), (0xCB03, ("E", )), (0xCB04, ("H", )), (0xCB05, ("L", ))], 0, "RLC {0}", 8) def rlc(instruction, registers, get_reads, data, r): if get_reads: return [] else: registers[r] = rotate_left_carry(registers, registers[r]) set_f5_f3(registers, registers[r]) return [] @instruction([(0xCB06, ( ))], 0, "RLC (HL)", 15) def rlc_hl_(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: val = rotate_left_carry(registers, data[0]) set_f5_f3(registers, val) return [(registers.HL, val)] @instruction([([0xDD, 0xCB, '-', 0x06], ("IX", )), ([0xFD, 0xCB, '-', 0x06], ("IY", ))], 2, "RLC ({0}+{1:X}H)", 23) def rlc_i_d(instruction, registers, get_reads, data, i, d): if get_reads: return [registers[i] + get_8bit_twos_comp(d)] else: new = rotate_left_carry(registers, data[0]) set_f5_f3(registers, new) return [(registers[i] + get_8bit_twos_comp(d), new)] # RL m @instruction([([0xCB, 0x10], ("B", )), ([0xCB, 0x11], ("C", )), ([0xCB, 0x12], ("D", )), ([0xCB, 0x13], ("E", )), ([0xCB, 0x14], ("H", )), ([0xCB, 0x15], ("L", )), ([0xCB, 0x17], ("A", ))], 2, "RL {0}", 8) def rl_r(instruction, registers, get_reads, data, r): if get_reads: return [] else: registers[r] = rotate_left(registers, registers[r]) set_f5_f3(registers, registers[r]) return [] @instruction([([0xCB, 0x16], ())], 2, "RL (HL)", 15) def rl_hl(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: val = rotate_left(registers, data[0]) set_f5_f3(registers, val) return [(registers.HL, val)] @instruction([([0xDD, 0xCB, "-", 0x16], ("IX", )), ([0xFD, 0xCB, "-", 0x16], ("IY", ))], 2, "RL ({0}+{1:X}H)", 23) def rl_i(instruction, registers, get_reads, data, i, d): if get_reads: return [registers[i] + get_8bit_twos_comp(d)] else: val = rotate_left(registers, data[0]) set_f5_f3(registers, val) return [(registers[i] + get_8bit_twos_comp(d), val)] # RRC m @instruction([(0xCB0F, ("A", )), (0xCB08, ("B", )), (0xCB09, ("C", )), (0xCB0A, ("D", )), (0xCB0B, ("E", )), (0xCB0C, ("H", )), (0xCB0D, ("L", ))], 0, "RRC {0}", 8) def rrc(instruction, registers, get_reads, data, r): if get_reads: return [] else: registers[r] = rotate_right_carry(registers, registers[r]) set_f5_f3(registers, registers[r]) return [] @instruction([(0xCB0E, ( ))], 0, "RRC (HL)", 15) def rrc_hl_(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: val = rotate_right_carry(registers, data[0]) set_f5_f3(registers, val) return [(registers.HL, val)] @instruction([([0xDD, 0xCB, '-', 0x0E], ("IX", )), ([0xFD, 0xCB, '-', 0x0E], ("IY", ))], 2, "RRC ({0}+{1:X}H)", 23) def rrc_i_d(instruction, registers, get_reads, data, i, d): if get_reads: return [registers[i] + get_8bit_twos_comp(d)] else: new = rotate_right_carry(registers, data[0]) set_f5_f3(registers, new) return [(registers[i] + get_8bit_twos_comp(d), new)] # RR m @instruction([([0xCB, 0x18], ("B", )), ([0xCB, 0x19], ("C", )), ([0xCB, 0x1A], ("D", )), ([0xCB, 0x1B], ("E", )), ([0xCB, 0x1C], ("H", )), ([0xCB, 0x1D], ("L", )), ([0xCB, 0x1F], ("A", ))], 2, "RR {0}", 8) def rr_r(instruction, registers, get_reads, data, r): if get_reads: return [] else: registers[r] = rotate_right(registers, registers[r]) set_f5_f3(registers, registers[r]) return [] @instruction([([0xCB, 0x1E], ())], 2, "RR (HL)", 15) def rr_hl(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: val = rotate_right(registers, data[0]) set_f5_f3(registers, val) return [(registers.HL, val)] @instruction([([0xDD, 0xCB, "-", 0x1E], ("IX", )), ([0xFD, 0xCB, "-", 0x1E], ("IY", ))], 2, "RR ({0}+{1:X}H)", 23) def rr_i(instruction, registers, get_reads, data, i, d): if get_reads: return [registers[i] + get_8bit_twos_comp(d)] else: val = rotate_right(registers, data[0]) set_f5_f3(registers, val) return [(registers[i] + get_8bit_twos_comp(d), val)] # SLA m @instruction([(0xCB27, ("A", )), (0xCB20, ("B", )), (0xCB21, ("C", )), (0xCB22, ("D", )), (0xCB23, ("E", )), (0xCB24, ("H", )), (0xCB25, ("L", ))], 0, "SLA {0}", 8) def sla_r(instruction, registers, get_reads, data, r): if get_reads: return [] else: registers[r] = shift_left(registers, registers[r]) set_f5_f3(registers, registers[r]) return [] @instruction([(0xCB26, ( ))], 0, "SLA (HL)", 15) def sla_hl_(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: val = shift_left(registers, data[0]) set_f5_f3(registers, val) return [(registers.HL, val)] @instruction([([0xDD, 0xCB, '-', 0x26], ("IX", )), ([0xFD, 0xCB, '-', 0x26], ("IY", ))], 2, "SLA ({0}+{1:X}H)", 23) def sla_i_d(instruction, registers, get_reads, data, i, d): if get_reads: return [registers[i] + get_8bit_twos_comp(d)] else: new = shift_left(registers, data[0]) set_f5_f3(registers, new) return [(registers[i] + get_8bit_twos_comp(d), new)] # SRA m @instruction([([0xCB, 0x28], ("B", )), ([0xCB, 0x29], ("C", )), ([0xCB, 0x2A], ("D", )), ([0xCB, 0x2B], ("E", )), ([0xCB, 0x2C], ("H", )), ([0xCB, 0x2D], ("L", )), ([0xCB, 0x2F], ("A", ))], 2, "SRA {0}", 8) def sra_r(instruction, registers, get_reads, data, r): if get_reads: return [] else: registers[r] = shift_right(registers, registers[r]) set_f5_f3(registers, registers[r]) return [] @instruction([([0xCB, 0x2E], ())], 2, "SRA (HL)", 15) def sra_hl(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: val = shift_right(registers, data[0]) set_f5_f3(registers, val) return [(registers.HL, val)] @instruction([([0xDD, 0xCB, "-", 0x2E], ("IX", )), ([0xFD, 0xCB, "-", 0x2E], ("IY", ))], 2, "SRA ({0}+{1:X}H)", 23) def sra_i(instruction, registers, get_reads, data, i, d): if get_reads: return [registers[i] + get_8bit_twos_comp(d)] else: val = shift_right(registers, data[0]) set_f5_f3(registers, val) return [(registers[i] + get_8bit_twos_comp(d), val)] @instruction([([0xED, 0x6F], ())], 2, "RLD", 18) def rld(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: a = (data[0] >> 4) | (registers.A & 0xF0) hl = ((registers.HL << 4) | (registers.A & 0x0f)) & 0xFF registers.A = a registers.condition.S = a >> 7 registers.condition.Z = a == 0 registers.condition.H = 0 registers.condition.N = 0 registers.condition.PV = parity(a) set_f5_f3(registers, registers.A) return [(registers.HL, hl)] @instruction([([0xED, 0x67], ())], 2, "RRD", 18) def rrd(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: a = (data[0] & 0x0F) | (registers.A & 0xF0) hl = ((registers.HL >> 4) | (registers.A << 4)) & 0xFF registers.A = a registers.condition.S = a >> 7 registers.condition.Z = a == 0 registers.condition.H = 0 registers.condition.N = 0 registers.condition.PV = parity(a) set_f5_f3(registers, registers.A) return [(registers.HL, hl)] #-------------------------------------------------------------------- # Bit Set, Reset, and Test Group #-------------------------------------------------------------------- @instruction([ ([0xCB, 0x40 + (b << 3) + register_bits[reg]], (b, reg)) for b in range(8) for reg in ['A', 'B', 'C', 'D', 'E', 'H', 'L'] ] , 2, "BIT {0}, {1}", 8) def bit_r(instruction, registers, get_reads, data, bit, reg): if get_reads: return [] else: # print "Test bit ", bit registers.condition.Z = (registers[reg] & (0x01 << bit)) == 0 registers.condition.H = 1 registers.condition.N = 0 registers.condition.PV = registers.condition.Z if bit == 7: registers.condition.S = (registers[reg] & (0x01 << bit)) #if bit == 5: #registers.condition.F5 = (registers[reg] & (0x01 << bit)) #if bit == 3: #registers.condition.F3 = (registers[reg] & (0x01 << bit)) set_f5_f3(registers, registers[reg]) return [] @instruction( [ ([0xCB, 0x40 + (b << 3) + 6], (b,)) for b in range(8) ] , 2, "BIT {0}, (HL)", 12) def bit_hl(instruction, registers, get_reads, data, bit): if get_reads: return [registers.HL] else: registers.condition.Z = (data[0] & (0x01 << bit)) == 0 registers.condition.H = 1 registers.condition.N = 0 registers.condition.PV = registers.condition.Z if bit == 7: registers.condition.S = (data[0] & (0x01 << bit)) set_f5_f3(registers, data[0]) return [] @instruction( [ ([I, 0xCB, '-', 0x40 + (b << 3) + 6], (Ir, b,)) for b in range(8) for I, Ir in index_bytes] , 2, "BIT {1}, ({0}+{2:X}H)", 20) def bit_i(instruction, registers, get_reads, data, i, bit, d): if get_reads: return [registers[i]+get_8bit_twos_comp(d)] else: registers.condition.Z = (data[0] & (0x01 << bit)) == 0 registers.condition.H = 1 registers.condition.N = 0 registers.condition.PV = registers.condition.Z if bit == 7: registers.condition.S = (data[0] & (0x01 << bit)) else: registers.condition.S = 0 set_f5_f3(registers, (registers[i]+get_8bit_twos_comp(d)) >> 8) return [] @instruction([ ([0xCB, 0xc0 + (b << 3) + register_bits[reg]], (b, reg)) for b in range(8) for reg in ['A', 'B', 'C', 'D', 'E', 'H', 'L'] ] , 2, "SET {0}, {1}", 8) def set_r(instruction, registers, get_reads, data, bit, reg): if get_reads: return [] else: registers[reg] |= (0x01 << bit) return [] @instruction( [ ([0xCB, 0xc0 + (b << 3) + 6], (b,)) for b in range(8) ] , 2, "SET {0}, (HL)", 15) def set_hl(instruction, registers, get_reads, data, bit): if get_reads: return [registers.HL] else: val = data[0] | (0x01 << bit) return [(registers.HL, val)] @instruction( [ ([I, 0xCB, '-', 0xc0 + (b << 3) + 6], (Ir, b,)) for b in range(8) for I, Ir in index_bytes] , 2, "SET {1}, ({0}+{2:X}H)", 23) def set_i(instruction, registers, get_reads, data, i, bit, d): if get_reads: return [registers[i] + get_8bit_twos_comp(d)] else: val = data[0] | (0x01 << bit) return [(registers[i] + get_8bit_twos_comp(d), val)] @instruction([ ([0xCB, 0x80 + (b << 3) + register_bits[reg]], (b, reg)) for b in range(8) for reg in ['A', 'B', 'C', 'D', 'E', 'H', 'L'] ] , 2, "RES {0}, {1}", 8) def res_r(instruction, registers, get_reads, data, bit, reg): if get_reads: return [] else: registers[reg] &= ~(0x01 << bit) return [] @instruction( [ ([0xCB, 0x80 + (b << 3) + 6], (b,)) for b in range(8) ] , 2, "RES {0}, (HL)", 15) def res_hl(instruction, registers, get_reads, data, bit): if get_reads: return [registers.HL] else: val = data[0] & ~(0x01 << bit) return [(registers.HL, val)] @instruction( [ ([I, 0xCB, '-', 0x80 + (b << 3) + 6], (Ir, b,)) for b in range(8) for I, Ir in index_bytes] , 2, "RES {1}, ({0}+{2:X}H)", 23) def res_i(instruction, registers, get_reads, data, i, bit, d): if get_reads: return [registers[i] + get_8bit_twos_comp(d)] else: val = data[0] & ~(0x01 << bit) return [(registers[i] + get_8bit_twos_comp(d), val)] #-------------------------------------------------------------------- # Jump Group #-------------------------------------------------------------------- @instruction([([0xC3, '-', '-'], ())], 2, "JP {1:X}{0:X}H", 10) def jp(instruction, registers, get_reads, data, n, n2): if get_reads: return [] else: registers.PC = n2 << 8 | n return [] @instruction([([0xC2+offset, '-', '-'], (reg, reg_name, val)) for offset, reg_name, reg, val in conditions], 2, "JP {1}, {4:x}{3:X}H", 10) def jp_c(instruction, registers, get_reads, data, reg, reg_name, val, n, n2): if get_reads: return [] else: if getattr(registers.condition, reg) == val: registers.PC = n2 << 8 | n return [] @instruction([([0x18, '-'], ())], 2, "JR {0:X}H", 12) def jr(instruction, registers, get_reads, data, n): if get_reads: return [] else: offset_pc(registers, n) return [] @instruction([([0x20, '-'], ())], 2, "JR NZ, {0:X}H", 12) def jr_nz(instruction, registers, get_reads, data, n): if get_reads: return [] else: if not registers.condition.Z: offset_pc(registers, n) instruction.tstates = 12 else: instruction.tstates = 7 return [] @instruction([([0x28, '-'], ())], 2, "JR Z, {0:X}H", 12) def jr_z(instruction, registers, get_reads, data, n): if get_reads: return [] else: if registers.condition.Z: offset_pc(registers, n) instruction.tstates = 12 else: instruction.tstates = 7 return [] @instruction([([0x30, '-'], ())], 2, "JR NC, {0:X}H", 12) def jr_nc(instruction, registers, get_reads, data, n): if get_reads: return [] else: if not registers.condition.C: offset_pc(registers, n) instruction.tstates = 12 else: instruction.tstates = 7 return [] @instruction([([0x38, '-'], ())], 2, "JR C, {0:X}H", 12) def jr_c(instruction, registers, get_reads, data, n): if get_reads: return [] else: if registers.condition.C: offset_pc(registers, n) instruction.tstates = 12 else: instruction.tstates = 7 return [] @instruction([([0xE9], ("HL", )),([0xDD, 0xE9], ("IX", ), 8),([0xFD, 0xE9], ("IY", ), 8) ], 2, "JP ({})", 4) def jp_r(instruction, registers, get_reads, data, r): if get_reads: return [] else: registers.PC = registers[r] return [] @instruction([([0x10, '-'], ())], 2, "DJNZ {0:X}H", 13) def djnz(instruction, registers, get_reads, data, n): if get_reads: return [] else: registers.B = dec8(registers.B) if not registers.B == 0: offset_pc(registers, n) instruction.tstates = 13 else: instruction.tstates = 8 return [] #-------------------------------------------------------------------- # Call And Return Group #-------------------------------------------------------------------- @instruction([([0xCD, '-', '-'], ())], 2, "CALL {1:X}{0:X}H", 17) def call(instruction, registers, get_reads, data, n, n2): if get_reads: return [] else: sp = registers.SP pc = registers.PC registers.SP = dec16(registers.SP) registers.SP = dec16(registers.SP) registers.PC = n2 << 8 | n return [(sp - 1, pc >> 8), (sp - 2, pc & 0xFF)] @instruction([([0xC4+offset, '-', '-'], (reg, reg_name, val)) for offset, reg_name, reg, val in conditions], 2, "CALL {1}, {4:x}{3:X}H", 17) def call_c(instruction, registers, get_reads, data, reg, reg_name, val, n, n2): if get_reads: return [] else: if getattr(registers.condition, reg) == val: instruction.tstates = 17 sp = registers.SP pc = registers.PC registers.SP = dec16(registers.SP) registers.SP = dec16(registers.SP) registers.PC = n2 << 8 | n return [(sp - 1, pc >> 8), (sp - 2, pc & 0xFF)] else: instruction.tstates = 10 return [] @instruction([([0xC9], ())], 2, "RET", 10) def ret(instruction, registers, get_reads, data): if get_reads: return [registers.SP, inc16(registers.SP)] else: registers.SP = inc16(registers.SP) registers.SP = inc16(registers.SP) registers.PC = data[1] << 8 | data[0] return [] @instruction([([0xC0+offset], (reg, reg_name, val)) for offset, reg_name, reg, val in conditions], 2, "RET {1}", 11) def ret_c(instruction, registers, get_reads, data, reg, reg_name, val): if get_reads: return [registers.SP, inc16(registers.SP)] else: if getattr(registers.condition, reg) == val: registers.SP = inc16(registers.SP) registers.SP = inc16(registers.SP) registers.PC = data[1] << 8 | data[0] instruction.tstates = 11 else: instruction.tstates = 5 return [] @instruction([([0xed, 0x4d], ())], 2, "RETI", 14) def reti(instruction, registers, get_reads, data): if get_reads: return [registers.SP, inc16(registers.SP)] else: #TODO: implement return from interrupt logging.warn("RETI not fully implemented") registers.SP = inc16(registers.SP) registers.SP = inc16(registers.SP) registers.PC = data[1] << 8 | data[0] return [] @instruction([([0xed, 0x45], ())], 2, "RETN", 14) def retn(instruction, registers, get_reads, data): if get_reads: return [registers.SP, inc16(registers.SP)] else: #TODO: implement from non masked interrupt logging.warn("RETN not fully implemented") registers.SP = inc16(registers.SP) registers.SP = inc16(registers.SP) registers.PC = data[1] << 8 | data[0] registers.IFF = registers.IFF2 return [] @instruction([([0xC7 + (t << 3) ], (p, )) for t, p in enumerate([0x0, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38]) ] , 2, "RST {0:X}H", 11) def rst_p(instruction, registers, get_reads, data, p): if get_reads: return [] else: sp = registers.SP pc = registers.PC registers.SP = dec16(registers.SP) registers.SP = dec16(registers.SP) registers.PC = p return [(sp - 1, pc >> 8), (sp - 2, pc & 0xFF)] #-------------------------------------------------------------------- # Input Output Group #-------------------------------------------------------------------- @instruction([([0xDB, '-'], ( )) ] , 2, "IN A, ({0:X}H)", 11) def in_a_n(instruction, registers, get_reads, data, n): if get_reads: address = n | (registers.A << 8) # registers.C | (registers.B << 8) return [address+0x10000] else: registers.A = data[0] return [] @instruction([([0xEd, 0x40+(i<<3)], (r, )) for i, r in enumerate("BCDEHLFA")] , 2, "IN {0}, (C)", 12) def in_r_c(instruction, registers, get_reads, data, r): if get_reads: address = registers[r] | (registers.B << 8) #n | (registers.A << 8) return [address+0x10000] else: registers.condition.S = data[0] & 0x80 registers.condition.Z = data[0] == 0 registers.condition.H = 0 registers.condition.PV = parity(data[0]) registers.condition.N = 0 if r == "F": return [] #registers[r] = data[0] return [] @instruction([([0xed, 0xa2], ( )) ] , 2, "INI", 16) def ini(instruction, registers, get_reads, data): if get_reads: address = registers.C | (registers.B << 8) return [address+0x10000] else: registers.B = dec8(registers.B) registers.HL = inc16(registers.HL) registers.condition.N = 1 registers.condition.Z = registers.B == 0 return [(dec16(registers.HL), data[0])] @instruction([([0xed, 0xb2], ( )) ] , 2, "INIR", 21) def inir(instruction, registers, get_reads, data): if get_reads: address = registers.C | (registers.B << 8) return [address+0x10000] else: registers.B = dec8(registers.B) registers.HL = inc16(registers.HL) registers.condition.N = 1 registers.condition.Z = registers.B == 0 if registers.B == 0: dec16(registers.PC) dec16(registers.PC) instruction.tstates = 16 else: instruction.tstates = 21 return [(dec16(registers.HL), data[0])] @instruction([([0xed, 0xaa], ( )) ] , 2, "IND", 16) def ind(instruction, registers, get_reads, data): if get_reads: address = registers.C | (registers.B << 8) return [address+0x10000] else: registers.B = dec8(registers.B) registers.HL = dec16(registers.HL) registers.condition.N = 1 registers.condition.Z = registers.B == 0 return [(dec16(registers.HL), data[0])] @instruction([([0xed, 0xba], ( )) ] , 2, "INDR", 21) def indr(instruction, registers, get_reads, data): if get_reads: address = registers.C | (registers.B << 8) return [address+0x10000] else: registers.B = dec8(registers.B) registers.HL = dec16(registers.HL) registers.condition.N = 1 registers.condition.Z = registers.B == 0 if not registers.B == 0: dec16(registers.PC) dec16(registers.PC) instruction.tstates = 21 else: instruction.tstates = 16 return [(dec16(registers.HL), data[0])] @instruction([([0xD3, '-'], ( )) ] , 2, "OUT ({0:X}H), A", 11) def out_a_n(instruction, registers, get_reads, data, n): if get_reads: return [] else: address = n | (registers.A << 8) #if n == 0x81: ##logging.info("=========================================== %s =="%chr(registers.A)) ##print chr(registers.A), #sys.stdout.flush() return [(address+0x10000, registers.A)] @instruction([([0xEd, 0x41+(i<<3)], (r, )) for i, r in enumerate("BCDEHLFA")] , 2, "OUT (C), {0}", 12) def out_r_c(instruction, registers, get_reads, data, r): if get_reads: return [] else: if r == "F": return [] return [(registers.BC+0x10000, registers[r])] @instruction([([0xed, 0xa3], ( )) ] , 2, "OUTI", 16) def outi(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: address = registers.C | (registers.B << 8) registers.B = dec8(registers.B) registers.HL = inc16(registers.HL) registers.condition.N = 1 registers.condition.Z = registers.B == 0 return [(address+0x10000, data[0])] @instruction([([0xed, 0xb3], ( )) ] , 2, "OTIR", 21) def otir(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: address = registers.C | (registers.B << 8) registers.B = dec8(registers.B) registers.HL = inc16(registers.HL) registers.condition.N = 1 registers.condition.Z = registers.B == 0 if not registers.B == 0: dec16(registers.PC) dec16(registers.PC) instruction.tstates = 21 else: instruction.tstates = 16 return [(registers.BC+0x10000, data[0])] @instruction([([0xed, 0xab], ( )) ] , 2, "OUTD", 16) def outd(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: address = registers.C | (registers.B << 8) registers.B = dec8(registers.B) registers.HL = dec16(registers.HL) registers.condition.N = 1 registers.condition.Z = registers.B == 0 return [(registers.BC+0x10000, data[0])] @instruction([([0xed, 0xbb], ( )) ] , 2, "OTDR", 21) def otdr(instruction, registers, get_reads, data): if get_reads: return [registers.HL] else: address = registers.C | (registers.B << 8) registers.B = dec8(registers.B) registers.HL = dec16(registers.HL) registers.condition.N = 1 registers.condition.Z = registers.B == 0 if not registers.B == 0: dec16(registers.PC) dec16(registers.PC) instruction.tstates = 21 else: instruction.tstates = 16 return [(registers.BC+0x10000, data[0])]