Added a decoder module which can deocde some RV32I/M instructions
Some of them even correctly O.okernel-mode
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…
Reference in New Issue