1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-26 10:38:07 +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 shell/shell: shell/shell.c $(SHELLOBJS) shell/shell-bin.h
$(CC) shell/shell.c $(SHELLOBJS) -o $@ $(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) 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 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
@ -39,10 +41,11 @@ forth/stage1: forth/stage.c $(OBJS) forth/forth0-bin.h
forth/stage1dbg: 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 $@ $(CC) -DDEBUG forth/stage.c $(OBJS) -o $@
# z80c.bin is not in the prerequisites because its a bootstrap binary that forth/core.bin: $(FORTHSRC_PATHS) forth/stage1
# should be updated manually through make fbootstrap. cat $(FORTHSRC_PATHS) | ./forth/stage1 | tee $@ > /dev/null
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/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 forth/forth1-bin.h: forth/forth1.bin
./bin2c.sh KERNEL < forth/forth1.bin | tee $@ > /dev/null ./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 forth/stage2: forth/stage.c $(OBJS) forth/forth1-bin.h
$(CC) -DSTAGE2 forth/stage.c $(OBJS) -o $@ $(CC) -DSTAGE2 forth/stage.c $(OBJS) -o $@
forth/stage2dbg: forth/stage.c $(OBJS) forth/forth1-bin.h forth/forth: forth/forth.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
$(CC) forth/forth.c $(OBJS) -o $@ $(CC) forth/forth.c $(OBJS) -o $@
zasm/kernel-bin.h: zasm/kernel.bin zasm/kernel-bin.h: zasm/kernel.bin
@ -108,9 +99,11 @@ updatebootstrap: $(ZASMBIN)
$(ZASMBIN) $(KERNEL) < zasm/glue.asm > zasm/kernel.bin $(ZASMBIN) $(KERNEL) < zasm/glue.asm > zasm/kernel.bin
$(ZASMBIN) $(KERNEL) $(APPS) zasm/user.h < $(APPS)/zasm/glue.asm > zasm/zasm.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 .PHONY: fbootstrap
fbootstrap: forth/stage1 fbootstrap: forth/stage2
cat $(FORTHSRC_PATHS) ../forth/z80c.fs ../forth/dummy.fs | ./forth/stage1 | tee forth/z80c.bin > /dev/null cat ../forth/dummy.fs ../forth/z80c.fs ../forth/dummy.fs | ./forth/stage2 | tee forth/z80c.bin > /dev/null
.PHONY: clean .PHONY: clean
clean: clean:

View File

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

View File

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

View File

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

View File

@ -3,6 +3,6 @@
.inc "stagec.asm" .inc "stagec.asm"
.inc "forth.asm" .inc "forth.asm"
.out $ ; should be the same as in stage{0,2}
.bin "z80c.bin" .bin "z80c.bin"
.bin "core.bin"
CODE_END: 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. [LITN] n -- *I* Immediate version of LITN.
ROUTINE x -- a Push the addr of the specified core routine ROUTINE x -- a Push the addr of the specified core routine
C=cellWord L=compiledWord V=nativeWord N=next S=LIT 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. VARIABLE c -- Creates cell x with 2 bytes allocation.
Compilation vs meta-compilation. When you compile a word with "[COMPILE] foo", 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 ; At the end of every compiledWord is an EXIT. This pops RS, sets IP to it, and
; continues. ; 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 *** ; *** Code ***
forthMain: forthMain:
; STACK OVERFLOW PROTECTION: ; STACK OVERFLOW PROTECTION:
@ -166,28 +174,23 @@ INTERPRET:
.dw FIND_ .dw FIND_
.dw CSKIP .dw CSKIP
.dw FBR .dw FBR
.db 32 .db 18
; It's a word, execute it ; It's a word, execute it
.dw FLAGS_ ; For now, we only have one flag, let's take advantage of
.dw FETCH ; this to keep code simple.
.dw ONE ; Bit 0 on .dw ONE ; Bit 0 on
.dw OR
.dw FLAGS_ .dw FLAGS_
.dw STORE .dw STORE
.dw EXECUTE .dw EXECUTE
.dw FLAGS_ .dw ZERO ; Bit 0 off
.dw FETCH
.dw NUMBER
.dw 0xfffe ; Bit 0 off
.dw AND
.dw FLAGS_ .dw FLAGS_
.dw STORE .dw STORE
.dw BBR .dw BBR
.db 39 .db 25
; FBR mark, try number ; FBR mark, try number
.dw PARSEI .dw PARSEI
.dw BBR .dw BBR
.db 44 .db 30
; infinite loop ; infinite loop
; *** Collapse OS lib copy *** ; *** Collapse OS lib copy ***
@ -814,7 +817,7 @@ ROUTINE:
ld de, nativeWord ld de, nativeWord
cp 'V' cp 'V'
jr z, .end jr z, .end
ld de, next ld de, JUMPTBL
cp 'N' cp 'N'
jr z, .end jr z, .end
ld de, sysvarWord ld de, sysvarWord
@ -827,9 +830,9 @@ ROUTINE:
cp 'S' cp 'S'
jr z, .end jr z, .end
ld de, NUMBER ld de, NUMBER
cp 'N' cp 'M'
jr z, .end jr z, .end
ld de, chkPS ld de, JUMPTBL+3
cp 'P' cp 'P'
jr nz, .notgood jr nz, .notgood
; continue to end on match ; continue to end on match
@ -1559,27 +1562,9 @@ DIVMOD:
jp next 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" .db "OR"
.fill 5 .fill 5
.dw $-AND .dw $-DIVMOD
.db 0 .db 0
OR: OR:
.dw nativeWord .dw nativeWord
@ -1764,4 +1749,3 @@ BBR:
.db "_______" .db "_______"
.dw $-BBR .dw $-BBR
.db 0 .db 0
LATEST:

View File

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

View File

@ -34,7 +34,7 @@ CODE ROT
CODE 2DUP CODE 2DUP
HL POPqq, ( B ) HL POPqq, ( B )
DE POPqq, ( A ) DE POPqq, ( A )
ROUTINE P CALLnn, chkPS,
DE PUSHqq, ( A ) DE PUSHqq, ( A )
HL PUSHqq, ( B ) HL PUSHqq, ( B )
DE PUSHqq, ( A ) DE PUSHqq, ( A )
@ -48,7 +48,7 @@ CODE 2OVER
DE POPqq, ( C ) DE POPqq, ( C )
BC POPqq, ( B ) BC POPqq, ( B )
IY POPqq, ( A ) IY POPqq, ( A )
ROUTINE P CALLnn, chkPS,
IY PUSHqq, ( A ) IY PUSHqq, ( A )
BC PUSHqq, ( B ) BC PUSHqq, ( B )
DE PUSHqq, ( C ) DE PUSHqq, ( C )
@ -64,10 +64,22 @@ CODE 2SWAP
DE POPqq, ( C ) DE POPqq, ( C )
BC POPqq, ( B ) BC POPqq, ( B )
IY POPqq, ( A ) IY POPqq, ( A )
ROUTINE P CALLnn, chkPS,
DE PUSHqq, ( C ) DE PUSHqq, ( C )
HL PUSHqq, ( D ) HL PUSHqq, ( D )
IY PUSHqq, ( A ) IY PUSHqq, ( A )
BC PUSHqq, ( B ) BC PUSHqq, ( B )
;CODE ;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