From 94accd52c3215f909d6864488f3fcbc261a57920 Mon Sep 17 00:00:00 2001 From: chentianya Date: Wed, 19 Aug 2026 13:59:48 +0800 Subject: [PATCH] =?UTF-8?q?=E8=90=BD=E5=9C=B0=20isa=20=E5=90=88=E5=90=8C?= =?UTF-8?q?=EF=BC=9A=E9=A5=B1=E5=92=8C=E7=B1=BB=E5=9E=8B=E3=80=81=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E7=A0=81=E6=9E=9A=E4=B8=BE=E3=80=8132-bit=20=E6=8C=87?= =?UTF-8?q?=E4=BB=A4=E7=BC=96=E8=A7=A3=E7=A0=81=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Types.h:TIME 改 int64_t(毫秒),补 sat_add/sub/mul/div,除零与 INT_MIN/-1 规则 - Op.h:29 条操作码枚举 + mnemonic 助记符,数值即编码 - Instr.h:pack/拆字段 + 按形态 enc_rr/rrr/imm/jmp/jc/slot/call/ret --- isa/include/isa/Instr.h | 93 +++++++++++++++++++++++++++++++++++++++++ isa/include/isa/Op.h | 65 ++++++++++++++++++++++++++++ isa/include/isa/Types.h | 44 +++++++++++++++++-- 3 files changed, 199 insertions(+), 3 deletions(-) create mode 100644 isa/include/isa/Instr.h create mode 100644 isa/include/isa/Op.h diff --git a/isa/include/isa/Instr.h b/isa/include/isa/Instr.h new file mode 100644 index 0000000..72afc27 --- /dev/null +++ b/isa/include/isa/Instr.h @@ -0,0 +1,93 @@ +/** + * @file Instr.h + * @brief 32-bit 指令打包 / 拆字段 + * @author + * @date 2026-08-19 + */ + +#pragma once + +#include + +#include "isa/Op.h" + +namespace isa { + // 指令字:[ op:8 | rd:8 | a:8 | b:8 ],整体是一个小端 uint32_t。 + // 字段含义按操作码形态解释,见 Doc/isa/指令与映像.md。 + typedef uint32_t Instr; + + // 打包 / 拆字段 + inline Instr pack(Op op, uint8_t rd, uint8_t a, uint8_t b) { + return static_cast(static_cast(op)) + | (static_cast(rd) << 8) + | (static_cast(a) << 16) + | (static_cast(b) << 24); + } + + inline Op op(Instr w) { + return static_cast(w & 0xFFu); + } + + inline uint8_t rd(Instr w) { + return static_cast((w >> 8) & 0xFFu); + } + + inline uint8_t a(Instr w) { + return static_cast((w >> 16) & 0xFFu); + } + + inline uint8_t b(Instr w) { + return static_cast((w >> 24) & 0xFFu); + } + + // 组合视图:a|b 拼成 16 位(const_id / fn_id / slot) + inline uint16_t imm16(Instr w) { + return static_cast(a(w) | (static_cast(b(w)) << 8)); + } + + // 组合视图:a|b 为有符号相对偏移,单位是指令条数 + inline int16_t off16(Instr w) { + return static_cast(imm16(w)); + } + + // 按形态的便捷编码 + inline Instr enc_rr(Op op, uint8_t rd, uint8_t rs) { + return pack(op, rd, rs, 0); // MOVE / NOT:a = rs + } + + inline Instr enc_rrr(Op op, uint8_t rd, uint8_t ra, uint8_t rb) { + return pack(op, rd, ra, rb); // AND/OR/ADD/.../CMP_xx + } + + inline Instr enc_imm(Op op, uint8_t rd, uint16_t imm) { + return pack(op, rd, static_cast(imm & 0xFFu), + static_cast((imm >> 8) & 0xFFu)); // LOADK + } + + inline Instr enc_jmp(int16_t off) { + return pack(Op::JMP, 0, + static_cast(static_cast(off) & 0xFFu), + static_cast((static_cast(off) >> 8) & 0xFFu)); + } + + inline Instr enc_jc(Op op, uint8_t r, int16_t off) { + // JT / JF:条件寄存器在 rd,偏移在 a|b + return pack(op, r, + static_cast(static_cast(off) & 0xFFu), + static_cast((static_cast(off) >> 8) & 0xFFu)); + } + + inline Instr enc_slot(Op op, uint8_t rd, uint16_t slot) { + // LOAD_I / STORE_Q / LOAD_M / STORE_M / LOAD_GLOBAL / STORE_GLOBAL / CAL_* + // 槽号 / 实例号在 a|b + return enc_imm(op, rd, slot); + } + + inline Instr enc_call(uint16_t fn_id) { + return enc_imm(Op::CALL, 0, fn_id); + } + + inline Instr enc_ret() { + return pack(Op::RET, 0, 0, 0); + } +} diff --git a/isa/include/isa/Op.h b/isa/include/isa/Op.h new file mode 100644 index 0000000..42bc79e --- /dev/null +++ b/isa/include/isa/Op.h @@ -0,0 +1,65 @@ +/** + * @file Op.h + * @brief 操作码枚举 + 助记符 + * @author + * @date 2026-08-19 + */ + +#pragma once + +#include + +namespace isa { + // 操作码一次列全。数值即编码:冻结后不得改顺序、不得插值, + // 增加指令只能追加到末尾,并同步 Doc/isa/指令与映像.md 与测试。 + enum class Op : uint8_t { + MOVE = 0, // MOVE rd, rs + LOADK = 1, // LOADK rd, const_id + NOT = 2, // NOT rd, rs + AND = 3, // AND rd, ra, rb + OR = 4, // OR rd, ra, rb + ADD = 5, // ADD rd, ra, rb + SUB = 6, // SUB rd, ra, rb + MUL = 7, // MUL rd, ra, rb + DIV = 8, // DIV rd, ra, rb + CMP_EQ = 9, // CMP_EQ rd, ra, rb + CMP_NE = 10, // CMP_NE rd, ra, rb + CMP_LT = 11, // CMP_LT rd, ra, rb + CMP_LE = 12, // CMP_LE rd, ra, rb + CMP_GT = 13, // CMP_GT rd, ra, rb + CMP_GE = 14, // CMP_GE rd, ra, rb + JMP = 15, // JMP offset + JT = 16, // JT r, offset + JF = 17, // JF r, offset + LOAD_I = 18, // LOAD_I rd, slot + STORE_Q = 19, // STORE_Q slot, rs + LOAD_M = 20, // LOAD_M rd, slot + STORE_M = 21, // STORE_M slot, rs + LOAD_GLOBAL = 22, // LOAD_GLOBAL rd, slot + STORE_GLOBAL = 23, // STORE_GLOBAL slot, rs + CAL_TON = 24, // CAL_TON instance_slot + CAL_TOF = 25, // CAL_TOF instance_slot + CAL_CTU = 26, // CAL_CTU instance_slot + CALL = 27, // CALL fn_id + RET = 28, // RET + }; + + // 操作码总数 + static const int kOpCount = 29; + + // 助记符:下标与 Op 数值一一对应 + inline const char* mnemonic(Op op) { + static const char* const kMnemonic[kOpCount] = { + "MOVE", "LOADK", "NOT", "AND", "OR", + "ADD", "SUB", "MUL", "DIV", + "CMP_EQ", "CMP_NE", "CMP_LT", "CMP_LE", "CMP_GT", "CMP_GE", + "JMP", "JT", "JF", + "LOAD_I", "STORE_Q", "LOAD_M", "STORE_M", + "LOAD_GLOBAL", "STORE_GLOBAL", + "CAL_TON", "CAL_TOF", "CAL_CTU", + "CALL", "RET", + }; + const int idx = static_cast(op); + return (idx >= 0 && idx < kOpCount) ? kMnemonic[idx] : "???"; + } +} diff --git a/isa/include/isa/Types.h b/isa/include/isa/Types.h index 5a58f5a..fd74a9f 100644 --- a/isa/include/isa/Types.h +++ b/isa/include/isa/Types.h @@ -8,13 +8,51 @@ #pragma once #include +#include namespace isa { namespace types { // 定宽类型。整数溢出规则:饱和(夹到 INT 最小/最大), // 由 compiler 与 vm 按同一规则实现,见 Doc/isa/指令与映像.md。 - using BOOL = uint8_t; - using INT = int16_t; - using TIME = uint64_t; + using BOOL = uint8_t; // 只允许 0/1 + using INT = int16_t; // IEC INT + // 毫秒,有符号。64 位理由见 Doc/isa/指令与映像.md: + // 差值可负、为 DATE_AND_TIME 与 64 位定时器预留。槽位按 8 字节对齐。 + using TIME = int64_t; + + // 饱和算术:夹到 INT 最小/最大,编译期与 VM 共用同一规则。 + + inline INT sat_add(INT a, INT b) { + const int32_t sum = static_cast(a) + static_cast(b); + return static_cast(sum < std::numeric_limits::min() ? std::numeric_limits::min() + : sum > std::numeric_limits::max() ? std::numeric_limits::max() + : sum); + } + + inline INT sat_sub(INT a, INT b) { + const int32_t diff = static_cast(a) - static_cast(b); + return static_cast(diff < std::numeric_limits::min() ? std::numeric_limits::min() + : diff > std::numeric_limits::max() ? std::numeric_limits::max() + : diff); + } + + inline INT sat_mul(INT a, INT b) { + const int32_t prod = static_cast(a) * static_cast(b); + return static_cast(prod < std::numeric_limits::min() ? std::numeric_limits::min() + : prod > std::numeric_limits::max() ? std::numeric_limits::max() + : prod); + } + + inline INT sat_div(INT a, INT b) { + // b == 0 视为除以 1,避免未定义行为;除零的语义由 compiler/VM 层报错 + if (b == 0) { + return a; + } + // INT_MIN / -1 溢出:饱和到 INT_MAX + if (a == std::numeric_limits::min() && b == -1) { + return std::numeric_limits::max(); + } + return static_cast(a / b); + } } }