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

Compare commits

...

3 Commits

Author SHA1 Message Date
Virgil Dupras
3a08fa7e74 forth: add a stable ABI 2020-03-24 23:02:06 -04:00
Virgil Dupras
f0ab57c8cc forth: Forth-ify "AND" 2020-03-24 22:09:52 -04:00
Virgil Dupras
6c5f39806b forth: improve bootstrap process 2020-03-24 21:13:02 -04:00
11 changed files with 76 additions and 87 deletions

View File

@ -27,8 +27,10 @@ shell/shell-bin.h: shell/shell.bin
shell/shell: shell/shell.c $(SHELLOBJS) shell/shell-bin.h
$(CC) shell/shell.c $(SHELLOBJS) -o $@
# z80c.bin is not in the prerequisites because its a bootstrap binary that
# should be updated manually through make fbootstrap.
forth/forth0.bin: forth/stage0.asm $(ZASMBIN)
$(ZASMBIN) $(KERNEL) ../forth forth/stagec.asm < forth/stage0.asm | tee $@ > /dev/null
$(ZASMBIN) $(KERNEL) ../forth forth/z80c.bin forth/stagec.asm < forth/stage0.asm | tee $@ > /dev/null
forth/forth0-bin.h: forth/forth0.bin
./bin2c.sh KERNEL < forth/forth0.bin | tee $@ > /dev/null
@ -39,10 +41,11 @@ forth/stage1: forth/stage.c $(OBJS) forth/forth0-bin.h
forth/stage1dbg: forth/stage.c $(OBJS) forth/forth0-bin.h
$(CC) -DDEBUG forth/stage.c $(OBJS) -o $@
# z80c.bin is not in the prerequisites because its a bootstrap binary that
# should be updated manually through make fbootstrap.
forth/forth1.bin: forth/stage1.asm forth/forth0.bin $(ZASMBIN)
$(ZASMBIN) $(KERNEL) ../forth forth/z80c.bin forth/stagec.asm < forth/stage1.asm | tee $@ > /dev/null
forth/core.bin: $(FORTHSRC_PATHS) forth/stage1
cat $(FORTHSRC_PATHS) | ./forth/stage1 | tee $@ > /dev/null
forth/forth1.bin: forth/stage1.asm forth/forth0.bin forth/core.bin $(ZASMBIN)
$(ZASMBIN) $(KERNEL) ../forth forth/z80c.bin forth/core.bin forth/stagec.asm < forth/stage1.asm | tee $@ > /dev/null
forth/forth1-bin.h: forth/forth1.bin
./bin2c.sh KERNEL < forth/forth1.bin | tee $@ > /dev/null
@ -50,19 +53,7 @@ forth/forth1-bin.h: forth/forth1.bin
forth/stage2: forth/stage.c $(OBJS) forth/forth1-bin.h
$(CC) -DSTAGE2 forth/stage.c $(OBJS) -o $@
forth/stage2dbg: forth/stage.c $(OBJS) forth/forth1-bin.h
$(CC) -DSTAGE2 -DDEBUG forth/stage.c $(OBJS) -o $@
forth/core.bin: $(FORTHSRC_PATHS) forth/stage2
cat $(FORTHSRC_PATHS) | ./forth/stage2 | tee $@ > /dev/null
forth/forth2.bin: forth/stage2.asm forth/core.bin $(ZASMBIN)
$(ZASMBIN) $(KERNEL) ../forth forth/core.bin forth/z80c.bin forth/stagec.asm < forth/stage2.asm | tee $@ > /dev/null
forth/forth2-bin.h: forth/forth2.bin
./bin2c.sh KERNEL < forth/forth2.bin | tee $@ > /dev/null
forth/forth: forth/forth.c $(OBJS) forth/forth2-bin.h
forth/forth: forth/forth.c $(OBJS) forth/forth1-bin.h
$(CC) forth/forth.c $(OBJS) -o $@
zasm/kernel-bin.h: zasm/kernel.bin
@ -108,9 +99,11 @@ updatebootstrap: $(ZASMBIN)
$(ZASMBIN) $(KERNEL) < zasm/glue.asm > zasm/kernel.bin
$(ZASMBIN) $(KERNEL) $(APPS) zasm/user.h < $(APPS)/zasm/glue.asm > zasm/zasm.bin
# We need to double wrap around dummy.fs because at stage3, we have high-level
# words and they write to HERE at initialization.
.PHONY: fbootstrap
fbootstrap: forth/stage1
cat $(FORTHSRC_PATHS) ../forth/z80c.fs ../forth/dummy.fs | ./forth/stage1 | tee forth/z80c.bin > /dev/null
fbootstrap: forth/stage2
cat ../forth/dummy.fs ../forth/z80c.fs ../forth/dummy.fs | ./forth/stage2 | tee forth/z80c.bin > /dev/null
.PHONY: clean
clean:

