def lift(self, il, addr): ip = LLIL_TEMP(il.temp_reg_count) il.append(il.set_reg(2, ip, il.pop(2))) cs = LLIL_TEMP(il.temp_reg_count) il.append(il.set_reg(2, cs, il.pop(2))) il.append(il.set_reg(2, 'sp', il.add(2, il.reg(2, 'sp'), il.const(2, self.imm)))) il.append(il.ret(self._lift_phys_addr(il, il.reg(2, cs), il.reg(2, ip))))
def call_helper(il, addr): # get sp and compute address il.append(il.set_reg(1, LLIL_TEMP(0), il.and_expr(1, il.reg(1, 'PSW'), il.const(1, 0x7)))) il.append(il.set_reg(2, LLIL_TEMP(1), il.add(2, il.shift_left(1, il.reg(1, LLIL_TEMP(0)), il.const(1, 1)), il.const(2, 8)))) # store return address and psw il.append(il.store(2, il.reg(2, LLIL_TEMP(1)), il.or_expr(2, il.shift_left( 2, il.and_expr(1, il.reg(1, 'PSW'), il.const(1, 0xf0)), il.const(1, 8)), il.const(2, (il.current_address & 0xfff) + 2) ) )) # increment sp il.append(il.set_reg(1, 'PSW', il.or_expr( 1, il.and_expr(1, il.reg(1, 'PSW'), il.const(1, 0xf8)), il.and_expr( 1, il.add( 1, il.reg(1, LLIL_TEMP(0)), il.const(1, 1)), il.const(1, 0x7) ) ))) # generate call if MEM_BANKS: # TODO: get address bit 11 from DBF pass else: il.append(il.call(il.const_pointer(2, addr)))
def _lift_load_far(self, il, addr): seg_off = LLIL_TEMP(il.temp_reg_count) il.append(il.set_reg(4, seg_off, il.load(4, addr))) seg = LLIL_TEMP(il.temp_reg_count) il.append(il.set_reg(2, seg, il.logical_shift_right(2, il.reg(4, seg_off), il.const(1, 16)))) off = LLIL_TEMP(il.temp_reg_count) il.append(il.set_reg(2, off, il.low_part(2, il.reg(4, seg_off)))) return il.reg(2, seg), il.reg(2, off)
def lift(self, il, addr): ip = LLIL_TEMP(il.temp_reg_count) il.append(il.set_reg(2, ip, il.pop(2))) cs = LLIL_TEMP(il.temp_reg_count) il.append(il.set_reg(2, cs, il.pop(2))) flags = LLIL_TEMP(il.temp_reg_count) il.append(il.set_reg(2, flags, il.pop(2))) for flag, flag_bit in flags_bits: bit = il.test_bit(2, il.reg(2, flags), il.const(2, flag_bit)) il.append(il.set_flag(flag, bit)) il.append(il.ret(self._lift_phys_addr(il, il.reg(2, cs), il.reg(2, ip))))
def load_zero_page_16(il, value): if il[value].operation == LowLevelILOperation.LLIL_CONST: if il[value].constant == 0xff: lo = il.zero_extend(2, il.load(1, il.const_pointer(2, 0xff))) hi = il.shift_left(2, il.zero_extend(2, il.load(1, il.const_pointer(2, 0)), il.const(2, 8))) return il.or_expr(2, lo, hi) return il.load(2, il.const_pointer(2, il[value].constant)) il.append(il.set_reg(1, LLIL_TEMP(0), value)) value = il.reg(1, LLIL_TEMP(0)) lo_addr = value hi_addr = il.add(1, value, il.const(1, 1)) lo = il.zero_extend(2, il.load(1, lo_addr)) hi = il.shift_left(2, il.zero_extend(2, il.load(1, hi_addr)), il.const(2, 8)) return il.or_expr(2, lo, hi)
def set_p_value(il, value): il.append(il.set_reg(1, LLIL_TEMP(0), value)) il.append( il.set_flag("c", il.test_bit(1, il.reg(1, LLIL_TEMP(0)), il.const(1, 0x01)))) il.append( il.set_flag("z", il.test_bit(1, il.reg(1, LLIL_TEMP(0)), il.const(1, 0x02)))) il.append( il.set_flag("i", il.test_bit(1, il.reg(1, LLIL_TEMP(0)), il.const(1, 0x04)))) il.append( il.set_flag("d", il.test_bit(1, il.reg(1, LLIL_TEMP(0)), il.const(1, 0x08)))) il.append( il.set_flag("b", il.test_bit(1, il.reg(1, LLIL_TEMP(0)), il.const(1, 0x10)))) il.append( il.set_flag("v", il.test_bit(1, il.reg(1, LLIL_TEMP(0)), il.const(1, 0x40)))) il.append( il.set_flag("s", il.test_bit(1, il.reg(1, LLIL_TEMP(0)), il.const(1, 0x80)))) return None
def expressionify(size, foo, il, temps_are_conds=False): """ turns the "reg or constant" operands to get_flag_write_low_level_il() into lifted expressions """ if isinstance(foo, int): return foo if isinstance(foo, ILRegister): # LowLevelILExpr is different than ILRegister if temps_are_conds and LLIL_TEMP(foo.index): # can't use il.reg() 'cause it will do lookup in architecture flags return il.expr(LowLevelILOperation.LLIL_FLAG, foo) #return il.reg(size, 'cond:%d' % LLIL_GET_TEMP_REG_INDEX(foo)) # promote it to an LLIL_REG (read register) return il.reg(size, foo) elif isinstance(foo, ILFlag): return il.flag(foo) elif isinstance(foo, int): return il.const(size, foo) else: raise Exception( 'expressionify() doesn\'t know how to handle il: %s\n%s\n' % (foo, type(foo)))
def lift(self, il, addr): w = self.width() name = 'inw' if w == 2 else 'inb' # See above. temp = LLIL_TEMP(il.temp_reg_count) il.append( il.intrinsic([ILRegister(il.arch, temp)], name, [il.reg(2, 'dx')])) il.append(il.set_reg(w, self.dst_reg(), il.reg(w, temp)))
def lift(self, il, addr): w = self.width() name = 'inw' if w == 2 else 'inb' # If assigning directly to ax, either the entire register needs to be assigned, # or the SSA translation misidentifiers registers. Not sure why, BN bug? temp = LLIL_TEMP(il.temp_reg_count) il.append( il.intrinsic([ILRegister(il.arch, temp)], name, [il.const(2, self.imm)])) il.append(il.set_reg(w, self.dst_reg(), il.reg(w, temp)))
def lift(self, il, addr): # CS is (if the calling convention matches, anyway) popped by the callee, but we # explicitly restore it at the call site because the callee may not be statically # known, and that it restores CS is a safe assumption. # Not quite semantically correct, but good enough and useful. temp = LLIL_TEMP(il.temp_reg_count) il.append(il.set_reg(2, temp, il.reg(2, 'cs'))) il.append(il.push(2, il.reg(2, 'cs'))) il.append(il.set_reg(2, 'cs', il.const(2, self.cs))) il.append(il.call_stack_adjust(il.const(3, self.target()), 2)) il.append(il.set_reg(2, 'cs', il.reg(2, temp)))
def lift(self, il, addr): if self._mod_bits() == 0b11: il.append(il.undefined()) return cs, ip = self._lift_load_far(il, self._lift_reg_mem(il)) il.append(il.set_reg(2, 'cs', cs)) old_cs = LLIL_TEMP(il.temp_reg_count) il.append(il.set_reg(2, old_cs, il.reg(2, 'cs'))) il.append(il.push(2, il.reg(2, 'cs'))) il.append(il.call_stack_adjust(self._lift_phys_addr(il, cs, ip), 2)) il.append(il.set_reg(2, 'cs', il.reg(2, old_cs)))
def ret_helper(il, psw): # get and decrement sp il.append(il.set_reg(1, LLIL_TEMP(0), il.and_expr(1, il.reg(1, 'PSW'), il.const(1, 0x7)))) il.append(il.set_reg(1, LLIL_TEMP(0), il.and_expr(1, il.sub(1, il.reg(1, LLIL_TEMP(0)), il.const(1, 1)), il.const(1, 0x7)))) # load return address and psw il.append(il.set_reg(2, LLIL_TEMP(1), il.load(2, il.add(2, il.shift_left(1, il.reg(1, LLIL_TEMP(0)), il.const(1, 1)), il.const(2, 8))))) # update psw if psw: il.append(il.set_reg(1, 'PSW', il.or_expr( 1, il.and_expr(1, il.reg(1, 'PSW'), il.const(1, 0xf)), il.logical_shift_right( 1, il.reg(2, LLIL_TEMP(1)), il.const(1, 12) ) ))) else: il.append(il.set_reg( 1, 'PSW', il.or_expr( 1, il.and_expr(1, il.reg(1, 'PSW'), il.const(1, 0xf8)), il.reg(1, LLIL_TEMP(0)) ) )) # generate return il.append(il.ret( il.or_expr( 2, il.and_expr(2, il.reg(2, LLIL_TEMP(1)), il.const(2, 0xfff)), il.const(2, CODE_OFFSET) ) ))
def lift(self, il, addr): temp = LLIL_TEMP(il.temp_reg_count) il.append(il.set_reg(2, temp, il.reg(2, self.regL()))) il.append(il.set_reg(2, self.regL(), il.reg(2, self.regR()))) il.append(il.set_reg(2, self.regR(), il.reg(2, temp)))
def gen_instr_il(addr, decoded, il): (oper_type, oper_val) = decoded.operands[0] if decoded.operands else (None, None) (operb_type, operb_val) = decoded.operands[1] if decoded.operands[1:] else (None, None) if decoded.op in [OP.ADD, OP.ADC]: assert len(decoded.operands) == 2 if oper_type == OPER_TYPE.REG: size = REG_TO_SIZE[oper_val] rhs = operand_to_il(operb_type, operb_val, il, size) lhs = operand_to_il(oper_type, oper_val, il) if decoded.op == OP.ADD: tmp = il.add(size, lhs, rhs, flags='*') else: tmp = il.add_carry(size, lhs, rhs, il.flag("c"), flags='*') tmp = il.set_reg(size, reg2str(oper_val), tmp) il.append(tmp) else: il.append(il.unimplemented()) elif decoded.op == OP.AND: tmp = il.reg(1, 'A') tmp = il.and_expr(1, operand_to_il(oper_type, oper_val, il, 1), tmp, flags='z') tmp = il.set_reg(1, 'A', tmp) il.append(tmp) elif decoded.op == OP.BIT: assert oper_type == OPER_TYPE.IMM assert oper_val >= 0 and oper_val <= 7 mask = il.const(1, 1 << oper_val) operand = operand_to_il(operb_type, operb_val, il, 1) il.append(il.and_expr(1, operand, mask, flags='*')) elif decoded.op == OP.CALL: if oper_type == OPER_TYPE.ADDR: il.append(il.call(il.const_pointer(2, oper_val))) else: # TODO: handle the conditional il.append(il.unimplemented()) elif decoded.op == OP.CCF: il.append(il.set_flag('c', il.not_expr(0, il.flag('c')))) elif decoded.op == OP.CP: # sub, but do not write to register lhs = il.reg(1, 'A') rhs = operand_to_il(oper_type, oper_val, il, 1) sub = il.sub(1, lhs, rhs, flags='*') il.append(sub) elif decoded.op == OP.DJNZ: # decrement B tmp = il.reg(1, 'B') tmp = il.add(1, tmp, il.const(1, -1)) tmp = il.set_reg(1, 'B', tmp) il.append(tmp) # if nonzero, jump! (the "go" is built into il.if_expr) t = il.get_label_for_address(Architecture['Z80'], oper_val) if not t: il.append(il.unimplemented()) return f = il.get_label_for_address(Architecture['Z80'], addr + decoded.len) if not f: il.append(il.unimplemented()) return tmp = il.compare_not_equal(1, il.reg(1, 'B'), il.const(1, 0)) il.append(il.if_expr(tmp, t, f)) elif decoded.op == OP.EX: # temp0 = lhs il.append( il.expr(LowLevelILOperation.LLIL_SET_REG, LLIL_TEMP(0), operand_to_il(oper_type, oper_val, il, 2), size=2)) # lhs = rhs rhs = operand_to_il(operb_type, operb_val, il, 2) if oper_type == OPER_TYPE.REG: il.append(il.set_reg(2, reg2str(oper_val), rhs)) else: il.append( il.store( 2, operand_to_il(oper_type, oper_val, il, 2, peel_load=True), rhs)) # rhs = temp0 il.append( il.set_reg(2, reg2str(operb_val), il.expr(LowLevelILOperation.LLIL_REG, LLIL_TEMP(0), 2))) elif decoded.op == OP.INC: # inc reg can be 1-byte or 2-byte if oper_type == OPER_TYPE.REG: size = REG_TO_SIZE[oper_val] tmp = il.add(size, operand_to_il(oper_type, oper_val, il), il.const(1, 1)) tmp = il.set_reg(size, reg2str(oper_val), tmp) else: tmp = il.add(1, operand_to_il(oper_type, oper_val, il), il.const(1, 1)) tmp = il.store( 1, operand_to_il(oper_type, oper_val, il, 1, peel_load=True), tmp) il.append(tmp) elif decoded.op in [OP.JP, OP.JR]: if oper_type == OPER_TYPE.COND: append_conditional_jump(oper_val, operb_type, operb_val, addr + decoded.len, il) else: il.append(goto_or_jump(oper_type, oper_val, il)) elif decoded.op == OP.LD: assert len(decoded.operands) == 2 if oper_type == OPER_TYPE.REG: size = REG_TO_SIZE[oper_val] # for two-byte nonzero loads, guess that it's an address if size == 2 and operb_type == OPER_TYPE.IMM and operb_val != 0: operb_type = OPER_TYPE.ADDR rhs = operand_to_il(operb_type, operb_val, il, size) set_reg = il.set_reg(size, reg2str(oper_val), rhs) il.append(set_reg) else: assert operb_type in [OPER_TYPE.REG, OPER_TYPE.IMM] if operb_type == OPER_TYPE.REG: # 1 or 2 byte stores are possible here: # ld (0xcdab),bc # ld (ix-0x55),a size = REG_TO_SIZE[operb_val] elif operb_type == OPER_TYPE.IMM: # only 1 byte stores are possible # eg: ld (ix-0x55),0xcd size = 1 src = operand_to_il(operb_type, operb_val, il, size) dst = operand_to_il(oper_type, oper_val, il, size, peel_load=True) il.append(il.store(size, dst, src)) elif decoded.op in [OP.LDI, OP.LDIR]: if decoded.op == OP.LDIR: t = LowLevelILLabel() f = il.get_label_for_address(Architecture['Z80'], addr + decoded.len) il.mark_label(t) il.append(il.store(1, il.reg(2, 'DE'), il.load(1, il.reg(2, 'HL')))) il.append( il.set_reg(2, 'DE', il.add(2, il.reg(2, 'DE'), il.const(2, 1)))) il.append( il.set_reg(2, 'HL', il.add(2, il.reg(2, 'HL'), il.const(2, 1)))) il.append( il.set_reg(2, 'BC', il.sub(2, il.reg(2, 'BC'), il.const(2, 1)))) if decoded.op == OP.LDIR: do_mark = False if not f: do_mark = True f = LowLevelILLabel() il.append( il.if_expr( il.compare_not_equal(2, il.reg(2, 'BC'), il.const(2, 0)), t, f)) if do_mark: il.mark_label(f) elif decoded.op == OP.NOP: il.append(il.nop()) elif decoded.op == OP.OR: tmp = il.reg(1, 'A') tmp = il.or_expr(1, operand_to_il(oper_type, oper_val, il, 1), tmp, flags='*') tmp = il.set_reg(1, 'A', tmp) il.append(tmp) elif decoded.op == OP.POP: # possible operands are: af bc de hl ix iy flag_write_type = '*' if oper_val == REG.AF else None size = REG_TO_SIZE[oper_val] tmp = il.pop(size) tmp = il.set_reg(size, reg2str(oper_val), tmp, flag_write_type) il.append(tmp) elif decoded.op == OP.PUSH: # possible operands are: af bc de hl ix iy # when pushing AF, actually push the flags if oper_val == REG.AF: # lo byte F first il.append( il.push( 2, il.or_expr( 2, il.or_expr( 1, il.or_expr( 1, il.shift_left(1, il.flag('s'), il.const(1, 7)), il.shift_left(1, il.flag('z'), il.const(1, 6))), il.or_expr( 1, il.or_expr( 1, il.shift_left(1, il.flag('h'), il.const(1, 4)), il.shift_left(1, il.flag('pv'), il.const(1, 2))), il.or_expr( 1, il.shift_left(1, il.flag('n'), il.const(1, 1)), il.flag('c')))), il.shift_left(2, il.reg(1, 'A'), il.const(1, 8))))) else: il.append(il.push( \ REG_TO_SIZE[oper_val], \ operand_to_il(oper_type, oper_val, il))) elif decoded.op in [OP.RL, OP.RLA]: # rotate THROUGH carry: b0=c, c=b8 # z80 'RL' -> llil 'RLC' if decoded.op == OP.RLA: src = il.reg(1, 'A') else: src = operand_to_il(oper_type, oper_val, il) rot = il.rotate_left_carry(1, src, il.const(1, 1), il.flag('c'), flags='c') if decoded.op == OP.RLA: il.append(il.set_reg(1, 'A', rot)) elif oper_type == OPER_TYPE.REG: il.append(il.set_reg(1, reg2str(oper_val), rot)) else: tmp = operand_to_il(oper_type, oper_val, il, 1, peel_load=True) il.append(il.store(1, tmp2, tmp)) elif decoded.op in [OP.RLC, OP.RLCA]: # rotate and COPY to carry: b0=c, c=b8 # z80 'RL' -> llil 'ROL' if decoded.op == OP.RLCA: src = il.reg(1, 'A') else: src = operand_to_il(oper_type, oper_val, il) rot = il.rotate_left(1, src, il.const(1, 1), flags='c') if decoded.op == OP.RLCA: il.append(il.set_reg(1, 'A', rot)) elif oper_type == OPER_TYPE.REG: il.append(il.set_reg(1, reg2str(oper_val), rot)) else: tmp = operand_to_il(oper_type, oper_val, il, 1, peel_load=True) il.append(il.store(1, tmp2, tmp)) elif decoded.op == OP.RET: tmp = il.ret(il.pop(2)) if decoded.operands: append_conditional_instr(decoded.operands[0][1], tmp, il) else: il.append(tmp) elif decoded.op in [OP.RR, OP.RRA]: # rotate THROUGH carry: b7=c, c=b0 # z80 'RL' -> llil 'RRC' if decoded.op == OP.RRA: src = il.reg(1, 'A') else: src = operand_to_il(oper_type, oper_val, il, 1) rot = il.rotate_right_carry(1, src, il.const(1, 1), il.flag('c'), flags='c') if decoded.op == OP.RRA: il.append(il.set_reg(1, 'A', rot)) elif oper_type == OPER_TYPE.REG: il.append(il.set_reg(1, reg2str(oper_val), rot)) else: tmp2 = operand_to_il(oper_type, oper_val, il, 1, peel_load=True) il.append(il.store(1, tmp2, rot)) elif decoded.op == OP.SRA: tmp = operand_to_il(oper_type, oper_val, il, 1) tmp = il.arith_shift_right(1, tmp, il.const(1, 1), flags='c') if oper_type == OPER_TYPE.REG: tmp = il.set_reg(1, reg2str(oper_val), tmp) else: tmp = il.store( 1, operand_to_il(oper_type, oper_val, il, 1, peel_load=True), tmp) il.append(tmp) elif decoded.op == OP.SUB: tmp = operand_to_il(oper_type, oper_val, il, 1) tmp = il.sub(1, il.reg(1, 'A'), tmp, flags='*') tmp = il.set_reg(1, 'A', tmp) il.append(tmp) elif decoded.op == OP.DEC: if oper_type == OPER_TYPE.REG: size = REG_TO_SIZE[oper_val] reg = operand_to_il(oper_type, oper_val, il, size) fwt = 'not_c' if size == 1 else None tmp = il.sub(size, reg, il.const(1, 1), flags=fwt) tmp = il.set_reg(size, reg2str(oper_val), tmp) il.append(tmp) else: mem = operand_to_il(oper_type, oper_val, il, 1) tmp = il.sub(1, mem, il.const(1, 1), flags='not_c') tmp = il.store(1, mem, tmp) il.append(tmp) elif decoded.op == OP.SBC: size = REG_TO_SIZE[oper_val] lhs = operand_to_il(oper_type, oper_val, il, size) rhs = operand_to_il(operb_type, operb_val, il, size) tmp = il.sub_borrow(size, lhs, rhs, il.flag('c'), flags='*') tmp = il.set_reg(1, 'A', tmp) il.append(tmp) elif decoded.op == OP.XOR: tmp = il.reg(1, 'A') tmp = il.xor_expr(1, operand_to_il(oper_type, oper_val, il, 1), tmp, flags='*') tmp = il.set_reg(1, 'A', tmp) il.append(tmp) else: il.append(il.unimplemented())
def xch(il, vs, ea): # a732 a8c3 v = 0 if not len(vs) else vs[0] il.append(il.set_reg(1, LLIL_TEMP(0), r(ops[0], il))) w(ops[0], il, r(ops[1], il, v)) w(ops[1], il, il.reg(1, LLIL_TEMP(0)), v)
def lift(self, il, addr): flags = LLIL_TEMP(il.temp_reg_count) il.append(il.set_reg(2, flags, il.pop(2))) for flag, flag_bit in flags_bits: bit = il.test_bit(2, il.reg(2, flags), il.const(2, flag_bit)) il.append(il.set_flag(flag, bit))
class MCS48_Base(Architecture): address_size = 2 default_int_size = 1 instr_alignment = 1 max_instr_length = 2 regs = { 'A': RegisterInfo('A', 1), 'T': RegisterInfo('T', 1), 'PSW': RegisterInfo('PSW', 1), 'SP': RegisterInfo('SP', 1), } if WREG_REG: for reg in range(8): regs['R{}'.format(reg)] = RegisterInfo('R{}'.format(reg), 1) for reg in range(8): regs['R{}\''.format(reg)] = RegisterInfo('R{}\''.format(reg), 1) stack_pointer = 'SP' global_regs = ['T', 'PSW'] # PSW: CY, AC, F0, BS, 1, S2, S1, S0 # carry, aux carry, flag 0, bank select, stack pointer # BS:0, addr=0, BS:1, addr=24 flags = [ 'CY', # carry 'AC', # auxiliary carry 'F0', # flag 0 'BS', # bank switch 'DBF', 'F1', # flag 1 'T0', # test 0 'T1', # test 1 'TF', # timer flag 'INT' # interrupt ] # The first flag write type is ignored currently. # See: https://github.com/Vector35/binaryninja-api/issues/513 flag_write_types = ['', 'C'] flags_written_by_flag_write_type = { 'C': ['CY'], } flag_roles = { 'CY': FlagRole.CarryFlagRole, 'AC': FlagRole.HalfCarryFlagRole, 'F0': FlagRole.SpecialFlagRole, 'BS': FlagRole.SpecialFlagRole, 'DBF': FlagRole.SpecialFlagRole, 'F1': FlagRole.SpecialFlagRole, 'T0': FlagRole.SpecialFlagRole, 'T1': FlagRole.SpecialFlagRole, 'TF': FlagRole.SpecialFlagRole, 'INT': FlagRole.SpecialFlagRole, } #flags_required_for_flag_condition = {} instructions = [ # 0x00-0x0f [('NOP', 1), [], lambda self, il: il.nop()], None, [('OUTL', 1), ['BUS', 'A'], lambda self, il: il.reg(1, 'A')], # dummy read [('ADD', 2), ['A', '#IMM8'], lambda self, il, imm: il.set_reg(1, 'A', il.add(1, il.reg(1, 'A'), il.const(1, imm), 'C'))], [('JMP', 2), ['ADDR11'], lambda self, il, imm: branch(il, CODE_ADDR(0x000, imm))], [('EN', 1), ['I']], None, [('DEC', 1), ['A'], lambda self, il: il.set_reg(1, 'A', il.sub(1, il.reg(1, 'A'), il.const(1, 1)))], [('INS', 1), ['A', 'BUS'], lambda self, il: il.set_reg(1, 'A', il.unimplemented())], [('IN', 1), ['A', 'P1'], lambda self, il: il.set_reg(1, 'A', il.unimplemented())], [('IN', 1), ['A', 'P2'], lambda self, il: il.set_reg(1, 'A', il.unimplemented())], None, [('MOVD', 1), ['A', 'P4'], lambda self, il: il.set_reg(1, 'A', il.unimplemented())], [('MOVD', 1), ['A', 'P5'], lambda self, il: il.set_reg(1, 'A', il.unimplemented())], [('MOVD', 1), ['A', 'P6'], lambda self, il: il.set_reg(1, 'A', il.unimplemented())], [('MOVD', 1), ['A', 'P7'], lambda self, il: il.set_reg(1, 'A', il.unimplemented())], # 0x10-0x1f [('INC', 1), ['@R0'], lambda self, il: il.store(1, self.wreg_get(il, 0), il.add(1, il.load(1, self.wreg_get(il, 0)), il.const(1, 1)))], [('INC', 1), ['@R1'], lambda self, il: il.store(1, self.wreg_get(il, 1), il.add(1, il.load(1, self.wreg_get(il, 1)), il.const(1, 1)))], [('JB0', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'B', 0)], [('ADDC', 2), ['A', '#IMM8'], lambda self, il, imm: il.set_reg(1, 'A', il.add_carry(1, il.reg(1, 'A'), il.const(1, imm), il.flag('CY'), 'C'))], [('CALL', 2), ['ADDR11'], lambda self, il, imm: call_helper(il, CODE_ADDR(0x000, imm))], [('DIS', 1), ['I']], [('JTF', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'TF', 1)], [('INC', 1), ['A'], lambda self, il: il.set_reg(1, 'A', il.add(1, il.reg(1, 'A'), il.const(1, 1)))], [('INC', 1), ['R0'], lambda self, il: self.wreg_set(il, 0, il.add(1, self.wreg_get(il, 0), il.const(1, 1)))], [('INC', 1), ['R1'], lambda self, il: self.wreg_set(il, 1, il.add(1, self.wreg_get(il, 1), il.const(1, 1)))], [('INC', 1), ['R2'], lambda self, il: self.wreg_set(il, 2, il.add(1, self.wreg_get(il, 2), il.const(1, 1)))], [('INC', 1), ['R3'], lambda self, il: self.wreg_set(il, 3, il.add(1, self.wreg_get(il, 3), il.const(1, 1)))], [('INC', 1), ['R4'], lambda self, il: self.wreg_set(il, 4, il.add(1, self.wreg_get(il, 4), il.const(1, 1)))], [('INC', 1), ['R5'], lambda self, il: self.wreg_set(il, 5, il.add(1, self.wreg_get(il, 5), il.const(1, 1)))], [('INC', 1), ['R6'], lambda self, il: self.wreg_set(il, 6, il.add(1, self.wreg_get(il, 6), il.const(1, 1)))], [('INC', 1), ['R7'], lambda self, il: self.wreg_set(il, 7, il.add(1, self.wreg_get(il, 7), il.const(1, 1)))], # 0x20-0x2f [('XCH', 1), ['A', '@R0'], lambda self, il: [ il.set_reg(1, LLIL_TEMP(1), il.reg(1, 'A')), il.set_reg(1, 'A', il.load(1, self.wreg_get(il, 0))), self.wreg_set(il, 0, il.reg(1, LLIL_TEMP(1))) ]], [('XCH', 1), ['A', '@R1'], lambda self, il: [ il.set_reg(1, LLIL_TEMP(1), il.reg(1, 'A')), il.set_reg(1, 'A', il.load(1, self.wreg_get(il, 1))), self.wreg_set(il, 1, il.reg(1, LLIL_TEMP(1))) ]], None, [('MOV', 2), ['A', '#IMM8'], lambda self, il, imm: il.set_reg(1, 'A', il.const(1, imm))], [('JMP', 2), ['ADDR11'], lambda self, il, imm: branch(il, CODE_ADDR(0x100, imm))], [('EN', 1), ['TCNTI']], [('JNT0', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'T0', 0)], [('CLR', 1), ['A'], lambda self, il: il.set_reg(1, 'A', il.const(1, 0))], [('XCH', 1), ['A', 'R0'], lambda self, il: [il.set_reg(1, LLIL_TEMP(1), il.reg(1, 'A')), il.set_reg(1, 'A', self.wreg_get(il, 0)), self.wreg_set(il, 0, il.reg(1, LLIL_TEMP(1)))]], [('XCH', 1), ['A', 'R1'], lambda self, il: [il.set_reg(1, LLIL_TEMP(1), il.reg(1, 'A')), il.set_reg(1, 'A', self.wreg_get(il, 1)), self.wreg_set(il, 1, il.reg(1, LLIL_TEMP(1)))]], [('XCH', 1), ['A', 'R2'], lambda self, il: [il.set_reg(1, LLIL_TEMP(1), il.reg(1, 'A')), il.set_reg(1, 'A', self.wreg_get(il, 2)), self.wreg_set(il, 2, il.reg(1, LLIL_TEMP(1)))]], [('XCH', 1), ['A', 'R3'], lambda self, il: [il.set_reg(1, LLIL_TEMP(1), il.reg(1, 'A')), il.set_reg(1, 'A', self.wreg_get(il, 3)), self.wreg_set(il, 3, il.reg(1, LLIL_TEMP(1)))]], [('XCH', 1), ['A', 'R4'], lambda self, il: [il.set_reg(1, LLIL_TEMP(1), il.reg(1, 'A')), il.set_reg(1, 'A', self.wreg_get(il, 4)), self.wreg_set(il, 4, il.reg(1, LLIL_TEMP(1)))]], [('XCH', 1), ['A', 'R5'], lambda self, il: [il.set_reg(1, LLIL_TEMP(1), il.reg(1, 'A')), il.set_reg(1, 'A', self.wreg_get(il, 5)), self.wreg_set(il, 5, il.reg(1, LLIL_TEMP(1)))]], [('XCH', 1), ['A', 'R6'], lambda self, il: [il.set_reg(1, LLIL_TEMP(1), il.reg(1, 'A')), il.set_reg(1, 'A', self.wreg_get(il, 6)), self.wreg_set(il, 6, il.reg(1, LLIL_TEMP(1)))]], [('XCH', 1), ['A', 'R7'], lambda self, il: [il.set_reg(1, LLIL_TEMP(1), il.reg(1, 'A')), il.set_reg(1, 'A', self.wreg_get(il, 7)), self.wreg_set(il, 7, il.reg(1, LLIL_TEMP(1)))]], # 0x30-0x3f [('XCHD', 1), ['A', '@R0']], [('XCHD', 1), ['A', '@R1']], [('JB1', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'B', 1)], None, [('CALL', 2), ['ADDR11'], lambda self, il, imm: call_helper(il, CODE_ADDR(0x100, imm))], [('DIS', 1), ['TCNTI']], [('JT0', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'T0', 1)], [('CPL', 1), ['A'], lambda self, il: il.set_reg(1, 'A', il.not_expr(1, il.reg(1, 'A')))], None, [('OUTL', 1), ['P1', 'A'], lambda self, il: il.reg(1, 'A')], # dummy read [('OUTL', 1), ['P2', 'A'], lambda self, il: il.reg(1, 'A')], # dummy read None, [('MOVD', 1), ['P4', 'A'], lambda self, il: il.reg(1, 'A')], # dummy read [('MOVD', 1), ['P5', 'A'], lambda self, il: il.reg(1, 'A')], # dummy read [('MOVD', 1), ['P6', 'A'], lambda self, il: il.reg(1, 'A')], # dummy read [('MOVD', 1), ['P7', 'A'], lambda self, il: il.reg(1, 'A')], # dummy read # 0x40-0x4f [('ORL', 1), ['A', '@R0'], lambda self, il: il.set_reg(1, 'A', il.or_expr(1, il.reg(1, 'A'), il.load(1, self.wreg_get(il, 0))))], [('ORL', 1), ['A', '@R1'], lambda self, il: il.set_reg(1, 'A', il.or_expr(1, il.reg(1, 'A'), il.load(1, self.wreg_get(il, 1))))], [('MOV', 1), ['A', 'T'], lambda self, il: il.set_reg(1, 'A', il.reg(1, 'T'))], [('ORL', 2), ['A', '#IMM8'], lambda self, il, imm: il.set_reg(1, 'A', il.or_expr(1, il.reg(1, 'A'), il.const(1, imm)))], [('JMP', 2), ['ADDR11'], lambda self, il, imm: branch(il, CODE_ADDR(0x200, imm))], [('STRT', 1), ['CNT']], [('JNT1', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'T1', 0)], [('SWAP', 1), ['A'], lambda self, il: il.set_reg(1, 'A', il.rotate_left(1, il.reg(1, 'A'), il.const(1, 4)))], [('ORL', 1), ['A', 'R0'], lambda self, il: il.set_reg(1, 'A', il.or_expr(1, il.reg(1, 'A'), self.wreg_get(il, 0)))], [('ORL', 1), ['A', 'R1'], lambda self, il: il.set_reg(1, 'A', il.or_expr(1, il.reg(1, 'A'), self.wreg_get(il, 1)))], [('ORL', 1), ['A', 'R2'], lambda self, il: il.set_reg(1, 'A', il.or_expr(1, il.reg(1, 'A'), self.wreg_get(il, 2)))], [('ORL', 1), ['A', 'R3'], lambda self, il: il.set_reg(1, 'A', il.or_expr(1, il.reg(1, 'A'), self.wreg_get(il, 3)))], [('ORL', 1), ['A', 'R4'], lambda self, il: il.set_reg(1, 'A', il.or_expr(1, il.reg(1, 'A'), self.wreg_get(il, 4)))], [('ORL', 1), ['A', 'R5'], lambda self, il: il.set_reg(1, 'A', il.or_expr(1, il.reg(1, 'A'), self.wreg_get(il, 5)))], [('ORL', 1), ['A', 'R6'], lambda self, il: il.set_reg(1, 'A', il.or_expr(1, il.reg(1, 'A'), self.wreg_get(il, 6)))], [('ORL', 1), ['A', 'R7'], lambda self, il: il.set_reg(1, 'A', il.or_expr(1, il.reg(1, 'A'), self.wreg_get(il, 7)))], # 0x50-0x5f [('ANL', 1), ['A', '@R0'], lambda self, il: il.set_reg(1, 'A', il.and_expr(1, il.reg(1, 'A'), il.load(1, self.wreg_get(il, 0))))], [('ANL', 1), ['A', '@R1'], lambda self, il: il.set_reg(1, 'A', il.and_expr(1, il.reg(1, 'A'), il.load(1, self.wreg_get(il, 1))))], [('JB2', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'B', 2)], [('ANL', 2), ['A', '#IMM8'], lambda self, il, imm: il.set_reg(1, 'A', il.and_expr(1, il.reg(1, 'A'), il.const(1, imm)))], [('CALL', 2), ['ADDR11'], lambda self, il, imm: call_helper(il, CODE_ADDR(0x200, imm))], [('STRT', 1), ['T'], lambda self, il: il.reg(1, 'T')], # DUMMY [('JT1', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'T1', 1)], [('DA', 1), ['A']], [('ANL', 1), ['A', 'R0'], lambda self, il: il.set_reg(1, 'A', il.and_expr(1, il.reg(1, 'A'), self.wreg_get(il, 0)))], [('ANL', 1), ['A', 'R1'], lambda self, il: il.set_reg(1, 'A', il.and_expr(1, il.reg(1, 'A'), self.wreg_get(il, 1)))], [('ANL', 1), ['A', 'R2'], lambda self, il: il.set_reg(1, 'A', il.and_expr(1, il.reg(1, 'A'), self.wreg_get(il, 2)))], [('ANL', 1), ['A', 'R3'], lambda self, il: il.set_reg(1, 'A', il.and_expr(1, il.reg(1, 'A'), self.wreg_get(il, 3)))], [('ANL', 1), ['A', 'R4'], lambda self, il: il.set_reg(1, 'A', il.and_expr(1, il.reg(1, 'A'), self.wreg_get(il, 4)))], [('ANL', 1), ['A', 'R5'], lambda self, il: il.set_reg(1, 'A', il.and_expr(1, il.reg(1, 'A'), self.wreg_get(il, 5)))], [('ANL', 1), ['A', 'R6'], lambda self, il: il.set_reg(1, 'A', il.and_expr(1, il.reg(1, 'A'), self.wreg_get(il, 6)))], [('ANL', 1), ['A', 'R7'], lambda self, il: il.set_reg(1, 'A', il.and_expr(1, il.reg(1, 'A'), self.wreg_get(il, 7)))], # 0x60-0x6f [('ADD', 1), ['A', '@R0'], lambda self, il: il.set_reg(1, 'A', il.add(1, il.reg(1, 'A'), il.load(1, self.wreg_get(il, 0)), 'C'))], [('ADD', 1), ['A', '@R1'], lambda self, il: il.set_reg(1, 'A', il.add(1, il.reg(1, 'A'), il.load(1, self.wreg_get(il, 1)), 'C'))], [('MOV', 1), ['T', 'A'], lambda self, il: il.set_reg(1, 'T', il.reg(1, 'A'))], None, [('JMP', 2), ['ADDR11'], lambda self, il, imm: branch(il, CODE_ADDR(0x300, imm))], [('STOP', 1), ['TCNT']], None, [('RRC', 1), ['A'], lambda self, il: il.set_reg(1, 'A', il.rotate_right_carry(1, il.reg(1, 'A'), il.const(1, 1), il.flag('CY'), 'C'))], [('ADD', 1), ['A', 'R0'], lambda self, il: il.set_reg(1, 'A', il.add(1, il.reg(1, 'A'), self.wreg_get(il, 0), 'C'))], [('ADD', 1), ['A', 'R1'], lambda self, il: il.set_reg(1, 'A', il.add(1, il.reg(1, 'A'), self.wreg_get(il, 1), 'C'))], [('ADD', 1), ['A', 'R2'], lambda self, il: il.set_reg(1, 'A', il.add(1, il.reg(1, 'A'), self.wreg_get(il, 2), 'C'))], [('ADD', 1), ['A', 'R3'], lambda self, il: il.set_reg(1, 'A', il.add(1, il.reg(1, 'A'), self.wreg_get(il, 3), 'C'))], [('ADD', 1), ['A', 'R4'], lambda self, il: il.set_reg(1, 'A', il.add(1, il.reg(1, 'A'), self.wreg_get(il, 4), 'C'))], [('ADD', 1), ['A', 'R5'], lambda self, il: il.set_reg(1, 'A', il.add(1, il.reg(1, 'A'), self.wreg_get(il, 5), 'C'))], [('ADD', 1), ['A', 'R6'], lambda self, il: il.set_reg(1, 'A', il.add(1, il.reg(1, 'A'), self.wreg_get(il, 6), 'C'))], [('ADD', 1), ['A', 'R7'], lambda self, il: il.set_reg(1, 'A', il.add(1, il.reg(1, 'A'), self.wreg_get(il, 7), 'C'))], # 0x70-0x7f [('ADDC', 1), ['A', '@R0'], lambda self, il: il.set_reg(1, 'A', il.add_carry(1, il.reg(1, 'A'), il.load(1, self.wreg_get(il, 0)), il.flag('CY'), 'C'))], [('ADDC', 1), ['A', '@R1'], lambda self, il: il.set_reg(1, 'A', il.add_carry(1, il.reg(1, 'A'), il.load(1, self.wreg_get(il, 1)), il.flag('CY'), 'C'))], [('JB3', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'B', 3)], None, [('CALL', 2), ['ADDR11'], lambda self, il, imm: call_helper(il, CODE_ADDR(0x300, imm))], [('ENT0', 1), ['CLK']], [('JF1', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'F1', 1)], [('RR', 1), ['A'], lambda self, il: il.set_reg(1, 'A', il.rotate_right(1, il.reg(1, 'A'), il.const(1, 1)))], [('ADDC', 1), ['A', 'R0'], lambda self, il: il.set_reg(1, 'A', il.add_carry(1, il.reg(1, 'A'), self.wreg_get(il, 0), il.flag('CY'), 'C'))], [('ADDC', 1), ['A', 'R1'], lambda self, il: il.set_reg(1, 'A', il.add_carry(1, il.reg(1, 'A'), self.wreg_get(il, 1), il.flag('CY'), 'C'))], [('ADDC', 1), ['A', 'R2'], lambda self, il: il.set_reg(1, 'A', il.add_carry(1, il.reg(1, 'A'), self.wreg_get(il, 2), il.flag('CY'), 'C'))], [('ADDC', 1), ['A', 'R3'], lambda self, il: il.set_reg(1, 'A', il.add_carry(1, il.reg(1, 'A'), self.wreg_get(il, 3), il.flag('CY'), 'C'))], [('ADDC', 1), ['A', 'R4'], lambda self, il: il.set_reg(1, 'A', il.add_carry(1, il.reg(1, 'A'), self.wreg_get(il, 4), il.flag('CY'), 'C'))], [('ADDC', 1), ['A', 'R5'], lambda self, il: il.set_reg(1, 'A', il.add_carry(1, il.reg(1, 'A'), self.wreg_get(il, 5), il.flag('CY'), 'C'))], [('ADDC', 1), ['A', 'R6'], lambda self, il: il.set_reg(1, 'A', il.add_carry(1, il.reg(1, 'A'), self.wreg_get(il, 6), il.flag('CY'), 'C'))], [('ADDC', 1), ['A', 'R7'], lambda self, il: il.set_reg(1, 'A', il.add_carry(1, il.reg(1, 'A'), self.wreg_get(il, 7), il.flag('CY'), 'C'))], # 0x80-0x8f [('MOVX', 1), ['A', '@R0']], [('MOVX', 1), ['A', '@R1']], None, [('RET', 1), [], lambda self, il: ret_helper(il, False)], [('JMP', 2), ['ADDR11'], lambda self, il, imm: branch(il, CODE_ADDR(0x400, imm))], [('CLR', 1), ['F0'], lambda self, il: il.set_flag('F0', il.const(0, 0))], [('JNI', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'INT', 0)], None, [('ORL', 2), ['BUS', '#IMM8']], [('ORL', 2), ['P1', '#IMM8']], [('ORL', 2), ['P2', '#IMM8']], None, [('ORLD', 1), ['P4', 'A'], lambda self, il: il.reg(1, 'A')], # dummy read [('ORLD', 1), ['P5', 'A'], lambda self, il: il.reg(1, 'A')], # dummy read [('ORLD', 1), ['P6', 'A'], lambda self, il: il.reg(1, 'A')], # dummy read [('ORLD', 1), ['P7', 'A'], lambda self, il: il.reg(1, 'A')], # dummy read # 0x90-0x9f [('MOVX', 1), ['@R0', 'A']], [('MOVX', 1), ['@R1', 'A']], [('JB4', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'B', 4)], [('RETR', 1), [], lambda self, il: ret_helper(il, True)], [('CALL', 2), ['ADDR11'], lambda self, il, imm: call_helper(il, CODE_ADDR(0x400, imm))], [('CPL', 1), ['F0'], lambda self, il: il.set_flag('F0', il.not_expr(0, il.flag('F0')))], [('JNZ', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'NZ')], [('CLR', 1), ['C'], lambda self, il: il.set_flag('CY', il.const(0, 0))], [('ANL', 2), ['BUS', '#IMM8']], [('ANL', 2), ['P1', '#IMM8']], [('ANL', 2), ['P2', '#IMM8']], None, [('ANLD', 1), ['P4', 'A'], lambda self, il: il.reg(1, 'A')], # dummy read [('ANLD', 1), ['P5', 'A'], lambda self, il: il.reg(1, 'A')], # dummy read [('ANLD', 1), ['P6', 'A'], lambda self, il: il.reg(1, 'A')], # dummy read [('ANLD', 1), ['P7', 'A'], lambda self, il: il.reg(1, 'A')], # dummy read # 0xa0-0xaf [('MOV', 1), ['@R0', 'A'], lambda self, il: il.store(1, self.wreg_get(il, 0), il.reg(1, 'A'))], [('MOV', 1), ['@R1', 'A'], lambda self, il: il.store(1, self.wreg_get(il, 1), il.reg(1, 'A'))], None, [('MOVP', 1), ['A', '@A'], lambda self, il: il.set_reg(1, 'A', il.load(1, il.or_expr(2, il.const(2, CODE_ADDR(il.current_address + 1, 0)), il.reg(1, 'A'))))], [('JMP', 2), ['ADDR11'], lambda self, il, imm: branch(il, CODE_ADDR(0x500, imm))], [('CLR', 1), ['F1'], lambda self, il: il.set_flag('F1', il.const(0, 0))], None, [('CPL', 1), ['C'], lambda self, il: il.set_flag('CY', il.not_expr(0, il.flag('CY')))], [('MOV', 1), ['R0', 'A'], lambda self, il: self.wreg_set(il, 0, il.reg(1, 'A'))], [('MOV', 1), ['R1', 'A'], lambda self, il: self.wreg_set(il, 1, il.reg(1, 'A'))], [('MOV', 1), ['R2', 'A'], lambda self, il: self.wreg_set(il, 2, il.reg(1, 'A'))], [('MOV', 1), ['R3', 'A'], lambda self, il: self.wreg_set(il, 3, il.reg(1, 'A'))], [('MOV', 1), ['R4', 'A'], lambda self, il: self.wreg_set(il, 4, il.reg(1, 'A'))], [('MOV', 1), ['R5', 'A'], lambda self, il: self.wreg_set(il, 5, il.reg(1, 'A'))], [('MOV', 1), ['R6', 'A'], lambda self, il: self.wreg_set(il, 6, il.reg(1, 'A'))], [('MOV', 1), ['R7', 'A'], lambda self, il: self.wreg_set(il, 7, il.reg(1, 'A'))], # 0xb0-0xbf [('MOV', 2), ['@R0', '#IMM8'], lambda self, il, imm: il.store(1, self.wreg_get(il, 0), il.const(1, imm))], [('MOV', 2), ['@R1', '#IMM8'], lambda self, il, imm: il.store(1, self.wreg_get(il, 1), il.const(1, imm))], [('JB5', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'B', 5)], [('JMPP', 1), ['@A'], lambda self, il: il.jump(il.or_expr(2, il.const(2, CODE_ADDR(il.current_address, 0)), il.reg(1, 'A')))], # FIXME: addr + 1? [('CALL', 2), ['ADDR11'], lambda self, il, imm: call_helper(il, CODE_ADDR(0x500, imm))], [('CPL', 1), ['F1'], lambda self, il: il.set_flag('F1', il.not_expr(0, il.flag('F1')))], [('JF0', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'F0', 1)], None, [('MOV', 2), ['R0', '#IMM8'], lambda self, il, imm: self.wreg_set(il, 0, il.const(1, imm))], [('MOV', 2), ['R1', '#IMM8'], lambda self, il, imm: self.wreg_set(il, 1, il.const(1, imm))], [('MOV', 2), ['R2', '#IMM8'], lambda self, il, imm: self.wreg_set(il, 2, il.const(1, imm))], [('MOV', 2), ['R3', '#IMM8'], lambda self, il, imm: self.wreg_set(il, 3, il.const(1, imm))], [('MOV', 2), ['R4', '#IMM8'], lambda self, il, imm: self.wreg_set(il, 4, il.const(1, imm))], [('MOV', 2), ['R5', '#IMM8'], lambda self, il, imm: self.wreg_set(il, 5, il.const(1, imm))], [('MOV', 2), ['R6', '#IMM8'], lambda self, il, imm: self.wreg_set(il, 6, il.const(1, imm))], [('MOV', 2), ['R7', '#IMM8'], lambda self, il, imm: self.wreg_set(il, 7, il.const(1, imm))], # 0xc0-0xcf None, None, None, None, [('JMP', 2), ['ADDR11'], lambda self, il, imm: branch(il, CODE_ADDR(0x600, imm))], [('SEL', 1), ['RB0'], lambda self, il: il.set_flag('BS', il.const(0, 0))], [('JZ', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'Z')], [('MOV', 1), ['A', 'PSW'], lambda self, il: il.set_reg(1, 'A', il.reg(1, 'PSW'))], [('DEC', 1), ['R0'], lambda self, il: self.wreg_set(il, 0, il.sub(1, self.wreg_get(il, 0), il.const(1, 1)))], [('DEC', 1), ['R1'], lambda self, il: self.wreg_set(il, 1, il.sub(1, self.wreg_get(il, 1), il.const(1, 1)))], [('DEC', 1), ['R2'], lambda self, il: self.wreg_set(il, 2, il.sub(1, self.wreg_get(il, 2), il.const(1, 1)))], [('DEC', 1), ['R3'], lambda self, il: self.wreg_set(il, 3, il.sub(1, self.wreg_get(il, 3), il.const(1, 1)))], [('DEC', 1), ['R4'], lambda self, il: self.wreg_set(il, 4, il.sub(1, self.wreg_get(il, 4), il.const(1, 1)))], [('DEC', 1), ['R5'], lambda self, il: self.wreg_set(il, 5, il.sub(1, self.wreg_get(il, 5), il.const(1, 1)))], [('DEC', 1), ['R6'], lambda self, il: self.wreg_set(il, 6, il.sub(1, self.wreg_get(il, 6), il.const(1, 1)))], [('DEC', 1), ['R7'], lambda self, il: self.wreg_set(il, 7, il.sub(1, self.wreg_get(il, 7), il.const(1, 1)))], # 0xd0-0xdf [('XRL', 1), ['A', '@R0'], lambda self, il: il.set_reg(1, 'A', il.xor_expr(1, il.reg(1, 'A'), il.load(1, self.wreg_get(il, 0))))], [('XRL', 1), ['A', '@R1'], lambda self, il: il.set_reg(1, 'A', il.xor_expr(1, il.reg(1, 'A'), il.load(1, self.wreg_get(il, 1))))], [('JB6', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'B', 6)], [('XRL', 2), ['A', '#IMM8'], lambda self, il, imm: il.set_reg(1, 'A', il.xor_expr(1, il.reg(1, 'A'), il.const(1, imm)))], [('CALL', 2), ['ADDR11'], lambda self, il, imm: call_helper(il, CODE_ADDR(0x600, imm))], [('SEL', 1), ['RB1'], lambda self, il: il.set_flag('BS', il.const(0, 1))], None, [('MOV', 1), ['PSW', 'A'], lambda self, il: il.set_reg(1, 'PSW', il.reg(1, 'A'))], # TODO: set/clear flags [('XRL', 1), ['A', 'R0'], lambda self, il: il.set_reg(1, 'A', il.xor_expr(1, il.reg(1, 'A'), self.wreg_get(il, 0)))], [('XRL', 1), ['A', 'R1'], lambda self, il: il.set_reg(1, 'A', il.xor_expr(1, il.reg(1, 'A'), self.wreg_get(il, 1)))], [('XRL', 1), ['A', 'R2'], lambda self, il: il.set_reg(1, 'A', il.xor_expr(1, il.reg(1, 'A'), self.wreg_get(il, 2)))], [('XRL', 1), ['A', 'R3'], lambda self, il: il.set_reg(1, 'A', il.xor_expr(1, il.reg(1, 'A'), self.wreg_get(il, 3)))], [('XRL', 1), ['A', 'R4'], lambda self, il: il.set_reg(1, 'A', il.xor_expr(1, il.reg(1, 'A'), self.wreg_get(il, 4)))], [('XRL', 1), ['A', 'R5'], lambda self, il: il.set_reg(1, 'A', il.xor_expr(1, il.reg(1, 'A'), self.wreg_get(il, 5)))], [('XRL', 1), ['A', 'R6'], lambda self, il: il.set_reg(1, 'A', il.xor_expr(1, il.reg(1, 'A'), self.wreg_get(il, 6)))], [('XRL', 1), ['A', 'R7'], lambda self, il: il.set_reg(1, 'A', il.xor_expr(1, il.reg(1, 'A'), self.wreg_get(il, 7)))], # 0xe0-0xef None, None, None, [('MOVP3', 1), ['A', '@A'], lambda self, il: il.set_reg(1, 'A', il.load(1, il.or_expr(2, il.const(2, CODE_ADDR(0x300, 0)), il.reg(1, 'A'))))], [('JMP', 2), ['ADDR11'], lambda self, il, imm: branch(il, CODE_ADDR(0x700, imm))], [('SEL', 1), ['MB0'], lambda self, il: il.set_flag('DBF', il.const(0, 0))], [('JNC', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'CY', 0)], [('RL', 1), ['A'], lambda self, il: il.set_reg(1, 'A', il.rotate_left(1, il.reg(1, 'A'), il.const(1, 1)))], [('DJNZ', 2), ['R0', 'ADDR8'], lambda self, il, imm: self.djnz_helper(il, CODE_ADDR(il.current_address, imm), 0)], [('DJNZ', 2), ['R1', 'ADDR8'], lambda self, il, imm: self.djnz_helper(il, CODE_ADDR(il.current_address, imm), 1)], [('DJNZ', 2), ['R2', 'ADDR8'], lambda self, il, imm: self.djnz_helper(il, CODE_ADDR(il.current_address, imm), 2)], [('DJNZ', 2), ['R3', 'ADDR8'], lambda self, il, imm: self.djnz_helper(il, CODE_ADDR(il.current_address, imm), 3)], [('DJNZ', 2), ['R4', 'ADDR8'], lambda self, il, imm: self.djnz_helper(il, CODE_ADDR(il.current_address, imm), 4)], [('DJNZ', 2), ['R5', 'ADDR8'], lambda self, il, imm: self.djnz_helper(il, CODE_ADDR(il.current_address, imm), 5)], [('DJNZ', 2), ['R6', 'ADDR8'], lambda self, il, imm: self.djnz_helper(il, CODE_ADDR(il.current_address, imm), 6)], [('DJNZ', 2), ['R7', 'ADDR8'], lambda self, il, imm: self.djnz_helper(il, CODE_ADDR(il.current_address, imm), 7)], # 0xf0-0xff [('MOV', 1), ['A', '@R0'], lambda self, il: il.set_reg(1, 'A', il.load(1, self.wreg_get(il, 0)))], [('MOV', 1), ['A', '@R1'], lambda self, il: il.set_reg(1, 'A', il.load(1, self.wreg_get(il, 1)))], [('JB7', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'B', 7)], None, [('CALL', 2), ['ADDR11'], lambda self, il, imm: call_helper(il, CODE_ADDR(0x700, imm))], [('SEL', 1), ['MB1'], lambda self, il: il.set_flag('DBF', il.const(0, 1))], [('JC', 2), ['ADDR8'], lambda self, il, imm: cond_branch(il, CODE_ADDR(il.current_address, imm), 'CY', 1)], [('RLC', 1), ['A'], lambda self, il: il.set_reg(1, 'A', il.rotate_left_carry(1, il.reg(1, 'A'), il.const(1, 1), il.flag('CY')))], [('MOV', 1), ['A', 'R0'], lambda self, il: il.set_reg(1, 'A', self.wreg_get(il, 0))], [('MOV', 1), ['A', 'R1'], lambda self, il: il.set_reg(1, 'A', self.wreg_get(il, 1))], [('MOV', 1), ['A', 'R2'], lambda self, il: il.set_reg(1, 'A', self.wreg_get(il, 2))], [('MOV', 1), ['A', 'R3'], lambda self, il: il.set_reg(1, 'A', self.wreg_get(il, 3))], [('MOV', 1), ['A', 'R4'], lambda self, il: il.set_reg(1, 'A', self.wreg_get(il, 4))], [('MOV', 1), ['A', 'R5'], lambda self, il: il.set_reg(1, 'A', self.wreg_get(il, 5))], [('MOV', 1), ['A', 'R6'], lambda self, il: il.set_reg(1, 'A', self.wreg_get(il, 6))], [('MOV', 1), ['A', 'R7'], lambda self, il: il.set_reg(1, 'A', self.wreg_get(il, 7))], ] def get_instruction_info(self, data, addr): # instruction lookup instruction = self.instructions[ord(data[0])] if instruction is None: return None (opcode, length) = instruction[0] result = InstructionInfo() result.length = length # add branches if opcode in ['RET', 'RETI', 'RETR']: result.add_branch(BranchType.FunctionReturn) elif opcode in ['JMP']: # TODO: memory bank selection result.add_branch(BranchType.UnconditionalBranch, CODE_ADDR((ord(data[0]) & 0xe0) << 3, ord(data[1]))) elif opcode in ['JMPP']: result.add_branch(BranchType.UnresolvedBranch) elif opcode == 'DJNZ' or opcode[0] == 'J': # conditional branches result.add_branch(BranchType.TrueBranch, CODE_ADDR(addr, ord(data[1]))) result.add_branch(BranchType.FalseBranch, addr + length) elif opcode == 'CALL': # TODO: memory bank selection result.add_branch(BranchType.CallDestination, CODE_ADDR((ord(data[0]) & 0xe0) << 3, ord(data[1]))) elif opcode == 'SEL': # FIXME: fake branches to support bank switching if instruction[1][0] == 'RB0': result.add_branch(BranchType.UnconditionalBranch, addr + length, Architecture['{}_rb{}mb{}'.format(self.device, 0, self.mb)]) elif instruction[1][0] == 'RB1': result.add_branch(BranchType.UnconditionalBranch, addr + length, Architecture['{}_rb{}mb{}'.format(self.device, 1, self.mb)]) elif instruction[1][0] == 'MB0': result.add_branch(BranchType.UnconditionalBranch, addr + length, Architecture['{}_rb{}mb{}'.format(self.device, self.rb, 0)]) elif instruction[1][0] == 'MB1': result.add_branch(BranchType.UnconditionalBranch, addr + length, Architecture['{}_rb{}mb{}'.format(self.device, self.rb, 1)]) return result def get_instruction_text(self, data, addr): # instruction lookup instruction = self.instructions[ord(data[0])] if instruction is None: return None (opcode, length) = instruction[0] # opcode tokens = [InstructionTextToken(InstructionTextTokenType.InstructionToken, '{:6}'.format(opcode))] # operands for operand in instruction[1]: # add a separator if needed if len(tokens) > 1: tokens += [InstructionTextToken(InstructionTextTokenType.OperandSeparatorToken, ',')] # append suffix for second bank working registers if self.rb == 1 and re.match('\@?R\d', operand) is not None: operand += '\'' if operand == '#IMM8': immediate = ord(data[1]) tokens += [InstructionTextToken(InstructionTextTokenType.IntegerToken, '#{:X}H'.format(immediate), immediate)] elif operand == 'ADDR8': address = (addr & 0xf00) | ord(data[1]) tokens += [InstructionTextToken(InstructionTextTokenType.PossibleAddressToken, '{:X}H'.format(address), CODE_ADDR(0, address))] elif operand == 'ADDR11': # TODO: memory bank selection address = ((ord(data[0]) & 0xe0) << 3) | ord(data[1]) tokens += [InstructionTextToken(InstructionTextTokenType.PossibleAddressToken, '{:X}H'.format(address), CODE_ADDR(0, address))] elif operand in self.regs: tokens += [InstructionTextToken(InstructionTextTokenType.RegisterToken, operand)] elif operand[0] == '@' and operand[1:] in self.regs: tokens += [InstructionTextToken(InstructionTextTokenType.InstructionToken, '@'), InstructionTextToken(InstructionTextTokenType.RegisterToken, operand[1:])] else: tokens += [InstructionTextToken(InstructionTextTokenType.TextToken, operand)] return tokens, length def get_instruction_low_level_il(self, data, addr, il): # instruction lookup instruction = self.instructions[ord(data[0])] if instruction is None: return None (opcode, length) = instruction[0] if len(instruction) == 3: # instructions are either one byte (opcode) or two bytes (opcode + immediate) if length == 1: il_instr = instruction[2](self, il) else: il_instr = instruction[2](self, il, ord(data[1])) if isinstance(il_instr, list): for i in [i for i in il_instr if i is not None]: il.append(i) elif il_instr is not None: il.append(il_instr) else: il.append(il.unimplemented()) return length def get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il): if flag == 'CY': if op == LowLevelILOperation.LLIL_RRC: return il.and_expr(1, il.reg(1, operands[0]), il.const(1, 0x01)) elif op == LowLevelILOperation.LLIL_RLC: return il.and_expr(1, il.reg(1, operands[0]), il.const(1, 0x80)) return Architecture.perform_get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il) def wreg_set(self, il, reg, expr): if WREG_REG: il.append(il.set_reg(1, 'R{}'.format(reg) if self.rb == 0 else 'R{}\''.format(reg), expr)) else: il.append(il.store(1, il.const_pointer(1, reg if self.rb == 0 else reg + 24), expr)) def wreg_get(self, il, reg): if WREG_REG: return il.reg(1, 'R{}'.format(reg) if self.rb == 0 else 'R{}\''.format(reg)) else: return il.load(1, il.const_pointer(1, reg if self.rb == 0 else reg + 24)) def djnz_helper(self, il, addr, reg): # decrement the register self.wreg_set(il, reg, il.sub(1, self.wreg_get(il, reg), il.const(1, 1))) # try to find a label for the branch target taken = il.get_label_for_address(il.arch, addr) # create taken target taken_found = True if taken is None: taken = LowLevelILLabel() taken_found = False # create untaken target untaken_found = True untaken = il.get_label_for_address(il.arch, il.current_address + 2) if untaken is None: untaken = LowLevelILLabel() untaken_found = False # generate the conditional branch LLIL il.append(il.if_expr(il.compare_not_equal(1, self.wreg_get(il, reg), il.const(1, 0)), taken, untaken)) # generate a jump to the branch target if a label couldn't be found if not taken_found: il.mark_label(taken) il.append(il.jump(il.const(2, addr))) # generate a label for the untaken branch if not untaken_found: il.mark_label(untaken)
def lift(self, il, addr): w = self.width() temp = LLIL_TEMP(il.temp_reg_count) il.append(il.set_reg(w, temp, il.reg(w, self.regL()))) il.append(il.set_reg(w, self.regL(), self._lift_reg_mem(il))) il.append(self._lift_reg_mem(il, store=il.reg(w, temp)))