Added a decoder module which can deocde some RV32I/M instructions

Some of them even correctly O.o
kernel-mode
Anton Lydike 4 years ago
parent 483a3f2416
commit a4735db388

@ -0,0 +1 @@
from .decoder import decode

@ -0,0 +1,17 @@
if __name__ == '__main__':
import code
import readline
import rlcompleter
from .decoder import *
from .formats import *
from instruction_table import *
from regs import *
sess_vars = globals()
sess_vars.update(locals())
readline.set_completer(rlcompleter.Completer(sess_vars).complete)
readline.set_completer(rlcompleter.Completer(sess_vars).complete)
readline.parse_and_bind("tab: complete")
code.InteractiveConsole(sess_vars).interact(banner="Interaktive decoding session started...", exitmsg="Closing...")

@ -0,0 +1,86 @@
from .instruction_table import *
from typing import Tuple, List
def print_ins(ins: int):
print(" f7 rs2 rs1 f3 rd op")
print(
f"0b{ins >> 25 :07b}_{(ins >> 20) & 0b11111:05b}_{(ins >> 15) & 0b11111:03b}_{(ins >> 12) & 0b111:03b}_{(ins >> 7) & 0b11111:05b}_{ins & 0b1111111:07b}");
STATIC_INSN = {
0x00000013: ("nop", []),
0x00008067: ("ret", []),
0xfe010113: ("addi", ["sp", "sp", -32]),
0x02010113: ("addi", ["sp", "sp", 32]),
0x00100073: ("ebreak", []),
0x00000073: ("ecall", [])
}
def int_from_ins(insn: bytearray):
return (insn[3] << (8 * 3)) + \
(insn[2] << (8 * 2)) + \
(insn[1] << 8) + \
insn[0]
def name_from_insn(ins: int):
opcode = op(ins)
if opcode not in RV32:
print_ins(ins)
raise RuntimeError(f"Invalid opcode: {opcode:0x} in insn {ins:x}")
dec = RV32[opcode]
if isinstance(dec, str):
return dec
fun = funct3(ins)
if fun not in dec:
print_ins(ins)
raise RuntimeError(f"Invalid funct3: {fun:0x} in insn {ins:x}")
dec = dec[fun]
if isinstance(dec, str):
return dec
if opcode == 0x1c and fun == 0:
# we have ecall/ebreak
token = imm110(ins)
if token in dec:
return dec[token]
print_ins(ins)
raise RuntimeError(f"Invalid instruction in ebreak/ecall region: {ins:x}")
fun = funct7(ins)
if fun in dec:
if opcode == 0x0C or (opcode == 0x04 and fun == 5):
mode = imm110(ins)
dec = dec[fun]
if mode in dec:
return dec[mode]
print_ins(ins)
raise RuntimeError("Unknown instruction!")
return dec[fun]
print_ins(ins)
raise RuntimeError(f"Invalid instruction: {ins:x}")
def decode(ins: bytearray) -> Tuple[str, List[Union[str, int]]]:
insn = int_from_ins(ins)
if insn & 3 != 3:
print_ins(insn)
raise RuntimeError("Not a RV32 instruction!")
if insn in STATIC_INSN:
return STATIC_INSN[insn]
opcode = op(insn)
if opcode not in INSTRUCTION_ARGS_DECODER:
print_ins(insn)
raise RuntimeError("No instruction decoder found for instruction")
return name_from_insn(insn), INSTRUCTION_ARGS_DECODER[opcode](insn)

