diff --git a/vm/src/Machine.cpp b/vm/src/Machine.cpp index e81f9b5..8dd0167 100644 --- a/vm/src/Machine.cpp +++ b/vm/src/Machine.cpp @@ -14,6 +14,8 @@ #include "vm/Machine.h" +#include + #include "isa/Encode.h" #include "isa/Instr.h" #include "isa/Op.h" @@ -248,15 +250,60 @@ bool Machine::exec_one() { } return true; } + case isa::Op::CALL: + fault_ = do_call(isa::imm16(w)); + return fault_ == Fault::None; case isa::Op::RET: - // MAIN 的 RET = 周期结束(步骤 3 处理非 MAIN 帧返回) - ended_ = true; - return false; + fault_ = do_ret(); + if (fault_ != Fault::None) { + return false; + } + return !ended_; // MAIN 的 RET → 周期结束(返回 false) default: - // CALL / CAL_TON / CAL_TOF / CAL_CTU(步骤 3 / 4 实现) + // CAL_TON / CAL_TOF / CAL_CTU(步骤 4 实现) fault_ = Fault::BadOp; return false; } } +Fault Machine::do_call(uint32_t fn_id) { + if (fn_id >= image_.header().n_funcs) { + return Fault::BadOp; + } + if (frames_.size() >= 64) { + return Fault::StackOverflow; + } + const isa::FuncRow row = image_.func_row(fn_id); + Frame f; + f.fn_id = fn_id; + f.regs.assign(row.nregs, 0); + f.ret_pc = pc_; // 已指向 CALL 的下一条 + f.ret_fn_id = cur_frame().fn_id; + // 调用约定:复制当前帧 r0..r7 → 新帧(实参已由调用点 MOVE 进 r1..r7) + const size_t n = std::min(8, std::min(cur_frame().regs.size(), f.regs.size())); + for (size_t i = 0; i < n; ++i) { + f.regs[i] = cur_frame().regs[i]; + } + frames_.push_back(std::move(f)); + pc_ = 0; + return Fault::None; +} + +Fault Machine::do_ret() { + if (frames_.size() <= 1) { + ended_ = true; // MAIN 的 RET:周期结束 + return Fault::None; + } + Frame& cur = cur_frame(); + Frame& caller = frames_[frames_.size() - 2]; + // 调用约定:复制当前帧 r0..r7 → 调用方(r0 = 结果,r1..r7 原样返回) + const size_t n = std::min(8, std::min(cur.regs.size(), caller.regs.size())); + for (size_t i = 0; i < n; ++i) { + caller.regs[i] = cur.regs[i]; + } + pc_ = cur.ret_pc; + frames_.pop_back(); + return Fault::None; +} + } // namespace vm