diff --git a/emul/Makefile b/emul/Makefile index 2229452..b6ee35a 100644 --- a/emul/Makefile +++ b/emul/Makefile @@ -103,7 +103,7 @@ updatebootstrap: $(ZASMBIN) # words and they write to HERE at initialization. .PHONY: fbootstrap fbootstrap: forth/stage2 - cat ../forth/dummy.fs ../forth/z80c.fs forth/emul.fs ../forth/dummy.fs | ./forth/stage2 | tee forth/z80c.bin > /dev/null + cat ../forth/dummy.fs ../forth/z80c.fs forth/emul.fs ../forth/icore.fs ../forth/dummy.fs | ./forth/stage2 | tee forth/z80c.bin > /dev/null .PHONY: clean clean: diff --git a/emul/forth/z80c.bin b/emul/forth/z80c.bin index f9c2830..50e7d95 100644 Binary files a/emul/forth/z80c.bin and b/emul/forth/z80c.bin differ diff --git a/forth/forth.asm b/forth/forth.asm index ae2381a..9161f2e 100644 --- a/forth/forth.asm +++ b/forth/forth.asm @@ -10,6 +10,14 @@ ; self-hosts in a more compact manner. File include is a big part of the ; complexity in zasm. If we can get rid of it, we'll be more compact. +; *** ABI STABILITY *** +; +; This unit needs to have some of its entry points stay at a stable offset. +; These have a comment over them indicating the expected offset. These should +; not move until the Grand Bootstrapping operation has been completed. +; +; When you see random ".fill" here and there, it's to ensure that stability. + ; *** Defines *** ; GETC: address of a GetC routine ; PUTC: address of a PutC routine @@ -110,6 +118,10 @@ JUMPTBL: jp nativeWord jp next jp chkPS +NUMBER: + .dw numberWord +LIT: + .dw litWord ; *** Code *** forthMain: @@ -175,31 +187,13 @@ BEGIN: INTERPRET: .dw compiledWord - ; BBR mark - .dw WORD + .dw LIT + .db "INTERPRET", 0 .dw FIND_ - .dw CSKIP - .dw FBR - .db 22 - ; It's a word, execute it - ; For now, we only have one flag, let's take advantage of - ; this to keep code simple. - .dw NUMBER ; Bit 0 on - .dw 1 - .dw FLAGS_ - .dw STORE + .dw DROP .dw EXECUTE - .dw NUMBER ; Bit 0 off - .dw 0 - .dw FLAGS_ - .dw STORE - .dw BBR - .db 29 - ; FBR mark, try number - .dw PARSEI - .dw BBR - .db 34 - ; infinite loop + +.fill 31 ; *** Collapse OS lib copy *** ; In the process of Forth-ifying Collapse OS, apps will be slowly rewritten to @@ -625,9 +619,6 @@ numberWord: push de jp next -NUMBER: - .dw numberWord - ; Similarly to numberWord, this is not a real word, but a string literal. ; Instead of being followed by a 2 bytes number, it's followed by a ; null-terminated string. When called, puts the string's address on PS @@ -639,9 +630,6 @@ litWord: ld (IP), hl jp next -LIT: - .dw litWord - ; Pop previous IP from Return stack and execute it. ; ( R:I -- ) .db "EXIT" @@ -835,6 +823,9 @@ ROUTINE: .db "EXECUTE" .dw $-ROUTINE .db 7 +; STABLE ABI +; Offset: 0388 +.out $ EXECUTE: .dw nativeWord pop iy ; is a wordref @@ -983,6 +974,9 @@ SCPY: .db "(find)" .dw $-SCPY .db 6 +; STABLE ABI +; Offset: 047c +.out $ FIND_: .dw nativeWord pop hl @@ -1070,6 +1064,9 @@ TOWORD: .db "WORD" .dw $-TOWORD .db 4 +; STABLE ABI +; Offset: 04f7 +.out $ WORD: .dw compiledWord .dw NUMBER ; ( a ) @@ -1202,6 +1199,9 @@ ENTRYHEAD: jp next +; STABLE ABI (every sysvars) +; Offset: 05ca +.out $ .db "HERE" .dw $-ENTRYHEAD .db 4 @@ -1241,6 +1241,9 @@ SYSVNXT_: .db "!" .dw $-SYSVNXT_ .db 1 +; STABLE ABI +; Offset: 0610 +.out $ STORE: .dw nativeWord pop iy @@ -1390,6 +1393,9 @@ CMP: .db "SKIP?" .dw $-CMP .db 5 +; STABLE ABI +; Offset: 06ee +.out $ CSKIP: .dw nativeWord pop hl @@ -1447,6 +1453,9 @@ CSKIP: .db "(fbr)" .dw $-CSKIP .db 5 +; STABLE ABI +; Offset: 073e +.out $ FBR: .dw nativeWord push de @@ -1460,6 +1469,9 @@ FBR: .db "(bbr)" .dw $-FBR .db 5 +; STABLE ABI +; Offset: 0757 +.out $ BBR: .dw nativeWord ld hl, (IP) diff --git a/forth/icore.fs b/forth/icore.fs new file mode 100644 index 0000000..56b621e --- /dev/null +++ b/forth/icore.fs @@ -0,0 +1,34 @@ +( Inner core. This unit represents core definitions that + happen right after native definitions. Before core.fs. + + Unlike core.fs and its followers, this unit isn't self- + sustained. Like native defs it uses the machinery of a + full Forth interpreter, notably for flow structures. + + Because of that, it has to obey specific rules: + + 1. It cannot compile a word from higher layers. Using + immediates is fine though. + 2. If it references a word from this unit or from native + definitions, these need to be properly offsetted + because their offset at compile time are not the same + as their runtime offsets. + 3. Anything they refer to in the boot binary has to be + properly stabilized. + 4. Make sure that the words you compile are not overridden + by the full interpreter. +) + +: INTERPRET + BEGIN + WORD + (find) + IF + 1 FLAGS ! + EXECUTE + 0 FLAGS ! + ELSE + (parse*) @ EXECUTE + THEN + AGAIN +;