Beispiel #1
0
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]
Beispiel #2
0
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]
Beispiel #3
0
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]
Beispiel #4
0
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]
Beispiel #5
0
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]
Beispiel #6
0
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']
Beispiel #7
0
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'])