/** * @file Codec.cpp * @brief 指令字编解码 + 配置驱动反汇编(编译器侧,V2) * @author * @date 2026-08-21 * * @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" #include namespace compiler { namespace { /** * @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 前缀定长:读字节 0 判指令长度。 * @param code 指令字节(至少 1 字节) * @return 4/8/16/32(前缀 `1`/`01`/`001`/`0001`) */ 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 推导形态前缀字符串。 * @param code 指令字节 * @return "11"/"10"/"011"/"010000".."010101"/"0010"/"0011"/"0001" */ 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 取分区内操作码。 * @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,JMP 形态,小端 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)); } /** * @brief 取 off32(55..24,JC 形态,小端 4 字节,有符号)。 * @param code 指令字节 * @return 字节偏移(相对下一条) */ int32_t off32_jc_of(const uint8_t* code) { return static_cast(static_cast(code[3]) | (static_cast(code[4]) << 8) | (static_cast(code[5]) << 16) | (static_cast(code[6]) << 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(0xC0 | (op & 0x3F)); // bit7..6 = 11 } else if (prefix == "10") { out[0] = static_cast(0x80 | (op & 0x3F)); // bit7..6 = 10 } else if (prefix == "011") { out[0] = static_cast(0x60 | (op & 0x1F)); // bit7..5 = 011 } 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_off32_jc(uint8_t* out, int32_t v) { const uint32_t u = static_cast(v); out[3] = static_cast(u & 0xFF); out[4] = static_cast((u >> 8) & 0xFF); out[5] = static_cast((u >> 16) & 0xFF); out[6] = 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 */ 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 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"); 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 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%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%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(off32_of(code))); } else if (f == "JC") { snprintf(out, cap, "%s r%u, %+d", op->name.c_str(), static_cast(rd_of(code)), static_cast(off32_jc_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()); } } } // namespace compiler