You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
3.5 KiB
C
106 lines
3.5 KiB
C
// foci - minimal forth implementation
|
|
// Copyright (C) 2025 Clyne Sullivan <clyne@bitgloo.com>
|
|
//
|
|
// 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 <http://www.gnu.org/licenses/>.
|
|
|
|
#ifndef FOCI_H
|
|
#define FOCI_H
|
|
|
|
#include <stdint.h>
|
|
|
|
#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 * const name##_body[]; \
|
|
const struct word_t w_##name = { \
|
|
name##_body, prev, attr + sizeof(tname) - 1, tname \
|
|
}; \
|
|
const void * const name##_body[] = {
|
|
#define LIT(x) push, (void *)(x)
|
|
#define FTH(w) enter, (w##_body)
|
|
#define END fexit, };
|
|
#define NATIVE(name, tname, prev, attr) \
|
|
const void * const name##_body[2]; \
|
|
NAKED void name(void); \
|
|
const struct word_t w_##name = { \
|
|
name##_body, prev, \
|
|
(attr | ATTR_NATIVE) + sizeof(tname) - 1, tname \
|
|
}; \
|
|
const void * const name##_body[2] = { 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)
|
|
|
|
struct word_t
|
|
{
|
|
const void * const *body;
|
|
const struct word_t *prev;
|
|
unsigned char attr;
|
|
char name[];
|
|
} __attribute__ ((packed));
|
|
|
|
#ifdef FOCI_ARM
|
|
register intptr_t * sp asm("r4"); // pointer to stack cells
|
|
register intptr_t *** rp asm("r5"); // stack of pp
|
|
register intptr_t ** pp asm("r6"); // pointer to ip
|
|
register intptr_t tmp asm("r7");
|
|
#define STASH asm("push {r4-r7}")
|
|
#define RESTORE asm("pop {r4-r7}")
|
|
#define NEXT goto *(*++pp)
|
|
#endif // FOCI_ARM
|
|
|
|
#ifdef FOCI_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")
|
|
#define NEXT goto *(*++pp)
|
|
#endif // FOCI_X86_64
|
|
|
|
#ifdef FOCI_MSP430
|
|
register intptr_t * sp asm("r4"); // pointer to stack cells
|
|
register intptr_t *** rp asm("r5"); // stack of pp
|
|
register intptr_t ** pp asm("r6"); // pointer to ip
|
|
register intptr_t tmp asm("r7");
|
|
#define STASH asm("push r4\npush r5\npush r6")
|
|
#define RESTORE asm("pop r6\npop r5\npop r4")
|
|
#define NEXT asm("incd r6\nbr @r6")
|
|
#endif // FOCI_MSP430
|
|
|
|
extern const struct word_t w_immediate;
|
|
#define LATEST_INIT &w_immediate
|
|
|
|
extern void foci_putchar(int);
|
|
extern int foci_getchar(void);
|
|
|
|
void init(intptr_t *dictmem);
|
|
int foci_depth(void);
|
|
int compiling(void);
|
|
void interpret(void);
|
|
void define(const struct word_t *w);
|
|
|
|
void fexit(void); // internal use only
|
|
|
|
#endif // FOCI_H
|
|
|