aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2023-02-23 18:04:49 -0500
committerClyne Sullivan <clyne@bitgloo.com>2023-02-23 18:04:49 -0500
commit9f0127c3c82203d308e4230a4b32304e155d05c7 (patch)
tree0f3952bdb308348cc913d842262a2f3872963d63
parent1815716fc702a745cf37db84757ab56a0d923f45 (diff)
fix cell size handling; optimize for speed
-rw-r--r--Makefile3
-rw-r--r--core.fth20
-rw-r--r--corewords.cpp408
-rw-r--r--corewords.hpp52
-rw-r--r--dictionary.cpp5
-rw-r--r--parser.cpp17
-rw-r--r--state.cpp64
-rw-r--r--state.hpp74
8 files changed, 258 insertions, 385 deletions
diff --git a/Makefile b/Makefile
index 94d425d..560defa 100644
--- a/Makefile
+++ b/Makefile
@@ -10,6 +10,9 @@ all: $(EXEFILE)
small: CXXFLAGS += -Os
small: $(EXEFILE)
+fast: CXXFLAGS += -O3 -march=native -mtune=native
+fast: $(EXEFILE)
+
$(EXEFILE): $(LIBFILE)
$(LIBFILE): $(OBJFILES)
diff --git a/core.fth b/core.fth
index 901d9b9..4f7ef81 100644
--- a/core.fth
+++ b/core.fth
@@ -1,14 +1,16 @@
+: cell+ 2 + ;
+: cells 2 * ;
+
+
: . 0 sys ;
: emit 1 sys ;
: 1+ 1 + ;
: 1- 1 - ;
-: ! 2 _! ;
-: @ 2 _@ ;
-: , here ! 2 allot ;
-: cell+ 2 + ;
-: cells 2 * ;
+: ! 1 _! ;
+: @ 1 _@ ;
+: , here ! 1 cells allot ;
: over 1 pick ;
: rot >r swap r> swap ;
@@ -21,8 +23,8 @@
: 2over 3 pick 3 pick ;
: 2swap rot >r rot r> ;
-: c! 1 _! ;
-: c@ 1 _@ ;
+: c! 0 _! ;
+: c@ 0 _@ ;
: c, here c! 1 allot ;
: char+ 1+ ;
: chars ;
@@ -77,8 +79,8 @@
: i postpone r@ ; imm
: j postpone 2r> postpone r@ ['] -rot , postpone 2>r ; imm
-: align here 1 & if 1 allot then ;
-: aligned dup 1 & if 1+ then ;
+: align here 1 cells 1- tuck & if 1 cells swap - allot else drop then ;
+: aligned dup 1 cells 1- tuck & if 1 cells swap - allot else drop then ;
: and & ;
: or | ;
diff --git a/corewords.cpp b/corewords.cpp
index 9c52c8d..64708e9 100644
--- a/corewords.cpp
+++ b/corewords.cpp
@@ -18,241 +18,185 @@
#include "corewords.hpp"
-Func CoreWords::get(int index)
-{
- static const Func ops[WordCount] = {
- op_drop, op_dup, op_swap, op_pick, op_sys,
- op_add, op_sub, op_mul, op_div, op_mod,
- /*10*/ op_peek, op_poke, op_pushr, op_popr, op_eq,
- op_lt, op_allot, op_and, op_or, op_xor,
- /*20*/ op_shl, op_shr, op_colon, op_semic, op_here,
- op_depth, op_key, op_exit, op_tick, op_execute,
- /*30*/ op_jmp, op_jmp0, op_lit, op_literal, op_rdepth
+void CoreWords::run(unsigned int index, State& state)
+{
+ auto getword = [&state] {
+ auto word = state.dict.input();
+ while (word.size() == 0) {
+ state.input(state);
+ word = state.dict.input();
+ }
+ return word;
+ };
+ auto newdef = [](Dictionary& dict, Word word) {
+ auto addr = dict.alignhere();
+ dict.addDefinition(word);
+ dict.write(addr,
+ (dict.read(addr) & 0x1F) |
+ ((addr - dict.latest()) << 6));
+ dict.latest(addr);
+ };
+ auto tick = [&state](Word word) {
+ if (auto j = state.dict.find(word); j > 0)
+ state.push(state.dict.getexec(j));
+ else if (auto i = CoreWords::findi(state, word); i >= 0)
+ state.push(i & ~CoreWords::Compiletime);
+ else
+ state.push(0);
};
- return index >= 0 && index < WordCount ? ops[index] : nullptr;
-}
-
-void CoreWords::op_drop(State& state)
-{
- state.pop();
-}
-
-void CoreWords::op_dup(State& state)
-{
- state.push(state.top());
-}
-
-void CoreWords::op_swap(State& state)
-{
- std::swap(state.top(), state.pick(1));
-}
-
-void CoreWords::op_pick(State& state)
-{
- state.push(state.pick(state.pop()));
-}
-
-void CoreWords::op_sys(State& state)
-{
- return user_sys(state);
-}
-
-void CoreWords::op_add(State& state)
-{
- const auto a = state.pop();
- state.top() += a;
-}
-
-void CoreWords::op_sub(State& state)
-{
- const auto a = state.pop();
- state.top() -= a;
-}
-
-void CoreWords::op_mul(State& state) {
- const auto a = state.pop();
- state.top() *= a;
-}
-
-void CoreWords::op_div(State& state) {
- const auto a = state.pop();
- state.top() /= a;
-}
-
-void CoreWords::op_mod(State& state) {
- const auto a = state.pop();
- state.top() %= a;
-}
-
-void CoreWords::op_peek(State& state) {
- if (auto w = state.pop(); w == 1)
- state.push(state.dict.readbyte(state.pop()));
- else
- state.push(state.dict.read(state.pop()));
-}
-
-void CoreWords::op_poke(State& state) {
- const auto w = state.pop();
- const auto addr = state.pop();
- if (w == 1)
- state.dict.writebyte(addr, state.pop());
- else
- state.dict.write(addr, state.pop());
-}
-
-void CoreWords::op_pushr(State& state) {
- state.pushr(state.pop());
-}
-
-void CoreWords::op_popr(State& state) {
- state.push(state.popr());
-}
-
-void CoreWords::op_eq(State& state) {
- const auto a = state.pop();
- state.top() = state.top() == a;
-}
-
-void CoreWords::op_lt(State& state) {
- const auto a = state.pop();
- state.top() = state.top() < a;
-}
-
-void CoreWords::op_allot(State& state) {
- state.dict.allot(state.pop());
-}
-
-void CoreWords::op_and(State& state) {
- const auto a = state.pop();
- state.top() &= a;
-}
-
-void CoreWords::op_or(State& state) {
- const auto a = state.pop();
- state.top() |= a;
-}
-
-void CoreWords::op_xor(State& state) {
- const auto a = state.pop();
- state.top() ^= a;
-}
-
-void CoreWords::op_shl(State& state) {
- const auto a = state.pop();
- state.top() <<= a;
-}
-
-void CoreWords::op_shr(State& state) {
- const auto a = state.pop();
- state.top() >>= a;
-}
-
-void CoreWords::op_colon(State& state) {
- Word word = state.dict.input();
- while (word.size() == 0) {
- state.input(state);
- word = state.dict.input();
- }
-
- const auto start = state.dict.alignhere();
- state.dict.addDefinition(word);
- state.dict.write(start,
- (state.dict.read(start) & 0x1F) |
- ((start - state.dict.latest()) << 6));
- state.dict.latest(start);
- state.compiling(true);
-}
-
-void CoreWords::op_tick(State& state) {
- Word word = state.dict.input();
- while (word.size() == 0) {
- state.input(state);
- word = state.dict.input();
- }
-
- Cell xt = 0;
- if (auto i = CoreWords::findi(state, word); i >= 0) {
- xt = i & ~CoreWords::Compiletime;
- } else if (auto j = state.dict.find(word); j > 0) {
- xt = state.dict.getexec(j);
- }
-
- state.push(xt);
-}
-
-void CoreWords::op_execute(State& state) {
- state.execute(state.pop());
-}
-
-void CoreWords::op_exit(State& state) {
- state.ip = state.popr();
-}
-
-void CoreWords::op_semic(State& state) {
- if (state.compiling()) {
+ Cell cell;
+
+ switch (index) {
+ default:
+ // must be calling a defined subroutine
+ state.pushr(state.ip);
+ state.ip = index - sizeof(Cell);
+ break;
+ case 0: // drop
+ state.pop();
+ break;
+ case 1: // dup
+ state.push(state.top());
+ break;
+ case 2: // swap
+ std::swap(state.top(), state.pick(1));
+ break;
+ case 3: // pick
+ state.push(state.pick(state.pop()));
+ break;
+ case 4: // sys
+ user_sys(state);
+ break;
+ case 5: // add
+ cell = state.pop();
+ state.top() += cell;
+ break;
+ case 6: // sub
+ cell = state.pop();
+ state.top() -= cell;
+ break;
+ case 7: // mul
+ cell = state.pop();
+ state.top() *= cell;
+ break;
+ case 8: // div
+ cell = state.pop();
+ state.top() /= cell;
+ break;
+ case 9: // mod
+ cell = state.pop();
+ state.top() %= cell;
+ break;
+ case 10: // peek
+ if (state.pop())
+ state.push(state.dict.read(state.pop()));
+ else
+ state.push(state.dict.readbyte(state.pop()));
+ break;
+ case 11: // poke
+ cell = state.pop();
+ if (auto addr = state.pop(); cell)
+ state.dict.write(addr, state.pop());
+ else
+ state.dict.writebyte(addr, state.pop());
+ break;
+ case 12: // pushr
+ state.pushr(state.pop());
+ break;
+ case 13: // popr
+ state.push(state.popr());
+ break;
+ case 14: // equal
+ cell = state.pop();
+ state.top() = state.top() == cell;
+ break;
+ case 15: // lt
+ cell = state.pop();
+ state.top() = state.top() < cell;
+ break;
+ case 16: // allot
+ state.dict.allot(state.pop());
+ break;
+ case 17: // and
+ cell = state.pop();
+ state.top() &= cell;
+ break;
+ case 18: // or
+ cell = state.pop();
+ state.top() |= cell;
+ break;
+ case 19: // xor
+ cell = state.pop();
+ state.top() ^= cell;
+ break;
+ case 20: // shl
+ cell = state.pop();
+ state.top() <<= cell;
+ break;
+ case 21: // shr
+ cell = state.pop();
+ state.top() >>= cell;
+ break;
+ case 22: // colon
+ newdef(state.dict, getword());
+ state.compiling(true);
+ break;
+ case 23: // tick
+ tick(getword());
+ break;
+ case 24: // execute
+ state.execute(state.pop());
+ break;
+ case 25: // exit
+ state.ip = state.popr();
+ break;
+ case 26: // semic
state.dict.add(findi("exit"));
state.compiling(false);
- }
-}
-
-void CoreWords::op_here(State& state) {
- state.push(state.dict.here);
-}
-
-void CoreWords::op_lit(State& state)
-{
- state.push(state.beyondip());
- state.ip += sizeof(Cell);
-}
-
-void CoreWords::op_literal(State& state)
-{
- if (state.compiling()) {
+ break;
+ case 27: // here
+ state.push(state.dict.here);
+ break;
+ case 28: // _lit
+ state.push(state.beyondip());
+ break;
+ case 29: // literal
state.dict.add(findi("_lit"));
state.dict.add(state.pop());
+ break;
+ case 30: // _jmp
+ state.ip = state.beyondip() - sizeof(Cell);
+ break;
+ case 31: // _jmp0
+ if (state.pop())
+ state.beyondip();
+ else
+ state.ip = state.beyondip() - sizeof(Cell);
+ break;
+ case 32: // depth
+ state.push(state.size());
+ break;
+ case 33: // _rdepth
+ state.push(state.rsize());
+ break;
+ case 34: // key
+ cell = state.dict.read(Dictionary::Input);
+ while (cell <= 0) {
+ state.input(state);
+ cell = state.dict.read(Dictionary::Input);
+ }
+
+ state.dict.write(Dictionary::Input, cell - 1);
+
+ state.push(
+ state.dict.readbyte(
+ Dictionary::Input + sizeof(Cell) +
+ Dictionary::InputCells - cell));
+ break;
}
}
-void CoreWords::op_jmp(State& state)
-{
- state.ip = state.beyondip() - sizeof(Cell);
-}
-
-void CoreWords::op_jmp0(State& state)
-{
- if (state.pop())
- state.ip += sizeof(Cell);
- else
- op_jmp(state);
-}
-
-void CoreWords::op_depth(State& state)
-{
- state.push(state.size());
-}
-
-void CoreWords::op_rdepth(State& state)
-{
- state.push(state.rsize());
-}
-
-void CoreWords::op_key(State& state)
-{
- auto len = state.dict.read(Dictionary::Input);
- while (len <= 0) {
- state.input(state);
- len = state.dict.read(Dictionary::Input);
- }
-
- state.dict.write(Dictionary::Input, len - 1);
- Addr addr = Dictionary::Input + sizeof(Cell) +
- Dictionary::InputCells - len;
- Cell val = state.dict.readbyte(addr);
-
- state.push(val);
-}
-
int CoreWords::findi(std::string_view word)
{
std::size_t i;
@@ -293,15 +237,3 @@ int CoreWords::findi(State& state, Word word)
return -1;
}
-Func CoreWords::find(State& state, Word word)
-{
- const auto i = findi(state, word);
- return i >= 0 ? get(i & ~Compiletime) : nullptr;
-}
-
-void CoreWords::run(int i, State& state)
-{
- if (i >= 0 && i < WordCount)
- get(i)(state);
-}
-
diff --git a/corewords.hpp b/corewords.hpp
index ce5bba0..6f982a0 100644
--- a/corewords.hpp
+++ b/corewords.hpp
@@ -36,8 +36,7 @@ public:
static int findi(std::string_view);
static int findi(State&, Word);
- static Func find(State&, Word);
- static void run(int, State&);
+ static void run(unsigned int, State&);
private:
// Ends with '\0': regular word
@@ -45,50 +44,11 @@ private:
constexpr static char wordsarr[] =
"drop\0dup\0swap\0pick\0sys\0"
"+\0-\0*\0/\0%\0"
- "_@\0_!\0>r\0r>\0"
- "=\0<\0allot\0&\0|\0"
- "^\0<<\0>>\0:\1"
- ";\1here\0depth\0"
- "key\0exit\0'\0execute\0_jmp\0"
- "_jmp0\0_lit\0literal\1_rdepth\0";
-
- static Func get(int);
-
- static void op_drop(State&);
- static void op_dup(State&);
- static void op_swap(State&);
- static void op_pick(State&);
- static void op_sys(State&);
- static void op_add(State&);
- static void op_sub(State&);
- static void op_mul(State&);
- static void op_div(State&);
- static void op_mod(State&);
- static void op_peek(State&);
- static void op_poke(State&);
- static void op_pushr(State&);
- static void op_popr(State&);
- static void op_eq(State&);
- static void op_lt(State&);
- static void op_allot(State&);
- static void op_and(State&);
- static void op_or(State&);
- static void op_xor(State&);
- static void op_shl(State&);
- static void op_shr(State&);
- static void op_colon(State&);
- static void op_semic(State&);
- static void op_here(State&);
- static void op_lit(State&);
- static void op_depth(State&);
- static void op_rdepth(State&);
- static void op_key(State&);
- static void op_exit(State&);
- static void op_tick(State&);
- static void op_execute(State&);
- static void op_jmp(State&);
- static void op_jmp0(State&);
- static void op_literal(State&);
+ "_@\0_!\0>r\0r>\0=\0"
+ "<\0allot\0&\0|\0^\0"
+ "<<\0>>\0:\0'\0execute\0"
+ "exit\0;\1here\0_lit\0literal\1"
+ "_jmp\0_jmp0\0depth\0_rdepth\0key\0";
};
#endif // ALEEFORTH_COREWORDS_HPP
diff --git a/dictionary.cpp b/dictionary.cpp
index 2ba6f88..de10303 100644
--- a/dictionary.cpp
+++ b/dictionary.cpp
@@ -34,8 +34,9 @@ void Dictionary::add(Cell value)
Addr Dictionary::aligned(Addr addr) const noexcept
{
- if (addr & (sizeof(Cell) - sizeof(uint8_t)))
- addr = (addr + sizeof(Cell)) & ~(sizeof(Cell) - sizeof(uint8_t));
+ auto unaligned = addr & (sizeof(Cell) - sizeof(uint8_t));
+ if (unaligned)
+ addr += sizeof(Cell) - unaligned;
return addr;
}
diff --git a/parser.cpp b/parser.cpp
index 8a77df5..0883230 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -54,19 +54,20 @@ ParseStatus Parser::parseWord(State& state, Word word)
{
int ins, imm;
- ins = CoreWords::findi(state, word);
- if (ins < 0) {
- ins = state.dict.find(word);
+ ins = state.dict.find(word);
- if (ins <= 0) {
+ if (ins <= 0) {
+ ins = CoreWords::findi(state, word);
+
+ if (ins < 0) {
return parseNumber(state, word);
} else {
- imm = state.dict.read(ins) & CoreWords::Immediate;
- ins = state.dict.getexec(ins);
+ imm = ins & CoreWords::Compiletime;
+ ins &= ~CoreWords::Compiletime;
}
} else {
- imm = ins & CoreWords::Compiletime;
- ins &= ~CoreWords::Compiletime;
+ imm = state.dict.read(ins) & CoreWords::Immediate;
+ ins = state.dict.getexec(ins);
}
if (state.dict.read(Dictionary::Postpone)) {
diff --git a/state.cpp b/state.cpp
index 16a573e..c371101 100644
--- a/state.cpp
+++ b/state.cpp
@@ -21,13 +21,6 @@
#include <iterator>
-struct pop {};
-struct push {};
-struct popr {};
-struct pushr {};
-struct top {};
-struct pick {};
-
bool State::compiling() const
{
return dict.read(Dictionary::Compiling);
@@ -41,7 +34,6 @@ void State::compiling(bool yes)
void State::execute(Addr addr)
{
if (addr < CoreWords::WordCount) {
- // Must be a core-word
CoreWords::run(addr, *this);
} else {
pushr(0);
@@ -49,65 +41,11 @@ void State::execute(Addr addr)
do {
ip += sizeof(Cell);
-
- const auto ins = dict.read(ip);
- if (ins < CoreWords::WordCount) {
- CoreWords::run(ins, *this);
- } else {
- pushr(ip);
- ip = ins - sizeof(Cell);
- }
+ CoreWords::run(dict.read(ip), *this);
} while (ip);
}
}
-Cell State::beyondip() const
-{
- return dict.read(ip + sizeof(Cell));
-}
-
-void State::pushr(Cell value)
-{
- if (rsize() == ReturnStackSize)
- throw ::pushr();
- *++rsp = value;
-}
-
-Cell State::popr()
-{
- if (rsize() == 0)
- throw ::popr();
- return *rsp--;
-}
-
-void State::push(Cell value)
-{
- if (size() == DataStackSize)
- throw ::push();
- *++dsp = value;
-}
-
-Cell State::pop()
-{
- if (size() == 0)
- throw ::pop();
- return *dsp--;
-}
-
-Cell& State::top()
-{
- if (size() == 0)
- throw ::top();
- return *dsp;
-}
-
-Cell& State::pick(std::size_t i)
-{
- if (i >= size())
- throw ::pick();
- return *(dsp - i);
-}
-
std::size_t State::size() const noexcept
{
return std::distance(dstack, static_cast<const Cell *>(dsp)) + 1;
diff --git a/state.hpp b/state.hpp
index 73bd8eb..279aefd 100644
--- a/state.hpp
+++ b/state.hpp
@@ -24,21 +24,20 @@
#include <cstddef>
-constexpr unsigned DataStackSize = 12;
-constexpr unsigned ReturnStackSize = 12;
+constexpr unsigned DataStackSize = 8;
+constexpr unsigned ReturnStackSize = 8;
-class State
+struct State
{
+ Addr ip = 0;
+ Dictionary& dict;
+ void (*input)(State&);
+
Cell dstack[DataStackSize] = {};
Cell rstack[ReturnStackSize] = {};
Cell *dsp = dstack - 1;
Cell *rsp = rstack - 1;
-public:
- Addr ip = 0;
- Dictionary& dict;
- void (*input)(State&);
-
constexpr State(Dictionary& d, void (*i)(State&)):
dict(d), input(i) {}
@@ -47,19 +46,56 @@ public:
void execute(Addr);
- Cell beyondip() const;
-
- void pushr(Cell);
- Cell popr();
-
- void push(Cell);
- Cell pop();
-
- Cell& top();
- Cell& pick(std::size_t);
-
std::size_t size() const noexcept;
std::size_t rsize() const noexcept;
+
+ inline void push(Cell value) {
+ if (dsp == dstack + DataStackSize - 1)
+ throw exc_push();
+ *++dsp = value;
+ }
+
+ inline Cell pop() {
+ if (dsp < dstack)
+ throw exc_pop();
+ return *dsp--;
+ }
+
+ inline Cell beyondip() {
+ ip += sizeof(Cell);
+ return dict.read(ip);
+ }
+
+ inline void pushr(Cell value) {
+ if (rsp == rstack + ReturnStackSize - 1)
+ throw exc_pushr();
+ *++rsp = value;
+ }
+
+ inline Cell popr() {
+ if (rsp < rstack)
+ throw exc_popr();
+ return *rsp--;
+ }
+
+ inline Cell& top() {
+ if (dsp < dstack)
+ throw exc_top();
+ return *dsp;
+ }
+
+ inline Cell& pick(std::size_t i) {
+ if (dsp - i < dstack)
+ throw exc_pick();
+ return *(dsp - i);
+ }
+
+ struct exc_pop {};
+ struct exc_push {};
+ struct exc_popr {};
+ struct exc_pushr {};
+ struct exc_top {};
+ struct exc_pick {};
};
#endif // ALEEFORTH_STATE_HPP