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)
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
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)