예제 #1
0
def encode_dataprocop(name, flags, condcode, operands):
    """
    check_dataprocop must be called before this.
    Encode the instruction and return it as a bytearray object.
    """
    operands = [x.strip() for x in operands.split(',')]
    sflag = (flags == 'S')
    if helpers.is_dataproc_fullop(name):
        dest = helpers.get_reg_num(operands[0])
        op1 = helpers.get_reg_num(operands[1])
        (iflag, op2) = encode_op2(','.join(operands[2:]))
    elif helpers.is_dataproc_testop(name):
        dest = 0
        op1 = helpers.get_reg_num(operands[0])
        (iflag, op2) = encode_op2(','.join(operands[1:]))
        sflag = True
    else:  # movop
        dest = helpers.get_reg_num(operands[0])
        op1 = 0
        (iflag, op2) = encode_op2(','.join(operands[1:]))
    ccval = helpers.get_condcode_value(condcode)
    dpn = helpers.get_dataprocop_num(name)
    encoded = helpers.encode_32bit([(28, 4, ccval), (25, 1, iflag),
                                    (21, 4, dpn), (20, 1, sflag), (16, 4, op1),
                                    (12, 4, dest), (0, 12, op2)])
    return helpers.bigendian_to_littleendian(encoded)
예제 #2
0
def encode_directive(name, operands, address):
    """
    check_directive must be called before this.
    Address must be the address of the directive.
    Encode the directive and return it as a bytes object.
    """
    if name == 'DCD' or name == 'DCDU':
        operands = [x.strip() for x in operands.split(',')]
        encoded = b''
        if name == 'DCD':
            encoded += b'\x00' * ((4 - (address % 4)) % 4)  # align
        for op in operands:
            i = helpers.numeric_literal_to_int(op)
            encoded += helpers.bigendian_to_littleendian(
                helpers.encode_32bit([(0, 32, i)]))
        return encoded
    if name == 'DCW' or name == 'DCWU':
        operands = [x.strip() for x in operands.split(',')]
        encoded = b''
        if name == 'DCW':
            encoded += b'\x00' * (address % 2)  # align
        for op in operands:
            i = helpers.numeric_literal_to_int(op)
            encoded += helpers.bigendian_to_littleendian_16bit(
                helpers.encode_16bit([(0, 16, i)]))
        return encoded
    if name == 'ALIGN':
        operands = [x.strip() for x in operands.split(',')]
        if len(operands) == 0 or len(
                operands[0]) == 0:  # implicit alignment to 4 bytes
            alignment = 4
        else:
            alignment = helpers.numeric_literal_to_int(operands[0])
        if len(operands) < 2:
            offset = 0
        else:
            offset = helpers.numeric_literal_to_int(operands[1])
        padsize = ((alignment - ((address + alignment - offset) % alignment)) %
                   alignment)
        return padsize * b'\x00'
    if name == 'DCB':
        operands = [x.strip() for x in operands.split(',')]
        encoded = b''
        for op in operands:
            if op[0] == '"':
                op = op[1:-1]
                for c in op:
                    c = ord(c)
                    encoded += bytes([c])
            else:  # is valid numeric literal because has to be checked before
                i = helpers.numeric_literal_to_int(op)
                encoded += bytes([i])
        return encoded
    if name == 'INCBIN':
        return filedict.filecontents(operands)
    return b''  # should never be reached
예제 #3
0
def encode_branchop(name, condcode, operands, address, labeldict):
    """
    check_branchop must be called before this.
    Encode the instruction and return it as a bytearray object.
    """
    operands = operands.strip()
    if name == 'BX':
        rn = helpers.get_reg_num(operands)
        ccval = helpers.get_condcode_value(condcode)
        encoded = helpers.encode_32bit([(28, 4, ccval), (4, 24, 0x12FFF1), (0, 4, rn)])
        return helpers.bigendian_to_littleendian(encoded)
    else:
        offset = helpers.pcrelative_expression_to_int(operands, address, labeldict)
        offset >>= 2
        offset = offset + (offset < 0)*(1 << 24)  # correction for negative offsets
        ccval = helpers.get_condcode_value(condcode)
        lflag = (name == 'BL')
        encoded = helpers.encode_32bit([(28, 4, ccval), (25, 3, 0x5), (24, 1, lflag), (0, 24, offset)])
        return helpers.bigendian_to_littleendian(encoded)