View File

@ -90,28 +90,26 @@ Because of that aim, it currently builds in a particular manner.
There are 3 build stages.
**Stage 0**: This stage is created with zasm by assembling `forth/forth.asm`
through `stage0.asm`. This yields `forth0.bin`. We then wrap this binary with
`stage.c` to create the `stage1` binary, which allows us to get to the next
stage.
and `z80c.bin` through `stage0.asm`. This yields `forth0.bin`. We then wrap
this binary with `stage.c` to create the `stage1` binary, which allows us to
get to the next stage.
The long term goal is to gradually extract contents from `forth.asm` and have
nothing but Forth source files.
`z80c.bin` is a "chicken-and-egg" typf of binary that is committed in the repo.
It is the result of compiling `z80c.fs`, but this needs stage2.
**Stage 1**: The `stage1` binary allows us to augment `forth0.bin` with
contents from `z80c.fs`, which compiles native words using Forth's Z80
assembler. This yields `z80c.bin`.
the compiled dictionary of a full Forth interpreter. We feed it with
`$(FORTHSRCS)` and then dump the resulting compiled dict.
This is where there's a chiken-and-egg issue: Forth's assembler needs our full
Forth interpreter, but that interpreter needs native words from `z80c.fs`. This
is why `z80c.bin` is committed into the git repo and it's built automatically
with `make`. Updating `z80c.bin` is a specific make rule, `fbootstrap`.
From there, we can create `forth1.bin`, which is wrapped by both the `forth`
and `stage2` executables. `forth` is the interpreter you'll use.
Then, from there, we augment `forth0.bin` with `z80c.bin` and yield
`forth1.bin`, from which we create `stage2`.
**Stage 2**: `stage2` is used to resolve the chicken-and-egg problem and use
the power of a full Forth intepreter, including an assembler, to assemble
`z80c.bin`. This is a manual step executed through `make fbootstrap`.
**Stage 2**: From there, the way is clear to compile the dict of our full Forth
interpreter, which we do using `stage2` and produce `forth2.bin`, from which we
can create our final `forth` executable.
Normally, running this step should yield the exact same `z80c.bin` as before,
unless of course you've changed the source.
## Problems?

View File

@ -3,7 +3,7 @@
#include <unistd.h>
#include <termios.h>
#include "../emul.h"
#include "forth2-bin.h"
#include "forth1-bin.h"
// in sync with glue.asm
#define RAMSTART 0x900

View File

@ -3,5 +3,5 @@
.inc "stagec.asm"
.inc "forth.asm"
.bin "z80c.bin"
CODE_END:
.out $ ; should be the same as in stage{1,2}

View File

@ -3,6 +3,6 @@
.inc "stagec.asm"
.inc "forth.asm"
.out $ ; should be the same as in stage{0,2}
.bin "z80c.bin"
.bin "core.bin"
CODE_END:

View File

@ -1,10 +0,0 @@
jp init
.inc "stagec.asm"
.inc "forth.asm"
.out $ ; should be the same as in stage{0,1}
.bin "z80c.bin"
.bin "core.bin"
CODE_END:

Binary file not shown.

View File

@ -55,7 +55,7 @@ LITN n -- Write number n as a literal.
[LITN] n -- *I* Immediate version of LITN.
ROUTINE x -- a Push the addr of the specified core routine
C=cellWord L=compiledWord V=nativeWord N=next S=LIT
N=NUMBER Y=sysvarWord D=doesWord
M=NUMBER Y=sysvarWord D=doesWord
VARIABLE c -- Creates cell x with 2 bytes allocation.
Compilation vs meta-compilation. When you compile a word with "[COMPILE] foo",

