1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-12-26 03:58:05 +11:00

forth: make bin staging process a bit less hackish

The goal being to add a new native code dict staging phase.
This commit is contained in:
Virgil Dupras 2020-03-22 21:46:43 -04:00
parent ffe61a12f8
commit 5387e08437
4 changed files with 30 additions and 27 deletions

View File

@ -33,11 +33,11 @@ forth/forth0.bin: forth/glue0.asm $(ZASMBIN)
forth/forth0-bin.h: forth/forth0.bin forth/forth0-bin.h: forth/forth0.bin
./bin2c.sh KERNEL < forth/forth0.bin | tee $@ > /dev/null ./bin2c.sh KERNEL < forth/forth0.bin | tee $@ > /dev/null
forth/stage1: forth/stage1.c $(OBJS) forth/forth0-bin.h forth/stage1: forth/stage.c $(OBJS) forth/forth0-bin.h
$(CC) forth/stage1.c $(OBJS) -o $@ $(CC) forth/stage.c $(OBJS) -o $@
forth/stage1dbg: forth/stage1.c $(OBJS) forth/forth0-bin.h forth/stage1dbg: forth/stage.c $(OBJS) forth/forth0-bin.h
$(CC) -DDEBUG forth/stage1.c $(OBJS) -o $@ $(CC) -DDEBUG forth/stage.c $(OBJS) -o $@
forth/core.bin: $(FORTHSRC_PATHS) forth/stage1 forth/core.bin: $(FORTHSRC_PATHS) forth/stage1
cat $(FORTHSRC_PATHS) | ./forth/stage1 | tee $@ > /dev/null cat $(FORTHSRC_PATHS) | ./forth/stage1 | tee $@ > /dev/null

View File

@ -1,13 +1,4 @@
; RAM disposition
;
; Because this glue code also serves stage0 which needs HERE to start right
; after the code, we have a peculiar RAM setup here: it lives at the very end
; of the address space, just under RS_ADDR at 0xf000
; Warning: The offsets of native dict entries must be exactly the same between
; glue0.asm and glue1.asm
.equ RAMSTART 0xe800 .equ RAMSTART 0xe800
.equ HERE 0xe700 ; override, in sync with stage1.c
.equ CURRENT 0xe702 ; override, in sync with stage1.c
.equ HERE_INITIAL CODE_END ; override .equ HERE_INITIAL CODE_END ; override
.equ STDIO_PORT 0x00 .equ STDIO_PORT 0x00

View File

@ -4,20 +4,19 @@
#include "../emul.h" #include "../emul.h"
#include "forth0-bin.h" #include "forth0-bin.h"
/* Stage 1 /* Staging binaries
The role of the stage 1 executable is to start from a bare Forth executable The role of a stage executable is to compile definitions in a dictionary and
(stage 0) that will compile core non-native definitions into binary form and then spit the difference between the starting binary and the new binary.
append this to existing bootstrap binary to form our final Forth bin.
That binary can then be grafted to an exiting Forth binary to augment its
dictionary.
We could, if we wanted, run only with the bootstrap binary and compile core We could, if we wanted, run only with the bootstrap binary and compile core
defs at runtime, but that would mean that those defs live in RAM. In may system, defs at runtime, but that would mean that those defs live in RAM. In may system,
RAM is much more constrained than ROM, so it's worth it to give ourselves the RAM is much more constrained than ROM, so it's worth it to give ourselves the
trouble of compiling defs to binary. trouble of compiling defs to binary.
This stage 0 executable has to be layed out in a particular manner: HERE must
directly follow executable's last byte so that we don't waste spce and also
that wordref offsets correspond.
*/ */
// When DEBUG is set, stage1 is a core-less forth that works interactively. // When DEBUG is set, stage1 is a core-less forth that works interactively.
@ -28,13 +27,12 @@ that wordref offsets correspond.
// in sync with glue.asm // in sync with glue.asm
#define RAMSTART 0x900 #define RAMSTART 0x900
#define STDIO_PORT 0x00 #define STDIO_PORT 0x00
// In sync with glue code. This way, we can know where HERE was when we stopped // To know which part of RAM to dump, we listen to port 2, which at the end of
// running // its compilation process, spits its HERE addr to port 2 (MSB first)
#define HERE 0xe700 #define HERE_PORT 0x02
// We also need to know what CURRENT is so we can write our first two bytes
#define CURRENT 0xe702
static int running; static int running;
static uint16_t ending_here = 0;
static uint8_t iord_stdio() static uint8_t iord_stdio()
{ {
@ -54,12 +52,19 @@ static void iowr_stdio(uint8_t val)
#endif #endif
} }
static void iowr_here(uint8_t val)
{
ending_here <<= 8;
ending_here |= val;
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
Machine *m = emul_init(); Machine *m = emul_init();
m->ramstart = RAMSTART; m->ramstart = RAMSTART;
m->iord[STDIO_PORT] = iord_stdio; m->iord[STDIO_PORT] = iord_stdio;
m->iowr[STDIO_PORT] = iowr_stdio; m->iowr[STDIO_PORT] = iowr_stdio;
m->iowr[HERE_PORT] = iowr_here;
// initialize memory // initialize memory
for (int i=0; i<sizeof(KERNEL); i++) { for (int i=0; i<sizeof(KERNEL); i++) {
m->mem[i] = KERNEL[i]; m->mem[i] = KERNEL[i];
@ -71,8 +76,8 @@ int main(int argc, char *argv[])
#ifndef DEBUG #ifndef DEBUG
// We're done, now let's spit dict data // We're done, now let's spit dict data
uint16_t here = m->mem[HERE] + (m->mem[HERE+1] << 8); fprintf(stderr, "hey, %x\n", ending_here);
for (int i=sizeof(KERNEL); i<here; i++) { for (int i=sizeof(KERNEL); i<ending_here; i++) {
putchar(m->mem[i]); putchar(m->mem[i]);
} }
#endif #endif

View File

@ -2,3 +2,10 @@
the end of it so that Forth knows how to hook LATEST into the end of it so that Forth knows how to hook LATEST into
it ) it )
WORD _______ (entry) WORD _______ (entry)
( After each dummy word like this, we poke IO port 2 with our
current HERE value. The staging executable needs it to know
what to dump. )
HERE @ 256 / 2 PC!
HERE @ 2 PC!