fix cell size handling; optimize for speed

llvm
Clyne 2 years ago
parent 1815716fc7
commit 9f0127c3c8

@ -10,6 +10,9 @@ all: $(EXEFILE)
small: CXXFLAGS += -Os small: CXXFLAGS += -Os
small: $(EXEFILE) small: $(EXEFILE)
fast: CXXFLAGS += -O3 -march=native -mtune=native
fast: $(EXEFILE)
$(EXEFILE): $(LIBFILE) $(EXEFILE): $(LIBFILE)
$(LIBFILE): $(OBJFILES) $(LIBFILE): $(OBJFILES)

@ -1,14 +1,16 @@
: cell+ 2 + ;
: cells 2 * ;
: . 0 sys ; : . 0 sys ;
: emit 1 sys ; : emit 1 sys ;
: 1+ 1 + ; : 1+ 1 + ;
: 1- 1 - ; : 1- 1 - ;
: ! 2 _! ; : ! 1 _! ;
: @ 2 _@ ; : @ 1 _@ ;
: , here ! 2 allot ; : , here ! 1 cells allot ;
: cell+ 2 + ;
: cells 2 * ;
: over 1 pick ; : over 1 pick ;
: rot >r swap r> swap ; : rot >r swap r> swap ;
@ -21,8 +23,8 @@
: 2over 3 pick 3 pick ; : 2over 3 pick 3 pick ;
: 2swap rot >r rot r> ; : 2swap rot >r rot r> ;
: c! 1 _! ; : c! 0 _! ;
: c@ 1 _@ ; : c@ 0 _@ ;
: c, here c! 1 allot ; : c, here c! 1 allot ;
: char+ 1+ ; : char+ 1+ ;
: chars ; : chars ;
@ -77,8 +79,8 @@
: i postpone r@ ; imm : i postpone r@ ; imm
: j postpone 2r> postpone r@ ['] -rot , postpone 2>r ; imm : j postpone 2r> postpone r@ ['] -rot , postpone 2>r ; imm
: align here 1 & if 1 allot then ; : align here 1 cells 1- tuck & if 1 cells swap - allot else drop then ;
: aligned dup 1 & if 1+ then ; : aligned dup 1 cells 1- tuck & if 1 cells swap - allot else drop then ;
: and & ; : and & ;
: or | ; : or | ;

