From 68261cd78ba1d674d937614912f178c76668cb10 Mon Sep 17 00:00:00 2001 From: chentianya Date: Thu, 27 Aug 2026 09:13:38 +0800 Subject: [PATCH] =?UTF-8?q?=E6=AD=A5=E9=AA=A4A=EF=BC=9Aisa+toml=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=20RS=5FOFF=20=E5=BD=A2=E6=80=81=EF=BC=88LOAD?= =?UTF-8?q?=5FPTR/STORE=5FPTR=EF=BC=8C0010=20=E5=89=8D=E7=BC=80=20op=3D8/9?= =?UTF-8?q?=EF=BC=89+=20=E5=BC=BA=E6=A0=A1=E9=AA=8C=E6=94=BE=E8=A1=8C=20+?= =?UTF-8?q?=20isa=5Ftest=20roundtrip?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compiler/machine.toml | 18 ++++++++++++++++++ compiler/src/MachineConfig.cpp | 10 +++++++--- isa/include/isa/Instr.h | 11 +++++++++++ isa/include/isa/Op.h | 2 ++ isa/src/Encode.cpp | 9 +++++++++ isa/src/Op.cpp | 6 ++++-- tests/src/isa_test.cpp | 19 +++++++++++++++++++ tests/src/machine_test.cpp | 2 +- 8 files changed, 71 insertions(+), 6 deletions(-) diff --git a/compiler/machine.toml b/compiler/machine.toml index a6dd199..a490b9f 100644 --- a/compiler/machine.toml +++ b/compiler/machine.toml @@ -669,6 +669,24 @@ func = "full" params = ["slot", "off", "rs"] enabled = true +[[op]] +name = "LOAD_PTR" +prefix = "0010" +op = 8 +fmt = "RS+off" +func = "full" +params = ["rd", "rs", "off"] +enabled = true + +[[op]] +name = "STORE_PTR" +prefix = "0010" +op = 9 +fmt = "RS+off" +func = "full" +params = ["rd", "rs", "off"] +enabled = true + [[op]] name = "STR_LEN" prefix = "0010" diff --git a/compiler/src/MachineConfig.cpp b/compiler/src/MachineConfig.cpp index 656ede4..75df9fc 100644 --- a/compiler/src/MachineConfig.cpp +++ b/compiler/src/MachineConfig.cpp @@ -89,6 +89,7 @@ namespace { if (fmt == "CALL") return 1; if (fmt == "CAL") return 2; if (fmt == "SLOT+off") return 3; + if (fmt == "RS+off") return 3; if (fmt == "IMM64") return 2; if (fmt == "预留") return 0; return -1; @@ -132,7 +133,7 @@ namespace { if (prefix == "010011") return "JC"; if (prefix == "010100") return "CALL"; if (prefix == "010101") return "CAL"; - if (prefix == "0010") return "SLOT+off"; + if (prefix == "0010") return "SLOT+off"; // 或 RS+off(LOAD_PTR/STORE_PTR) if (prefix == "0011") return "IMM64"; if (prefix == "0001") return "预留"; return ""; @@ -392,9 +393,12 @@ bool MachineConfig::load(const std::string& path, std::string* err) { fail(err, "op '" + op.name + "': bad prefix '" + op.prefix + "'"); return false; } - // prefix ↔ fmt 互锁 + // prefix ↔ fmt 互锁(0010 允许 SLOT+off 与 RS+off 两种形态) const char* want_fmt = fmt_of_prefix(op.prefix); - if (want_fmt == nullptr || op.fmt != want_fmt) { + const bool ok_fmt = + op.fmt == want_fmt || + (op.prefix == "0010" && op.fmt == "RS+off"); + if (!ok_fmt) { fail(err, "op '" + op.name + "': prefix '" + op.prefix + "' must pair with fmt '" + std::string(want_fmt ? want_fmt : "?") + "'"); return false; diff --git a/isa/include/isa/Instr.h b/isa/include/isa/Instr.h index 0a36410..7a52ecb 100644 --- a/isa/include/isa/Instr.h +++ b/isa/include/isa/Instr.h @@ -295,6 +295,17 @@ namespace isa { return instr_len(out); } + /// @brief 编码 RS_OFF(LOAD_PTR/STORE_PTR,0010 区),返回指令长度。 + inline size_t enc_rs_off(uint8_t* out, uint8_t op, uint8_t func, + uint8_t rd, uint8_t rs, int32_t off) { + set_byte0(out, "0010", op); + set_func(out, func); + set_rd(out, rd); + set_rs1(out, rs); + set_off32_hi(out, off); + return instr_len(out); + } + /// @brief 编码 RET(10 区),返回指令长度。 inline size_t enc_ret(uint8_t* out) { set_byte0(out, "10", static_cast(Op::RET)); diff --git a/isa/include/isa/Op.h b/isa/include/isa/Op.h index 8ebbf18..606f182 100644 --- a/isa/include/isa/Op.h +++ b/isa/include/isa/Op.h @@ -46,6 +46,7 @@ namespace isa { // 16B(前缀 0010/0011,op 4 位) LOAD_OFF = 0, STORE_OFF = 1, STR_LEN = 2, STR_CMP = 3, STR_EQ = 4, STR_MID = 5, STR_LEFT = 6, STR_RIGHT = 7, + LOAD_PTR = 8, STORE_PTR = 9, LOADK64 = 0, // 32B 预留(前缀 0001,op 4 位) JTBL = 0, STR_CONCAT = 1, STR_FIND = 2, STR_REPLACE = 3, @@ -66,6 +67,7 @@ namespace isa { CALL, ///< fn_id32(8B) CAL, ///< fb_id16, slot32(8B) SLOT_OFF, ///< rd, slot32, off32(16B) + RS_OFF, ///< rd, rs(基址寄存器), off32(16B) IMM64, ///< rd, imm64(16B) RESERVED, ///< 32B 预留 }; diff --git a/isa/src/Encode.cpp b/isa/src/Encode.cpp index 6a34fe1..9cae8bd 100644 --- a/isa/src/Encode.cpp +++ b/isa/src/Encode.cpp @@ -84,6 +84,8 @@ Decoded decode(const uint8_t* code, size_t len) { } else if (f == OpFormat::SLOT_OFF) { d.imm32 = slot32_of(code); d.off_hi = off32_hi_of(code); + } else if (f == OpFormat::RS_OFF) { + d.off_hi = off32_hi_of(code); } return d; } @@ -112,6 +114,8 @@ size_t encode(const Decoded& d, uint8_t* out) { } else if (f == OpFormat::SLOT_OFF) { set_slot32(out, d.imm32); set_off32_hi(out, d.off_hi); + } else if (f == OpFormat::RS_OFF) { + set_off32_hi(out, d.off_hi); } return instr_len(out); } @@ -178,6 +182,11 @@ void disasm(const uint8_t* code, size_t len, char* out, size_t cap) { static_cast(d.rd), static_cast(d.imm32), static_cast(d.off_hi)); break; + case OpFormat::RS_OFF: + snprintf(out, cap, "%s%s r%u, r%u, %d", od.name, suffix.c_str(), + static_cast(d.rd), static_cast(d.rs1), + static_cast(d.off_hi)); + break; case OpFormat::IMM64: case OpFormat::NONE: case OpFormat::RESERVED: diff --git a/isa/src/Op.cpp b/isa/src/Op.cpp index a937849..d7d2919 100644 --- a/isa/src/Op.cpp +++ b/isa/src/Op.cpp @@ -88,6 +88,8 @@ namespace isa { {"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}, + {"LOAD_PTR", "0010", Op::LOAD_PTR, OpFormat::RS_OFF, FuncMode::Full}, + {"STORE_PTR", "0010", Op::STORE_PTR, OpFormat::RS_OFF, FuncMode::Full}, {"LOADK64", "0011", Op::LOADK64, OpFormat::IMM64, FuncMode::Full}, // 32B 预留 {"JTBL", "0001", Op::JTBL, OpFormat::RESERVED, FuncMode::None}, @@ -144,11 +146,11 @@ namespace isa { 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; + f == OpFormat::RS_OFF || f == OpFormat::IMM64; } bool uses_rs1(OpFormat f) { - return f == OpFormat::RR || f == OpFormat::RRR; + return f == OpFormat::RR || f == OpFormat::RRR || f == OpFormat::RS_OFF; } bool uses_rs2(OpFormat f) { diff --git a/tests/src/isa_test.cpp b/tests/src/isa_test.cpp index 2424a28..d272cc9 100644 --- a/tests/src/isa_test.cpp +++ b/tests/src/isa_test.cpp @@ -128,6 +128,11 @@ static bool test_fields() { enc_slot_off(buf, static_cast(isa::Op::LOAD_OFF), 3, 1, 9, -12); CHECK(slot32_of(buf) == 9); CHECK(off32_hi_of(buf) == -12); + // RS_OFF(0010 op=8/9:rd@2、rs1@3、off@87..56) + enc_rs_off(buf, static_cast(isa::Op::LOAD_PTR), 3, 5, 1, -12); + CHECK(rd_of(buf) == 5); + CHECK(rs1_of(buf) == 1); + CHECK(off32_hi_of(buf) == -12); // RET enc_ret(buf); CHECK(op_of(buf) == static_cast(isa::Op::RET)); @@ -197,6 +202,20 @@ static bool test_disasm() { enc_slot_off(buf, static_cast(isa::Op::LOAD_OFF), 3, 2, 8, 16); isa::disasm(buf, 16, out, sizeof out); CHECK(std::strcmp(out, "LOAD_OFF.I16 r2, s8, 16") == 0); + // RS_OFF(LOAD_PTR/STORE_PTR) + enc_rs_off(buf, static_cast(isa::Op::LOAD_PTR), 3, 2, 1, 16); + isa::disasm(buf, 16, out, sizeof out); + CHECK(std::strcmp(out, "LOAD_PTR.I16 r2, r1, 16") == 0); + enc_rs_off(buf, static_cast(isa::Op::STORE_PTR), 9, 9, 1, -4); + isa::disasm(buf, 16, out, sizeof out); + CHECK(std::strcmp(out, "STORE_PTR.F64 r9, r1, -4") == 0); + // decode 回读(encode 路径) + { + isa::Decoded d = isa::decode(buf, 16); + isa::encode(d, buf); + isa::disasm(buf, 16, out, sizeof out); + CHECK(std::strcmp(out, "STORE_PTR.F64 r9, r1, -4") == 0); + } // 未知(010110 预留区) buf[0] = 0x58; isa::disasm(buf, 8, out, sizeof out); diff --git a/tests/src/machine_test.cpp b/tests/src/machine_test.cpp index 2159a83..1dab450 100644 --- a/tests/src/machine_test.cpp +++ b/tests/src/machine_test.cpp @@ -132,7 +132,7 @@ static bool test_positive() { CHECK(cfg.find_type("DT") != nullptr && cfg.find_type("DT")->func == 6); CHECK(cfg.find_type("NOPE") == nullptr); - CHECK(cfg.ops().size() == 72); + CHECK(cfg.ops().size() == 74); const compiler::ConfigOp* move = cfg.find_op("MOVE"); CHECK(move != nullptr && move->prefix == "11" && move->op == 0 && move->fmt == "RR" && move->func_mode == "width" && move->params.size() == 2);