Files
Interpreter/isa
Admin 5fccbadaa8 阶段 C 步骤 7:isa 拆出 Image,vm 依赖收窄。
- 删 isa/Image.h + Image.cpp(ImageView/FNV/写文件/sidecar 不再属于 isa)
- vm 自实现只读视图 vm/Image.h/cpp:头 104(12.13)/段校验/缺 SHA 尾报错
  (型号匹配与 SHA 校验留步骤 8);Machine 改用 vm::Image + vm::ImageHeader
- executor:本地读文件(替换 isa::read_stb_file)
- 测试:isa_test 删映像/FNV 部分;codegen_test/vm_test 改用 compiler::StbView /
  vm::ConstEntry;vm_test 手拼映像适配新格式(头 104 + 尾 32 占位)
- 验证:line1 编译 288 字节 → BytecodeExecutor 回放 Q 正确;ctest 12/12
2026-08-21 22:24:57 +08:00
..

isa

指令集 + 映像 + 定宽类型。CMake 目标:isaSTATIC),无依赖。

compiler 写映像、vm 读映像,两边只依赖本目录,不互链。

STCompiler      → compiler → isa
BytecodeExecutor → vm      → isa

类型、操作码、指令字、映像布局以 doc/isa/指令与映像.md 为准。 头文件实现该文,本 README 不另当规范。.stb 结构面向使用者的拆解见 doc/isa/stb文件格式.md。全工程阶段见 doc/初步计划.md 12.012.1。

公开头:isa/include/isa/


做 / 不做

做: 操作码与 32-bit 指令、映像头与段、BOOL/INT/TIME 宽度与饱和、编解码、工程哈希、一条指令的文本转储。

不做: toml、关键字、符号表、AST、VM switch、扫描周期、I/O 采样。AND/OR 只组合已算好的值;短路由 compiler 编成跳转。


实现步骤

原则:先冻合同,再头文件,再 .cpp,再最小测试。每步能编过再进下一步。改编码或映像字段时,先改规范文和本模块,再动 compiler / vm

目标目录(与规范一致):

isa/
  CMakeLists.txt
  README.md
  include/isa/
    Types.h                 # 宽度、饱和、槽值
    Op.h                    # 操作码枚举 + 助记符
    Instr.h                 # 32-bit 打包/拆字段(inline
    Encode.h                # encode / decode / disasm
    Image.h                 # 头、段、FNV、读写缓冲
  src/
    Encode.cpp
    Image.cpp
add_library(isa STATIC src/Encode.cpp src/Image.cpp)
target_include_directories(isa PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

compiler / vmtarget_link_libraries(... PUBLIC isa)


0. CMake 骨架

CMakeLists.txtadd_subdirectorycompiler / vm / executor。这三个目录若没有 CMakeLists.txt,顶层 configure 失败,isa 也编不过。

本步只让工程能配置、能链,不写业务。

  • 写本目录 CMakeLists.txt(上面那段即可)
  • compiler / vm:空 .cpp + PUBLICisa
  • executorBytecodeExecutormain 打印版本,链 vmisaSTCompiler 入口在 compiler/src/main.cpp,链 compilerisa
  • 根 CMakeenable_testing()(测试文件下一步再加)

完成:cmake --build 过。


1. 冻合同(先改规范文)

指令与映像.md 已有助记符和 [ op:8 | rd:8 | a:8 | b:8 ],还缺数值和映像字节。头文件不得自己发明一份表。

把下面这些写进规范文,再写代码(细则以该文最终落笔为准):

  • 指令字:小端 uint32_top/rd/a/b 各 8 bitimm16 = a | (b << 8)off16 为有符号、单位是指令条数
  • 操作码 0..28 连续赋值,以后只追加不插队
  • 各指令操作数字面(LOADK/JMP/CALL/LOAD_*/STORE_*/CAL_*/RET
  • INT 饱和、INT_MIN / -1、除零、BOOL 只允许 0/1
  • FNV-1a 64 的 basis/prime;路径只当排序键,对文件内容 update;空集合 = basis
  • 映像魔数 STSC、版本 1、头字段偏移与长度、常量表/函数表/FB 表一行的字节
  • 第一版可写映像:空槽、空常量表/FB、MAINfn_id=0)、一条 RET

完成:规范文能当唯一合同;本 README 仍只指向它。


2. Types.h

include/isa/Types.hinline,无对应 .cpp。命名空间 isa。C++20;本模块保持简单结构体,不依赖花哨特性。

  • Bool = uint8_tInt = int16_tTime = int64_t(毫秒;理由见规范文)
  • TypeTagBool / Int / Time
  • sat_add / sat_sub / sat_mul / sat_div(规则见规范文)
  • pack_bool / pack_int / pack_time → 4 字节 cell;对应 unpack

完成:单独包含该头能编译。


3. Op.h + Instr.h

  • Op.henum Op : uint8_t,取值与规范文一致;mnemonic(Op) 助记符(已在头内落地)
  • Instr.htypedef uint32_t Instrpack、取 op/rd/a/bimm16/off16;按形态 enc_rr / enc_rrr / enc_imm / enc_jmp / enc_jc

完成:能打包/拆开一条 32-bit 指令,不依赖 .cpp


4. Encode.h + Encode.cpp

STCompiler --disasm 和测试往返打印:

  • Decoded { Op op; uint8_t rd, a, b; }
  • Instr encode(Decoded) / Decoded decode(Instr)
  • disasm(Instr, char* out, size_t cap)

disasm 格式冻在规范文,例如:RETMOVE r1, r2LOADK r0, 3ADD r1, r2, r3JMP +4JT r0, -1CALL 1LOAD_I r0, 2CAL_TON 0

完成:一条指令能编、能解、能打出一行文本。


5. Image.h + Image.cpp

  • fnv1a64 / fnv1a64_update
  • ImageView:只读视图,指向外部缓冲
  • read_image:校验魔数、版本、头大小、各段不越界、entry_fn_id 落在函数表内
  • write_ret_main(cycle_limit, dt_ms, hash)std::vector<uint8_t>:空槽 + MAIN + 一条 RET
  • .stb 文件读写与 <name>.runtime.toml sidecarI/O 绑定 var → 槽号 → channel/bit

小端 put_* / get_* 只放 .cpp,不把 packed struct 当 ABI。本阶段不写完整 ImageBuilder(等 codegen)。

完成:能写出并读回「空映像 + 一条 RET」。


6. 最小测试

tests/ 加一个只链 isa 的 CTest 可执行文件(不是第 12.2 节那 20 个用例):

  • RET / ADD / LOADK / JMP -1encode 后再 decode,字段一致;disasm 非空
  • write_ret_mainread_image:魔数、version=1、n_funcs=1、入口是 RET
  • fnv1a64 空输入等于 basis

完成:ctest 过上述用例。


验收

  • cmake --build 过;ctest 过 isa 往返
  • compiler / vm#include <isa/...>,不互相包含
  • 操作码或映像有变:先改 指令与映像.md + 本目录 + 本测试,再改两端