]> code.bitgloo.com Git - bitgloo/alee-forth.git/commitdiff
fix cell size handling; optimize for speed
authorClyne Sullivan <clyne@bitgloo.com>
Thu, 23 Feb 2023 23:04:49 +0000 (18:04 -0500)
committerClyne Sullivan <clyne@bitgloo.com>
Thu, 23 Feb 2023 23:04:49 +0000 (18:04 -0500)
Makefile
core.fth
corewords.cpp
corewords.hpp
dictionary.cpp
parser.cpp
state.cpp
state.hpp

index 94d425db70d3f2a21fc7c99474a545bb20b97316..560defa7ee758425f67155ab25051c5cae4a3e54 100644 (file)
--- 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)
index 901d9b967171281305c5a09fe7b0e6cf910988e3..4f7ef814cf6c266946a9f99776457fb23f7da468 100644 (file)
--- 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       | ;
index 9c52c8d9caa27e9cb550a960625cdab73ca488f8..64708e9a250bf4c71f9696d9ab834d4e07d240a9 100644 (file)
 
 #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);
-}
-
index ce5bba0dc2a9fb31f326950b0a789d55e347a5dc..6f982a0be296974e7ff5fba86db644eb786d4f19 100644 (file)
@@ -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
index 2ba6f889288ca29197a356f62788cf709a9e57cf..de103034e2301ee3d8ee97ea091fae3f1cde9289 100644 (file)
@@ -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;
 }
index 8a77df5e371f1e61c898b03d5c261c812a6068b5..088323051f8d88a4a870e0545763f245ce2ca810 100644 (file)
@@ -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)) {
index 16a573e1a7d8e8290b928a91ae78eb6b9acb0247..c3711016cc867b92528f8248a2db183ed856e5d1 100644 (file)
--- a/state.cpp
+++ b/state.cpp
 
 #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;
index 73bd8eb6b273841f08ad6a0d6b7630a59fba6f5a..279aefd2f57317d95cdbde8873f253f84779dbbc 100644 (file)
--- a/state.hpp
+++ b/state.hpp
 
 #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