From 835ae03119f9e53f1e6f29c40b6c57447059bbc7 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Mon, 2 Jan 2023 22:44:22 -0600 Subject: [PATCH] starting work on disassembling OVM code --- interpreter/include/vm.h | 2 + interpreter/src/debug/debug_thread.c | 7 ++ interpreter/src/vm/disasm.c | 151 +++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 interpreter/src/vm/disasm.c diff --git a/interpreter/include/vm.h b/interpreter/include/vm.h index 89eb7880..7e436c5f 100644 --- a/interpreter/include/vm.h +++ b/interpreter/include/vm.h @@ -360,5 +360,7 @@ struct ovm_instr_t { #define OVM_TYPED_INSTR(instr, type) (((instr) << 3) | (type)) +void ovm_disassemble(ovm_program_t *program, u32 instr_addr, bh_buffer *instr_text); + #endif diff --git a/interpreter/src/debug/debug_thread.c b/interpreter/src/debug/debug_thread.c index 52e8d948..c01f74fe 100644 --- a/interpreter/src/debug/debug_thread.c +++ b/interpreter/src/debug/debug_thread.c @@ -20,6 +20,7 @@ #define CMD_VARS 8 #define CMD_MEM_R 9 #define CMD_MEM_W 10 +#define CMD_DISASM 11 #define EVT_NOP 0 #define EVT_BRK_HIT 1 @@ -464,6 +465,11 @@ static DEBUG_COMMAND_HANDLER(debug_command_memory_write) { send_int(debug, count); } +static DEBUG_COMMAND_HANDLER(debug_command_disassmble) { + u32 addr = parse_int(debug, ctx); + u32 count = parse_int(debug, ctx); +} + static debug_command_handler_t command_handlers[] = { [CMD_NOP] = debug_command_nop, [CMD_RES] = debug_command_res, @@ -476,6 +482,7 @@ static debug_command_handler_t command_handlers[] = { [CMD_VARS] = debug_command_vars, [CMD_MEM_R] = debug_command_memory_read, [CMD_MEM_W] = debug_command_memory_write, + [CMD_DISASM] = debug_command_disassmble, }; static void process_command(debug_state_t *debug, struct msg_parse_ctx_t *ctx) { diff --git a/interpreter/src/vm/disasm.c b/interpreter/src/vm/disasm.c new file mode 100644 index 00000000..25d3028b --- /dev/null +++ b/interpreter/src/vm/disasm.c @@ -0,0 +1,151 @@ +// +// Disassembler +// + +#include "vm.h" + +enum instr_format_kind_t { + instr_format_none, + + instr_format_rab, + instr_format_ra, + instr_format_a, + + instr_format_imm, + + instr_format_load, + instr_format_store, + + instr_format_idx_arr, +}; + +typedef struct instr_format_t { + char *instr; + enum instr_format_kind_t kind; +} instr_format_t; + +static instr_format_t instr_formats[] = { + { "nop", instr_format_none }, + { "add", instr_format_rab }, + { "sub", instr_format_rab }, + { "mul", instr_format_rab }, + { "div", instr_format_rab }, + { "div_s", instr_format_rab }, + { "rem", instr_format_rab }, + { "rem_s", instr_format_rab }, + { "and", instr_format_rab }, + { "or", instr_format_rab }, + { "xor", instr_format_rab }, + { "shl", instr_format_rab }, + { "shr", instr_format_rab }, + { "sar", instr_format_rab }, + + { "illegal", instr_format_none }, + { "illegal", instr_format_none }, + + { "imm", instr_format_imm }, + { "mov", instr_format_ra }, + { "load", instr_format_load }, + { "store", instr_format_store }, + + { "copy", instr_format_rab }, + { "fill", instr_format_rab }, + + { "global_get", instr_format_ra }, + { "global_set", instr_format_ra }, + + { "idx_arr", instr_format_idx_arr }, + + { "lt", instr_format_rab }, + { "lt_s", instr_format_rab }, + { "le", instr_format_rab }, + { "le_s", instr_format_rab }, + { "eq", instr_format_rab }, + { "ge", instr_format_rab }, + { "ge_s", instr_format_rab }, + { "gt", instr_format_rab }, + { "gt_s", instr_format_rab }, + { "ne", instr_format_rab }, + + { "param", instr_format_a }, + { "return", instr_format_a }, + { "call", instr_format_call }, + { "calli", instr_format_calli }, + + { "br", instr_format_br }, + { "br_z", instr_format_br_cond }, + { "br_nz", instr_format_br_cond }, + + { "bri", instr_format_bri }, + { "bri_z", instr_format_bri_cond }, + { "bri_nz", instr_format_bri_cond }, + + { "clz", instr_format_ra }, + { "ctz", instr_format_ra }, + { "popcnt", instr_format_ra }, + { "rotl", instr_format_rab }, + { "rotr", instr_format_rab }, + + { "abs", instr_format_ra }, + { "neg", instr_format_ra }, + { "ceil", instr_format_ra }, + { "floor", instr_format_ra }, + { "trunc", instr_format_ra }, + { "nearest", instr_format_ra }, + { "sqrt", instr_format_ra }, + { "min", instr_format_ra }, + { "max", instr_format_ra }, + { "copysign", instr_format_rab }, + + { "cvt_i8", instr_format_ra }, + { "cvt_i8_s", instr_format_ra }, + { "cvt_i16", instr_format_ra }, + { "cvt_i16_s", instr_format_ra }, + { "cvt_i32", instr_format_ra }, + { "cvt_i32_s", instr_format_ra }, + { "cvt_i64", instr_format_ra }, + { "cvt_i64_s", instr_format_ra }, + { "cvt_f32", instr_format_ra }, + { "cvt_f32_s", instr_format_ra }, + { "cvt_f64", instr_format_ra }, + { "cvt_f64_s", instr_format_ra }, + { "transmute_i32", instr_format_ra }, + { "transmute_i64", instr_format_ra }, + { "transmute_f32", instr_format_ra }, + { "transmute_f64", instr_format_ra }, + + { "cmpxchg", instr_format_rab } +}; + +void ovm_disassemble(ovm_program_t *program, u32 instr_addr, bh_buffer *instr_text) { + static char buf[256]; + + ovm_instr_t *instr = &program->code[instr_addr]; + switch (OVM_INSTR_TYPE(*instr)) { + case OVM_TYPE_I8: bh_buffer_write_string(instr_text, "i8."); break; + case OVM_TYPE_I16: bh_buffer_write_string(instr_text, "i16."); break; + case OVM_TYPE_I32: bh_buffer_write_string(instr_text, "i32."); break; + case OVM_TYPE_I64: bh_buffer_write_string(instr_text, "i64."); break; + case OVM_TYPE_F32: bh_buffer_write_string(instr_text, "f32."); break; + case OVM_TYPE_F64: bh_buffer_write_string(instr_text, "f64."); break; + case OVM_TYPE_V128: bh_buffer_write_string(instr_text, "v128."); break; + } + + instr_format_t *format = &instr_formats[OVM_INSTR_INSTR(instr)]; + + bh_buffer_write(instr_text, format->instr); + + char *formatted = NULL; + switch (format->kind) { + case instr_format_rab: formatted = snprintf(buf, 255, "%%%d, %%%d, %%%d", instr->r, instr->a, instr->b); break; + case instr_format_ra: formatted = snprintf(buf, 255, "%%%d, %%%d", instr->r, instr->a); break; + case instr_format_a: formatted = snprintf(buf, 255, "%%%d", instr->a); break; + } + + if (formatted) { + bh_buffer_write_byte(instr_text, ' '); + bh_buffer_write_string(instr_text, formatted); + } +} + + -- 2.25.1