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: $(EXEFILE)
fast: CXXFLAGS += -O3 -march=native -mtune=native
fast: $(EXEFILE)
$(EXEFILE): $(LIBFILE)
$(LIBFILE): $(OBJFILES)

@ -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 | ;

@ -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);
}

@ -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

@ -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;
}

@ -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)) {

@ -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;

@ -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

Loading…
Cancel
Save