// foci - minimal forth implementation // Copyright (C) 2025 Clyne Sullivan // // This program is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation, either version 3 of the License, or (at your option) // any later version. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details. // // You should have received a copy of the GNU General Public License along with // this program. If not, see . #ifndef FOCI_H #define FOCI_H #include #define NAKED __attribute__((naked)) #define ATTR_NATIVE (1 << 7) #define ATTR_IMMEDIATE (1 << 6) #define ATTR_LEN (0x3F) #define WORD(name, tname, prev, attr) \ extern const void *name##_body[]; \ struct word_t w_##name = { \ name##_body, prev, attr + sizeof(tname) - 1, tname \ }; \ const void *name##_body[] = { #define LIT(x) push, (void *)(x) #define FTH(w) enter, (w##_body) #define END fexit, }; #define NATIVE(name, tname, prev, attr) \ extern const void *name##_body[]; \ NAKED void name(void); \ struct word_t w_##name = { \ name##_body, prev, \ (attr | ATTR_NATIVE) + sizeof(tname) - 1, tname \ }; \ const void *name##_body[] = { name, fexit }; \ NAKED void name(void) #define W(name, tname, prev) WORD(name, tname, prev, 0) #define I(name, tname, prev) WORD(name, tname, prev, ATTR_IMMEDIATE) #define N(name, tname, prev) NATIVE(name, tname, prev, 0) #define C(name, tname, prev) NATIVE(name, tname, prev, ATTR_IMMEDIATE) #define NEXT { goto *(*++pp); } struct word_t { const void **body; struct word_t *prev; unsigned char attr; char name[]; } __attribute__ ((packed)); // ARM Cortex-M: //register intptr_t * sp asm("r0"); // pointer to stack cells //register intptr_t *** rp asm("r1"); // stack of pp //register intptr_t ** pp asm("r2"); // pointer to ip //register intptr_t tmp asm("r8"); //#define STASH asm("push {r0-r2,r8}") //#define RESTORE asm("pop {r0-r2,r8}") // x86_64 register intptr_t * sp asm("r12"); // pointer to stack cells register intptr_t *** rp asm("r13"); // stack of pp register intptr_t ** pp asm("r14"); // pointer to ip register intptr_t tmp asm("r15"); #define STASH asm("push %r12; push %r13; push %r14") #define RESTORE asm("pop %r14; pop %r13; pop %r12") extern void foci_putchar(int); extern int foci_getchar(void); void init(void); int depth(void); int compiling(void); void parse_word(const char *buf, const char *s); void define(struct word_t *w); void fexit(void); // internal use only #endif // FOCI_H