From d3046d56b9830bc924ca6a0e529ff0dbe7167614 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Tue, 28 Jan 2025 07:40:23 -0500 Subject: [PATCH] add do loop, immediate; branchless fexit --- README.md | 4 ++-- foci.c | 29 +++++++++++++++++++++++++++-- foci.h | 1 + 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 721d29f..91d2a9d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Register usage is the only platform-specific requirement; otherwise, `foci` is written in 100% portable C. There is active support for x86\_64, ARM Cortex-M, and MSP430 architectures. -`foci` compiles to a binary object that can easily be linked into another application. Code size is generally a few kilobytes, while RAM usage is primarily set by the size of `foci`'s two stacks and dictionary. +`foci` compiles to a binary object that can easily be linked into another application. Code size is less than 5 kB, while RAM usage is in the hundreds of bytes (primarily influenced by the configured stack and dictionary sizes). ## Available words @@ -12,7 +12,7 @@ Register usage is the only platform-specific requirement; otherwise, `foci` is w dup drop swap rot -rot over tuck @ ! c@ c! + +! - * / mod and or xor = < [ ] , cell cell+ cells base here allot latest negate invert 1- 1+ aligned align : ; literal if then else ' ['] execute decimal hex . emit begin until again while -repeat >r r> 2>r 2r> +repeat >r r> 2>r 2r> r@ do loop i immediate ``` ## Build instructions diff --git a/foci.c b/foci.c index 2488c9c..fdf7d76 100644 --- a/foci.c +++ b/foci.c @@ -32,7 +32,10 @@ static intptr_t ***saved_rp; NAKED void enter(void) { *--rp = ++pp; pp = (intptr_t **)*pp; goto *(*pp); } NAKED void push(void) { *--sp = (intptr_t)*++pp; NEXT; } - void fexit(void) { if (rp < END_OF(rstack)) { pp = *rp++; NEXT; } } +NAKED void fexit(void) { pp = *rp++; NEXT; } + +void fend(void) {} +static const void * const fend_b[2] = { 0, fend }; NAKED void compname(void) { @@ -161,7 +164,23 @@ N(pushr2, "2>r", &w_popr) { *--rp = (intptr_t **)sp[1]; *--rp = (intptr_t **)sp[0]; sp += 2; NEXT; } N(popr2, "2r>", &w_pushr2) { *--sp = (intptr_t)rp[1]; *--sp = (intptr_t)rp[0]; rp += 2; NEXT; } -#define LATEST_INIT &w_popr2 +N(rpeek, "r@", &w_popr2) { *--sp = (intptr_t)*rp; NEXT; } +N(i, "i", &w_rpeek) { *--sp = (intptr_t)*rp; NEXT; } +I(fdo, "do", &w_i) LIT(pushr2), comma, FTH(begin), END +I(loop, "loop", &w_fdo) LIT(popr), comma, + LIT(enter), comma, + LIT(inc_body), comma, + LIT(rpeek), comma, + LIT(over), comma, + LIT(eq), comma, + LIT(swap), comma, + LIT(pushr), comma, + FTH(until), + LIT(popr2), comma, + LIT(drop), comma, LIT(drop), comma, END +W(immediate, "immediate", &w_loop) FTH(latest), LIT(2 * sizeof(intptr_t)), add, + LIT(ATTR_IMMEDIATE), over, cpeek, or, swap, cpoke, END +#define LATEST_INIT &w_immediate void enter_forth(const void *ptr) { @@ -170,6 +189,7 @@ void enter_forth(const void *ptr) rp = saved_rp; pp = ptr; + *--rp = (intptr_t **)fend_b; ((void (*)())*pp)(); saved_sp = sp; @@ -303,6 +323,11 @@ int depth(void) return END_OF(dstack) - saved_sp; } +int rdepth(void) +{ + return END_OF(rstack) - saved_rp; +} + int compiling(void) { return STATE; diff --git a/foci.h b/foci.h index b666b96..aae4946 100644 --- a/foci.h +++ b/foci.h @@ -92,6 +92,7 @@ extern int foci_getchar(void); void init(intptr_t *dictmem); int depth(void); +int rdepth(void); int compiling(void); void interpret(void); void define(struct word_t *w);