Beispiel #1
0
 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)))
Beispiel #3
0
 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)
Beispiel #4
0
 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))))
Beispiel #5
0
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)
Beispiel #6
0
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
Beispiel #7
0
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)))
Beispiel #8
0
 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)))
Beispiel #9
0
 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)))
Beispiel #10
0
 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)))
Beispiel #11
0
    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)
        )
    ))
Beispiel #13
0
 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)))
Beispiel #14
0
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())
Beispiel #15
0
 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)
Beispiel #16
0
 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)
Beispiel #18
0
 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)))