예제 #4
0
def encode_swiop(name, condcode, operands):
    """
    check_swiop must be called before this.
    Encode the instruction and return it as a bytearray object.
    """
    operands = operands.strip()
    ccval = helpers.get_condcode_value(condcode)
    com = helpers.imval_to_int(operands)
    encoded = helpers.encode_32bit([(28, 4, ccval), (24, 4, 0xF), (0, 24, com)])
    return helpers.bigendian_to_littleendian(encoded)
예제 #5
0
def encode_miscarithmeticop(name, condcode, operands):
    """
    check_miscarithmeticop must be called before this.
    Encode the instruction and return it as a bytearray object.
    """
    operands = [x.strip() for x in operands.split(',')]
    rd = helpers.get_reg_num(operands[0])
    rm = helpers.get_reg_num(operands[1])
    ccval = helpers.get_condcode_value(condcode)
    encoded = helpers.encode_32bit([(28, 4, ccval), (16, 12, 0x16F), (12, 4, rd), (4, 8, 0xF1), (0, 4, rm)])
    return helpers.bigendian_to_littleendian(encoded)
예제 #6
0
def encode_longmulop(name, flags, condcode, operands):
    """
    check_longmulop must be called before this.
    Encode the instruction and return it as a bytearray object.
    """
    (rdlo, rdhi, rm, rs) = [helpers.get_reg_num(x.strip()) for x in operands.split(',')]
    sflag = (flags == 'S')
    signedflag = (name[0] == 'S')
    aflag = (name[3] == 'A')
    ccval = helpers.get_condcode_value(condcode)
    encoded = helpers.encode_32bit([(28, 4, ccval), (23, 5, 0x1), (22, 1, signedflag), (21, 1, aflag),
                                    (20, 1, sflag), (16, 4, rdhi), (12, 4, rdlo), (8, 4, rs), (4, 4, 0x9), (0, 4, rm)])
    return helpers.bigendian_to_littleendian(encoded)
예제 #7
0
def encode_blockdatatransop(name, flags, condcode, operands):
    """
    check_blockdatatransop must be called before this.
    Encode the instruction and return it as a bytearray object.
    """
    operands = [x.strip() for x in operands.split(',')]
    if operands[0][-1] == '!':
        writeback = True
        operands[0] = operands[0][:-1].strip()
    else:
        writeback = False
    base = helpers.get_reg_num(operands[0])
    if operands[-1][-1] == '^':
        sbit = True
        operands[-1] = operands[-1][:-1].strip()
    else:
        sbit = False
    operands[1] = operands[1][1:].strip()  # strip the curly brackets
    operands[-1] = operands[-1][:-1].strip()
    reglist = []
    for op in operands[1:]:
        if '-' in op:
            (start,
             end) = [helpers.get_reg_num(r.strip()) for r in op.split('-')]
            reglist += list(range(start,
                                  end + 1))  # upy needs explicit conversion
        else:
            reglist.append(helpers.get_reg_num(op))
    regfield = 0
    for r in reglist:
        regfield |= (1 << r)
    lflag = (name == 'LDM')
    addrmodedict = {
        'ED': (lflag, lflag),
        'IB': (1, 1),
        'FD': (lflag, not lflag),
        'IA': (1, 0),
        'EA': (not lflag, lflag),
        'DB': (0, 1),
        'FA': (not lflag, not lflag),
        'DA': (0, 0)
    }
    (uflag, pflag) = addrmodedict[flags]
    ccval = helpers.get_condcode_value(condcode)
    encoded = helpers.encode_32bit([(28, 4, ccval), (25, 3, 0x4),
                                    (24, 1, pflag), (23, 1, uflag),
                                    (22, 1, sbit), (21, 1, writeback),
                                    (20, 1, lflag), (16, 4, base),
                                    (0, 16, regfield)])
    return helpers.bigendian_to_littleendian(encoded)
예제 #8
0
def encode_swapop(name, flags, condcode, operands):
    """
    check_swapop must be called before this.
    Encode the instruction and return it as a bytearray object.
    """
    operands = [x.strip() for x in operands.split(',')]
    operands[2] = operands[2][1:-1].strip()
    operands = [helpers.get_reg_num(x) for x in operands]
    byteflag = (flags == 'B')
    ccval = helpers.get_condcode_value(condcode)
    encoded = helpers.encode_32bit([(28, 4, ccval), (23, 5, 0x2),
                                    (22, 1, byteflag), (16, 4, operands[2]),
                                    (12, 4, operands[0]), (4, 4, 0x9),
                                    (0, 4, operands[1])])
    return helpers.bigendian_to_littleendian(encoded)
