aboutsummaryrefslogtreecommitdiffstats
path: root/libalee/state.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libalee/state.cpp')
-rw-r--r--libalee/state.cpp26
1 files changed, 24 insertions, 2 deletions
diff --git a/libalee/state.cpp b/libalee/state.cpp
index 6e12999..34e4936 100644
--- a/libalee/state.cpp
+++ b/libalee/state.cpp
@@ -42,17 +42,39 @@ void State::load(const State::Context& ctx)
context = ctx;
}
+void State::execute1(Addr ins)
+{
+repeat:
+ if (ins >= Dictionary::Begin) [[likely]] {
+ // Subroutine call
+ pushr(context.ip);
+ context.ip = ins;
+ } else {
+ if (ins < CoreWords::WordCount) {
+ if (CoreWords::run(ins, *this)) [[unlikely]] {
+ ins = pop();
+ goto repeat;
+ }
+ } else {
+ push(static_cast<Cell>(ins - CoreWords::WordCount));
+ }
+
+ context.ip += sizeof(Cell);
+ }
+}
+
Error State::execute(Addr addr)
{
auto stat = static_cast<Error>(setjmp(context.jmpbuf));
if (stat == Error::none) {
- CoreWords::run(addr, *this);
+ context.ip = 0;
+ execute1(addr);
if (context.ip >= Dictionary::Begin) {
// longjmp will exit this loop.
for (;;)
- CoreWords::run(dict.read(context.ip), *this);
+ execute1(dict.read(context.ip));
} else {
// addr was a CoreWord, all done now.
context.ip = 0;