阶段2-3:Codec V2 化(变长指令字编解码 + 配置驱动 disasm 类型后缀)

- 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 重写)
This commit is contained in:
2026-08-25 20:08:37 +08:00
parent a4335693d4
commit 246fe09646
4 changed files with 387 additions and 96 deletions
+98 -34
View File
@@ -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 <cstddef>
#include <cstdint>
#include <string>
#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 op4B 6 位 / 8B 5 位或 2 位 / 16B·32B 4 位)
*/
uint8_t op_of(const uint8_t* code);
/**
* @brief 取 func 位段(字节 1 高 4 位)。
* @param code 指令字节
* @return 0..150..9 有效)
*/
uint8_t func_of(const uint8_t* code);
/// @brief 取 rd23..16)。
uint8_t rd_of(const uint8_t* code);
/// @brief 取 rs131..24)。
uint8_t rs1_of(const uint8_t* code);
/// @brief 取 rs239..32)。
uint8_t rs2_of(const uint8_t* code);
/// @brief 取 imm3255..24IMM 形态)。
uint32_t imm32_of(const uint8_t* code);
/// @brief 取 slot3255..24SLOT 形态)。
uint32_t slot32_of(const uint8_t* code);
/// @brief 取 off3247..16JMP/JC 形态,有符号字节偏移)。
int32_t off32_of(const uint8_t* code);
/// @brief 取 fn_id3247..16CALL 形态)。
uint32_t fn_id32_of(const uint8_t* code);
/// @brief 取 fb_id1631..16CAL 形态)。
uint16_t fb_id16_of(const uint8_t* code);
/// @brief 取 CAL 的实例槽号(63..32)。
uint32_t cal_slot32_of(const uint8_t* code);
/// @brief 取 16B 形态的 off3287..56)。
int32_t off32_hi_of(const uint8_t* code);
/// @brief 取 imm6487..24IMM64 形态)。
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 写 rd23..16)。
void set_rd(uint8_t* out, uint8_t rd);
/// @brief 写 rs131..24)。
void set_rs1(uint8_t* out, uint8_t rs1);
/// @brief 写 rs239..32)。
void set_rs2(uint8_t* out, uint8_t rs2);
/// @brief 写 imm3255..24)。
void set_imm32(uint8_t* out, uint32_t v);
/// @brief 写 slot3255..24)。
void set_slot32(uint8_t* out, uint32_t v);
/// @brief 写 off3247..16)。
void set_off32(uint8_t* out, int32_t v);
/// @brief 写 fn_id3247..16)。
void set_fn_id32(uint8_t* out, uint32_t v);
/// @brief 写 fb_id1631..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 形态的 off3287..56)。
void set_off32_hi(uint8_t* out, int32_t v);
/// @brief 写 imm6487..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<hex>`。
* @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<hex dump>`。
*/
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);
}