View File

@ -108,6 +108,14 @@
; At the end of every compiledWord is an EXIT. This pops RS, sets IP to it, and
; continues.
; *** Stable ABI ***
; Those jumps below are supposed to stay at these offsets, always. If they
; change bootstrap binaries have to be adjusted because they rely on them.
.fill 0x1a-$
JUMPTBL:
jp next
jp chkPS
; *** Code ***
forthMain:
; STACK OVERFLOW PROTECTION:
@ -166,28 +174,23 @@ INTERPRET:
.dw FIND_
.dw CSKIP
.dw FBR
.db 32
.db 18
; It's a word, execute it
.dw FLAGS_
.dw FETCH
; For now, we only have one flag, let's take advantage of
; this to keep code simple.
.dw ONE ; Bit 0 on
.dw OR
.dw FLAGS_
.dw STORE
.dw EXECUTE
.dw FLAGS_
.dw FETCH
.dw NUMBER
.dw 0xfffe ; Bit 0 off
.dw AND
.dw ZERO ; Bit 0 off
.dw FLAGS_
.dw STORE
.dw BBR
.db 39
.db 25
; FBR mark, try number
.dw PARSEI
.dw BBR
.db 44
.db 30
; infinite loop
; *** Collapse OS lib copy ***
@ -814,7 +817,7 @@ ROUTINE:
ld de, nativeWord
cp 'V'
jr z, .end
ld de, next
ld de, JUMPTBL
cp 'N'
jr z, .end
ld de, sysvarWord
@ -827,9 +830,9 @@ ROUTINE:
cp 'S'
jr z, .end
ld de, NUMBER
cp 'N'
cp 'M'
jr z, .end
ld de, chkPS
ld de, JUMPTBL+3
cp 'P'
jr nz, .notgood
; continue to end on match
@ -1559,27 +1562,9 @@ DIVMOD:
jp next
.db "AND"
.fill 4
.dw $-DIVMOD
.db 0
AND:
.dw nativeWord
pop hl
pop de
call chkPS
ld a, e
and l
ld l, a
ld a, d
and h
ld h, a
push hl
jp next
.db "OR"
.fill 5
.dw $-AND
.dw $-DIVMOD
.db 0
OR:
.dw nativeWord
@ -1764,4 +1749,3 @@ BBR:
.db "_______"
.dw $-BBR
.db 0
LATEST:

View File

@ -45,6 +45,15 @@
0x46 OP1r LDr(HL),
0x70 OP1r LD(HL)r,
( r -- )
: OP1r0
CREATE C,
DOES>
C@ ( r op )
OR A,
;
0xa0 OP1r0 ANDr,
( qq -- also works for ss )
: OP1qq
CREATE C,
@ -138,3 +147,6 @@
: ;CODE JPNEXT, ;
( Routines )
: chkPS, ROUTINE P [LITN] CALLnn, ;

View File

@ -34,7 +34,7 @@ CODE ROT
CODE 2DUP
HL POPqq, ( B )
DE POPqq, ( A )
ROUTINE P CALLnn,
chkPS,
DE PUSHqq, ( A )
HL PUSHqq, ( B )
DE PUSHqq, ( A )
@ -48,7 +48,7 @@ CODE 2OVER
DE POPqq, ( C )
BC POPqq, ( B )
IY POPqq, ( A )
ROUTINE P CALLnn,
chkPS,
IY PUSHqq, ( A )
BC PUSHqq, ( B )
DE PUSHqq, ( C )
@ -64,10 +64,22 @@ CODE 2SWAP
DE POPqq, ( C )
BC POPqq, ( B )
IY POPqq, ( A )
ROUTINE P CALLnn,
chkPS,
DE PUSHqq, ( C )
HL PUSHqq, ( D )
IY PUSHqq, ( A )
BC PUSHqq, ( B )
;CODE
CODE AND
HL POPqq,
DE POPqq,
chkPS,
A E LDrr,
L ANDr,
L A LDrr,
A D LDrr,
H ANDr,
H A LDrr,
HL PUSHqq,
;CODE