aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2023-11-08 15:31:44 -0500
committerClyne Sullivan <clyne@bitgloo.com>2023-11-08 15:31:44 -0500
commitb33c0c564c51252ff241a2143e467dadfb8d8994 (patch)
tree1e090f690843d9daf9c3fda7e08187bc7ea9fadb
parent8e7cb05cfb2903e3c6a3e0bf713282cf50563590 (diff)
fib.fth benchmark; some minor coreword optimizations
-rw-r--r--alee.cpp17
-rw-r--r--forth/fib.fth19
-rw-r--r--libalee/corewords.cpp150
-rw-r--r--libalee/state.hpp25
4 files changed, 121 insertions, 90 deletions
diff --git a/alee.cpp b/alee.cpp
index 55cae57..99bc276 100644
--- a/alee.cpp
+++ b/alee.cpp
@@ -20,6 +20,7 @@
#include "memdict.hpp"
#include <charconv>
+#include <chrono>
#include <fstream>
#include <iostream>
#include <vector>
@@ -82,6 +83,8 @@ static void load(State& state)
void user_sys(State& state)
{
+ static std::chrono::time_point<std::chrono::high_resolution_clock> last;
+ static bool start = false;
char buf[32] = {0};
switch (state.pop()) {
@@ -102,6 +105,20 @@ void user_sys(State& state)
case 4: // load
load(state);
break;
+ case 5: // time
+ if (!start) {
+ start = true;
+ last = std::chrono::high_resolution_clock::now();
+ } else {
+ start = false;
+ auto diff = std::chrono::duration_cast<std::chrono::microseconds>(
+ std::chrono::high_resolution_clock::now() - last);
+ state.push((Cell)diff.count());
+ }
+ break;
+ case 6: // double-add
+ { auto sum = state.popd() + state.popd(); state.pushd(sum); }
+ break;
default:
break;
}
diff --git a/forth/fib.fth b/forth/fib.fth
new file mode 100644
index 0000000..82c87cd
--- /dev/null
+++ b/forth/fib.fth
@@ -0,0 +1,19 @@
+: fib ( n -- d )
+ >r 0 dup 1 0 r> 0 do
+ 2dup 2>r 2swap 6 sys 2r> 2swap loop 2drop ;
+
+: fibtest ( n -- )
+ 0 do i fib <# #s #> type space loop ;
+
+: fibbench ( n -- )
+ 5 sys fib 5 sys >r 2drop r> ;
+
+variable avg 0 avg !
+100 constant iters
+
+: bench ( -- )
+ iters 0 do 100 fibbench avg +! loop
+ avg @ iters / avg ! ;
+
+bench ." avg time: " avg @ . ." us" cr
+bye
diff --git a/libalee/corewords.cpp b/libalee/corewords.cpp
index e3ba6b3..e323ed9 100644
--- a/libalee/corewords.cpp
+++ b/libalee/corewords.cpp
@@ -39,31 +39,17 @@ void find(State& state, Word word)
void CoreWords::run(Cell ins, State& state)
{
- Cell cell;
DoubleCell dcell;
-
- Addr index = ins;
-
+ const Addr index = ins;
auto& ip = state.ip();
- auto popd = [](State& s) {
- DoubleCell dcell = s.pop();
- dcell <<= sizeof(Cell) * 8;
- dcell |= static_cast<Addr>(s.pop());
- return dcell;
- };
-
- auto pushd = [](State& s, DoubleCell d) {
- s.push(static_cast<Cell>(d));
- s.push(static_cast<Cell>(d >> (sizeof(Cell) * 8)));
- };
-
-execute:
if (index >= Dictionary::Begin) {
// must be calling a defined subroutine
state.pushr(ip);
ip = index;
return;
+ } else if (index >= WordCount) {
+ state.push(index - WordCount);
} else switch (index) {
case 0: // _lit
state.push(state.beyondip());
@@ -84,27 +70,25 @@ execute:
user_sys(state);
break;
case 6: // add
- cell = state.pop();
- state.top() += cell;
+ { auto& cell = state.pop(); state.top() += cell; }
break;
case 7: // sub
- cell = state.pop();
- state.top() -= cell;
+ { auto& cell = state.pop(); state.top() -= cell; }
break;
case 8: // mul ( n n -- d )
- cell = state.pop();
- dcell = state.pop() * cell;
- pushd(state, dcell);
+ { auto& cell = state.pop();
+ dcell = state.pop() * cell;
+ state.pushd(dcell); }
break;
case 9: // div ( d n -- n )
- cell = state.pop();
- dcell = popd(state);
- state.push(static_cast<Cell>(dcell / cell));
+ { auto& cell = state.pop();
+ dcell = state.popd();
+ state.push(static_cast<Cell>(dcell / cell)); }
break;
case 10: // mod ( d n -- n )
- cell = state.pop();
- dcell = popd(state);
- state.push(static_cast<Cell>(dcell % cell));
+ { auto& cell = state.pop();
+ dcell = state.popd();
+ state.push(static_cast<Cell>(dcell % cell)); }
break;
case 11: // peek
if (state.pop())
@@ -113,11 +97,11 @@ execute:
state.push(state.dict.readbyte(state.pop()));
break;
case 12: // poke
- cell = state.pop();
- if (auto addr = state.pop(); cell)
- state.dict.write(addr, state.pop());
- else
- state.dict.writebyte(addr, state.pop() & 0xFFu);
+ { auto& cell = state.pop();
+ if (auto addr = state.pop(); cell)
+ state.dict.write(addr, state.pop());
+ else
+ state.dict.writebyte(addr, state.pop() & 0xFFu); }
break;
case 13: // pushr
state.pushr(state.pop());
@@ -126,32 +110,29 @@ execute:
state.push(state.popr());
break;
case 15: // equal
- cell = state.pop();
- state.top() = state.top() == cell ? -1 : 0;
+ { auto& cell = state.pop();
+ state.top() = state.top() == cell ? -1 : 0; }
break;
case 16: // lt
- cell = state.pop();
- state.top() = state.top() < cell ? -1 : 0;
+ { auto& cell = state.pop();
+ state.top() = state.top() < cell ? -1 : 0; }
break;
case 17: // and
- cell = state.pop();
- state.top() &= cell;
+ { auto& cell = state.pop(); state.top() &= cell; }
break;
case 18: // or
- cell = state.pop();
- state.top() |= cell;
+ { auto& cell = state.pop(); state.top() |= cell; }
break;
case 19: // xor
- cell = state.pop();
- state.top() ^= cell;
+ { auto& cell = state.pop(); state.top() ^= cell; }
break;
case 20: // shl
- cell = state.pop();
- reinterpret_cast<Addr&>(state.top()) <<= static_cast<Addr>(cell);
+ { auto& cell = state.pop();
+ reinterpret_cast<Addr&>(state.top()) <<= static_cast<Addr>(cell); }
break;
case 21: // shr
- cell = state.pop();
- reinterpret_cast<Addr&>(state.top()) >>= static_cast<Addr>(cell);
+ { auto& cell = state.pop();
+ reinterpret_cast<Addr&>(state.top()) >>= static_cast<Addr>(cell); }
break;
case 22: // colon
state.push(state.dict.alignhere());
@@ -167,8 +148,8 @@ execute:
find(state, state.dict.input());
break;
case 24: // execute
- index = state.pop();
- goto execute;
+ ip = state.pop();
+ return;
case 25: // exit
ip = state.popr();
state.verify(ip != 0, Error::exit);
@@ -177,14 +158,18 @@ execute:
state.dict.add(findi("exit"));
state.compiling(false);
- cell = state.pop();
- dcell = cell - state.dict.latest();
- if (dcell > (1 << (sizeof(Cell) * 8 - 6)) - 1) {
- state.dict.write(static_cast<Addr>(cell) + sizeof(Cell), static_cast<Cell>(dcell));
- dcell = ((1 << (sizeof(Cell) * 8 - 6)) - 1);
+ {
+ auto& cell = state.pop();
+ dcell = cell - state.dict.latest();
+ if (dcell > (1 << (sizeof(Cell) * 8 - 6)) - 1) {
+ state.dict.write(static_cast<Addr>(cell) + sizeof(Cell),
+ static_cast<Cell>(dcell));
+ dcell = ((1 << (sizeof(Cell) * 8 - 6)) - 1);
+ }
+ state.dict.write(cell,
+ (state.dict.read(cell) & 0x1F) | static_cast<Cell>(dcell << 6));
+ state.dict.latest(cell);
}
- state.dict.write(cell, (state.dict.read(cell) & 0x1F) | static_cast<Cell>(dcell << 6));
- state.dict.latest(cell);
break;
case 27: // _jmp0
if (state.pop()) {
@@ -213,39 +198,38 @@ execute:
}
break;
case 33: // find
- cell = state.pop();
- find(state,
- Word::fromLength(static_cast<Addr>(cell + 1),
- state.dict.readbyte(cell)));
+ { auto& cell = state.pop();
+ find(state,
+ Word::fromLength(static_cast<Addr>(cell + 1),
+ state.dict.readbyte(cell))); }
break;
case 34: // _uma
{
- const auto plus = state.pop();
- cell = state.pop();
- dcell = popd(state);
- dcell *= static_cast<Addr>(cell);
- dcell += static_cast<Addr>(plus);
- pushd(state, dcell);
+ const auto& plus = state.pop();
+ const auto& cell = state.pop();
+ dcell = state.popd();
+ dcell *= static_cast<Addr>(cell);
+ dcell += static_cast<Addr>(plus);
+ state.pushd(dcell);
}
break;
case 35: // u<
- cell = state.pop();
- state.top() = static_cast<Addr>(state.top()) <
- static_cast<Addr>(cell) ? -1 : 0;
+ { auto& cell = state.pop();
+ state.top() = static_cast<Addr>(state.top()) <
+ static_cast<Addr>(cell) ? -1 : 0; }
break;
case 36: // um/mod
- cell = state.pop();
- dcell = popd(state);
-
- state.push(static_cast<Cell>(
- static_cast<DoubleAddr>(dcell) %
- static_cast<Addr>(cell)));
- state.push(static_cast<Cell>(
- static_cast<DoubleAddr>(dcell) /
- static_cast<Addr>(cell)));
- break;
- default:
- state.push(ins - WordCount);
+ {
+ const auto& cell = state.pop();
+ dcell = state.popd();
+
+ state.push(static_cast<Cell>(
+ static_cast<DoubleAddr>(dcell) %
+ static_cast<Addr>(cell)));
+ state.push(static_cast<Cell>(
+ static_cast<DoubleAddr>(dcell) /
+ static_cast<Addr>(cell)));
+ }
break;
}
diff --git a/libalee/state.hpp b/libalee/state.hpp
index e77a223..2e69463 100644
--- a/libalee/state.hpp
+++ b/libalee/state.hpp
@@ -87,31 +87,42 @@ public:
*dsp++ = value;
}
- inline Cell pop() {
+ inline const Cell& pop() {
verify(dsp > dstack, Error::pop);
return *--dsp;
}
+ inline DoubleCell popd() {
+ DoubleCell dcell = pop();
+ dcell <<= sizeof(Cell) * 8;
+ dcell |= static_cast<Addr>(pop());
+ return dcell;
+ }
+
+ inline void pushd(DoubleCell d) {
+ push(static_cast<Cell>(d));
+ push(static_cast<Cell>(d >> (sizeof(Cell) * 8)));
+ }
+
inline void pushr(Cell value) {
verify(rsp < rstack + ReturnStackSize, Error::pushr);
*rsp++ = value;
}
- inline Cell popr() {
+ inline const Cell& popr() {
verify(rsp > rstack, Error::popr);
return *--rsp;
}
- inline Cell& top() {
- verify(dsp > dstack, Error::top);
- return *(dsp - 1);
- }
-
inline Cell& pick(std::size_t i) {
verify(dsp - i > dstack, Error::pick);
return *(dsp - i - 1);
}
+ inline Cell& top() {
+ return pick(0);
+ }
+
// Advances the instruction pointer and returns that cell's contents.
inline Cell beyondip() {
context.ip += sizeof(Cell);