From 246fe09646e05d4354fdfd4ec5ac7e5f66a274a6 Mon Sep 17 00:00:00 2001 From: chentianya Date: Tue, 25 Aug 2026 20:08:37 +0800 Subject: [PATCH] =?UTF-8?q?=E9=98=B6=E6=AE=B52-3=EF=BC=9ACodec=20V2=20?= =?UTF-8?q?=E5=8C=96=EF=BC=88=E5=8F=98=E9=95=BF=E6=8C=87=E4=BB=A4=E5=AD=97?= =?UTF-8?q?=E7=BC=96=E8=A7=A3=E7=A0=81=20+=20=E9=85=8D=E7=BD=AE=E9=A9=B1?= =?UTF-8?q?=E5=8A=A8=20disasm=20=E7=B1=BB=E5=9E=8B=E5=90=8E=E7=BC=80?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - instr_len 前缀定长(1/01/001/0001 → 4/8/16/32B) - prefix_of/op_of/func_of + 全部位号 get/set(rd/rs1/rs2/imm32/slot32/off32/ fn_id32/fb_id16/cal_slot32/off32_hi/imm64) - set_byte0 按前缀写(11/10/011/010xxx 形态位/0010/0011/0001) - disasm:find_op_by_key 查配置;full/float/dst 类显示 .TYPE 后缀 (U8/I8/.../F64);CAL 打印 fb 名(CAL.TON s5);未知输出 ??? 0x hex - main.cpp --disasm 调用适配(TODO V2 待 Stb 重写) - 状态:编译仅剩 Codegen.cpp(84 处 V1 残留,下一步阶段2-5 重写) --- compiler/include/compiler/Codec.h | 132 +++++++++--- compiler/src/Codec.cpp | 341 +++++++++++++++++++++++++----- compiler/src/main.cpp | 4 +- tests/src/machine_test.cpp | 6 +- 4 files changed, 387 insertions(+), 96 deletions(-) diff --git a/compiler/include/compiler/Codec.h b/compiler/include/compiler/Codec.h index 3a38dfc..a7d93c8 100644 --- a/compiler/include/compiler/Codec.h +++ b/compiler/include/compiler/Codec.h @@ -1,59 +1,123 @@ /** * @file Codec.h - * @brief 指令字编解码 + 配置驱动反汇编(编译器侧) + * @brief 指令字编解码 + 配置驱动反汇编(编译器侧,V2) * @author * @date 2026-08-21 * - * @details 编译器不依赖 isa:指令字布局([op:8|rd:8|a:8|b:8] 小端)与 - * 反汇编输出(按 machine.toml 的 format/参数名)全部由本模块 + MachineConfig 提供, - * 保证与执行器(isa)产生的字节一致。 + * @details 编译器不依赖 isa:变长指令字(前缀分区编码,4/8/16/32B)与 + * 反汇编输出(按 machine.toml 的 prefix/op/func/fmt)全部由本模块 + MachineConfig + * 提供,保证与执行器(isa V2)产生的字节一致。位号见 Doc/isa/指令编码.md。 */ #pragma once #include #include +#include #include "compiler/MachineConfig.h" namespace compiler { - /// 指令字:`[ op:8 | rd:8 | a:8 | b:8 ]`,小端 u32。 - typedef uint32_t Instr; + /// 指令字最大长度(字节)。 + static constexpr size_t kMaxInstrLen = 16; /** - * @brief 打包:opcode + 三个 8 位字段拼成一条指令字。 - * @param opcode 操作码(低 8 位) - * @param rd 目标寄存器 / 条件寄存器(第 8..15 位) - * @param a 源寄存器 / 立即数低 8 位 / 偏移低 8 位(第 16..23 位) - * @param b 源寄存器 / 立即数高 8 位 / 偏移高 8 位(第 24..31 位) - * @return 打包后的指令字(小端 u32) - * @details 布局与执行器 isa 一致,保证编译器产出的字节可被执行。 + * @brief 前缀定长:读字节 0 判指令长度。 + * @param code 指令字节(至少 1 字节) + * @return 4/8/16/32(前缀 `1`/`01`/`001`/`0001`) */ - Instr pack(uint8_t opcode, uint8_t rd, uint8_t a, uint8_t b); - - /// @brief 取操作码(低 8 位)。 - uint8_t op_of(Instr w); - /// @brief 取 rd 字段(第 8..15 位)。 - uint8_t rd_of(Instr w); - /// @brief 取 a 字段(第 16..23 位)。 - uint8_t a_of(Instr w); - /// @brief 取 b 字段(第 24..31 位)。 - uint8_t b_of(Instr w); - /// @brief a|b 拼 16 位无符号数(const_id / slot / fn_id)。 - uint16_t imm16_of(Instr w); - /// @brief a|b 为有符号相对偏移(单位:指令条数,相对下一条指令)。 - int16_t off16_of(Instr w); + size_t instr_len(const uint8_t* code); /** - * @brief 配置驱动反汇编:按 machine.toml 的 format 输出一行文本。 - * @param cfg 机器配置(opcode 名 / format / 参数名来源) - * @param w 指令字 + * @brief 推导形态前缀字符串。 + * @param code 指令字节 + * @return "11"/"10"/"011"/"010000".."010101"/"0010"/"0011"/"0001" + */ + std::string prefix_of(const uint8_t* code); + + /** + * @brief 取分区内操作码。 + * @param code 指令字节 + * @return op(4B 6 位 / 8B 5 位或 2 位 / 16B·32B 4 位) + */ + uint8_t op_of(const uint8_t* code); + + /** + * @brief 取 func 位段(字节 1 高 4 位)。 + * @param code 指令字节 + * @return 0..15(0..9 有效) + */ + uint8_t func_of(const uint8_t* code); + + /// @brief 取 rd(23..16)。 + uint8_t rd_of(const uint8_t* code); + /// @brief 取 rs1(31..24)。 + uint8_t rs1_of(const uint8_t* code); + /// @brief 取 rs2(39..32)。 + uint8_t rs2_of(const uint8_t* code); + /// @brief 取 imm32(55..24,IMM 形态)。 + uint32_t imm32_of(const uint8_t* code); + /// @brief 取 slot32(55..24,SLOT 形态)。 + uint32_t slot32_of(const uint8_t* code); + /// @brief 取 off32(47..16,JMP/JC 形态,有符号字节偏移)。 + int32_t off32_of(const uint8_t* code); + /// @brief 取 fn_id32(47..16,CALL 形态)。 + uint32_t fn_id32_of(const uint8_t* code); + /// @brief 取 fb_id16(31..16,CAL 形态)。 + uint16_t fb_id16_of(const uint8_t* code); + /// @brief 取 CAL 的实例槽号(63..32)。 + uint32_t cal_slot32_of(const uint8_t* code); + /// @brief 取 16B 形态的 off32(87..56)。 + int32_t off32_hi_of(const uint8_t* code); + /// @brief 取 imm64(87..24,IMM64 形态)。 + uint64_t imm64_of(const uint8_t* code); + + /** + * @brief 写字节 0(前缀 + 操作码)。 + * @param out 指令缓冲(≥16B,写入后高位补 0 由调用方保证) + * @param prefix 形态前缀(11/10/011/010000..010101/0010/0011/0001) + * @param op 分区内编号 + */ + void set_byte0(uint8_t* out, const std::string& prefix, uint32_t op); + + /// @brief 写字节 1 的 func(高 4 位)。 + void set_func(uint8_t* out, uint8_t func); + /// @brief 写 rd(23..16)。 + void set_rd(uint8_t* out, uint8_t rd); + /// @brief 写 rs1(31..24)。 + void set_rs1(uint8_t* out, uint8_t rs1); + /// @brief 写 rs2(39..32)。 + void set_rs2(uint8_t* out, uint8_t rs2); + /// @brief 写 imm32(55..24)。 + void set_imm32(uint8_t* out, uint32_t v); + /// @brief 写 slot32(55..24)。 + void set_slot32(uint8_t* out, uint32_t v); + /// @brief 写 off32(47..16)。 + void set_off32(uint8_t* out, int32_t v); + /// @brief 写 fn_id32(47..16)。 + void set_fn_id32(uint8_t* out, uint32_t v); + /// @brief 写 fb_id16(31..16)。 + void set_fb_id16(uint8_t* out, uint16_t v); + /// @brief 写 CAL 实例槽号(63..32)。 + void set_cal_slot32(uint8_t* out, uint32_t v); + /// @brief 写 16B 形态的 off32(87..56)。 + void set_off32_hi(uint8_t* out, int32_t v); + /// @brief 写 imm64(87..24)。 + void set_imm64(uint8_t* out, uint64_t v); + + /** + * @brief 配置驱动反汇编:按 machine.toml 的 prefix/op/func/fmt 输出一行文本。 + * @param cfg 机器配置(指令名 / fmt / func 类别 / fb 名来源) + * @param code 指令字节 + * @param len 指令长度(instr_len 定) * @param out 输出缓冲 * @param cap 缓冲容量(含 '\0');cap==0 时直接返回、不写 out - * @details 文本格式与 Doc/isa/指令与映像.md 一致(如 `MOVE r1, r2`、 - * `LOADK r0, 3`、`JMP +4`、`JT r0, -1`、`CALL 1`、`CAL_TON 0`、`RET`); - * 未知操作码输出 `??? 0x`。 + * @details 文本格式与 Doc/isa/指令与映像.md §10 一致: + * `MOVE r1, r2`、`LOAD.I16 r5, s3`(full/float/dst 类显示类型后缀)、 + * `JMP +4`、`JT r0, -1`、`CALL 1`、`CAL.TON s5`、`RET`; + * 未知 (prefix, op) 输出 `??? 0x`。 */ - void disasm(const MachineConfig& cfg, Instr w, char* out, size_t cap); + void disasm(const MachineConfig& cfg, const uint8_t* code, size_t len, + char* out, size_t cap); } diff --git a/compiler/src/Codec.cpp b/compiler/src/Codec.cpp index 96f7c65..f77de8c 100644 --- a/compiler/src/Codec.cpp +++ b/compiler/src/Codec.cpp @@ -1,11 +1,12 @@ /** * @file Codec.cpp - * @brief 指令字编解码 + 配置驱动反汇编(编译器侧) + * @brief 指令字编解码 + 配置驱动反汇编(编译器侧,V2) * @author * @date 2026-08-21 * - * @details pack / op_of / imm16_of / off16_of 与执行器 isa 字节布局一致; - * disasm 由 MachineConfig 驱动(opcode 名 / format / 参数名来自配置)。 + * @details 变长指令字(前缀分区)的位号读写与 disasm;位号见 Doc/isa/指令编码.md: + * - 字节 0 = [长度前缀+形态分区 | op];字节 1 = [func:4 | 空:4] + * - 操作数区 bit16 起(rd=23..16、imm32/slot32=55..24、off32/fn_id32=47..16 等) */ #include "compiler/Codec.h" @@ -14,84 +15,310 @@ namespace compiler { -/** - * @brief 打包:四个字段拼成一条指令字。 - * @param opcode 操作码(低 8 位) - * @param rd 目标寄存器 / 条件寄存器(第 8..15 位) - * @param a 源寄存器 / 立即数低 8 位 / 偏移低 8 位(第 16..23 位) - * @param b 源寄存器 / 立即数高 8 位 / 偏移高 8 位(第 24..31 位) - * @return 打包后的指令字(小端 u32) - */ -Instr pack(uint8_t opcode, uint8_t rd, uint8_t a, uint8_t b) { - return static_cast(opcode) - | (static_cast(rd) << 8) - | (static_cast(a) << 16) - | (static_cast(b) << 24); -} +namespace { -/// @brief 取操作码(低 8 位)。 -uint8_t op_of(Instr w) { return static_cast(w & 0xFFu); } -/// @brief 取 rd 字段(第 8..15 位)。 -uint8_t rd_of(Instr w) { return static_cast((w >> 8) & 0xFFu); } -/// @brief 取 a 字段(第 16..23 位)。 -uint8_t a_of(Instr w) { return static_cast((w >> 16) & 0xFFu); } -/// @brief 取 b 字段(第 24..31 位)。 -uint8_t b_of(Instr w) { return static_cast((w >> 24) & 0xFFu); } + /** + * @brief func → 类型后缀(disasm 用,A7 定案)。 + * @param func func 值(0..9) + * @return 后缀串("U8"/"I8"/.../"F64");越界返回 "?" + */ + const char* type_suffix(uint8_t func) { + static const char* kSuffix[16] = { + "U8", "I8", "U16", "I16", "U32", "I32", "U64", "I64", + "F32", "F64", "?", "?", "?", "?", "?", "?", + }; + return kSuffix[func & 0x0F]; + } + + /** + * @brief 形态前缀是否带类型后缀(disasm 显示 .TYPE)。 + * @param mode func 类别(none/width/uint/full/float/dst) + * @return full/float/dst → true(显示类型后缀) + */ + bool shows_type_suffix(const std::string& mode) { + return mode == "full" || mode == "float" || mode == "dst"; + } + +} // namespace /** - * @brief a|b 拼成 16 位无符号数。 - * @param w 指令字 - * @return 小端拼出的 16 位值(const_id / slot / fn_id) + * @brief 前缀定长:读字节 0 判指令长度。 + * @param code 指令字节(至少 1 字节) + * @return 4/8/16/32(前缀 `1`/`01`/`001`/`0001`) */ -uint16_t imm16_of(Instr w) { - return static_cast(a_of(w) | (static_cast(b_of(w)) << 8)); +size_t instr_len(const uint8_t* code) { + const uint8_t b = code[0]; + if (b & 0x80) return 4; // 1xxxxxxx → 4B + if ((b & 0xC0) == 0x40) return 8; // 01xxxxxx → 8B + if ((b & 0xE0) == 0x20) return 16; // 001xxxxx → 16B + return 32; // 0001xxxx → 32B } /** - * @brief a|b 为有符号相对偏移。 - * @param w 指令字 - * @return 偏移量(单位:指令条数,相对下一条指令) + * @brief 推导形态前缀字符串。 + * @param code 指令字节 + * @return "11"/"10"/"011"/"010000".."010101"/"0010"/"0011"/"0001" */ -int16_t off16_of(Instr w) { return static_cast(imm16_of(w)); } +std::string prefix_of(const uint8_t* code) { + const uint8_t b = code[0]; + if (b & 0x80) { + return (b & 0x40) ? "11" : "10"; // 4B:bit6 区分 11/10 + } + if ((b & 0xC0) == 0x40) { + if (b & 0x20) { + return "011"; // 8B RRR + } + static const char* kShapes[8] = { + "010000", "010001", "010010", "010011", "010100", "010101", "010110", "010111", + }; + return kShapes[(b >> 2) & 0x07]; // 8B 010:形态位 3 位 + } + if ((b & 0xE0) == 0x20) { + return (b & 0x10) ? "0011" : "0010"; // 16B + } + return "0001"; // 32B +} /** - * @brief 配置驱动反汇编:按 machine.toml 的 format 输出一行文本。 - * @param cfg 机器配置(opcode 名 / format / 参数名来源) - * @param w 指令字 + * @brief 取分区内操作码。 + * @param code 指令字节 + * @return op(4B 6 位 / 8B 5 位或 2 位 / 16B·32B 4 位) + */ +uint8_t op_of(const uint8_t* code) { + const uint8_t b = code[0]; + if (b & 0x80) return b & 0x3F; // 4B:6 位 + if ((b & 0xC0) == 0x40) { + return (b & 0x20) ? (b & 0x1F) : (b & 0x03); // 8B:011 → 5 位;010 → 2 位 + } + return b & 0x0F; // 16B/32B:4 位 +} + +/** + * @brief 取 func 位段(字节 1 高 4 位)。 + * @param code 指令字节 + * @return 0..15(0..9 有效) + */ +uint8_t func_of(const uint8_t* code) { + return static_cast((code[1] >> 4) & 0x0F); +} + +uint8_t rd_of(const uint8_t* code) { return code[2]; } +uint8_t rs1_of(const uint8_t* code) { return code[3]; } +uint8_t rs2_of(const uint8_t* code) { return code[4]; } + +/** + * @brief 取 imm32(55..24,小端 4 字节)。 + * @param code 指令字节 + * @return 32 位立即数 + */ +uint32_t imm32_of(const uint8_t* code) { + return static_cast(code[3]) + | (static_cast(code[4]) << 8) + | (static_cast(code[5]) << 16) + | (static_cast(code[6]) << 24); +} + +uint32_t slot32_of(const uint8_t* code) { return imm32_of(code); } + +/** + * @brief 取 off32(47..16,小端 4 字节,有符号)。 + * @param code 指令字节 + * @return 字节偏移(相对下一条) + */ +int32_t off32_of(const uint8_t* code) { + return static_cast(static_cast(code[2]) + | (static_cast(code[3]) << 8) + | (static_cast(code[4]) << 16) + | (static_cast(code[5]) << 24)); +} + +uint32_t fn_id32_of(const uint8_t* code) { + return static_cast(code[2]) + | (static_cast(code[3]) << 8) + | (static_cast(code[4]) << 16) + | (static_cast(code[5]) << 24); +} + +/** + * @brief 取 fb_id16(31..16)。 + * @param code 指令字节 + * @return FB 类型 id + */ +uint16_t fb_id16_of(const uint8_t* code) { + return static_cast(code[2] | (static_cast(code[3]) << 8)); +} + +/** + * @brief 取 CAL 的实例槽号(63..32)。 + * @param code 指令字节 + * @return 槽号 + */ +uint32_t cal_slot32_of(const uint8_t* code) { + return static_cast(code[4]) + | (static_cast(code[5]) << 8) + | (static_cast(code[6]) << 16) + | (static_cast(code[7]) << 24); +} + +/** + * @brief 取 16B 形态的 off32(87..56)。 + * @param code 指令字节 + * @return 字段偏移(字节) + */ +int32_t off32_hi_of(const uint8_t* code) { + return static_cast(static_cast(code[7]) + | (static_cast(code[8]) << 8) + | (static_cast(code[9]) << 16) + | (static_cast(code[10]) << 24)); +} + +/** + * @brief 取 imm64(87..24)。 + * @param code 指令字节 + * @return 64 位立即数 + */ +uint64_t imm64_of(const uint8_t* code) { + uint64_t v = 0; + for (int i = 0; i < 8; ++i) { + v |= static_cast(code[3 + i]) << (8 * i); + } + return v; +} + +/** + * @brief 写字节 0(前缀 + 操作码)。 + * @param out 指令缓冲(≥16B) + * @param prefix 形态前缀 + * @param op 分区内编号 + */ +void set_byte0(uint8_t* out, const std::string& prefix, uint32_t op) { + if (prefix == "11") { + out[0] = static_cast(0x80 | (op & 0x3F)); + } else if (prefix == "10") { + out[0] = static_cast(0x80 | 0x40 | (op & 0x3F)); + } else if (prefix == "011") { + out[0] = static_cast(0x40 | (op & 0x1F)); + } else if (prefix.size() == 6 && prefix.compare(0, 3, "010") == 0) { + const uint32_t shape = static_cast(prefix[3] - '0') * 4 + + static_cast(prefix[4] - '0') * 2 + + static_cast(prefix[5] - '0'); + out[0] = static_cast(0x40 | (shape << 2) | (op & 0x03)); + } else if (prefix == "0010") { + out[0] = static_cast(0x20 | (op & 0x0F)); + } else if (prefix == "0011") { + out[0] = static_cast(0x30 | (op & 0x0F)); + } else { // "0001" + out[0] = static_cast(0x10 | (op & 0x0F)); + } +} + +void set_func(uint8_t* out, uint8_t func) { + out[1] = static_cast((out[1] & 0x0F) | ((func & 0x0F) << 4)); +} +void set_rd(uint8_t* out, uint8_t rd) { out[2] = rd; } +void set_rs1(uint8_t* out, uint8_t rs1) { out[3] = rs1; } +void set_rs2(uint8_t* out, uint8_t rs2) { out[4] = rs2; } +void set_imm32(uint8_t* out, uint32_t v) { + out[3] = static_cast(v & 0xFF); + out[4] = static_cast((v >> 8) & 0xFF); + out[5] = static_cast((v >> 16) & 0xFF); + out[6] = static_cast((v >> 24) & 0xFF); +} +void set_slot32(uint8_t* out, uint32_t v) { set_imm32(out, v); } +void set_off32(uint8_t* out, int32_t v) { + const uint32_t u = static_cast(v); + out[2] = static_cast(u & 0xFF); + out[3] = static_cast((u >> 8) & 0xFF); + out[4] = static_cast((u >> 16) & 0xFF); + out[5] = static_cast((u >> 24) & 0xFF); +} +void set_fn_id32(uint8_t* out, uint32_t v) { set_off32(out, static_cast(v)); } +void set_fb_id16(uint8_t* out, uint16_t v) { + out[2] = static_cast(v & 0xFF); + out[3] = static_cast((v >> 8) & 0xFF); +} +void set_cal_slot32(uint8_t* out, uint32_t v) { + out[4] = static_cast(v & 0xFF); + out[5] = static_cast((v >> 8) & 0xFF); + out[6] = static_cast((v >> 16) & 0xFF); + out[7] = static_cast((v >> 24) & 0xFF); +} +void set_off32_hi(uint8_t* out, int32_t v) { + const uint32_t u = static_cast(v); + out[7] = static_cast(u & 0xFF); + out[8] = static_cast((u >> 8) & 0xFF); + out[9] = static_cast((u >> 16) & 0xFF); + out[10] = static_cast((u >> 24) & 0xFF); +} +void set_imm64(uint8_t* out, uint64_t v) { + for (int i = 0; i < 8; ++i) { + out[3 + i] = static_cast((v >> (8 * i)) & 0xFF); + } +} + +/** + * @brief 配置驱动反汇编:按 machine.toml 的 prefix/op/func/fmt 输出一行文本。 + * @param cfg 机器配置 + * @param code 指令字节 + * @param len 指令长度 * @param out 输出缓冲 * @param cap 缓冲容量(含 '\0');cap==0 时直接返回、不写 out - * @details 未知操作码输出 `??? 0x%08x`;format 分支 RR/RRR/IMM/SLOT/JMP/JC/CALL/CAL/NONE - * 输出文本与 Doc/isa/指令与映像.md 一致。 */ -void disasm(const MachineConfig& cfg, Instr w, char* out, size_t cap) { +void disasm(const MachineConfig& cfg, const uint8_t* code, size_t len, + char* out, size_t cap) { if (cap == 0) { return; } out[0] = '\0'; - const ConfigOp* op = cfg.find_op_by_code(op_of(w)); + const std::string prefix = prefix_of(code); + const ConfigOp* op = cfg.find_op_by_key(prefix, op_of(code)); if (op == nullptr) { - snprintf(out, cap, "??? 0x%08x", static_cast(w)); + snprintf(out, cap, "??? 0x"); + size_t used = 4; + for (size_t i = 0; i < len && used + 2 < cap; ++i) { + snprintf(out + used, cap - used, "%02x", static_cast(code[i])); + used += 2; + } return; } - const uint8_t rd = rd_of(w); - const std::string& f = op->format; + const uint8_t func = func_of(code); + const std::string suffix = + shows_type_suffix(op->func_mode) ? std::string(".") + type_suffix(func) : ""; + const std::string& f = op->fmt; if (f == "RR") { - snprintf(out, cap, "%s r%u, r%u", op->name.c_str(), static_cast(rd), - static_cast(a_of(w))); + snprintf(out, cap, "%s%s r%u, r%u", op->name.c_str(), suffix.c_str(), + static_cast(rd_of(code)), static_cast(rs1_of(code))); } else if (f == "RRR") { - snprintf(out, cap, "%s r%u, r%u, r%u", op->name.c_str(), static_cast(rd), - static_cast(a_of(w)), static_cast(b_of(w))); - } else if (f == "IMM" || f == "SLOT") { - snprintf(out, cap, "%s r%u, %u", op->name.c_str(), static_cast(rd), - static_cast(imm16_of(w))); + snprintf(out, cap, "%s%s r%u, r%u, r%u", op->name.c_str(), suffix.c_str(), + static_cast(rd_of(code)), static_cast(rs1_of(code)), + static_cast(rs2_of(code))); + } else if (f == "IMM") { + snprintf(out, cap, "%s%s r%u, %u", op->name.c_str(), suffix.c_str(), + static_cast(rd_of(code)), static_cast(imm32_of(code))); + } else if (f == "SLOT") { + snprintf(out, cap, "%s%s r%u, s%u", op->name.c_str(), suffix.c_str(), + static_cast(rd_of(code)), static_cast(slot32_of(code))); } else if (f == "JMP") { - snprintf(out, cap, "%s %+d", op->name.c_str(), static_cast(off16_of(w))); + snprintf(out, cap, "%s %+d", op->name.c_str(), static_cast(off32_of(code))); } else if (f == "JC") { - snprintf(out, cap, "%s r%u, %+d", op->name.c_str(), static_cast(rd), - static_cast(off16_of(w))); - } else if (f == "CALL" || f == "CAL") { - snprintf(out, cap, "%s %u", op->name.c_str(), static_cast(imm16_of(w))); - } else { // NONE + snprintf(out, cap, "%s r%u, %+d", op->name.c_str(), + static_cast(rd_of(code)), static_cast(off32_of(code))); + } else if (f == "CALL") { + snprintf(out, cap, "%s %u", op->name.c_str(), static_cast(fn_id32_of(code))); + } else if (f == "CAL") { + const ConfigFb* fb = cfg.find_fb_by_id(fb_id16_of(code)); + if (fb != nullptr) { + snprintf(out, cap, "CAL.%s s%u", fb->name.c_str(), + static_cast(cal_slot32_of(code))); + } else { + snprintf(out, cap, "CAL ?%u s%u", static_cast(fb_id16_of(code)), + static_cast(cal_slot32_of(code))); + } + } else if (f == "SLOT+off") { + snprintf(out, cap, "%s%s r%u, s%u, %d", op->name.c_str(), suffix.c_str(), + static_cast(rd_of(code)), static_cast(slot32_of(code)), + static_cast(off32_hi_of(code))); + } else { // NONE / 预留 snprintf(out, cap, "%s", op->name.c_str()); } } diff --git a/compiler/src/main.cpp b/compiler/src/main.cpp index c3575de..b6f6a58 100644 --- a/compiler/src/main.cpp +++ b/compiler/src/main.cpp @@ -84,8 +84,8 @@ namespace { const uint8_t* base = v.code_bytes() + r.code_offset; for (uint32_t j = 0; j < r.code_len; ++j) { char buf[64]; - compiler::disasm(cfg, reinterpret_cast(base)[j], buf, - sizeof buf); + // TODO(V2): Stb 重写(阶段2-4)后 code_len 为字节、instr_len 定长 + compiler::disasm(cfg, base + j * 4, 4, buf, sizeof buf); std::printf(" 0x%04x %s\n", v.offset_code() + r.code_offset + j * 4, buf); } diff --git a/tests/src/machine_test.cpp b/tests/src/machine_test.cpp index f0f819b..2d35490 100644 --- a/tests/src/machine_test.cpp +++ b/tests/src/machine_test.cpp @@ -31,16 +31,16 @@ static int g_checks = 0; // ---- 写临时 toml ---- -static std::string write_tmp(const char* name, const char* content) { +static std::string write_tmp(const char* name, const std::string& content) { const std::filesystem::path dir = std::filesystem::temp_directory_path(); const std::filesystem::path path = dir / name; std::FILE* f = std::fopen(path.string().c_str(), "w"); - std::fputs(content, f); + std::fputs(content.c_str(), f); std::fclose(f); return path.string(); } -static bool expect_load_err(const char* name, const char* content, const char* keyword) { +static bool expect_load_err(const char* name, const std::string& content, const char* keyword) { const std::string path = write_tmp(name, content); compiler::MachineConfig cfg; std::string err;