@ -0,0 +1,114 @@
from typing import Dict, Callable, List, Union
from .regs import RISCV_REGS
def op(ins: int):
return (ins >> 2) & 31
def rd(ins: int):
return (ins >> 7) & 31
def funct3(ins: int):
return (ins >> 12) & 7
def rs1(ins: int):
return (ins >> 15) & 31
def rs2(ins: int):
return (ins >> 20) & 31
def funct7(ins: int):
return ins >> 25
def imm110(ins: int):
return ins >> 20
def imm3112(ins: int):
return ins >> 12
def imm_i(ins: int):
return sign_extend(imm110(ins), 12)
def imm_s(ins: int):
num = (funct7(ins) << 5) + rd(ins)
return sign_extend(num, 12)
def imm_b(ins: int):
lower = rd(ins)
higher = funct7(ins)
num = (lower & 0b11110) + ((higher & 0b0111111) << 5) + ((lower & 1) << 11) + ((higher >> 6) << 12)
return sign_extend(num, 13)
def imm_u(ins: int):
return sign_extend(imm3112(ins), 20)
def imm_j(ins: int):
imm = ins >> 12
return sign_extend(
((imm >> 8) & 0b1111111111) +
((imm & 1) << 10) +
((imm & 0b11111111) << 11) +
(imm & 0b10000000000000000000), 20
)
def sign_extend(num, bits):
sign_mask = 1 << (bits - 1)
return (num & (sign_mask - 1)) - (num & sign_mask)
def decode_i(ins: int) -> List[Union[str, int]]:
return [RISCV_REGS[rd(ins)], RISCV_REGS[rs1(ins)], imm_i(ins)]
def decode_b(ins: int) -> List[Union[str, int]]:
return [RISCV_REGS[rs1(ins)], RISCV_REGS[rs2(ins)], imm_b(ins)]
def decode_u(ins: int) -> List[Union[str, int]]:
return [RISCV_REGS[rd(ins)], imm_u(ins)]
def decode_r(ins: int) -> List[Union[str, int]]:
return [RISCV_REGS[rd(ins)], RISCV_REGS[rs1(ins)], RISCV_REGS[rs2(ins)]]
def decode_s(ins: int) -> List[Union[str, int]]:
return [RISCV_REGS[rs1(ins)], RISCV_REGS[rs2(ins)], imm_s(ins)]
def decode_j(ins: int) -> List[Union[str, int]]:
return [RISCV_REGS[rd(ins)], imm_j(ins)]
def decode_i_shamt(ins: int) -> List[Union[str, int]]:
if funct3(ins) in (1, 5):
return [RISCV_REGS[rd(ins)], RISCV_REGS[rs1(ins)], rs2(ins)]
else:
return [RISCV_REGS[rd(ins)], RISCV_REGS[rs1(ins)], imm110(ins)]
INSTRUCTION_ARGS_DECODER: Dict[int, Callable[[int], List[Union[str, int]]]] = {
0x00: decode_i,
0x04: decode_i_shamt,
0x05: decode_u,
0x08: decode_s,
0x0C: decode_r,
0x0D: decode_u,
0x18: decode_b,
0x19: decode_i,
0x1b: decode_j,
0x1c: decode_i
}

@ -0,0 +1,69 @@
from collections import defaultdict
from .formats import *
tbl = lambda: defaultdict(tbl)
RV32 = tbl()
RV32[0x1b] = "jal"
RV32[0x0D] = "lui"
RV32[0x05] = "auipc"
RV32[0x19][0] = "jalr"
RV32[0x04][0] = "addi"
RV32[0x04][1] = "slli"
RV32[0x04][2] = "slti"
RV32[0x04][3] = "sltiu"
RV32[0x04][4] = "xori"
RV32[0x04][5][0x00] = "srli"
RV32[0x04][5][0x20] = "srai"
RV32[0x04][6] = "ori"
RV32[0x04][7] = "andi"
RV32[0x18][0] = "beq"
RV32[0x18][1] = "bne"
RV32[0x18][4] = "blt"
RV32[0x18][5] = "bge"
RV32[0x18][6] = "bltu"
RV32[0x18][7] = "bgeu"
RV32[0x00][0] = "lb"
RV32[0x00][1] = "lh"
RV32[0x00][2] = "lw"
RV32[0x00][4] = "lbu"
RV32[0x00][5] = "lhu"
RV32[0x08][0] = "sb"
RV32[0x08][1] = "sh"
RV32[0x08][2] = "sw"
RV32[0x1c][1] = "csrrw"
RV32[0x1c][2] = "csrrs"
RV32[0x1c][3] = "csrrc"
RV32[0x1c][5] = "csrrwi"
RV32[0x1c][6] = "csrrsi"
RV32[0x1c][7] = "csrrci"
RV32[0x1c][0][0] = "ecall"
RV32[0x1c][0][1] = "ebreak"
RV32[0x0C][0][0] = "add"
RV32[0x0C][0][32] = "sub"
RV32[0x0C][1][0] = "sll"
RV32[0x0C][2][0] = "slt"
RV32[0x0C][3][0] = "sltu"
RV32[0x0C][4][0] = "xor"
RV32[0x0C][5][0] = "srl"
RV32[0x0C][5][32] = "sra"
RV32[0x0C][6][0] = "or"
RV32[0x0C][7][0] = "and"
# rv32m
RV32[0x0C][0][1] = "mul"
RV32[0x0C][1][1] = "mulh"
RV32[0x0C][2][1] = "mulhsu"
RV32[0x0C][3][1] = "mulhu"
RV32[0x0C][4][1] = "div"
RV32[0x0C][5][1] = "divu"
RV32[0x0C][6][1] = "rem"
RV32[0x0C][7][1] = "remu"

@ -0,0 +1,6 @@
RISCV_REGS = [
'zero', 'ra', 'sp', 'gp', 'tp', 't0', 't1', 't2',
's0', 's1', 'a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7',
's2', 's3', 's4', 's5', 's6', 's7', 's8', 's9', 's10', 's11',
't3', 't4', 't5', 't6'
]
Loading…
Cancel
Save