@ -18,241 +18,185 @@
#include "corewords.hpp" #include "corewords.hpp"
Func CoreWords::get(int index) void CoreWords::run(unsigned int index, State& state)
{ {
static const Func ops[WordCount] = { auto getword = [&state] {
op_drop, op_dup, op_swap, op_pick, op_sys, auto word = state.dict.input();
op_add, op_sub, op_mul, op_div, op_mod, while (word.size() == 0) {
/*10*/ op_peek, op_poke, op_pushr, op_popr, op_eq, state.input(state);
op_lt, op_allot, op_and, op_or, op_xor, word = state.dict.input();
/*20*/ op_shl, op_shr, op_colon, op_semic, op_here, }
op_depth, op_key, op_exit, op_tick, op_execute, return word;
/*30*/ op_jmp, op_jmp0, op_lit, op_literal, op_rdepth };
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; Cell cell;
}
switch (index) {
void CoreWords::op_drop(State& state) default:
{ // must be calling a defined subroutine
state.pop(); state.pushr(state.ip);
} state.ip = index - sizeof(Cell);
break;
void CoreWords::op_dup(State& state) case 0: // drop
{ state.pop();
state.push(state.top()); break;
} case 1: // dup
state.push(state.top());
void CoreWords::op_swap(State& state) break;
{ case 2: // swap
std::swap(state.top(), state.pick(1)); std::swap(state.top(), state.pick(1));
} break;
case 3: // pick
void CoreWords::op_pick(State& state) state.push(state.pick(state.pop()));
{ break;
state.push(state.pick(state.pop())); case 4: // sys
} user_sys(state);
break;
void CoreWords::op_sys(State& state) case 5: // add
{ cell = state.pop();
return user_sys(state); state.top() += cell;
} break;
case 6: // sub
void CoreWords::op_add(State& state) cell = state.pop();
{ state.top() -= cell;
const auto a = state.pop(); break;
state.top() += a; case 7: // mul
} cell = state.pop();
state.top() *= cell;
void CoreWords::op_sub(State& state) break;
{ case 8: // div
const auto a = state.pop(); cell = state.pop();
state.top() -= a; state.top() /= cell;
} break;
case 9: // mod
void CoreWords::op_mul(State& state) { cell = state.pop();
const auto a = state.pop(); state.top() %= cell;
state.top() *= a; break;
} case 10: // peek
if (state.pop())
void CoreWords::op_div(State& state) { state.push(state.dict.read(state.pop()));
const auto a = state.pop(); else
state.top() /= a; state.push(state.dict.readbyte(state.pop()));
} break;
case 11: // poke
void CoreWords::op_mod(State& state) { cell = state.pop();
const auto a = state.pop(); if (auto addr = state.pop(); cell)
state.top() %= a; state.dict.write(addr, state.pop());
} else
state.dict.writebyte(addr, state.pop());
void CoreWords::op_peek(State& state) { break;
if (auto w = state.pop(); w == 1) case 12: // pushr
state.push(state.dict.readbyte(state.pop())); state.pushr(state.pop());
else break;
state.push(state.dict.read(state.pop())); case 13: // popr
} state.push(state.popr());
break;
void CoreWords::op_poke(State& state) { case 14: // equal
const auto w = state.pop(); cell = state.pop();
const auto addr = state.pop(); state.top() = state.top() == cell;
if (w == 1) break;
state.dict.writebyte(addr, state.pop()); case 15: // lt
else cell = state.pop();
state.dict.write(addr, state.pop()); state.top() = state.top() < cell;
} break;
case 16: // allot
void CoreWords::op_pushr(State& state) { state.dict.allot(state.pop());
state.pushr(state.pop()); break;
} case 17: // and
cell = state.pop();
void CoreWords::op_popr(State& state) { state.top() &= cell;
state.push(state.popr()); break;
} case 18: // or
cell = state.pop();
void CoreWords::op_eq(State& state) { state.top() |= cell;
const auto a = state.pop(); break;
state.top() = state.top() == a; case 19: // xor
} cell = state.pop();
state.top() ^= cell;
void CoreWords::op_lt(State& state) { break;
const auto a = state.pop(); case 20: // shl
state.top() = state.top() < a; cell = state.pop();
} state.top() <<= cell;
break;
void CoreWords::op_allot(State& state) { case 21: // shr
state.dict.allot(state.pop()); cell = state.pop();
} state.top() >>= cell;
break;
void CoreWords::op_and(State& state) { case 22: // colon
const auto a = state.pop(); newdef(state.dict, getword());
state.top() &= a; state.compiling(true);
} break;
case 23: // tick
void CoreWords::op_or(State& state) { tick(getword());
const auto a = state.pop(); break;
state.top() |= a; case 24: // execute
} state.execute(state.pop());
break;
void CoreWords::op_xor(State& state) { case 25: // exit
const auto a = state.pop(); state.ip = state.popr();
state.top() ^= a; break;
} case 26: // semic
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()) {
state.dict.add(findi("exit")); state.dict.add(findi("exit"));
state.compiling(false); state.compiling(false);
} break;
} case 27: // here
state.push(state.dict.here);
void CoreWords::op_here(State& state) { break;
state.push(state.dict.here); case 28: // _lit
} state.push(state.beyondip());
break;
void CoreWords::op_lit(State& state) case 29: // literal
{
state.push(state.beyondip());
state.ip += sizeof(Cell);
}
void CoreWords::op_literal(State& state)
{
if (state.compiling()) {
state.dict.add(findi("_lit")); state.dict.add(findi("_lit"));
state.dict.add(state.pop()); 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) int CoreWords::findi(std::string_view word)
{ {
std::size_t i; std::size_t i;
@ -293,15 +237,3 @@ int CoreWords::findi(State& state, Word word)
return -1; 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);
}

@ -36,8 +36,7 @@ public:
static int findi(std::string_view); static int findi(std::string_view);
static int findi(State&, Word); static int findi(State&, Word);
static Func find(State&, Word); static void run(unsigned int, State&);
static void run(int, State&);
private: private:
// Ends with '\0': regular word // Ends with '\0': regular word
@ -45,50 +44,11 @@ private:
constexpr static char wordsarr[] = constexpr static char wordsarr[] =
"drop\0dup\0swap\0pick\0sys\0" "drop\0dup\0swap\0pick\0sys\0"
"+\0-\0*\0/\0%\0" "+\0-\0*\0/\0%\0"
"_@\0_!\0>r\0r>\0" "_@\0_!\0>r\0r>\0=\0"
"=\0<\0allot\0&\0|\0" "<\0allot\0&\0|\0^\0"
"^\0<<\0>>\0:\1" "<<\0>>\0:\0'\0execute\0"
";\1here\0depth\0" "exit\0;\1here\0_lit\0literal\1"
"key\0exit\0'\0execute\0_jmp\0" "_jmp\0_jmp0\0depth\0_rdepth\0key\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&);
}; };
#endif // ALEEFORTH_COREWORDS_HPP #endif // ALEEFORTH_COREWORDS_HPP

