def pack_j(instr): """ verify & pack J-type instructions. >>> pack_j([(0x6f, 'jal'), (0, 'rd', 'x0'), (0, 'off20')]) [(111, 7), (0, 5), (0, 8), (0, 1), (0, 10), (0, 1)] >>> pack_j([(0x6f, 'jal'), (0, 'rd', 'x0'), (-2, 'off20')]) [(111, 7), (0, 5), (255, 8), (1, 1), (1022, 10), (1, 1)] >>> pack_j([(0x6f, 'jal'), (2, 'rd', 'x2'), ('home', 'off20')]) [(111, 7), (2, 5), ('home[19:12]', 'off8'), ('home[11:11]', 'off1'), ('home[10:1]', 'off10'), ('home[20:20]', 'off1')] """ (op, rd, imm) = instr op = bits.u(subv.untag(op), 7) rd = bits.u(subv.untag(rd, 'rd'), 5) if subv.is_reference(imm): imm = default_slice(imm, 20, 1) else: imm = bits.i(subv.untag(imm, 'off20'), 20) imm_lo = slice_bit_or_ref(imm, 9, 0) # + ('off[10:1]',) imm_11 = slice_bit_or_ref(imm, 10, 10) # + ('off[11]',) imm_hi = slice_bit_or_ref(imm, 18, 11) # + ('off[19:12]',) imm_20 = slice_bit_or_ref(imm, 19, 19) # + ('off[20]',) return [op, rd, imm_hi, imm_11, imm_lo, imm_20]
def pack_b(instr): """ verify & pack B-type instructions. >>> pack_b([(0x63, 'branch'), (0, 'subop', '=='), (6, 'rs'), (0, 'rs'), (0, 'off12')]) [(99, 7), (0, 1), (0, 4), (0, 3), (6, 5), (0, 5), (0, 6), (0, 1)] >>> pack_b([(0x63, 'branch'), (0, 'subop', '=='), (6, 'rs'), (0, 'rs'), (-2, 'off12')]) [(99, 7), (1, 1), (14, 4), (0, 3), (6, 5), (0, 5), (63, 6), (1, 1)] >>> pack_b([(0x63, 'branch'), (0, 'subop', '=='), (6, 'rs'), (0, 'rs'), ('home', 'off12')]) [(99, 7), ('home[11:11]', 'off1'), ('home[4:1]', 'off4'), (0, 3), (6, 5), (0, 5), ('home[10:5]', 'off6'), ('home[12:12]', 'off1')] """ (op, sub, rs1, rs2, imm) = instr op = bits.u(subv.untag(op), 7) sub = bits.u(subv.untag(sub, 'subop'), 3) rs1 = bits.u(subv.untag(rs1, 'rs'), 5) rs2 = bits.u(subv.untag(rs2, 'rs'), 5) if subv.is_reference(imm): imm = default_slice(imm, 12, 1) else: imm = bits.i(subv.untag(imm, 'off12'), 12) imm_lo = slice_bit_or_ref(imm, 3, 0) # + ('off[4:1]',) imm_md = slice_bit_or_ref(imm, 9, 4) # + ('off[10:5]',) imm_11 = slice_bit_or_ref(imm, 10, 10) # + ('off[11]',) imm_12 = slice_bit_or_ref(imm, 11, 11) # + ('off[12]',) return [op, imm_11, imm_lo, sub, rs1, rs2, imm_md, imm_12]
def pack_u(instr): """ verify & pack U-type instructions. >>> pack_u([(0x37, 'lui'), (5, 'rd', 't0'), (0x10010, 'imm20')]) [(55, 7), (5, 5), (65552, 20)] >>> pack_u([(0x37, 'lui'), (5, 'rd', 't0'), ('pos', 'imm20')]) [(55, 7), (5, 5), ('pos[31:12]', 'imm20')] >>> pack_u([(0x37, 'lui'), (5, 'rd', 't0'), ('pos[19:0]', 'imm20')]) [(55, 7), (5, 5), ('pos[19:0]', 'imm20')] >>> pack_u([(0x37, 'lui'), (5, 'rd', 't0'), ('pos[31:0]', 'imm20')]) Traceback (most recent call last): ... AssertionError: expected 20 bit slice """ (op, rd, imm) = instr op = bits.u(subv.untag(op), 7) rd = bits.u(subv.untag(rd, 'rd'), 5) if subv.is_reference(imm): imm = default_slice(imm, 31, 12) else: imm = bits.i(subv.untag(imm, 'imm20'), 20) return [op, rd, imm]
def pack_i(instr): """ verify & pack I-type instructions. >>> pack_i([(0x13, 'opi'), (0, 'subop', 'add'), (6, 'rd', 't1'), (0, 'rs', 'x0'), (101, 'imm12')]) [(19, 7), (6, 5), (0, 3), (0, 5), (101, 12)] >>> pack_i([(0x13, 'opi'), (0, 'subop', 'add'), (6, 'rd', 't1'), (0, 'rs', 'x0'), ('label', 'imm12')]) [(19, 7), (6, 5), (0, 3), (0, 5), ('label[11:0]', 'imm12')] """ (op, sub, rd, rs, imm) = instr op = bits.u(subv.untag(op), 7) sub = bits.u(subv.untag(sub, 'subop'), 3) rd = bits.u(subv.untag(rd, 'rd'), 5) rs = bits.u(subv.untag(rs, 'rs'), 5) if subv.is_reference(imm): imm = default_slice(imm, 11, 0) else: imm = bits.i(subv.untag(imm, 'imm12'), 12) return [op, rd, sub, rs, imm]
def pack_s(instr): """ verify & pack S-type instructions. >>> pack_s([(0x23, 'store'), (2, 'subop', 'word'), (5, 'rs', 't0'), (6, 'rs', 't1'), (0, 'off12')]) [(35, 7), (0, 5), (2, 3), (5, 5), (6, 5), (0, 7)] >>> pack_s([(0x23, 'store'), (2, 'subop', 'word'), (5, 'rs', 't0'), (6, 'rs', 't1'), ('home', 'off12')]) [(35, 7), ('home[4:0]', 'off5'), (2, 3), (5, 5), (6, 5), ('home[11:5]', 'off7')] """ (op, sub, rs1, rs2, imm) = instr op = bits.u(subv.untag(op), 7) sub = bits.u(subv.untag(sub, 'subop'), 3) rs1 = bits.u(subv.untag(rs1, 'rs'), 5) rs2 = bits.u(subv.untag(rs2, 'rs'), 5) if subv.is_reference(imm): imm = default_slice(imm, 11, 0) else: imm = bits.i(subv.untag(imm, 'off12'), 12) imm_lo = slice_bit_or_ref(imm, 4, 0) # + ('off[4:0]',) imm_hi = slice_bit_or_ref(imm, 11, 5) # + ('off[11:5]',) return [op, imm_lo, sub, rs1, rs2, imm_hi]
def survey(iter): queue = [] map = {} addr = -1 for line in iter: line = subv.parse(line) line['addr'] = addr queue.append(line) # step forward addr if line['type'] == 'segment': segment, addr = line['segment'] elif line['type'] == 'label': map[line['label']] = addr elif line['type'] == 'instr': bits = 0 for part in line['instr']: if subv.is_reference(part): ref = subv.parse_reference(part) bits += ref['size'] else: bits += int(part[1]) assert bits % 8 == 0, "line not byte-aligned" addr += bits // 8 for line in queue: if line['type'] == 'instr': instr = [] for part in line['instr']: observed = observe(part, line['addr'], map) instr.append(observed) line['instr'] = instr yield subv.format(line) elif line['type'] == 'segment': yield line['raw']
def observe(part, rel_addr, map): """ resolve a label reference. >>> observe((3, '3'), 0, {}) (3, '3') >>> observe(('label[31:0]', 'imm32'), 0, {'label': 1234}) (1234, 32) >>> observe(('label[1:0]', 'imm32'), 0, {'label': 1234}) (2, 2) >>> observe(('label[31:0]', 'off32'), 1000, {'label': 1234}) (234, 32) >>> observe(('label[31:12]', 'off32'), 1000, {'label': 1234}) (0, 20) >>> observe(('label[31:0]', 'off32'), 2000, {'label': 1000}) (4294966296, 32) >>> observe(('label[32:0]', 'imm32'), 0, {}) Traceback (most recent call last): ... AssertionError: undefined label 'label' """ if not subv.is_reference(part): return part ref = subv.parse_reference(part) assert ref['label'] in map, "undefined label '{}'".format(ref['label']) addr = map[ref['label']] # @TODO: the hardcoded 32 here is not right, this is going to blow up # in some circumstances (e.g. a backwards branch 2<<18 bytes away) if ref['mode'] == 'imm': addr = bits.u(addr, 32) else: addr = bits.i(addr - rel_addr, 32) return bits.slice(addr, ref['hi'], ref['lo'])