- Doc/isa/指令配置.md:格式(全属性必填)、OpTable(解析+与枚举强校验)、 各端接线(STCompiler --ops 编译路径必填/屏蔽传导;BytecodeExecutor 可选加载/Disabled 故障)、 加指令/屏蔽流程、7 步执行计划 - FB 注册并入 ops.txt 列为待讨论(未定案) - 索引登记
4.3 KiB
4.3 KiB
指令配置文件(ops.txt)
指令集的唯一事实来源:name / opcode / format / 参数名 / enabled。代码实现与配置文件在启动时强校验一致,防止两处漂移。
目标
- 加指令/屏蔽指令的登记集中在一处(配置文件),不再散落在代码各处手改
- 执行器(VM):语义实现必须在代码里,不能纯从文件加载;配置文件用于屏蔽(
enabled=false的指令执行到 → 故障) - 编译器(STCompiler):启动时从文件加载(校验 + 屏蔽传导)
.stbABI 不变:opcode 数值仍是冻结契约;屏蔽是编译期/运行期策略,不改数值
配置文件格式(isa/ops.txt)
全属性必填,不可省略;# 注释、空行忽略:
# 格式:op <name> <opcode> <format> <参数名...> enabled
op MOVE 0 RR rd rs enabled
op LOADK 1 IMM rd const_id enabled
op NOT 2 RR rd rs enabled
op AND 3 RRR rd ra rb enabled
op ADD 5 RRR rd ra rb enabled
op CMP_EQ 9 RRR rd ra rb enabled
op JMP 15 JMP off enabled
op JT 16 JC r off enabled
op LOAD_I 18 SLOT rd slot enabled
op CAL_TON 24 CAL instance enabled
op CALL 32 CALL fn_id enabled
op RET 33 NONE enabled
- 参数个数由 format 决定,解析时校验字段数:
| format | 参数 | 现有指令 |
|---|---|---|
RR |
2(rd rs) | MOVE / NOT |
RRR |
3(rd ra rb) | AND/OR/ADD/SUB/MUL/DIV/CMP_xx |
IMM |
2(rd const_id) | LOADK |
SLOT |
2(rd slot) | LOAD_I/STORE_Q/LOAD_M/STORE_M/LOAD_GLOBAL/STORE_GLOBAL |
JMP |
1(off) | JMP |
JC |
2(r off) | JT / JF |
CALL |
1(fn_id) | CALL |
CAL |
1(instance) | CAL_*(8 个) |
NONE |
0 | RET |
isa 层:OpTable
class OpTable {
bool load(const char* path, std::string* err); // 解析 + 强校验
bool enabled(uint8_t op) const;
// name / format / 参数名查询(后续 FB 注册也走这里)
};
强校验(load 时):
- 语法:字段数符合 format、enabled 必须出现
- 操作码唯一、0..255
- 与编译期枚举一致:文件里每条指令的 name/opcode/format 必须与代码(
Op枚举 + 助记符 +OpFormat)逐条一致,任一不符 → 报错列出差异 - 任一失败 →
load返回 false,调用方报错退出
前置改造:OpFormat 显式化——现有隐式"形态"(disasm 的 case)变成枚举 RR/RRR/IMM/SLOT/JMP/JC/CALL/CAL/NONE;disasm 改表驱动(输出文本不变,现有断言兼容)。
各端接线
| 端 | 参数 | 行为 |
|---|---|---|
| STCompiler | STCompiler <project.toml> [-o out.stb] --ops <ops.txt> |
仅 -o 编译路径要求;加载/校验失败 → 报错退出;codegen 生成被屏蔽指令 → 编译错误(屏蔽传导) |
| BytecodeExecutor | --ops <ops.txt>(可选) |
不传 = 全部启用(兼容现有用法);传入 → 加载 + 校验,执行到 disabled 指令 → Fault::Disabled,周期中止退出码 1 |
| 语义实现 | — | 仍在 VM 代码里(每指令一个 case,不可省) |
加东西的流程(改造后)
加普通指令:ops.txt 加一行(op name opcode format 参数 enabled)
+ Op.h 枚举加一项 + VM 一个语义 case → 重建 isa/VM
屏蔽指令:ops.txt 把 enabled 改 disabled
→ 编译器拒绝生成、执行器运行时报 Disabled 故障(零代码改动)
执行计划(单步确认)
- OpFormat 显式化:新增
OpFormat枚举;disasm改表驱动(输出不变,11 个 ctest 全绿) ops.txt落地:34 条指令,全属性必填OpTable:isa/include/isa/OpTable.h+isa/src/OpTable.cpp(解析 + 强校验 + 查询)- STCompiler
--ops:加载/校验/屏蔽传导 - BytecodeExecutor
--ops:可选加载 /Fault::Disabled - 测试:
ops_test(正例 + 缺属性/字段数错/重号/与枚举不一致负例)、屏蔽传导用例、11 个 ctest 回归 - 文档 + 提交
待讨论(未定案)
- 内建 FB 注册是否并入
ops.txt(关键字/字段布局/CAL 操作码一行登记)——若并入,加 FB = 配置文件一行 + VM 一个语义 case,编译器免重建。讨论定案后另行实施,本次只做指令表。