aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/vm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/engine/vm.cpp')
-rw-r--r--engines/sci/engine/vm.cpp67
1 files changed, 57 insertions, 10 deletions
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index 111e17d0eb..7c3e5cb03d 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -54,6 +54,53 @@ int script_gc_interval = GC_INTERVAL; // Number of steps in between gcs // FIXME
static bool breakpointWasHit = false; // FIXME: Avoid non-const global vars
+
+#define SCI_XS_CALLEE_LOCALS ((SegmentId)-1)
+
+/**
+ * Adds an entry to the top of the execution stack.
+ *
+ * @param[in] s The state with which to execute
+ * @param[in] pc The initial program counter
+ * @param[in] sp The initial stack pointer
+ * @param[in] objp Pointer to the beginning of the current object
+ * @param[in] argc Number of parameters to call with
+ * @param[in] argp Heap pointer to the first parameter
+ * @param[in] selector The selector by which it was called or
+ * NULL_SELECTOR if n.a. For debugging.
+ * @param[in] sendp Pointer to the object which the message was
+ * sent to. Equal to objp for anything but super.
+ * @param[in] origin Number of the execution stack element this
+ * entry was created by (usually the current TOS
+ * number, except for multiple sends).
+ * @param[in] local_segment The segment to use for local variables,
+ * or SCI_XS_CALLEE_LOCALS to use obj's segment.
+ * @return A pointer to the new exec stack TOS entry
+ */
+static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t pc, StackPtr sp,
+ reg_t objp, int argc, StackPtr argp, Selector selector,
+ reg_t sendp, int origin, SegmentId local_segment);
+
+
+/**
+ * Adds one varselector access to the execution stack.
+ * This function is called from send_selector only.
+ * @param[in] s The EngineState to use
+ * @param[in] objp Pointer to the object owning the selector
+ * @param[in] argc 1 for writing, 0 for reading
+ * @param[in] argp Pointer to the address of the data to write -2
+ * @param[in] selector Selector name
+ * @param[in] address Heap address of the selector
+ * @param[in] origin Stack frame which the access originated from
+ * @return Pointer to the new exec-TOS element
+ */
+static ExecStack *add_exec_stack_varselector(Common::List<ExecStack> &execStack, reg_t objp, int argc,
+ StackPtr argp, Selector selector, const ObjVarRef& address,
+ int origin);
+
+
+
+
// validation functionality
#ifndef DISABLE_VALIDATIONS
@@ -258,7 +305,7 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP
}
}
- return add_exec_stack_entry(s, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, calling_obj, s->_executionStack.size()-1, seg);
+ return add_exec_stack_entry(s->_executionStack, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, calling_obj, s->_executionStack.size()-1, seg);
}
@@ -431,10 +478,10 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
while (!sendCalls.empty()) {
CallsStruct call = sendCalls.pop();
if (call.type == EXEC_STACK_TYPE_VARSELECTOR) // Write/read variable?
- add_exec_stack_varselector(s, work_obj, call.argc, call.argp,
+ add_exec_stack_varselector(s->_executionStack, work_obj, call.argc, call.argp,
call.selector, call.address.var, origin);
else
- add_exec_stack_entry(s, call.address.func, call.sp, work_obj,
+ add_exec_stack_entry(s->_executionStack, call.address.func, call.sp, work_obj,
call.argc, call.argp,
call.selector, send_obj, origin, SCI_XS_CALLEE_LOCALS);
}
@@ -446,8 +493,8 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
return &(s->_executionStack.back());
}
-ExecStack *add_exec_stack_varselector(EngineState *s, reg_t objp, int argc, StackPtr argp, Selector selector, const ObjVarRef& address, int origin) {
- ExecStack *xstack = add_exec_stack_entry(s, NULL_REG, 0, objp, argc, argp, selector, objp, origin, SCI_XS_CALLEE_LOCALS);
+static ExecStack *add_exec_stack_varselector(Common::List<ExecStack> &execStack, reg_t objp, int argc, StackPtr argp, Selector selector, const ObjVarRef& address, int origin) {
+ ExecStack *xstack = add_exec_stack_entry(execStack, NULL_REG, 0, objp, argc, argp, selector, objp, origin, SCI_XS_CALLEE_LOCALS);
// Store selector address in sp
xstack->addr.varp = address;
@@ -456,7 +503,7 @@ ExecStack *add_exec_stack_varselector(EngineState *s, reg_t objp, int argc, Stac
return xstack;
}
-ExecStack *add_exec_stack_entry(EngineState *s, reg_t pc, StackPtr sp, reg_t objp, int argc,
+static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t pc, StackPtr sp, reg_t objp, int argc,
StackPtr argp, Selector selector, reg_t sendp, int origin, SegmentId _localsSegment) {
// Returns new TOS element for the execution stack
// _localsSegment may be -1 if derived from the called object
@@ -486,8 +533,8 @@ ExecStack *add_exec_stack_entry(EngineState *s, reg_t pc, StackPtr sp, reg_t obj
xstack.type = EXEC_STACK_TYPE_CALL; // Normal call
- s->_executionStack.push_back(xstack);
- return &(s->_executionStack.back());
+ execStack.push_back(xstack);
+ return &(execStack.back());
}
#ifdef DISABLE_VALIDATIONS
@@ -982,7 +1029,7 @@ void run_vm(EngineState *s, bool restoring) {
StackPtr call_base = scriptState.xs->sp - argc;
scriptState.xs->sp[1].offset += scriptState.restAdjust;
- xs_new = add_exec_stack_entry(s, make_reg(scriptState.xs->addr.pc.segment,
+ xs_new = add_exec_stack_entry(s->_executionStack, make_reg(scriptState.xs->addr.pc.segment,
scriptState.xs->addr.pc.offset + opparams[0]),
scriptState.xs->sp, scriptState.xs->objp,
(validate_arithmetic(*call_base)) + scriptState.restAdjust,
@@ -1026,7 +1073,7 @@ void run_vm(EngineState *s, bool restoring) {
// This is useful in debugger backtraces if this
// kernel function calls a script itself.
ExecStack *xstack;
- xstack = add_exec_stack_entry(s, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, NULL_REG,
+ xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, NULL_REG,
s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS);
xstack->selector = opparams[0];
xstack->type = EXEC_STACK_TYPE_KERNEL;