rvemu

RISC-V RV32I execution engine
git clone git://mcdim.xyz/revemu.git
Log | Files | Refs

commit 6531dc54564c59c9c4aeb0c919ea7591bc619977
parent 51338a4f65ca4f32e7c62461d0b0c59ea670af1c
Author: Michail Konstantinos Dimopoulos <mk@mcdim.xyz>
Date:   Wed,  2 Sep 2026 18:38:33 +0300

Added basic static disassembler

Diffstat:
MMakefile | 9++++++++-
Adisasm.c | 284+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adisasm.h | 6++++++
Mmain.c | 3+++
4 files changed, 301 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile @@ -1,5 +1,12 @@ all: - gcc -g main.c \ + gcc -g main.c disasm.c \ + -Wall -Wextra -Wpedantic \ + -Wconversion -Wsign-conversion \ + -Wshadow -Wstrict-prototypes \ + -Wmissing-prototypes -Wformat=2 + +disasm: + gcc -g disasm.c \ -Wall -Wextra -Wpedantic \ -Wconversion -Wsign-conversion \ -Wshadow -Wstrict-prototypes \ diff --git a/disasm.c b/disasm.c @@ -0,0 +1,284 @@ +#include <stdint.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "decode.h" +#include "disasm.h" + +#define MEMSIZE 2052 + + +typedef struct { + uint32_t x[32]; /* general purpose registers */ + uint32_t pc; +} cpu_state_t; + +/* +static inline int32_t get_branch_target(uint32_t pc, int32_t offset) { + return (int32_t)((int64_t)pc + (int64_t)offset); +} + +static inline int32_t get_jalr_target(uint32_t base, int32_t offset) { + return (int32_t)(((int64_t)base + (int64_t)offset) & ~INT64_C(1)); +} +*/ + +static void disasm_itype(uint32_t inst) { + itype_t i; + decode_itype(&i, inst); + + switch(i.funct3) { + case 0x0: + printf("addi"); + break; + case 0x1: + if (i.funct7 != 0x00) { + printf("slli"); + } else { + printf("Illegal funct7\n"); + return; + } + break; + case 0x2: + printf("slti"); + break; + case 0x3: + printf("sltui"); + break; + case 0x4: + printf("xori"); + break; + case 0x5: + switch(i.funct7) { + case 0x00: + printf("srli"); + break; + case 0x20: + printf("srai"); + break; + default: + printf("Illegal funct7\n"); + return; + } + break; + case 0x6: + printf("ori"); + break; + case 0x7: + printf("andi"); + break; + default: + printf("Illegal funct3\n"); + return; + } + printf(" x%d, %" PRIu8 ", %" PRIu8 "\n", i.rd, i.rs1, i.imm); +} + +static void disasm_rtype(uint32_t inst) { + rtype_t r; + decode_rtype(&r, inst); + + switch(r.funct3) { + case 0x0: + switch(r.funct7) { + case 0x00: + printf("add x%d, x%d\n", r.rs1, r.rs2); + break; + case 0x20: + printf("sub x%d, x%d\n", r.rs1, r.rs2); + break; + default: + printf("Illegal funct7\n"); + return; + } + break; + case 0x1: + printf("ssl x%d, x%d\n", r.rs1, r.rs2); + break; + case 0x2: + printf("slt x%d, x%d\n", r.rs1, r.rs2); + break; + case 0x3: + printf("sltu x%d, x%d\n", r.rs1, r.rs2); + break; + case 0x4: + printf("xor x%d, x%d\n", r.rs1, r.rs2); + break; + case 0x5: + switch(r.funct7) { + case 0x00: + printf("srl x%d, x%d\n", r.rs1, r.rs2); + break; + case 0x20: + printf("sra x%d, x%d\n", r.rs1, r.rs2); + break; + default: + printf("Illegal funct7\n"); + return; + } + break; + case 0x6: + printf("or x%d, x%d\n", r.rs1, r.rs2); + break; + case 0x7: + printf("and x%d, x%d\n", r.rs1, r.rs2); + break; + default: + printf("Illegal funct3\n"); + return; + } +} + +static void disasm_itype_loads(uint32_t inst) { + itype_t i; + decode_itype(&i, inst); + + switch(i.funct3) { + case 0x0: + printf("lb"); + break; + case 0x1: + printf("lh"); + break; + case 0x2: + printf("lw"); + break; + case 0x4: + printf("lbu"); + break; + case 0x5: + printf("lhu"); + break; + default: + printf("Illegal funct3\n"); + return; + } + + printf(" x%" PRIu32 ", %" PRId32 "(x%" PRIu32 ")", + i.rd, (int32_t)(int16_t)i.imm, i.rs1); +} + +static void disasm_stype(uint32_t inst) { + stype_t s; + decode_stype(&s, inst); + + switch(s.funct3) { + case 0x0: + printf("sb"); + break; + case 0x1: + printf("sh"); + break; + case 0x2: + printf("sw"); + break; + default: + printf("Illegal funct3\n"); + return; + } + + printf(" x%" PRIu32 ", %" PRId32 "(x%" PRIu32 ")", + s.rs2, (int32_t)(int16_t)s.imm, s.rs1); +} + +static void disasm_btype(uint32_t inst) { + btype_t b; + decode_btype(&b, inst); + + switch (b.funct3) { + case 0x0: + printf("beq"); + break; + case 0x1: + printf("bne"); + break; + case 0x4: + printf("blt"); + break; + case 0x5: + printf("bge"); + break; + case 0x6: + printf("bltu"); + break; + case 0x7: + printf("bgeu"); + break; + default: + printf("Illegal funct3\n"); + return; + } + + printf(" x%" PRIu32 ", x%" PRIu32 ", %" PRId32 "\n", + b.rs1, b.rs2, (int32_t)(int16_t)b.imm); + + +} + +static void disasm_itype_jalr(uint32_t inst) { + itype_t i; + decode_itype(&i, inst); + + if (i.funct3 != 0x0u) { + fprintf(stderr, "Illegal JALR funct3\n"); + return; + } + + printf("x%" PRIu32 ", %" PRId32 "(x%" PRIu32 ")\n", + i.rd, (int32_t)(int16_t)i.imm, i.rs1); + +} + +static void disasm_jtype(uint32_t inst) { + jtype_t j; + decode_jtype(&j, inst); + + printf("x%" PRIu32 ", %" PRId32 "\n", + j.rd, (int32_t)j.imm); + +} + +static void disasm_utype(uint32_t inst) { + utype_t u; + decode_utype(&u, inst); + + printf("lui x%" PRIu8 ", 0x%05" PRIx32 "\n", u.rd, u.imm); +} + +static void disasm_utype_auipc(uint32_t inst) { + utype_t u; + decode_utype(&u, inst); + + printf("auipc x%" PRIu8 ", 0x%05" PRIx32 "\n", u.rd, u.imm); +} + +typedef void (*disasm_fn)(uint32_t inst); + +static disasm_fn opcode_table[128]; + +static void +init_opcode_table(void) +{ + opcode_table[0x33] = disasm_rtype; + opcode_table[0x13] = disasm_itype; + opcode_table[0x03] = disasm_itype_loads; + opcode_table[0x67] = disasm_itype_jalr; + opcode_table[0x23] = disasm_stype; + opcode_table[0x63] = disasm_btype; + opcode_table[0x6f] = disasm_jtype; + opcode_table[0x37] = disasm_utype; + opcode_table[0x17] = disasm_utype_auipc; +} + +void disassemble_instruction(uint32_t inst) { + init_opcode_table(); + uint16_t opcode = inst & 0x7f; + disasm_fn fn = opcode_table[opcode]; + if (!fn) { + fprintf(stderr, "Illegal opcode\n"); + exit(EXIT_FAILURE); + } + fn(inst); +} diff --git a/disasm.h b/disasm.h @@ -0,0 +1,6 @@ +#ifndef DISASM_H +#define DISASM_H + +void disassemble_instruction(uint32_t inst); + +#endif diff --git a/main.c b/main.c @@ -5,6 +5,7 @@ #include <string.h> #include "decode.h" +#include "disasm.h" #define MEMSIZE 2052 @@ -348,6 +349,7 @@ static void exec_stype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { uint32_t addr = s.imm + cpu->x[s.rs1]; + /* TODO: helpers, better checks */ switch(s.funct3) { case 0x0: printf("STORE BYTE\n"); @@ -679,6 +681,7 @@ int main() { strncmp(line, "next", 4) == 0) { uint32_t inst = make_instruction(mem, cpu.pc); + disassemble_instruction(inst); printf("------------INST------\n"); print_bin32(inst);