12.9 步骤 2:VM 译码 switch(标量/跳转/LOAD-STORE)。
- Machine.cpp:create(拷贝数据段+建 MAIN 帧)、run_cycle、step、exec_one - 标量:MOVE/LOADK(常量表 tag 定值表示)/NOT/AND/OR/四则饱和/CMP 全宽比较 - 跳转:JMP/JT/JF(相对下一条);LOAD/STORE:slot×8 定宽槽,BadSlot 校验 - 寄存器越界检查按指令形态(a|b 作偏移/槽号/常量 id 时不查) - 修:ImageView 默认构造公开(无效态)、Codegen 两个编译警告 - 冒烟:用例 02/04/07/05 跑通、06 触发 CycleLimit、step 单步
This commit is contained in:
@@ -242,9 +242,6 @@ namespace {
|
|||||||
if (d.type.kind == TypeKind::FbUser || d.type.kind == TypeKind::FbBuiltin) {
|
if (d.type.kind == TypeKind::FbUser || d.type.kind == TypeKind::FbBuiltin) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (r > 255) {
|
|
||||||
return fail("register overflow in function '" + pou.name + "'");
|
|
||||||
}
|
|
||||||
f->regs[d.name] = r++;
|
f->regs[d.name] = r++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -660,8 +657,8 @@ namespace {
|
|||||||
case BinOp::Le: return isa::Op::CMP_LE;
|
case BinOp::Le: return isa::Op::CMP_LE;
|
||||||
case BinOp::Gt: return isa::Op::CMP_GT;
|
case BinOp::Gt: return isa::Op::CMP_GT;
|
||||||
case BinOp::Ge: return isa::Op::CMP_GE;
|
case BinOp::Ge: return isa::Op::CMP_GE;
|
||||||
|
default: return isa::Op::CMP_EQ; // Add/Sub/Mul/Div 不经此函数
|
||||||
}
|
}
|
||||||
return isa::Op::CMP_EQ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ namespace isa {
|
|||||||
// 只读视图:校验过的映像
|
// 只读视图:校验过的映像
|
||||||
class ImageView {
|
class ImageView {
|
||||||
public:
|
public:
|
||||||
|
// 默认构造为无效态(ok() == false,error() == "uninitialized")
|
||||||
|
ImageView();
|
||||||
static ImageView from(const uint8_t* buf, size_t len);
|
static ImageView from(const uint8_t* buf, size_t len);
|
||||||
static ImageView from(const std::vector<uint8_t>& buf);
|
static ImageView from(const std::vector<uint8_t>& buf);
|
||||||
|
|
||||||
@@ -96,7 +98,7 @@ namespace isa {
|
|||||||
size_t data_len() const; // 字节数
|
size_t data_len() const; // 字节数
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ImageView();
|
// 私有成员与内部构造辅助(from 使用)
|
||||||
|
|
||||||
const uint8_t* buf_;
|
const uint8_t* buf_;
|
||||||
size_t len_;
|
size_t len_;
|
||||||
|
|||||||
+256
-2
@@ -1,8 +1,262 @@
|
|||||||
/**
|
/**
|
||||||
* @file Machine.cpp
|
* @file Machine.cpp
|
||||||
* @brief 寄存器虚拟机(12.9 实现)
|
* @brief 寄存器虚拟机(12.9,步骤 2:译码 switch)
|
||||||
* @date 2026-08-19
|
* @author
|
||||||
|
* @date 2026-08-21
|
||||||
|
*
|
||||||
|
* @details 设计说明(详见 Doc/vm/指令执行.md):
|
||||||
|
* - 步骤 2 范围:create / run_cycle / step + 标量指令(MOVE/LOADK/NOT/AND/OR/算术/CMP)、
|
||||||
|
* 跳转(JMP/JT/JF)、LOAD/STORE(slot × 8);RET 仅处理 MAIN(周期结束)
|
||||||
|
* - 步骤 3 补 CALL/RET 帧栈与栈深/坏操作码故障;步骤 4 补 CAL_* 定时器
|
||||||
|
* - 取指:函数表 → code_offset(字节)→ u32;执行后 pc 先 +1,跳转再 pc += off
|
||||||
|
* - 数据区 8 字节定宽槽:偏移 = slot × 8
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "vm/Machine.h"
|
||||||
|
|
||||||
|
#include "isa/Encode.h"
|
||||||
|
#include "isa/Instr.h"
|
||||||
|
#include "isa/Op.h"
|
||||||
|
#include "isa/Types.h"
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
|
bool Machine::create(const std::vector<uint8_t>& image, Machine* out,
|
||||||
|
std::string* err) {
|
||||||
|
out->image_ = isa::ImageView::from(image);
|
||||||
|
if (!out->image_.ok()) {
|
||||||
|
if (err) {
|
||||||
|
*err = out->image_.error();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 数据区工作副本(8 字节定宽槽)
|
||||||
|
out->data_.assign(out->image_.data_bytes(),
|
||||||
|
out->image_.data_bytes() + out->image_.data_len());
|
||||||
|
out->ctu_prev_.assign(out->data_len() / 8, 0);
|
||||||
|
|
||||||
|
// MAIN 帧(跨周期保留)
|
||||||
|
const uint32_t entry = out->image_.header().entry_fn_id;
|
||||||
|
const isa::FuncRow main = out->image_.func_row(entry);
|
||||||
|
out->frames_.clear();
|
||||||
|
Frame f;
|
||||||
|
f.fn_id = entry;
|
||||||
|
f.regs.assign(main.nregs, 0);
|
||||||
|
out->frames_.push_back(std::move(f));
|
||||||
|
|
||||||
|
out->pc_ = 0;
|
||||||
|
out->cycle_count_ = 0;
|
||||||
|
out->fault_ = Fault::None;
|
||||||
|
out->ended_ = false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Fault Machine::run_cycle() {
|
||||||
|
cycle_count_ = 0;
|
||||||
|
ended_ = false;
|
||||||
|
fault_ = Fault::None;
|
||||||
|
pc_ = 0;
|
||||||
|
while (!ended_ && fault_ == Fault::None) {
|
||||||
|
if (!exec_one()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 周期结束:清调用栈(保留 MAIN 帧,PROGRAM 变量状态跨周期)
|
||||||
|
while (frames_.size() > 1) {
|
||||||
|
frames_.pop_back();
|
||||||
|
}
|
||||||
|
return fault_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Machine::step() {
|
||||||
|
if (ended_ || fault_ != Fault::None) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return exec_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
Fault Machine::fault() const { return fault_; }
|
||||||
|
uint32_t Machine::pc() const { return pc_; }
|
||||||
|
uint32_t Machine::fn_id() const { return cur_frame().fn_id; }
|
||||||
|
uint32_t Machine::cycle_count() const { return cycle_count_; }
|
||||||
|
uint32_t Machine::call_depth() const { return static_cast<uint32_t>(frames_.size()); }
|
||||||
|
uint8_t* Machine::data() { return data_.data(); }
|
||||||
|
const uint8_t* Machine::data() const { return data_.data(); }
|
||||||
|
size_t Machine::data_len() const { return data_.size(); }
|
||||||
|
int64_t Machine::reg(uint8_t i) const { return cur_frame().regs[i]; }
|
||||||
|
|
||||||
|
Machine::Frame& Machine::cur_frame() { return frames_.back(); }
|
||||||
|
const Machine::Frame& Machine::cur_frame() const { return frames_.back(); }
|
||||||
|
|
||||||
|
bool Machine::exec_one() {
|
||||||
|
// ---- 取指 ----
|
||||||
|
const isa::FuncRow row = image_.func_row(cur_frame().fn_id);
|
||||||
|
if (pc_ >= row.code_len) {
|
||||||
|
fault_ = Fault::BadOp;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const uint8_t* base = image_.code_bytes() + row.code_offset;
|
||||||
|
const isa::Instr w = reinterpret_cast<const uint32_t*>(base)[pc_];
|
||||||
|
|
||||||
|
// ---- 周期指令计数 ----
|
||||||
|
++cycle_count_;
|
||||||
|
if (cycle_count_ > image_.header().cycle_limit) {
|
||||||
|
fault_ = Fault::CycleLimit;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 先指向下一条(跳转指令再按"相对下一条"语义叠加偏移)
|
||||||
|
++pc_;
|
||||||
|
|
||||||
|
const isa::Op op = isa::op(w);
|
||||||
|
const uint8_t rd = isa::rd(w);
|
||||||
|
const uint8_t ra = isa::a(w);
|
||||||
|
const uint8_t rb = isa::b(w);
|
||||||
|
std::vector<int64_t>& regs = cur_frame().regs;
|
||||||
|
|
||||||
|
// 寄存器越界检查(仅对把字段当寄存器的指令;a|b 作偏移/槽号/常量 id 时跳过)
|
||||||
|
const bool uses_rd = op == isa::Op::MOVE || op == isa::Op::NOT || op == isa::Op::AND ||
|
||||||
|
op == isa::Op::OR || op == isa::Op::ADD || op == isa::Op::SUB ||
|
||||||
|
op == isa::Op::MUL || op == isa::Op::DIV || op == isa::Op::CMP_EQ ||
|
||||||
|
op == isa::Op::CMP_NE || op == isa::Op::CMP_LT ||
|
||||||
|
op == isa::Op::CMP_LE || op == isa::Op::CMP_GT ||
|
||||||
|
op == isa::Op::CMP_GE || op == isa::Op::JT || op == isa::Op::JF ||
|
||||||
|
op == isa::Op::LOADK || op == isa::Op::LOAD_I ||
|
||||||
|
op == isa::Op::LOAD_M || op == isa::Op::LOAD_GLOBAL ||
|
||||||
|
op == isa::Op::STORE_Q || op == isa::Op::STORE_M ||
|
||||||
|
op == isa::Op::STORE_GLOBAL;
|
||||||
|
const bool uses_ra = op == isa::Op::MOVE || op == isa::Op::NOT || op == isa::Op::AND ||
|
||||||
|
op == isa::Op::OR || op == isa::Op::ADD || op == isa::Op::SUB ||
|
||||||
|
op == isa::Op::MUL || op == isa::Op::DIV || op == isa::Op::CMP_EQ ||
|
||||||
|
op == isa::Op::CMP_NE || op == isa::Op::CMP_LT ||
|
||||||
|
op == isa::Op::CMP_LE || op == isa::Op::CMP_GT ||
|
||||||
|
op == isa::Op::CMP_GE;
|
||||||
|
const bool uses_rb = uses_ra;
|
||||||
|
if ((uses_rd && rd >= regs.size()) || (uses_ra && ra >= regs.size()) ||
|
||||||
|
(uses_rb && rb >= regs.size())) {
|
||||||
|
fault_ = Fault::BadOp;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case isa::Op::MOVE:
|
||||||
|
regs[rd] = regs[ra];
|
||||||
|
return true;
|
||||||
|
case isa::Op::LOADK: {
|
||||||
|
const uint16_t cid = isa::imm16(w);
|
||||||
|
if (cid >= image_.header().n_consts) {
|
||||||
|
fault_ = Fault::BadConst;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const isa::ConstEntry c = image_.const_entry(cid);
|
||||||
|
if (c.tag == isa::types::Bool) {
|
||||||
|
regs[rd] = c.value ? 1 : 0;
|
||||||
|
} else if (c.tag == isa::types::Int) {
|
||||||
|
regs[rd] = static_cast<int16_t>(c.value); // 符号扩展
|
||||||
|
} else {
|
||||||
|
regs[rd] = static_cast<int64_t>(c.value);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case isa::Op::NOT:
|
||||||
|
regs[rd] = (regs[ra] == 0) ? 1 : 0;
|
||||||
|
return true;
|
||||||
|
case isa::Op::AND:
|
||||||
|
regs[rd] = (regs[ra] != 0 && regs[rb] != 0) ? 1 : 0;
|
||||||
|
return true;
|
||||||
|
case isa::Op::OR:
|
||||||
|
regs[rd] = (regs[ra] != 0 || regs[rb] != 0) ? 1 : 0;
|
||||||
|
return true;
|
||||||
|
case isa::Op::ADD:
|
||||||
|
regs[rd] = isa::types::sat_add(static_cast<int16_t>(regs[ra]),
|
||||||
|
static_cast<int16_t>(regs[rb]));
|
||||||
|
return true;
|
||||||
|
case isa::Op::SUB:
|
||||||
|
regs[rd] = isa::types::sat_sub(static_cast<int16_t>(regs[ra]),
|
||||||
|
static_cast<int16_t>(regs[rb]));
|
||||||
|
return true;
|
||||||
|
case isa::Op::MUL:
|
||||||
|
regs[rd] = isa::types::sat_mul(static_cast<int16_t>(regs[ra]),
|
||||||
|
static_cast<int16_t>(regs[rb]));
|
||||||
|
return true;
|
||||||
|
case isa::Op::DIV:
|
||||||
|
regs[rd] = isa::types::sat_div(static_cast<int16_t>(regs[ra]),
|
||||||
|
static_cast<int16_t>(regs[rb]));
|
||||||
|
return true;
|
||||||
|
case isa::Op::CMP_EQ:
|
||||||
|
case isa::Op::CMP_NE:
|
||||||
|
case isa::Op::CMP_LT:
|
||||||
|
case isa::Op::CMP_LE:
|
||||||
|
case isa::Op::CMP_GT:
|
||||||
|
case isa::Op::CMP_GE: {
|
||||||
|
const int64_t l = regs[ra];
|
||||||
|
const int64_t r = regs[rb];
|
||||||
|
bool res = false;
|
||||||
|
switch (op) {
|
||||||
|
case isa::Op::CMP_EQ: res = (l == r); break;
|
||||||
|
case isa::Op::CMP_NE: res = (l != r); break;
|
||||||
|
case isa::Op::CMP_LT: res = (l < r); break;
|
||||||
|
case isa::Op::CMP_LE: res = (l <= r); break;
|
||||||
|
case isa::Op::CMP_GT: res = (l > r); break;
|
||||||
|
case isa::Op::CMP_GE: res = (l >= r); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
regs[rd] = res ? 1 : 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case isa::Op::JMP:
|
||||||
|
pc_ += isa::off16(w);
|
||||||
|
return true;
|
||||||
|
case isa::Op::JT:
|
||||||
|
if (regs[rd] != 0) {
|
||||||
|
pc_ += isa::off16(w);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case isa::Op::JF:
|
||||||
|
if (regs[rd] == 0) {
|
||||||
|
pc_ += isa::off16(w);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case isa::Op::LOAD_I:
|
||||||
|
case isa::Op::LOAD_M:
|
||||||
|
case isa::Op::LOAD_GLOBAL: {
|
||||||
|
const uint16_t slot = isa::imm16(w);
|
||||||
|
const size_t off = static_cast<size_t>(slot) * 8;
|
||||||
|
if (off + 8 > data_.size()) {
|
||||||
|
fault_ = Fault::BadSlot;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int64_t v = 0;
|
||||||
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
v |= static_cast<int64_t>(data_[off + i]) << (8 * i);
|
||||||
|
}
|
||||||
|
regs[rd] = v;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case isa::Op::STORE_Q:
|
||||||
|
case isa::Op::STORE_M:
|
||||||
|
case isa::Op::STORE_GLOBAL: {
|
||||||
|
const uint16_t slot = isa::imm16(w);
|
||||||
|
const size_t off = static_cast<size_t>(slot) * 8;
|
||||||
|
if (off + 8 > data_.size()) {
|
||||||
|
fault_ = Fault::BadSlot;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const int64_t v = regs[rd];
|
||||||
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
data_[off + i] = static_cast<uint8_t>((v >> (8 * i)) & 0xFFu);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case isa::Op::RET:
|
||||||
|
// MAIN 的 RET = 周期结束(步骤 3 处理非 MAIN 帧返回)
|
||||||
|
ended_ = true;
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
// CALL / CAL_TON / CAL_TOF / CAL_CTU(步骤 3 / 4 实现)
|
||||||
|
fault_ = Fault::BadOp;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace vm
|
||||||
|
|||||||
Reference in New Issue
Block a user