예제 #9
0
def encode_psrtransop(name, condcode, operands):
    """
    check_psrtransop must be called before this.
    Encode the instruction and return it as a bytearray object.
    """
    operands = [x.strip() for x in operands.split(',')]
    if name == 'MRS':
        rd = helpers.get_reg_num(operands[0])
        if operands[1].upper()[0] == 'C':  # CPSR
            spsrflag = False
        else:
            spsrflag = True
        ccval = helpers.get_condcode_value(condcode)
        encoded = helpers.encode_32bit([(28, 4, ccval), (23, 5, 0x2), (22, 1, spsrflag), (16, 6, 0xF), (12, 4, rd)])
        return helpers.bigendian_to_littleendian(encoded)
    else:
        if operands[0].upper()[0] == 'C':  # CPSR
            spsrflag = False
        else:
            spsrflag = True
        if operands[0].upper().endswith('FLG'):
            allflag = False
        else:
            allflag = True
        if helpers.is_reg(operands[1]):
            iflag = False
            rm = helpers.get_reg_num(operands[1])
            op2field = rm
        else:
            iflag = True
            op2field = helpers.encode_imval(operands[1])
        ccval = helpers.get_condcode_value(condcode)
        encoded = helpers.encode_32bit([(28, 4, ccval), (25, 1, iflag), (23, 2, 0x2),
                                        (22, 1, spsrflag), (17, 5, 0x14), (16, 1, allflag),
                                        (12, 4, 0xF), (0, 12, op2field)])
        return helpers.bigendian_to_littleendian(encoded)
예제 #10
0
def encode_mulop(name, flags, condcode, operands):
    """
    check_mulop must be called before this.
    Encode the instruction and return it as a bytearray object.
    """
    operands = [helpers.get_reg_num(x.strip()) for x in operands.split(',')]
    sflag = (flags == 'S')
    (rd, rm, rs) = operands[0:3]
    if name == 'MUL':
        rn = 0
        aflag = False
    else:
        rn = operands[3]
        aflag = True
    ccval = helpers.get_condcode_value(condcode)
    encoded = helpers.encode_32bit([(28, 4, ccval), (21, 1, aflag), (20, 1, sflag), (16, 4, rd),
                                    (12, 4, rn), (8, 4, rs), (4, 4, 0x9), (0, 4, rm)])
    return helpers.bigendian_to_littleendian(encoded)
예제 #11
0
def encode_singledatatransop(name, flags, condcode, operands, address,
                             labeldict):
    """
    check_singledatatransop must be called before this.
    Encode the instruction and return it as a bytearray object.
    """
    (writeback, preindexed, loadflag, upflag, iflag, rd, rn,
     offset) = parse_datatrans(name, operands, address, labeldict)
    if 'T' in flags:
        writeback = True
    byteflag = ('B' in flags)
    ccval = helpers.get_condcode_value(condcode)
    encoded = helpers.encode_32bit([(28, 4, ccval), (26, 2, 0x1),
                                    (25, 1, iflag), (24, 1, preindexed),
                                    (23, 1, upflag), (22, 1, byteflag),
                                    (21, 1, writeback), (20, 1, loadflag),
                                    (16, 4, rn), (12, 4, rd), (0, 12, offset)])
    return helpers.bigendian_to_littleendian(encoded)
예제 #12
0
def encode_halfsigneddatatransop(name, flags, condcode, operands, address,
                                 labeldict):
    """
    check_halfsigneddatatransop must be called before this.
    Encode the instruction and return it as a bytearray object.
    """
    (writeback, preindexed, loadflag, upflag, iflag, rd, rn,
     offset) = parse_datatrans(name, operands, address, labeldict)
    assert not (
        offset & 0xF00
    )  # either iflag and only lowest 4 bit used or not iflag and only lowest 8 bit used
    assert (not iflag) or not (offset & 0xFF0)
    hflag = ('H' in flags)
    sflag = ('S' in flags)
    ccval = helpers.get_condcode_value(condcode)
    encoded = helpers.encode_32bit([(28, 4, ccval), (24, 1, preindexed),
                                    (23, 1, upflag), (22, 1, not iflag),
                                    (21, 1, writeback), (20, 1, loadflag),
                                    (16, 4, rn), (12, 4, rd),
                                    (8, 4, offset >> 4), (7, 1, 0x1),
                                    (6, 1, sflag), (5, 1, hflag), (4, 1, 0x1),
                                    (0, 4, offset)])
    return helpers.bigendian_to_littleendian(encoded)