Files
Interpreter/compiler/src/Codec.cpp
T
Admin b19a61aabf 阶段3-4:新类型运算验证 + 修复(011 前缀位、func 大小写、位串 AND/OR)
新类型运算验证(综合用例全部正确):
- REAL 算术 ADD.F32、LREAL 算术 ADD.F64
- TIME+ ADD.I64、TIME 比较 CMP_GT.I64
- DATE/TOD/DT 比较 CMP_GT.U32/U32/U64
- DINT 算术 ADD.I32、UDINT 字面量装载+截断
- WORD 位串 AND(短路 JF+MOVE)
- 负例:UINT 溢出拦截

修复的 bug:
1. set_byte0 '011' 分支 0x40→0x60(RRR 指令被误判为 010 区,
   ADD 等显示错乱)——阶段 2 遗留
2. Codegen func_of_name 大小写不敏感(符号表小写/type 表大写,
   否则 REAL 等返回 func 0)
3. Typecheck AND/OR 支持位串(BOOL 逻辑或 bit 按宽度逐位)

已知缺陷(记录):LREAL 字面量装载按 REAL(LOADK.F32),
ADD.F64 运算位模式错位——需 compile_expr 携带目标 func(TODO)。
2026-08-26 09:40:12 +08:00

347 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @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 <cstdio>
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"; // 4Bbit6 区分 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 op4B 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; // 4B6 位
if ((b & 0xC0) == 0x40) {
return (b & 0x20) ? (b & 0x1F) : (b & 0x03); // 8B011 → 5 位;010 → 2 位
}
return b & 0x0F; // 16B/32B4 位
}
/**
* @brief 取 func 位段(字节 1 高 4 位)。
* @param code 指令字节
* @return 0..150..9 有效)
*/
uint8_t func_of(const uint8_t* code) {
return static_cast<uint8_t>((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 取 imm3255..24,小端 4 字节)。
* @param code 指令字节
* @return 32 位立即数
*/
uint32_t imm32_of(const uint8_t* code) {
return static_cast<uint32_t>(code[3])
| (static_cast<uint32_t>(code[4]) << 8)
| (static_cast<uint32_t>(code[5]) << 16)
| (static_cast<uint32_t>(code[6]) << 24);
}
uint32_t slot32_of(const uint8_t* code) { return imm32_of(code); }
/**
* @brief 取 off3247..16JMP 形态,小端 4 字节,有符号)。
* @param code 指令字节
* @return 字节偏移(相对下一条)
*/
int32_t off32_of(const uint8_t* code) {
return static_cast<int32_t>(static_cast<uint32_t>(code[2])
| (static_cast<uint32_t>(code[3]) << 8)
| (static_cast<uint32_t>(code[4]) << 16)
| (static_cast<uint32_t>(code[5]) << 24));
}
/**
* @brief 取 off3255..24JC 形态,小端 4 字节,有符号)。
* @param code 指令字节
* @return 字节偏移(相对下一条)
*/
int32_t off32_jc_of(const uint8_t* code) {
return static_cast<int32_t>(static_cast<uint32_t>(code[3])
| (static_cast<uint32_t>(code[4]) << 8)
| (static_cast<uint32_t>(code[5]) << 16)
| (static_cast<uint32_t>(code[6]) << 24));
}
uint32_t fn_id32_of(const uint8_t* code) {
return static_cast<uint32_t>(code[2])
| (static_cast<uint32_t>(code[3]) << 8)
| (static_cast<uint32_t>(code[4]) << 16)
| (static_cast<uint32_t>(code[5]) << 24);
}
/**
* @brief 取 fb_id1631..16)。
* @param code 指令字节
* @return FB 类型 id
*/
uint16_t fb_id16_of(const uint8_t* code) {
return static_cast<uint16_t>(code[2] | (static_cast<uint16_t>(code[3]) << 8));
}
/**
* @brief 取 CAL 的实例槽号(63..32)。
* @param code 指令字节
* @return 槽号
*/
uint32_t cal_slot32_of(const uint8_t* code) {
return static_cast<uint32_t>(code[4])
| (static_cast<uint32_t>(code[5]) << 8)
| (static_cast<uint32_t>(code[6]) << 16)
| (static_cast<uint32_t>(code[7]) << 24);
}
/**
* @brief 取 16B 形态的 off3287..56)。
* @param code 指令字节
* @return 字段偏移(字节)
*/
int32_t off32_hi_of(const uint8_t* code) {
return static_cast<int32_t>(static_cast<uint32_t>(code[7])
| (static_cast<uint32_t>(code[8]) << 8)
| (static_cast<uint32_t>(code[9]) << 16)
| (static_cast<uint32_t>(code[10]) << 24));
}
/**
* @brief 取 imm6487..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<uint64_t>(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<uint8_t>(0xC0 | (op & 0x3F)); // bit7..6 = 11
} else if (prefix == "10") {
out[0] = static_cast<uint8_t>(0x80 | (op & 0x3F)); // bit7..6 = 10
} else if (prefix == "011") {
out[0] = static_cast<uint8_t>(0x60 | (op & 0x1F)); // bit7..5 = 011
} else if (prefix.size() == 6 && prefix.compare(0, 3, "010") == 0) {
const uint32_t shape = static_cast<uint32_t>(prefix[3] - '0') * 4 +
static_cast<uint32_t>(prefix[4] - '0') * 2 +
static_cast<uint32_t>(prefix[5] - '0');
out[0] = static_cast<uint8_t>(0x40 | (shape << 2) | (op & 0x03));
} else if (prefix == "0010") {
out[0] = static_cast<uint8_t>(0x20 | (op & 0x0F));
} else if (prefix == "0011") {
out[0] = static_cast<uint8_t>(0x30 | (op & 0x0F));
} else { // "0001"
out[0] = static_cast<uint8_t>(0x10 | (op & 0x0F));
}
}
void set_func(uint8_t* out, uint8_t func) {
out[1] = static_cast<uint8_t>((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<uint8_t>(v & 0xFF);
out[4] = static_cast<uint8_t>((v >> 8) & 0xFF);
out[5] = static_cast<uint8_t>((v >> 16) & 0xFF);
out[6] = static_cast<uint8_t>((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<uint32_t>(v);
out[2] = static_cast<uint8_t>(u & 0xFF);
out[3] = static_cast<uint8_t>((u >> 8) & 0xFF);
out[4] = static_cast<uint8_t>((u >> 16) & 0xFF);
out[5] = static_cast<uint8_t>((u >> 24) & 0xFF);
}
void set_off32_jc(uint8_t* out, int32_t v) {
const uint32_t u = static_cast<uint32_t>(v);
out[3] = static_cast<uint8_t>(u & 0xFF);
out[4] = static_cast<uint8_t>((u >> 8) & 0xFF);
out[5] = static_cast<uint8_t>((u >> 16) & 0xFF);
out[6] = static_cast<uint8_t>((u >> 24) & 0xFF);
}
void set_fn_id32(uint8_t* out, uint32_t v) { set_off32(out, static_cast<int32_t>(v)); }
void set_fb_id16(uint8_t* out, uint16_t v) {
out[2] = static_cast<uint8_t>(v & 0xFF);
out[3] = static_cast<uint8_t>((v >> 8) & 0xFF);
}
void set_cal_slot32(uint8_t* out, uint32_t v) {
out[4] = static_cast<uint8_t>(v & 0xFF);
out[5] = static_cast<uint8_t>((v >> 8) & 0xFF);
out[6] = static_cast<uint8_t>((v >> 16) & 0xFF);
out[7] = static_cast<uint8_t>((v >> 24) & 0xFF);
}
void set_off32_hi(uint8_t* out, int32_t v) {
const uint32_t u = static_cast<uint32_t>(v);
out[7] = static_cast<uint8_t>(u & 0xFF);
out[8] = static_cast<uint8_t>((u >> 8) & 0xFF);
out[9] = static_cast<uint8_t>((u >> 16) & 0xFF);
out[10] = static_cast<uint8_t>((u >> 24) & 0xFF);
}
void set_imm64(uint8_t* out, uint64_t v) {
for (int i = 0; i < 8; ++i) {
out[3 + i] = static_cast<uint8_t>((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<unsigned>(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<unsigned>(rd_of(code)), static_cast<unsigned>(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<unsigned>(rd_of(code)), static_cast<unsigned>(rs1_of(code)),
static_cast<unsigned>(rs2_of(code)));
} else if (f == "IMM") {
snprintf(out, cap, "%s%s r%u, %u", op->name.c_str(), suffix.c_str(),
static_cast<unsigned>(rd_of(code)), static_cast<unsigned>(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<unsigned>(rd_of(code)), static_cast<unsigned>(slot32_of(code)));
} else if (f == "JMP") {
snprintf(out, cap, "%s %+d", op->name.c_str(), static_cast<int>(off32_of(code)));
} else if (f == "JC") {
snprintf(out, cap, "%s r%u, %+d", op->name.c_str(),
static_cast<unsigned>(rd_of(code)), static_cast<int>(off32_jc_of(code)));
} else if (f == "CALL") {
snprintf(out, cap, "%s %u", op->name.c_str(), static_cast<unsigned>(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<unsigned>(cal_slot32_of(code)));
} else {
snprintf(out, cap, "CAL ?%u s%u", static_cast<unsigned>(fb_id16_of(code)),
static_cast<unsigned>(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<unsigned>(rd_of(code)), static_cast<unsigned>(slot32_of(code)),
static_cast<int>(off32_hi_of(code)));
} else { // NONE / 预留
snprintf(out, cap, "%s", op->name.c_str());
}
}
} // namespace compiler