@ -34,8 +34,9 @@ void Dictionary::add(Cell value)
Addr Dictionary::aligned(Addr addr) const noexcept Addr Dictionary::aligned(Addr addr) const noexcept
{ {
if (addr & (sizeof(Cell) - sizeof(uint8_t))) auto unaligned = addr & (sizeof(Cell) - sizeof(uint8_t));
addr = (addr + sizeof(Cell)) & ~(sizeof(Cell) - sizeof(uint8_t)); if (unaligned)
addr += sizeof(Cell) - unaligned;
return addr; return addr;
} }

@ -54,19 +54,20 @@ ParseStatus Parser::parseWord(State& state, Word word)
{ {
int ins, imm; int ins, imm;
ins = CoreWords::findi(state, word); ins = state.dict.find(word);
if (ins < 0) {
ins = state.dict.find(word);
if (ins <= 0) { if (ins <= 0) {
ins = CoreWords::findi(state, word);
if (ins < 0) {
return parseNumber(state, word); return parseNumber(state, word);
} else { } else {
imm = state.dict.read(ins) & CoreWords::Immediate; imm = ins & CoreWords::Compiletime;
ins = state.dict.getexec(ins); ins &= ~CoreWords::Compiletime;
} }
} else { } else {
imm = ins & CoreWords::Compiletime; imm = state.dict.read(ins) & CoreWords::Immediate;
ins &= ~CoreWords::Compiletime; ins = state.dict.getexec(ins);
} }
if (state.dict.read(Dictionary::Postpone)) { if (state.dict.read(Dictionary::Postpone)) {

@ -21,13 +21,6 @@
#include <iterator> #include <iterator>
struct pop {};
struct push {};
struct popr {};
struct pushr {};
struct top {};
struct pick {};
bool State::compiling() const bool State::compiling() const
{ {
return dict.read(Dictionary::Compiling); return dict.read(Dictionary::Compiling);
@ -41,7 +34,6 @@ void State::compiling(bool yes)
void State::execute(Addr addr) void State::execute(Addr addr)
{ {
if (addr < CoreWords::WordCount) { if (addr < CoreWords::WordCount) {
// Must be a core-word
CoreWords::run(addr, *this); CoreWords::run(addr, *this);
} else { } else {
pushr(0); pushr(0);
@ -49,65 +41,11 @@ void State::execute(Addr addr)
do { do {
ip += sizeof(Cell); ip += sizeof(Cell);
CoreWords::run(dict.read(ip), *this);
const auto ins = dict.read(ip);
if (ins < CoreWords::WordCount) {
CoreWords::run(ins, *this);
} else {
pushr(ip);
ip = ins - sizeof(Cell);
}
} while (ip); } 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 std::size_t State::size() const noexcept
{ {
return std::distance(dstack, static_cast<const Cell *>(dsp)) + 1; return std::distance(dstack, static_cast<const Cell *>(dsp)) + 1;

@ -24,21 +24,20 @@
#include <cstddef> #include <cstddef>
constexpr unsigned DataStackSize = 12; constexpr unsigned DataStackSize = 8;
constexpr unsigned ReturnStackSize = 12; constexpr unsigned ReturnStackSize = 8;
class State struct State
{ {
Addr ip = 0;
Dictionary& dict;
void (*input)(State&);
Cell dstack[DataStackSize] = {}; Cell dstack[DataStackSize] = {};
Cell rstack[ReturnStackSize] = {}; Cell rstack[ReturnStackSize] = {};
Cell *dsp = dstack - 1; Cell *dsp = dstack - 1;
Cell *rsp = rstack - 1; Cell *rsp = rstack - 1;
public:
Addr ip = 0;
Dictionary& dict;
void (*input)(State&);
constexpr State(Dictionary& d, void (*i)(State&)): constexpr State(Dictionary& d, void (*i)(State&)):
dict(d), input(i) {} dict(d), input(i) {}
@ -47,19 +46,56 @@ public:
void execute(Addr); 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 size() const noexcept;
std::size_t rsize() 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 #endif // ALEEFORTH_STATE_HPP

Loading…
Cancel
Save