阶段4-1:isa 重构 V2 完成(Types/Op/Instr/Encode + isa_test 91 checks)
- Types.h:func 宽度/符号表(kFuncWidth/kFuncSigned)、饱和模板(各宽度 __int128 中间量 + 除法 A:除零返回被除数/MIN/-1 夹界/截断)、删 TypeTag - Op.h/.cpp:前缀分区 + 72 条指令表(与 machine.toml 强校验一致)、 uses_rd/rs1/rs2 直推、kFbNames(15 内建 FB) - Instr.h:变长 instr_len、位号 get/set(含 JC off@55..24、SLOT_OFF off@87..56)、 enc_* 发射器 - Encode.h/.cpp:decode/encode 往返、disasm(类型后缀 + CAL fb 名 + 未知 0x dump) - isa_test V2:饱和边界/func 表/前缀定长/位号往返/编解码/disasm/uses_*/指令表 修复的实现 bug:find_op 字符串比较(指针==)、set_byte0 11/10 与 010xxx 分支、 CAL 字段约定((slot<<16)|fb_id)、disasm 未知前缀 used 长度 状态:vm/executor 编译暂破(V1 代码引用旧 isa 接口),4-2 同步
This commit is contained in:
+144
-46
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @file Encode.cpp
|
||||
* @brief 指令编解码与反汇编实现
|
||||
* @brief 指令编解码与反汇编实现(V2)
|
||||
* @author
|
||||
* @date 2026-08-19
|
||||
*/
|
||||
@@ -8,83 +8,181 @@
|
||||
#include "isa/Encode.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
namespace isa {
|
||||
|
||||
/**
|
||||
* @brief 编码:字段视图打包成一条 32 位指令字。
|
||||
* @param d 解码后的字段视图
|
||||
* @return 打包后的指令字;满足 encode(decode(w)) == w
|
||||
*/
|
||||
Instr encode(Decoded d) {
|
||||
return pack(d.op, d.rd, d.a, d.b);
|
||||
}
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* @brief func → 类型后缀(disasm 用)。
|
||||
* @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];
|
||||
}
|
||||
|
||||
/// 形态是否显示类型后缀(full/float/dst 类)。
|
||||
bool shows_type_suffix(FuncMode m) {
|
||||
return m == FuncMode::Full || m == FuncMode::Float || m == FuncMode::Dst;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/**
|
||||
* @brief 解码:指令字拆成字段视图。
|
||||
* @param w 32 位指令字
|
||||
* @return 各字段视图
|
||||
* @brief 解码:指令字节 → 字段视图。
|
||||
*/
|
||||
Decoded decode(Instr w) {
|
||||
Decoded decode(const uint8_t* code, size_t len) {
|
||||
Decoded d;
|
||||
d.op = op(w);
|
||||
d.rd = rd(w);
|
||||
d.a = a(w);
|
||||
d.b = b(w);
|
||||
(void)len;
|
||||
// 前缀推导(按字节 0 位模式)
|
||||
const uint8_t b = code[0];
|
||||
if (b & 0x80) {
|
||||
d.prefix = (b & 0x40) ? "11" : "10";
|
||||
d.op = b & 0x3F;
|
||||
} else if ((b & 0xC0) == 0x40) {
|
||||
if (b & 0x20) {
|
||||
d.prefix = "011";
|
||||
d.op = b & 0x1F;
|
||||
} else {
|
||||
static const char* kShapes[8] = {
|
||||
"010000", "010001", "010010", "010011",
|
||||
"010100", "010101", "010110", "010111",
|
||||
};
|
||||
d.prefix = kShapes[(b >> 2) & 0x07];
|
||||
d.op = b & 0x03;
|
||||
}
|
||||
} else if ((b & 0xE0) == 0x20) {
|
||||
d.prefix = (b & 0x10) ? "0011" : "0010";
|
||||
d.op = b & 0x0F;
|
||||
} else {
|
||||
d.prefix = "0001";
|
||||
d.op = b & 0x0F;
|
||||
}
|
||||
d.func = func_of(code);
|
||||
d.rd = rd_of(code);
|
||||
d.rs1 = rs1_of(code);
|
||||
d.rs2 = rs2_of(code);
|
||||
// 数值字段(按形态解释):IMM/SLOT → imm32;JMP/JC → off;CALL → fn_id
|
||||
const OpFormat f = format_of(d.prefix, d.op);
|
||||
if (f == OpFormat::IMM || f == OpFormat::SLOT) {
|
||||
d.imm32 = imm32_of(code);
|
||||
} else if (f == OpFormat::JMP) {
|
||||
d.imm32 = static_cast<uint32_t>(off32_of(code));
|
||||
} else if (f == OpFormat::JC) {
|
||||
d.imm32 = static_cast<uint32_t>(off32_jc_of(code));
|
||||
} else if (f == OpFormat::CALL) {
|
||||
d.imm32 = fn_id32_of(code);
|
||||
} else if (f == OpFormat::CAL) {
|
||||
d.imm32 = (cal_slot32_of(code) << 16) | fb_id16_of(code); // (slot<<16)|fb_id
|
||||
} else if (f == OpFormat::SLOT_OFF) {
|
||||
d.imm32 = slot32_of(code);
|
||||
d.off_hi = off32_hi_of(code);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 反汇编一条指令为一行文本。
|
||||
* @param w 指令字
|
||||
* @param out 输出缓冲
|
||||
* @param cap 缓冲容量(含 '\0');cap==0 时直接返回、不写 out
|
||||
* @details 按操作数形态表驱动输出,文本与 Doc/isa/指令与映像.md 一致;
|
||||
* 未知操作码输出 `??? 0x<w>`。
|
||||
* @brief 编码:字段视图 → 指令字节。
|
||||
*/
|
||||
void disasm(Instr w, char* out, size_t cap) {
|
||||
size_t encode(const Decoded& d, uint8_t* out) {
|
||||
set_byte0(out, d.prefix, d.op);
|
||||
set_func(out, d.func);
|
||||
set_rd(out, d.rd);
|
||||
set_rs1(out, d.rs1);
|
||||
set_rs2(out, d.rs2);
|
||||
const OpFormat f = format_of(d.prefix, d.op);
|
||||
if (f == OpFormat::IMM || f == OpFormat::SLOT) {
|
||||
set_imm32(out, d.imm32);
|
||||
} else if (f == OpFormat::JMP) {
|
||||
set_off32(out, static_cast<int32_t>(d.imm32));
|
||||
} else if (f == OpFormat::JC) {
|
||||
set_off32_jc(out, static_cast<int32_t>(d.imm32));
|
||||
} else if (f == OpFormat::CALL) {
|
||||
set_fn_id32(out, d.imm32);
|
||||
} else if (f == OpFormat::CAL) {
|
||||
set_fb_id16(out, static_cast<uint16_t>(d.imm32 & 0xFFFF));
|
||||
set_cal_slot32(out, d.imm32);
|
||||
} else if (f == OpFormat::SLOT_OFF) {
|
||||
set_slot32(out, d.imm32);
|
||||
set_off32_hi(out, d.off_hi);
|
||||
}
|
||||
return instr_len(out);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 反汇编一条指令为一行文本。
|
||||
*/
|
||||
void disasm(const uint8_t* code, size_t len, char* out, size_t cap) {
|
||||
if (cap == 0) {
|
||||
return;
|
||||
}
|
||||
out[0] = '\0';
|
||||
|
||||
const Op o = op(w);
|
||||
const int idx = static_cast<int>(o);
|
||||
if (idx < 0 || idx >= kOpCount) {
|
||||
snprintf(out, cap, "??? 0x%08x", static_cast<unsigned>(w));
|
||||
const Decoded d = decode(code, len);
|
||||
const int idx = find_op(d.prefix, d.op);
|
||||
if (idx < 0) {
|
||||
snprintf(out, cap, "??? 0x");
|
||||
size_t used = 6; // "??? 0x" 长度
|
||||
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 char* m = mnemonic(o);
|
||||
|
||||
// 表驱动:按操作数形态输出(文本与 Doc/isa/指令与映像.md 一致)
|
||||
switch (format(o)) {
|
||||
const OpDef& od = kOps[idx];
|
||||
const std::string suffix =
|
||||
shows_type_suffix(od.func_mode) ? std::string(".") + type_suffix(d.func) : "";
|
||||
const OpFormat f = od.format;
|
||||
switch (f) {
|
||||
case OpFormat::RR:
|
||||
snprintf(out, cap, "%s r%u, r%u", m,
|
||||
static_cast<unsigned>(rd(w)), static_cast<unsigned>(a(w)));
|
||||
snprintf(out, cap, "%s%s r%u, r%u", od.name, suffix.c_str(),
|
||||
static_cast<unsigned>(d.rd), static_cast<unsigned>(d.rs1));
|
||||
break;
|
||||
case OpFormat::RRR:
|
||||
snprintf(out, cap, "%s r%u, r%u, r%u", m,
|
||||
static_cast<unsigned>(rd(w)), static_cast<unsigned>(a(w)),
|
||||
static_cast<unsigned>(b(w)));
|
||||
snprintf(out, cap, "%s%s r%u, r%u, r%u", od.name, suffix.c_str(),
|
||||
static_cast<unsigned>(d.rd), static_cast<unsigned>(d.rs1),
|
||||
static_cast<unsigned>(d.rs2));
|
||||
break;
|
||||
case OpFormat::IMM:
|
||||
snprintf(out, cap, "%s%s r%u, %u", od.name, suffix.c_str(),
|
||||
static_cast<unsigned>(d.rd), static_cast<unsigned>(d.imm32));
|
||||
break;
|
||||
case OpFormat::SLOT:
|
||||
snprintf(out, cap, "%s r%u, %u", m,
|
||||
static_cast<unsigned>(rd(w)), static_cast<unsigned>(imm16(w)));
|
||||
snprintf(out, cap, "%s%s r%u, s%u", od.name, suffix.c_str(),
|
||||
static_cast<unsigned>(d.rd), static_cast<unsigned>(d.imm32));
|
||||
break;
|
||||
case OpFormat::JMP:
|
||||
snprintf(out, cap, "%s %+d", m, static_cast<int>(off16(w)));
|
||||
snprintf(out, cap, "%s %+d", od.name, static_cast<int>(d.imm32));
|
||||
break;
|
||||
case OpFormat::JC:
|
||||
snprintf(out, cap, "%s r%u, %+d", m,
|
||||
static_cast<unsigned>(rd(w)), static_cast<int>(off16(w)));
|
||||
snprintf(out, cap, "%s r%u, %+d", od.name, static_cast<unsigned>(d.rd),
|
||||
static_cast<int>(d.imm32));
|
||||
break;
|
||||
case OpFormat::CALL:
|
||||
case OpFormat::CAL:
|
||||
snprintf(out, cap, "%s %u", m, static_cast<unsigned>(imm16(w)));
|
||||
snprintf(out, cap, "%s %u", od.name, static_cast<unsigned>(d.imm32));
|
||||
break;
|
||||
case OpFormat::CAL: {
|
||||
const uint16_t fb = static_cast<uint16_t>(d.imm32 & 0xFFFF);
|
||||
const char* fbname = (fb < 15) ? kFbNames[fb] : "?";
|
||||
snprintf(out, cap, "CAL.%s s%u", fbname, static_cast<unsigned>(d.imm32 >> 16));
|
||||
break;
|
||||
}
|
||||
case OpFormat::SLOT_OFF:
|
||||
snprintf(out, cap, "%s%s r%u, s%u, %d", od.name, suffix.c_str(),
|
||||
static_cast<unsigned>(d.rd), static_cast<unsigned>(d.imm32),
|
||||
static_cast<int>(d.off_hi));
|
||||
break;
|
||||
case OpFormat::IMM64:
|
||||
case OpFormat::NONE:
|
||||
snprintf(out, cap, "%s", m);
|
||||
case OpFormat::RESERVED:
|
||||
default:
|
||||
snprintf(out, cap, "%s", od.name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* @file Op.cpp
|
||||
* @brief 操作码表与查询实现(V2)
|
||||
* @details 指令表与 compiler/machine.toml 的 72 条 op 行强校验一致;
|
||||
* uses_* 由形态直推(前缀分区表达,零查表)。
|
||||
* @author
|
||||
* @date 2026-08-19
|
||||
*/
|
||||
|
||||
#include "isa/Op.h"
|
||||
|
||||
namespace isa {
|
||||
|
||||
const char* kPrefixNames[12] = {
|
||||
"11", "10", "011", "010000", "010001", "010010",
|
||||
"010011", "010100", "010101", "0010", "0011", "0001",
|
||||
};
|
||||
|
||||
// 指令表(72 条;顺序与 machine.toml [[op]] 一致)
|
||||
const OpDef kOps[] = {
|
||||
// 4B RR(前缀 11)
|
||||
{"MOVE", "11", Op::MOVE, OpFormat::RR, FuncMode::Width},
|
||||
{"NOT", "11", Op::NOT, OpFormat::RR, FuncMode::Uint},
|
||||
{"NEG", "11", Op::NEG, OpFormat::RR, FuncMode::Full},
|
||||
{"ABS", "11", Op::ABS, OpFormat::RR, FuncMode::Full},
|
||||
{"INC", "11", Op::INC, OpFormat::RR, FuncMode::Full},
|
||||
{"DEC", "11", Op::DEC, OpFormat::RR, FuncMode::Full},
|
||||
{"SQRT", "11", Op::SQRT, OpFormat::RR, FuncMode::Float},
|
||||
{"SIN", "11", Op::SIN, OpFormat::RR, FuncMode::Float},
|
||||
{"COS", "11", Op::COS, OpFormat::RR, FuncMode::Float},
|
||||
{"TAN", "11", Op::TAN, OpFormat::RR, FuncMode::Float},
|
||||
{"ASIN", "11", Op::ASIN, OpFormat::RR, FuncMode::Float},
|
||||
{"ACOS", "11", Op::ACOS, OpFormat::RR, FuncMode::Float},
|
||||
{"ATAN", "11", Op::ATAN, OpFormat::RR, FuncMode::Float},
|
||||
{"LN", "11", Op::LN, OpFormat::RR, FuncMode::Float},
|
||||
{"LOG", "11", Op::LOG, OpFormat::RR, FuncMode::Float},
|
||||
{"EXP", "11", Op::EXP, OpFormat::RR, FuncMode::Float},
|
||||
{"ROUND", "11", Op::ROUND, OpFormat::RR, FuncMode::Float},
|
||||
{"TRUNC", "11", Op::TRUNC, OpFormat::RR, FuncMode::Float},
|
||||
{"FLOOR", "11", Op::FLOOR, OpFormat::RR, FuncMode::Float},
|
||||
{"CEIL", "11", Op::CEIL, OpFormat::RR, FuncMode::Float},
|
||||
{"CONV", "11", Op::CONV, OpFormat::RR, FuncMode::Dst},
|
||||
// 4B NONE(前缀 10)
|
||||
{"NOP", "10", Op::NOP, OpFormat::NONE, FuncMode::None},
|
||||
{"RET", "10", Op::RET, OpFormat::NONE, FuncMode::None},
|
||||
// 8B RRR(前缀 011)
|
||||
{"ADD", "011", Op::ADD, OpFormat::RRR, FuncMode::Full},
|
||||
{"SUB", "011", Op::SUB, OpFormat::RRR, FuncMode::Full},
|
||||
{"MUL", "011", Op::MUL, OpFormat::RRR, FuncMode::Full},
|
||||
{"DIV", "011", Op::DIV, OpFormat::RRR, FuncMode::Full},
|
||||
{"MOD", "011", Op::MOD, OpFormat::RRR, FuncMode::Full},
|
||||
{"EXPT", "011", Op::EXPT, OpFormat::RRR, FuncMode::Full},
|
||||
{"AND", "011", Op::AND, OpFormat::RRR, FuncMode::Uint},
|
||||
{"OR", "011", Op::OR, OpFormat::RRR, FuncMode::Uint},
|
||||
{"XOR", "011", Op::XOR, OpFormat::RRR, FuncMode::Uint},
|
||||
{"NAND", "011", Op::NAND, OpFormat::RRR, FuncMode::Uint},
|
||||
{"NOR", "011", Op::NOR, OpFormat::RRR, FuncMode::Uint},
|
||||
{"XNOR", "011", Op::XNOR, OpFormat::RRR, FuncMode::Uint},
|
||||
{"SHL", "011", Op::SHL, OpFormat::RRR, FuncMode::Uint},
|
||||
{"SHR", "011", Op::SHR, OpFormat::RRR, FuncMode::Full},
|
||||
{"ROL", "011", Op::ROL, OpFormat::RRR, FuncMode::Uint},
|
||||
{"ROR", "011", Op::ROR, OpFormat::RRR, FuncMode::Uint},
|
||||
{"CMP_EQ", "011", Op::CMP_EQ, OpFormat::RRR, FuncMode::Full},
|
||||
{"CMP_NE", "011", Op::CMP_NE, OpFormat::RRR, FuncMode::Full},
|
||||
{"CMP_LT", "011", Op::CMP_LT, OpFormat::RRR, FuncMode::Full},
|
||||
{"CMP_LE", "011", Op::CMP_LE, OpFormat::RRR, FuncMode::Full},
|
||||
{"CMP_GT", "011", Op::CMP_GT, OpFormat::RRR, FuncMode::Full},
|
||||
{"CMP_GE", "011", Op::CMP_GE, OpFormat::RRR, FuncMode::Full},
|
||||
{"GETBIT", "011", Op::GETBIT, OpFormat::RRR, FuncMode::None},
|
||||
{"SETBIT", "011", Op::SETBIT, OpFormat::RRR, FuncMode::None},
|
||||
{"CLRBIT", "011", Op::CLRBIT, OpFormat::RRR, FuncMode::None},
|
||||
{"TOGBIT", "011", Op::TOGBIT, OpFormat::RRR, FuncMode::None},
|
||||
// 8B 010 区
|
||||
{"LOADK", "010000", Op::LOADK, OpFormat::IMM, FuncMode::Full},
|
||||
{"LOAD", "010001", Op::LOAD, OpFormat::SLOT, FuncMode::Full},
|
||||
{"STORE", "010001", Op::STORE, OpFormat::SLOT, FuncMode::Full},
|
||||
{"JMP", "010010", Op::JMP, OpFormat::JMP, FuncMode::None},
|
||||
{"JT", "010011", Op::JT, OpFormat::JC, FuncMode::None},
|
||||
{"JF", "010011", Op::JF, OpFormat::JC, FuncMode::None},
|
||||
{"CALL", "010100", Op::CALL, OpFormat::CALL, FuncMode::None},
|
||||
{"CAL", "010101", Op::CAL, OpFormat::CAL, FuncMode::None},
|
||||
// 16B
|
||||
{"LOAD_OFF", "0010", Op::LOAD_OFF, OpFormat::SLOT_OFF, FuncMode::Full},
|
||||
{"STORE_OFF", "0010", Op::STORE_OFF, OpFormat::SLOT_OFF, FuncMode::Full},
|
||||
{"STR_LEN", "0010", Op::STR_LEN, OpFormat::SLOT_OFF, FuncMode::None},
|
||||
{"STR_CMP", "0010", Op::STR_CMP, OpFormat::SLOT_OFF, FuncMode::None},
|
||||
{"STR_EQ", "0010", Op::STR_EQ, OpFormat::SLOT_OFF, FuncMode::None},
|
||||
{"STR_MID", "0010", Op::STR_MID, OpFormat::SLOT_OFF, FuncMode::None},
|
||||
{"STR_LEFT", "0010", Op::STR_LEFT, OpFormat::SLOT_OFF, FuncMode::None},
|
||||
{"STR_RIGHT", "0010", Op::STR_RIGHT, OpFormat::SLOT_OFF, FuncMode::None},
|
||||
{"LOADK64", "0011", Op::LOADK64, OpFormat::IMM64, FuncMode::Full},
|
||||
// 32B 预留
|
||||
{"JTBL", "0001", Op::JTBL, OpFormat::RESERVED, FuncMode::None},
|
||||
{"STR_CONCAT", "0001", Op::STR_CONCAT, OpFormat::RESERVED, FuncMode::None},
|
||||
{"STR_FIND", "0001", Op::STR_FIND, OpFormat::RESERVED, FuncMode::None},
|
||||
{"STR_REPLACE", "0001", Op::STR_REPLACE, OpFormat::RESERVED, FuncMode::None},
|
||||
{"ARR_LOAD", "0001", Op::ARR_LOAD, OpFormat::RESERVED, FuncMode::None},
|
||||
{"ARR_STORE", "0001", Op::ARR_STORE, OpFormat::RESERVED, FuncMode::None},
|
||||
};
|
||||
|
||||
int find_op(const char* prefix, uint8_t op) {
|
||||
for (int i = 0; i < kOpCount; ++i) {
|
||||
const char* p = kOps[i].prefix;
|
||||
const char* q = prefix;
|
||||
bool eq = true;
|
||||
while (*p && *q) {
|
||||
if (*p != *q) { eq = false; break; }
|
||||
++p; ++q;
|
||||
}
|
||||
if (eq && *p == *q && static_cast<uint8_t>(kOps[i].op) == op) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int find_op_by_name(const char* name) {
|
||||
for (int i = 0; i < kOpCount; ++i) {
|
||||
const char* p = kOps[i].name;
|
||||
const char* q = name;
|
||||
while (*p && *q && *p == *q) { ++p; ++q; }
|
||||
if (*p == '\0' && *q == '\0') {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char* mnemonic(const char* prefix, uint8_t op) {
|
||||
const int i = find_op(prefix, op);
|
||||
return i >= 0 ? kOps[i].name : "???";
|
||||
}
|
||||
|
||||
OpFormat format_of(const char* prefix, uint8_t op) {
|
||||
const int i = find_op(prefix, op);
|
||||
return i >= 0 ? kOps[i].format : OpFormat::RESERVED;
|
||||
}
|
||||
|
||||
FuncMode func_mode_of(const char* prefix, uint8_t op) {
|
||||
const int i = find_op(prefix, op);
|
||||
return i >= 0 ? kOps[i].func_mode : FuncMode::None;
|
||||
}
|
||||
|
||||
bool uses_rd(OpFormat f) {
|
||||
return f == OpFormat::RR || f == OpFormat::RRR || f == OpFormat::IMM ||
|
||||
f == OpFormat::SLOT || f == OpFormat::JC || f == OpFormat::SLOT_OFF ||
|
||||
f == OpFormat::IMM64;
|
||||
}
|
||||
|
||||
bool uses_rs1(OpFormat f) {
|
||||
return f == OpFormat::RR || f == OpFormat::RRR;
|
||||
}
|
||||
|
||||
bool uses_rs2(OpFormat f) {
|
||||
return f == OpFormat::RRR;
|
||||
}
|
||||
|
||||
const char* kFbNames[15] = {
|
||||
"TON", "TOF", "TP", "CTU", "DCTU", "CTD", "DCTD", "CTUD",
|
||||
"DCTUD", "R_TRIG", "F_TRIG", "SR", "RS", "PWM", "RTC",
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user