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:
| M | Makefile | | | 9 | ++++++++- |
| A | disasm.c | | | 284 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | disasm.h | | | 6 | ++++++ |
| M | main.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);