From df227c795a94b62c6788ee8c09630e8e8d065f75 Mon Sep 17 00:00:00 2001 From: Nick Downing Date: Fri, 22 Apr 2022 13:40:34 +1000 Subject: [PATCH 1/9] Add .gitignore, rationalize make clean, remove a gforth warning in tokenizer --- .gitignore | 9 +++++++++ preForth/Makefile | 2 +- preForth/seedForth-tokenizer.fs | 6 +++--- 3 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7e0a06e --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +*.Darwin +*.Linux +*.asm +*.o +*.seed +/preForth/preForthdemo +/preForth/preForth +/preForth/forth +/preForth/seedForth diff --git a/preForth/Makefile b/preForth/Makefile index e50cd04..7c72bad 100644 --- a/preForth/Makefile +++ b/preForth/Makefile @@ -101,4 +101,4 @@ seedForth: seedForth.$(UNIXFLAVOUR) .PHONY=clean clean: - rm -f *.asm *.o *.fas *.s *.c *.Darwin *.Linux preForthdemo preForth forth seedForth seedForthDemo.seed seedForthInteractive.seed + rm -f *.Darwin *.Linux *.asm *.o *.seed preForthdemo preForth seedForth diff --git a/preForth/seedForth-tokenizer.fs b/preForth/seedForth-tokenizer.fs index 3cbd559..cc6160b 100644 --- a/preForth/seedForth-tokenizer.fs +++ b/preForth/seedForth-tokenizer.fs @@ -97,7 +97,7 @@ Variable #tokens 0 #tokens ! : process-digit? ( x c -- x' flag ) '0' - dup 10 u< IF swap 10 * + true EXIT THEN drop false ; -: number? ( c-addr u -- x flag ) +: process-number? ( c-addr u -- x flag ) dup 0= IF 2drop 0 false EXIT THEN over c@ '-' = dup >r IF 1 /string THEN >r >r 0 r> r> bounds @@ -109,7 +109,7 @@ Variable #tokens 0 #tokens ! : seed-name ( c-addr u -- ) 2dup token@ dup IF nip nip execute EXIT THEN drop 2dup char-lit? IF nip nip seed num seed-number seed exit EXIT THEN drop - 2dup number? IF nip nip seed num seed-number seed exit EXIT THEN drop + 2dup process-number? IF nip nip seed num seed-number seed exit EXIT THEN drop cr type ." not found" abort ; : seed-line ( -- ) @@ -277,4 +277,4 @@ end-macro Macro restore-#tokens postpone #tokens postpone ! -end-macro \ No newline at end of file +end-macro From 56c4dcff3bfd1f6bc7f3bcb196bea9dc701cd53c Mon Sep 17 00:00:00 2001 From: Nick Downing Date: Fri, 22 Apr 2022 14:32:33 +1000 Subject: [PATCH 2/9] Remove .$(UNIXFLAVOUR) extension and file copies in favour of ifeq (GNU make) --- .gitignore | 2 -- preForth/Makefile | 27 +++++++++++---------------- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index 7e0a06e..666eb1c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ -*.Darwin -*.Linux *.asm *.o *.seed diff --git a/preForth/Makefile b/preForth/Makefile index 7c72bad..95ec272 100644 --- a/preForth/Makefile +++ b/preForth/Makefile @@ -29,21 +29,16 @@ seedForth-i386.asm: seedForth-i386.pre preForth cat seedForth-i386.pre | ./preForth >seedForth-i386.asm # preForth connected to stdin - output to preForth.asm -preForth.asm: preForth.pre preForth-i386-backend.pre load-i386-preForth.fs +preForth.asm: preForth-i386-rts.pre preForth-rts.pre preForth-i386-backend.pre preForth.pre load-i386-preForth.fs cat preForth-i386-rts.pre preForth-rts.pre preForth-i386-backend.pre preForth.pre \ | $(HOSTFORTH) load-i386-preForth.fs >preForth.asm -preForth: preForth.$(UNIXFLAVOUR) - cp preForth.$(UNIXFLAVOUR) preForth - %.asm: %.pre preForth preForth-i386-rts.pre preForth-rts.pre cat preForth-i386-rts.pre preForth-rts.pre $< | ./preForth >$@ -%: %.$(UNIXFLAVOUR) - cp $< $@ - +ifeq ($(UNIXFLAVOUR),Linux) # assemble and link executable on linux -%.Linux: %.asm +%: %.asm fasm $< $@.o LDEMULATION=elf_i386 ld -arch i386 -o $@ \ -dynamic-linker /lib32/ld-linux.so.2 \ @@ -51,19 +46,22 @@ preForth: preForth.$(UNIXFLAVOUR) $@.o \ -lc /usr/lib/i386-linux-gnu/crtn.o # rm $@.o - +else +ifeq ($(UNIXFLAVOUR),Darwin) # assemble and link executable on MacOS -%.Darwin: %.asm +%: %.asm fasm $< $@.o objconv -fmacho32 -nu $@.o $@_m.o ld -arch i386 -macosx_version_min 10.6 -o $@ \ $@_m.o /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/crt1.o /usr/lib/libc.dylib # rm $@.o $@_m.o +endif +endif # run preForth on its own source code to perform a bootstrap # should produce identical results -bootstrap: preForth preForth-i386-backend.pre preForth.pre preForth.$(EXT) - cat preForth-i386-rts.pre preForth-rts.pre preForth-i386-backend.pre preForth.pre\ +bootstrap: preForth-i386-rts.pre preForth-rts.pre preForth-i386-backend.pre preForth.pre preForth preForth.$(EXT) + cat preForth-i386-rts.pre preForth-rts.pre preForth-i386-backend.pre preForth.pre \ | ./preForth >preForth1.$(EXT) cmp preForth.$(EXT) preForth1.$(EXT) @@ -92,13 +90,10 @@ rundocker: docker-image seedForth.$(EXT): seedForth-i386.pre preForth cat seedForth-i386.pre | ./preForth >seedForth.$(EXT) -seedForth: seedForth.$(UNIXFLAVOUR) - cp seedForth.$(UNIXFLAVOUR) seedForth - %.seed: %.seedsource seedForth-tokenizer.fs gforth seedForth-tokenizer.fs $< .PHONY=clean clean: - rm -f *.Darwin *.Linux *.asm *.o *.seed preForthdemo preForth seedForth + rm -f *.asm *.o *.seed preForthdemo preForth seedForth From a2e4911bbed68bf9979fd2bb4ad308ae01bbff50 Mon Sep 17 00:00:00 2001 From: Nick Downing Date: Fri, 22 Apr 2022 13:47:16 +1000 Subject: [PATCH 3/9] Remove redundant stuff in the preForth-generated asm code --- preForth/preForth-i386-backend.pre | 21 +++++++++++---------- preForth/preForth-i386-rts.pre | 2 -- preForth/preForth.pre | 4 ++-- preForth/seedForth-i386.pre | 2 -- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/preForth/preForth-i386-backend.pre b/preForth/preForth-i386-backend.pre index f218fbb..663bff5 100644 --- a/preForth/preForth-i386-backend.pre +++ b/preForth/preForth-i386-backend.pre @@ -150,17 +150,18 @@ body ,_lit '>' 'r' 2 ,>word ; -: ."done" ( -- ) - ';' emit space 'd' emit 'o' emit 'n' emit 'e' emit ; - -: ."last:" ( -- ) - ';' emit space 'l' emit 'a' emit 's' emit 't' emit ':' emit space ; +\ : ."done" ( -- ) +\ ';' emit space 'd' emit 'o' emit 'n' emit 'e' emit ; +\ +\ : ."last:" ( -- ) +\ ';' emit space 'l' emit 'a' emit 's' emit 't' emit ':' emit space ; : ,end ( S -- ) - cr ."last:" alter show - cr ."done" cr ; + \ cr ."last:" alter show + \ cr ."done" cr + ; -\ create a new header with given name S2 and flags - do nothing -: header ( S1 S2 flags -- S3 S2 ) - drop ; +\ \ create a new header with given name S2 and flags - do nothing +\ : header ( S1 S2 flags -- S3 S2 ) +\ drop ; diff --git a/preForth/preForth-i386-rts.pre b/preForth/preForth-i386-rts.pre index 09f5efd..2d276fb 100644 --- a/preForth/preForth-i386-rts.pre +++ b/preForth/preForth-i386-rts.pre @@ -53,8 +53,6 @@ _nest: lea ebp, [ebp-4] lea esi, [eax+4] next -_O = 0 - ; code bye ( -- ) diff --git a/preForth/preForth.pre b/preForth/preForth.pre index ee9f710..741d2dc 100644 --- a/preForth/preForth.pre +++ b/preForth/preForth.pre @@ -130,7 +130,7 @@ : code ( -- ) token _dup ,comment - 0 header + \ 0 header ,code line _drop pre ,end-code ; \ Colon definitions - the preForth compiler @@ -262,7 +262,7 @@ : :' ( -- ) token _dup ,comment - 0 header + \ 0 header (: ; \ ----------- diff --git a/preForth/seedForth-i386.pre b/preForth/seedForth-i386.pre index 7f603df..be4cc19 100644 --- a/preForth/seedForth-i386.pre +++ b/preForth/seedForth-i386.pre @@ -104,8 +104,6 @@ _dovar: ; ( -- addr ) push eax next -_O = 0 - ; From cb3ba98a04fd976e84e89f98672fedb503072b64 Mon Sep 17 00:00:00 2001 From: Nick Downing Date: Fri, 22 Apr 2022 14:27:56 +1000 Subject: [PATCH 4/9] Use tabs in preForth-i386-rts.pre and seedForth-i386.pre, improve consistency --- preForth/preForth-i386-rts.pre | 201 +++++++------- preForth/seedForth-i386.pre | 481 ++++++++++++++++----------------- 2 files changed, 335 insertions(+), 347 deletions(-) diff --git a/preForth/preForth-i386-rts.pre b/preForth/preForth-i386-rts.pre index 2d276fb..4d92b2c 100644 --- a/preForth/preForth-i386-rts.pre +++ b/preForth/preForth-i386-rts.pre @@ -7,167 +7,158 @@ \ EBP return stack pointer \ ESP data stack pointer -prelude +pre ;;; This is a preForth generated file using preForth-i386-backend. ;;; Only modify it, if you know what you are doing. - -; -prefix -format ELF +format ELF + +section '.bss' executable writeable -section '.bss' writeable executable + DD 10000 dup(0) +stck: DD 16 dup(0) - DD 10000 dup (0) -stck: DD 16 dup(0) - - DD 10000 dup(0) -rstck: DD 16 dup(0) + DD 10000 dup(0) +rstck: DD 16 dup(0) section '.text' executable writeable -public main +public main extrn putchar extrn getchar extrn fflush extrn exit - + macro next { - lodsd - jmp dword [eax] + lodsd + jmp dword [eax] } +main: cld + mov esp,dword stck + mov ebp,dword rstck + mov esi,main1 + next -main: cld - mov esp, dword stck - mov ebp, dword rstck - mov esi, main1 - next - -main1: DD _cold - DD _bye - - -_nest: lea ebp, [ebp-4] - mov [ebp], esi - lea esi, [eax+4] - next +main1: DD _cold + DD _bye +_nest: lea ebp,[ebp-4] + mov [ebp],esi + lea esi,[eax+4] + next ; code bye ( -- ) - push ebp - mov ebp, esp - and esp, 0xfffffff0 - mov eax, 0 - mov [esp], eax - call exit + push ebp + mov ebp,esp + and esp,0xfffffff0 + mov eax,0 + mov [esp],eax + call exit ; - + code emit ( c -- ) - pop eax + pop eax - push ebp - mov ebp, esp - push eax - and esp, 0xfffffff0 + push ebp + mov ebp,esp + push eax + and esp,0xfffffff0 - mov dword [esp], eax - call putchar + mov dword [esp],eax + call putchar - mov eax, 0 - mov [esp], eax - call fflush ; flush all output streams + mov eax,0 + mov [esp],eax + call fflush ; flush all output streams - mov esp, ebp - pop ebp - next + mov esp,ebp + pop ebp + next ; code key ( -- c ) - push ebp - mov ebp, esp - and esp, 0xfffffff0 - - call getchar - mov esp, ebp - pop ebp - cmp eax,-1 - jnz key1 - mov eax,4 -key1: push eax - next + push ebp + mov ebp,esp + and esp,0xfffffff0 + + call getchar + mov esp,ebp + pop ebp + cmp eax,-1 + jnz key1 + mov eax,4 ; eof: return Ctrl-D +key1: push eax + next ; code dup ( x -- x x ) - pop eax - push eax - push eax - next + pop eax + push eax + push eax + next ; code swap ( x y -- y x ) - pop edx - pop eax - push edx - push eax - next + pop edx + pop eax + push edx + push eax + next ; code drop ( x -- ) - pop eax - next + pop eax + next ; code 0< ( x -- flag ) - pop eax - or eax, eax - mov eax, 0 - jns zless1 - dec eax -zless1: push eax - next + pop eax + sar eax,31 + push eax + next ; -code ?exit ( f -- ) - pop eax - or eax, eax - jz qexit1 - mov esi, [ebp] - lea ebp,[ebp+4] -qexit1: next +code ?exit ( f -- ) \ high level: IF exit THEN + pop eax + or eax,eax + jz qexit1 + mov esi,[ebp] + lea ebp,[ebp+4] +qexit1: next ; code >r ( x -- ) ( R -- x ) - pop ebx - lea ebp,[ebp-4] - mov [ebp], ebx - next + pop ebx + lea ebp,[ebp-4] + mov [ebp],ebx + next ; code r> ( R x -- ) ( -- x ) - mov eax,[ebp] - lea ebp, [ebp+4] - push eax - next + mov eax,[ebp] + lea ebp,[ebp+4] + push eax + next ; code - ( x1 x2 -- x3 ) - pop edx - pop eax - sub eax, edx - push eax - next + pop edx + pop eax + sub eax,edx + push eax + next ; code unnest ( -- ) - mov esi,[ebp] - lea ebp,[ebp+4] - next + mov esi,[ebp] + lea ebp,[ebp+4] + next ; code lit ( -- ) - lodsd - push eax - next + lodsd + push eax + next ; diff --git a/preForth/seedForth-i386.pre b/preForth/seedForth-i386.pre index be4cc19..199f623 100644 --- a/preForth/seedForth-i386.pre +++ b/preForth/seedForth-i386.pre @@ -7,8 +7,8 @@ \ EBP return stack pointer \ ESP data stack pointer -prelude -;;; This is seedForth - a small, potentially interactive Forth, that dynamically +pre +;;; This is seedForth - a small,potentially interactive Forth, that dynamically ;;; bootstraps from a minimal kernel. ;;; ;;; cat seedForth.seed - | ./seedForth @@ -16,28 +16,26 @@ prelude ;;; .seed-files are in byte-tokenized source code format. ;;; ;;; Use the seedForth tokenizer to convert human readable source code to byte-token form. -; -prefix -format ELF +format ELF + +section '.bss' executable writeable -section '.bss' executable writable + DD 10000 dup(0) +stck: DD 16 dup(0) - DD 10000 dup(0) -stck: DD 16 dup(0) + DD 10000 dup(0) +rstck: DD 16 dup(0) - DD 10000 dup(0) -rstck: DD 16 dup(0) - -_dp: DD _start ; dictionary pointer: points to next free location in memory +_dp: DD _start ; dictionary pointer: points to next free location in memory ; free memory starts at _start -__hp: DD 0 ; head pointer: index of first unused head -_head: DD 10000 dup (0) +__hp: DD 0 ; head pointer: index of first unused head +_head: DD 10000 dup (0) -section '.text' executable writable align 4096 +section '.text' executable writeable align 4096 -public main +public main extrn putchar extrn getchar extrn fflush @@ -45,336 +43,334 @@ extrn exit extrn mprotect extrn ioctl extrn usleep - + macro next { - lodsd - jmp dword [eax] + lodsd + jmp dword [eax] } origin: -main: cld - mov esp, dword stck - mov ebp, dword rstck - - ; make section writable - push ebp - mov ebp, esp - sub esp, 16 - and esp, 0xfffffff0 - mov dword [esp+8], 7 ; rwx - mov eax, _memtop - sub eax, origin - mov dword [esp+4], eax - mov dword [esp], origin - call mprotect - mov esp, ebp - pop ebp - or eax, eax ; error? - jz main0 - push ebp - mov ebp, esp - push eax - and esp, 0xfffffff0 - ; call __error ; get error code on Mac OS - ; mov eax, [eax] - ; call __errno_location ; get error on Linux - ; mov eax, [eax] - mov [esp], eax - call exit - -main0: mov esi, main1 - next - -main1: DD _cold - DD _bye +main: cld + mov esp,dword stck + mov ebp,dword rstck + + ; make section writeable + push ebp + mov ebp,esp + sub esp,16 + and esp,0xfffffff0 + mov dword [esp+8],7 ; rwx + mov eax,_memtop + sub eax,origin + mov dword [esp+4],eax + mov dword [esp],origin + call mprotect + mov esp,ebp + pop ebp + or eax,eax ; error? + jz main0 + push ebp + mov ebp,esp + push eax + and esp,0xfffffff0 + ;call __error ; get error code on Mac OS + ;mov eax,[eax] + ;call __errno_location ; get error on Linux + ;mov eax,[eax] + mov [esp],eax + call exit + +main0: mov esi,main1 + next + +main1: DD _cold + DD _bye _nest: -_enter: lea ebp, [ebp-4] - mov [ebp], esi - lea esi, [eax+4] - next +_enter: lea ebp,[ebp-4] + mov [ebp],esi + lea esi,[eax+4] + next _dodoes: ; ( -- addr ) - lea ebp, [ebp-4] ; push IP - mov [ebp], esi - mov esi,[eax-4] ; set IP + lea ebp,[ebp-4] ; push IP + mov [ebp],esi + mov esi,[eax-4] ; set IP _dovar: ; ( -- addr ) - lea eax,[eax+4] ; to parameter field - push eax - next - + lea eax,[eax+4] ; to parameter field + push eax + next ; - code bye ( -- ) - push ebp - mov ebp, esp - and esp, 0xfffffff0 - mov eax, 0 - mov [esp], eax - call exit -; - + push ebp + mov ebp,esp + and esp,0xfffffff0 + mov eax,0 + mov [esp],eax + call exit +; + code emit ( c -- ) - pop eax + pop eax - push ebp - mov ebp, esp - push eax - and esp, 0xfffffff0 + push ebp + mov ebp,esp + push eax + and esp,0xfffffff0 - mov dword [esp], eax - call putchar + mov dword [esp],eax + call putchar - mov eax, 0 - mov [esp], eax - call fflush ; flush all output streams + mov eax,0 + mov [esp],eax + call fflush ; flush all output streams - mov esp, ebp - pop ebp - next + mov esp,ebp + pop ebp + next ; code key ( -- c ) - push ebp - mov ebp, esp - and esp, 0xfffffff0 - - call getchar - mov esp, ebp - pop ebp - cmp eax,-1 - jnz key1 - mov eax,4 ; eof: return Ctrl-D -key1: push eax - next + push ebp + mov ebp,esp + and esp,0xfffffff0 + + call getchar + mov esp,ebp + pop ebp + cmp eax,-1 + jnz key1 + mov eax,4 ; eof: return Ctrl-D +key1: push eax + next ; code key? ( -- f ) - push ebp - mov ebp, esp - and esp, 0xfffffff0 - sub esp, 32 + push ebp + mov ebp,esp + and esp,0xfffffff0 + sub esp,32 - mov dword [esp], 0 - mov dword [esp+4], 1074030207 ; FIONREAD - lea dword eax, [esp+24] - mov dword [esp+8], eax + mov dword [esp],0 + mov dword [esp+4],1074030207 ; FIONREAD + lea dword eax,[esp+24] + mov dword [esp+8],eax - call ioctl - mov dword eax, [esp+24] + call ioctl + mov dword eax,[esp+24] - mov esp, ebp - pop ebp + mov esp,ebp + pop ebp - cmp eax, 0 - jz keyq1 - mov eax, -1 -keyq1: push eax - next + cmp eax,0 + jz keyq1 + mov eax,-1 +keyq1: push eax + next ; code dup ( x -- x x ) - pop eax - push eax - push eax - next + pop eax + push eax + push eax + next ; code swap ( x y -- y x ) - pop edx - pop eax - push edx - push eax - next + pop edx + pop eax + push edx + push eax + next ; code drop ( x -- ) - pop eax - next + pop eax + next ; code 0< ( x -- flag ) - pop eax - sar eax,31 - push eax - next + pop eax + sar eax,31 + push eax + next ; code ?exit ( f -- ) \ high level: IF exit THEN - pop eax - or eax, eax - jz qexit1 - mov esi, [ebp] - lea ebp,[ebp+4] -qexit1: next + pop eax + or eax,eax + jz qexit1 + mov esi,[ebp] + lea ebp,[ebp+4] +qexit1: next ; code >r ( x -- ) ( R -- x ) - pop ebx - lea ebp,[ebp-4] - mov [ebp], ebx - next + pop ebx + lea ebp,[ebp-4] + mov [ebp],ebx + next ; code r> ( R x -- ) ( -- x ) - mov eax,[ebp] - lea ebp, [ebp+4] - push eax - next + mov eax,[ebp] + lea ebp,[ebp+4] + push eax + next ; code - ( x1 x2 -- x3 ) - pop edx - pop eax - sub eax, edx - push eax - next + pop edx + pop eax + sub eax,edx + push eax + next ; -code or ( x1 x2 -- x3 ) - pop edx - pop eax - or eax, edx - push eax - next +code or ( x1 x2 -- x3 ) + pop edx + pop eax + or eax,edx + push eax + next ; -code and ( x1 x2 -- x3 ) - pop edx - pop eax - and eax, edx - push eax - next +code and ( x1 x2 -- x3 ) + pop edx + pop eax + and eax,edx + push eax + next ; -pre +pre _unnest: ; code exit ( -- ) - mov esi,[ebp] - lea ebp,[ebp+4] - next + mov esi,[ebp] + lea ebp,[ebp+4] + next ; code lit ( -- ) - lodsd - push eax - next + lodsd + push eax + next ; code @ ( addr -- x ) - pop eax - mov eax,[eax] - push eax - next + pop eax + mov eax,[eax] + push eax + next ; code c@ ( c-addr -- c ) - pop edx - xor eax, eax - mov al,byte [edx] - push eax - next + pop edx + xor eax,eax + mov al,byte [edx] + push eax + next ; code ! ( x addr -- ) - pop edx - pop eax - mov dword [edx],eax - next + pop edx + pop eax + mov dword [edx],eax + next ; code c! ( c c-addr -- ) - pop edx - pop eax - mov byte [edx], al - next + pop edx + pop eax + mov byte [edx],al + next ; \ code invoke ( addr -- ) \ native code: >r ; -code execute ( addr -- ) \ this version uses token numbers as execution tokens and finds their code address via the headers table - pop edx - mov dword eax, [_head+edx*4] - jmp dword [eax] +code execute ( addr -- ) \ this version uses token numbers as execution tokens and finds their code address via the headers table + pop edx + mov dword eax,[_head+edx*4] + jmp dword [eax] ; code branch ( -- ) \ threaded code: r> @ >r ; - lodsd - mov esi,eax - next + lodsd + mov esi,eax + next ; code ?branch ( f -- ) \ threaded code: ?exit r> @ >r ; - pop eax - or eax,eax - jz _branchX - lea esi,[esi+4] - next + pop eax + or eax,eax + jz _branchX + lea esi,[esi+4] + next ; code depth ( -- n ) - mov eax, stck - sub eax, esp - sar eax,2 - push eax - next + mov eax,stck + sub eax,esp + sar eax,2 + push eax + next ; code sp@ ( -- x ) - push esp - next + push esp + next ; code sp! ( x -- ) - pop esp - next + pop esp + next ; code rp@ ( -- x ) - push ebp - next + push ebp + next ; code rp! ( x -- ) - pop ebp - next + pop ebp + next ; code um* ( u1 u2 -- ud ) - pop edx - pop eax - mul edx - push eax - push edx - next + pop edx + pop eax + mul edx + push eax + push edx + next ; code um/mod ( ud u1 -- u2 u3 ) - pop ebx - pop edx - pop eax - div ebx - push edx - push eax - next + pop ebx + pop edx + pop eax + div ebx + push edx + push eax + next ; code usleep ( c -- ) - pop eax + pop eax - push ebp - mov ebp, esp - push eax - and esp, 0xfffffff0 + push ebp + mov ebp,esp + push eax + and esp,0xfffffff0 - mov dword [esp], eax - call usleep + mov dword [esp],eax + call usleep - mov esp, ebp - pop ebp - next + mov esp,ebp + pop ebp + next ; @@ -426,7 +422,7 @@ code usleep ( c -- ) : compile, ( x -- ) h@ , ; -\ token are in the range 0 .. 767: +\ token are in the range 0 .. 767: \ 0, 3 .. 255 are single byte tokens \ 256 .. 511 are double byte tokens of the form 01 xx \ 511 .. 767 are double byte tokens of the form 02 xx @@ -438,16 +434,16 @@ code usleep ( c -- ) : interpreter ( -- ) token execute tail interpreter ; \ executing exit will leave this loop -: num ( -- x ) +: num ( -- x ) tail interpreter ; -: ?lit ( xt -- xt | ) +: ?lit ( xt -- xt | ) dup h@ lit num - ?exit drop \ not num token: exit i.e. normal compile action lit lit , num , \ generate lit x num call puts x on stack r> drop tail compiler ; : compiler ( -- ) - token ?dup 0= ?exit ?lit + token ?dup 0= ?exit ?lit compile, tail compiler ; : new ( -- xt ) @@ -470,7 +466,7 @@ code usleep ( c -- ) r> swap h@ dup >r 1 cells - ! lit dodoes r> ! ; -: unused ( -- u ) +: unused ( -- u ) lit memtop here - ; : cold ( -- ) @@ -537,7 +533,8 @@ code usleep ( c -- ) interpreter bye ; pre - _start: DB 43 - DD 100000 dup (0) - _memtop: DD 0 +_start: DB 43 + DD 100000 dup (0) +_memtop: + DD 0 ; From fa4f0c26cfd143f54637eda86e6d421892f1317d Mon Sep 17 00:00:00 2001 From: Nick Downing Date: Sat, 23 Apr 2022 01:16:09 +1000 Subject: [PATCH 5/9] Rationalize how cr is emitted in generated preForth code, make DB/DD lowercase --- preForth/preForth-i386-backend.pre | 52 +++++++++++------------------- preForth/preForth-i386-rts.pre | 14 ++++---- preForth/preForth.pre | 4 +-- preForth/seedForth-i386.pre | 24 +++++++------- 4 files changed, 40 insertions(+), 54 deletions(-) diff --git a/preForth/preForth-i386-backend.pre b/preForth/preForth-i386-backend.pre index 663bff5..6881741 100644 --- a/preForth/preForth-i386-backend.pre +++ b/preForth/preForth-i386-backend.pre @@ -23,7 +23,7 @@ 'Q' swap '?' case? ?exit nip 'R' swap '"' case? ?exit nip \ 'S' swap '!' case? ?exit nip - 'T' swap '*' case? ?exit nip + 'T' swap '*' case? ?exit nip 'U' swap '(' case? ?exit nip 'V' swap '|' case? ?exit nip 'W' swap ',' case? ?exit nip @@ -42,22 +42,13 @@ \ output words \ ------------ \ Output is done by emit. -\ We define convenience words of the form ."xxx" to output xxx and >"xxx" to output xxx on a new line indented by a tab. +\ We define convenience words of the form ."xxx" to output xxx (maybe tabbed) : ."dd" ( -- ) - 'D' emit 'D' emit space ; - -: >"dd" ( -- ) - cr tab ."dd" ; + tab 'd' emit 'd' emit tab ; : ."db" ( -- ) - 'D' emit 'B' emit space ; - -: >"db" ( -- ) - cr tab ."db" ; - -: >"ds" ( -- ) - cr tab 'D' emit 'S' emit space ; + tab 'd' emit 'b' emit tab ; : ."nest" ( -- ) 'n' 'e' 's' 't' 4 alter show ; @@ -74,55 +65,50 @@ \ ,string compiles the topmost string as a sequence of numeric DB values. : ,string ( S -- ) - \ ."ds" show ; ?dup 0= ?exit - dup roll >"db" u. \ 1st char + dup roll ."db" u. cr \ 1st char 1- ,string ; \ reproduce a verbatim line : ,line ( x1 ...cn n -- ) show ; -\ compile a reference to an invoked word +\ compile a reference to an invoked word : ,word ( S -- ) - ."dd" alter show ; - -\ compile a reference to an invoked word on a new line -: ,>word ( S -- ) - >"dd" alter show ; + ."dd" alter show cr ; \ compile reference to nest primitive : ,nest ( -- ) - ."dd" ."nest" ; + ."dd" ."nest" cr ; \ compile reference to unnest primitive : ,unnest ( -- ) - >"dd" ."unnest" - cr ; + ."dd" ."unnest" cr cr ; \ compile signed number : ,n ( n -- ) - >"dd" . ; + ."dd" . cr ; \ compile unsigned number : ,u ( u -- ) - >"dd" u. ; + ."dd" u. cr ; \ compile literal : ,_lit ( S -- ) - >"dd" ."lit" ,>word ; + ."dd" ."lit" cr ,word ; \ compile literal : ,lit ( x -- ) - >"dd" ."lit" ,n ; + ."dd" ."lit" cr ,n ; \ output string as comment : ,comment ( S -- ) - cr tab ';' emit space show ; + tab ';' emit space show cr ; \ create a new symbolic label +\ if label is 6 characters or less, stay on same line for following code : label ( S -- ) - cr alter show ':' emit tab ; + alter dup >r show ':' emit r> 7 - 0< ?exit cr ; \ body calculates the name of the body from a token : body ( S1 -- S2 ) @@ -138,7 +124,7 @@ : ,end-code ( -- ) cr ; - + \ ----------------------------------- \ tail call optimization tail word ; -> [ ' word >body ] literal >r ; @@ -148,11 +134,11 @@ \ ,tail compiles a tail call : ,tail ( S -- ) body ,_lit - '>' 'r' 2 ,>word ; + '>' 'r' 2 ,word ; \ : ."done" ( -- ) \ ';' emit space 'd' emit 'o' emit 'n' emit 'e' emit ; -\ +\ \ : ."last:" ( -- ) \ ';' emit space 'l' emit 'a' emit 's' emit 't' emit ':' emit space ; diff --git a/preForth/preForth-i386-rts.pre b/preForth/preForth-i386-rts.pre index 4d92b2c..fc5a7a4 100644 --- a/preForth/preForth-i386-rts.pre +++ b/preForth/preForth-i386-rts.pre @@ -15,14 +15,14 @@ format ELF section '.bss' executable writeable - DD 10000 dup(0) -stck: DD 16 dup(0) - - DD 10000 dup(0) -rstck: DD 16 dup(0) + dd 10000 dup(0) +stck: dd 16 dup(0) + dd 10000 dup(0) +rstck: dd 16 dup(0) section '.text' executable writeable + public main extrn putchar extrn getchar @@ -40,8 +40,8 @@ main: cld mov esi,main1 next -main1: DD _cold - DD _bye +main1: dd _cold + dd _bye _nest: lea ebp,[ebp-4] mov [ebp],esi diff --git a/preForth/preForth.pre b/preForth/preForth.pre index 741d2dc..751fb0d 100644 --- a/preForth/preForth.pre +++ b/preForth/preForth.pre @@ -38,7 +38,7 @@ \ \ compiler words: \ ,line ,comment ,codefield ,end -\ ,lit ,>word ,nest ,unnest ,tail +\ ,lit ,word ,nest ,unnest ,tail \ \ header creation: \ header label bodylabel @@ -238,7 +238,7 @@ \ ?word detects and handles words by compiling them as reference. : ?word ( S -- 0 | S ) - dup 0= ?exit ,>word 0 ; + dup 0= ?exit ,word 0 ; \ Compiler loop \ ------------- diff --git a/preForth/seedForth-i386.pre b/preForth/seedForth-i386.pre index 199f623..778ca7b 100644 --- a/preForth/seedForth-i386.pre +++ b/preForth/seedForth-i386.pre @@ -21,17 +21,17 @@ format ELF section '.bss' executable writeable - DD 10000 dup(0) -stck: DD 16 dup(0) + dd 10000 dup(0) +stck: dd 16 dup(0) - DD 10000 dup(0) -rstck: DD 16 dup(0) + dd 10000 dup(0) +rstck: dd 16 dup(0) -_dp: DD _start ; dictionary pointer: points to next free location in memory +_dp: dd _start ; dictionary pointer: points to next free location in memory ; free memory starts at _start -__hp: DD 0 ; head pointer: index of first unused head -_head: DD 10000 dup (0) +__hp: dd 0 ; head pointer: index of first unused head +_head: dd 10000 dup (0) section '.text' executable writeable align 4096 @@ -84,8 +84,8 @@ main: cld main0: mov esi,main1 next -main1: DD _cold - DD _bye +main1: dd _cold + dd _bye _nest: _enter: lea ebp,[ebp-4] @@ -533,8 +533,8 @@ code usleep ( c -- ) interpreter bye ; pre -_start: DB 43 - DD 100000 dup (0) +_start: db 43 + dd 100000 dup (0) _memtop: - DD 0 + dd 0 ; From 927ca5ae133c5c4b41cbfb9541e386c650f29140 Mon Sep 17 00:00:00 2001 From: Nick Downing Date: Sat, 23 Apr 2022 02:08:40 +1000 Subject: [PATCH 6/9] Rationalize the sections in assembly output, make code be compiled into bss rather than text section which avoids the need to call mprotect(), rename things --- preForth/preForth-i386-rts.pre | 32 +++++++++----- preForth/seedForth-i386.pre | 77 ++++++++++++---------------------- 2 files changed, 47 insertions(+), 62 deletions(-) diff --git a/preForth/preForth-i386-rts.pre b/preForth/preForth-i386-rts.pre index fc5a7a4..9adda37 100644 --- a/preForth/preForth-i386-rts.pre +++ b/preForth/preForth-i386-rts.pre @@ -11,17 +11,12 @@ pre ;;; This is a preForth generated file using preForth-i386-backend. ;;; Only modify it, if you know what you are doing. -format ELF - -section '.bss' executable writeable - - dd 10000 dup(0) -stck: dd 16 dup(0) +DATA_STACK_SIZE = 40000 +RETURN_STACK_SIZE = 40000 - dd 10000 dup(0) -rstck: dd 16 dup(0) +format ELF -section '.text' executable writeable +section '.text' executable public main extrn putchar @@ -35,8 +30,8 @@ macro next { } main: cld - mov esp,dword stck - mov ebp,dword rstck + mov esp,data_stack + DATA_STACK_SIZE + mov ebp,return_stack + RETURN_STACK_SIZE mov esi,main1 next @@ -162,3 +157,18 @@ code lit ( -- ) push eax next ; + +\ we want the text section to be first and bss last (for linkers that output +\ sections in definition order), so it would be good to have the bss section +\ be output by the ",end" hook, but at present we cannot call "pre" from a +\ defined word, so we make do by switching to bss and then back to text again +pre +section '.bss' writeable + +data_stack: + db DATA_STACK_SIZE dup (0) +return_stack: + db RETURN_STACK_SIZE dup (0) + +section '.text' executable +; diff --git a/preForth/seedForth-i386.pre b/preForth/seedForth-i386.pre index 778ca7b..008b0e6 100644 --- a/preForth/seedForth-i386.pre +++ b/preForth/seedForth-i386.pre @@ -17,30 +17,20 @@ pre ;;; ;;; Use the seedForth tokenizer to convert human readable source code to byte-token form. -format ELF - -section '.bss' executable writeable - - dd 10000 dup(0) -stck: dd 16 dup(0) +DATA_STACK_SIZE = 40000 +RETURN_STACK_SIZE = 40000 +HEAD_SIZE = 40000 +MEM_SIZE = 400000 - dd 10000 dup(0) -rstck: dd 16 dup(0) - -_dp: dd _start ; dictionary pointer: points to next free location in memory - ; free memory starts at _start - -__hp: dd 0 ; head pointer: index of first unused head -_head: dd 10000 dup (0) +format ELF -section '.text' executable writeable align 4096 +section '.text' executable public main extrn putchar extrn getchar extrn fflush extrn exit -extrn mprotect extrn ioctl extrn usleep @@ -52,36 +42,9 @@ macro next { origin: main: cld - mov esp,dword stck - mov ebp,dword rstck - - ; make section writeable - push ebp - mov ebp,esp - sub esp,16 - and esp,0xfffffff0 - mov dword [esp+8],7 ; rwx - mov eax,_memtop - sub eax,origin - mov dword [esp+4],eax - mov dword [esp],origin - call mprotect - mov esp,ebp - pop ebp - or eax,eax ; error? - jz main0 - push ebp - mov ebp,esp - push eax - and esp,0xfffffff0 - ;call __error ; get error code on Mac OS - ;mov eax,[eax] - ;call __errno_location ; get error on Linux - ;mov eax,[eax] - mov [esp],eax - call exit - -main0: mov esi,main1 + mov esp,data_stack + DATA_STACK_SIZE + mov ebp,return_stack + RETURN_STACK_SIZE + mov esi,main1 next main1: dd _cold @@ -311,7 +274,7 @@ code ?branch ( f -- ) \ threaded code: ?exit r> @ >r ; ; code depth ( -- n ) - mov eax,stck + mov eax,data_stack + DATA_STACK_SIZE sub eax,esp sar eax,2 push eax @@ -373,7 +336,6 @@ code usleep ( c -- ) next ; - : negate ( n1 -- n2 ) 0 swap - ; @@ -533,8 +495,21 @@ code usleep ( c -- ) interpreter bye ; pre -_start: db 43 - dd 100000 dup (0) +section '.bss' writeable + +data_stack: + db DATA_STACK_SIZE dup (0) +return_stack: + db RETURN_STACK_SIZE dup (0) + + ; dictionary pointer: points to next free location in memory +_dp: dd _mem + + ; head pointer: index of first unused head +__hp: dd 0 +_head: dd HEAD_SIZE dup (0) + + ; free memory starts at _mem +_mem: db MEM_SIZE dup (0) _memtop: - dd 0 ; From 77b48fed936116a1ec537c547eeea06ade473fa6 Mon Sep 17 00:00:00 2001 From: Nick Downing Date: Sat, 23 Apr 2022 02:36:05 +1000 Subject: [PATCH 7/9] Split seedForth-i386.pre into machine dependent/less machine dependent portions --- preForth/Makefile | 60 ++++++++----- preForth/seed | 6 +- preForth/seedForth-i386.pre | 166 ++---------------------------------- preForth/seedForth.pre | 159 ++++++++++++++++++++++++++++++++++ 4 files changed, 209 insertions(+), 182 deletions(-) create mode 100644 preForth/seedForth.pre diff --git a/preForth/Makefile b/preForth/Makefile index 95ec272..a07d51c 100644 --- a/preForth/Makefile +++ b/preForth/Makefile @@ -16,7 +16,7 @@ test: runseedforthdemo runseedforthinteractive .PHONY=runseedforthdemo runseedforthdemo: seedForth seedForthDemo.seed - cat seedForthDemo.seed | ./seedForth + cat seedForthDemo.seed |./seedForth .PHONY=runseedfortinteractive runseedforthinteractive: seedForth seedForthInteractive.seed @@ -25,26 +25,31 @@ runseedforthinteractive: seedForth seedForthInteractive.seed UNIXFLAVOUR=$(shell uname -s) EXT=asm -seedForth-i386.asm: seedForth-i386.pre preForth - cat seedForth-i386.pre | ./preForth >seedForth-i386.asm - -# preForth connected to stdin - output to preForth.asm -preForth.asm: preForth-i386-rts.pre preForth-rts.pre preForth-i386-backend.pre preForth.pre load-i386-preForth.fs - cat preForth-i386-rts.pre preForth-rts.pre preForth-i386-backend.pre preForth.pre \ - | $(HOSTFORTH) load-i386-preForth.fs >preForth.asm - -%.asm: %.pre preForth preForth-i386-rts.pre preForth-rts.pre - cat preForth-i386-rts.pre preForth-rts.pre $< | ./preForth >$@ +preForth.asm: \ +preForth-i386-rts.pre \ +preForth-rts.pre \ +preForth-i386-backend.pre \ +preForth.pre \ +load-i386-preForth.fs + cat \ +preForth-i386-rts.pre \ +preForth-rts.pre \ +preForth-i386-backend.pre \ +preForth.pre \ +|$(HOSTFORTH) load-i386-preForth.fs >preForth.asm + +%.asm: %.pre preForth-i386-rts.pre preForth-rts.pre preForth + cat preForth-i386-rts.pre preForth-rts.pre $< |./preForth >$@ ifeq ($(UNIXFLAVOUR),Linux) # assemble and link executable on linux %: %.asm fasm $< $@.o LDEMULATION=elf_i386 ld -arch i386 -o $@ \ - -dynamic-linker /lib32/ld-linux.so.2 \ - /usr/lib/i386-linux-gnu/crt1.o /usr/lib/i386-linux-gnu/crti.o \ - $@.o \ - -lc /usr/lib/i386-linux-gnu/crtn.o +-dynamic-linker /lib32/ld-linux.so.2 \ +/usr/lib/i386-linux-gnu/crt1.o /usr/lib/i386-linux-gnu/crti.o \ +$@.o \ +-lc /usr/lib/i386-linux-gnu/crtn.o # rm $@.o else ifeq ($(UNIXFLAVOUR),Darwin) @@ -53,22 +58,33 @@ ifeq ($(UNIXFLAVOUR),Darwin) fasm $< $@.o objconv -fmacho32 -nu $@.o $@_m.o ld -arch i386 -macosx_version_min 10.6 -o $@ \ - $@_m.o /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/crt1.o /usr/lib/libc.dylib +$@_m.o /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/crt1.o \ +/usr/lib/libc.dylib # rm $@.o $@_m.o endif endif # run preForth on its own source code to perform a bootstrap # should produce identical results -bootstrap: preForth-i386-rts.pre preForth-rts.pre preForth-i386-backend.pre preForth.pre preForth preForth.$(EXT) - cat preForth-i386-rts.pre preForth-rts.pre preForth-i386-backend.pre preForth.pre \ - | ./preForth >preForth1.$(EXT) +bootstrap: \ +preForth-i386-rts.pre \ +preForth-rts.pre \ +preForth-i386-backend.pre \ +preForth.pre \ +preForth \ +preForth.$(EXT) + cat \ +preForth-i386-rts.pre \ +preForth-rts.pre \ +preForth-i386-backend.pre \ +preForth.pre \ +|./preForth >preForth1.$(EXT) cmp preForth.$(EXT) preForth1.$(EXT) # preForth connected to stdin - output to stdout .PHONY=visible-bootstrap visible-bootstrap: preForth preForth-i386-backend.pre preForth.pre - cat preForth-i386-backend.pre preForth.pre | ./preForth + cat preForth-i386-backend.pre preForth.pre |./preForth # ------------------------------------------------------------------------ # Docker support (for Linux version) @@ -87,8 +103,8 @@ rundocker: docker-image # ------------------------------------------------------------------------ # seedForth # ------------------------------------------------------------------------ -seedForth.$(EXT): seedForth-i386.pre preForth - cat seedForth-i386.pre | ./preForth >seedForth.$(EXT) +seedForth.$(EXT): seedForth-i386.pre seedForth.pre preForth + cat seedForth-i386.pre seedForth.pre |./preForth >seedForth.$(EXT) %.seed: %.seedsource seedForth-tokenizer.fs gforth seedForth-tokenizer.fs $< diff --git a/preForth/seed b/preForth/seed index 52ff983..35f5ac0 100755 --- a/preForth/seed +++ b/preForth/seed @@ -1,6 +1,8 @@ #!/bin/bash +# note: we need to fix the below so it exits cleanly +# when seedForth quits, the "cat" doesn't realize until user types something + stty raw -echo -cat seedForthInteractive.seed hi.forth - | ./seedForth +cat seedForthInteractive.seed hi.forth - |./seedForth stty sane - diff --git a/preForth/seedForth-i386.pre b/preForth/seedForth-i386.pre index 008b0e6..1c59965 100644 --- a/preForth/seedForth-i386.pre +++ b/preForth/seedForth-i386.pre @@ -1,3 +1,5 @@ +\ seedForth: machine dependent portion + \ seedForth - seed it, feed it, grow it - i386 (32 bit) ITC flavour uho 2018-04-13 \ ---------------------------------------------------------------------------------- \ @@ -336,164 +338,10 @@ code usleep ( c -- ) next ; -: negate ( n1 -- n2 ) - 0 swap - ; - -: + ( x1 x2 -- x3 ) - negate - ; - -: 0= ( x -- flag ) - 0 swap ?exit drop -1 ; - -: ?dup ( x -- x x | 0 ) - dup 0= ?exit dup ; - -: 2* ( x1 -- x2 ) - dup + ; - -: cells ( x1 -- x2 ) - 2* 2* ; - -: +! ( x addr -- ) - swap >r dup @ r> + swap ! ; - -: hp ( -- addr ) - lit _hp ; - -: h@ ( i -- addr ) - cells lit head + @ ; - -: h! ( x i -- ) - cells lit head + ! ; - -: h, ( x -- ) - hp @ h! 1 hp +! ; - -: here ( -- addr ) - lit dp @ ; - -: allot ( n -- ) - lit dp +! ; - -: , ( x -- ) - here 1 cells allot ! ; - -: c, ( c -- ) - here 1 allot c! ; - -: compile, ( x -- ) - h@ , ; - -\ token are in the range 0 .. 767: -\ 0, 3 .. 255 are single byte tokens -\ 256 .. 511 are double byte tokens of the form 01 xx -\ 511 .. 767 are double byte tokens of the form 02 xx -: token ( -- x ) - key dup 0= ?exit \ 0 -> single byte token - dup 3 - 0< 0= ?exit \ not 1 2 -> single byte token - key couple ; \ double byte token - -: interpreter ( -- ) - token execute tail interpreter ; \ executing exit will leave this loop - -: num ( -- x ) - tail interpreter ; - -: ?lit ( xt -- xt | ) - dup h@ lit num - ?exit drop \ not num token: exit i.e. normal compile action - lit lit , num , \ generate lit x num call puts x on stack - r> drop tail compiler ; - -: compiler ( -- ) - token ?dup 0= ?exit ?lit - compile, tail compiler ; - -: new ( -- xt ) - hp @ here h, lit enter , ; - -: fun ( -- ) - new drop compiler ; - -: couple ( hi lo -- hilo ) - >r 2* 2* 2* 2* 2* 2* 2* 2* r> + ; - -: $lit ( -- addr u ) - r> dup 1 + dup >r swap c@ dup r> + >r ; - -: create ( -- xt ) - 0 , \ dummy does> field - hp @ here h, lit dovar , ; - -: does> ( xt -- ) \ set code field of last defined word - r> swap h@ dup >r 1 cells - ! lit dodoes r> ! -; - -: unused ( -- u ) - lit memtop here - ; - -: cold ( -- ) - \ 's' emit 'e' dup emit emit 'd' emit 10 emit - lit bye h, \ 0 00 code - 0 h, \ 1 01 prefix - 0 h, \ 2 02 prefix - lit emit h, \ 3 03 code - lit key h, \ 4 04 code - lit dup h, \ 5 05 code - lit swap h, \ 6 06 code - lit drop h, \ 7 07 code - lit 0< h, \ 8 08 code - lit ?exit h, \ 9 09 code - lit >r h, \ 10 0A code - lit r> h, \ 11 0B code - lit - h, \ 12 0C code - lit exit h, \ 13 0D code - lit lit h, \ 14 0E code - lit @ h, \ 15 0F code - lit c@ h, \ 16 10 code - lit ! h, \ 17 11 code - lit c! h, \ 18 12 code - lit execute h, \ 19 13 code - lit branch h, \ 20 14 code - lit ?branch h, \ 21 15 code - lit negate h, \ 22 16 - lit + h, \ 23 17 - lit 0= h, \ 24 18 - lit ?dup h, \ 25 19 - lit cells h, \ 26 1A - lit +! h, \ 27 1B - lit h@ h, \ 28 1C - lit h, h, \ 29 1D - lit here h, \ 30 1E - lit allot h, \ 31 1F - lit , h, \ 32 20 - lit c, h, \ 33 21 - lit fun h, \ 34 22 - lit interpreter h, \ 35 23 - lit compiler h, \ 36 24 - lit create h, \ 37 25 - lit does> h, \ 38 26 - lit cold h, \ 39 27 - lit depth h, \ 40 28 code - lit compile, h, \ 41 29 - lit new h, \ 42 2A - lit couple h, \ 43 2B - lit and h, \ 44 2C code - lit or h, \ 45 2D code - lit sp@ h, \ 46 2E code - lit sp! h, \ 47 2F code - lit rp@ h, \ 48 30 code - lit rp! h, \ 49 31 code - lit $lit h, \ 50 32 - lit num h, \ 51 33 - lit um* h, \ 52 34 code - lit um/mod h, \ 53 35 code - lit unused h, \ 54 36 - lit key? h, \ 55 37 - lit token h, \ 56 38 - lit usleep h, \ 57 39 code - lit hp h, \ 58 40 - interpreter bye ; - +\ we want the text section to be first and bss last (for linkers that output +\ sections in definition order), so it would be good to have the bss section +\ be output by the ",end" hook, but at present we cannot call "pre" from a +\ defined word, so we make do by switching to bss and then back to text again pre section '.bss' writeable @@ -512,4 +360,6 @@ _head: dd HEAD_SIZE dup (0) ; free memory starts at _mem _mem: db MEM_SIZE dup (0) _memtop: + +section '.text' executable ; diff --git a/preForth/seedForth.pre b/preForth/seedForth.pre new file mode 100644 index 0000000..4ca1fbe --- /dev/null +++ b/preForth/seedForth.pre @@ -0,0 +1,159 @@ +\ seedForth: less machine dependent portion + +: negate ( n1 -- n2 ) + 0 swap - ; + +: + ( x1 x2 -- x3 ) + negate - ; + +: 0= ( x -- flag ) + 0 swap ?exit drop -1 ; + +: ?dup ( x -- x x | 0 ) + dup 0= ?exit dup ; + +: 2* ( x1 -- x2 ) + dup + ; + +: cells ( x1 -- x2 ) + 2* 2* ; + +: +! ( x addr -- ) + swap >r dup @ r> + swap ! ; + +: hp ( -- addr ) + lit _hp ; + +: h@ ( i -- addr ) + cells lit head + @ ; + +: h! ( x i -- ) + cells lit head + ! ; + +: h, ( x -- ) + hp @ h! 1 hp +! ; + +: here ( -- addr ) + lit dp @ ; + +: allot ( n -- ) + lit dp +! ; + +: , ( x -- ) + here 1 cells allot ! ; + +: c, ( c -- ) + here 1 allot c! ; + +: compile, ( x -- ) + h@ , ; + +\ token are in the range 0 .. 767: +\ 0, 3 .. 255 are single byte tokens +\ 256 .. 511 are double byte tokens of the form 01 xx +\ 511 .. 767 are double byte tokens of the form 02 xx +: token ( -- x ) + key dup 0= ?exit \ 0 -> single byte token + dup 3 - 0< 0= ?exit \ not 1 2 -> single byte token + key couple ; \ double byte token + +: interpreter ( -- ) + token execute tail interpreter ; \ executing exit will leave this loop + +: num ( -- x ) + tail interpreter ; + +: ?lit ( xt -- xt | ) + dup h@ lit num - ?exit drop \ not num token: exit i.e. normal compile action + lit lit , num , \ generate lit x num call puts x on stack + r> drop tail compiler ; + +: compiler ( -- ) + token ?dup 0= ?exit ?lit + compile, tail compiler ; + +: new ( -- xt ) + hp @ here h, lit enter , ; + +: fun ( -- ) + new drop compiler ; + +: couple ( hi lo -- hilo ) + >r 2* 2* 2* 2* 2* 2* 2* 2* r> + ; + +: $lit ( -- addr u ) + r> dup 1 + dup >r swap c@ dup r> + >r ; + +: create ( -- xt ) + 0 , \ dummy does> field + hp @ here h, lit dovar , ; + +: does> ( xt -- ) \ set code field of last defined word + r> swap h@ dup >r 1 cells - ! lit dodoes r> ! +; + +: unused ( -- u ) + lit memtop here - ; + +: cold ( -- ) + \ 's' emit 'e' dup emit emit 'd' emit 10 emit + lit bye h, \ 0 00 code + 0 h, \ 1 01 prefix + 0 h, \ 2 02 prefix + lit emit h, \ 3 03 code + lit key h, \ 4 04 code + lit dup h, \ 5 05 code + lit swap h, \ 6 06 code + lit drop h, \ 7 07 code + lit 0< h, \ 8 08 code + lit ?exit h, \ 9 09 code + lit >r h, \ 10 0A code + lit r> h, \ 11 0B code + lit - h, \ 12 0C code + lit exit h, \ 13 0D code + lit lit h, \ 14 0E code + lit @ h, \ 15 0F code + lit c@ h, \ 16 10 code + lit ! h, \ 17 11 code + lit c! h, \ 18 12 code + lit execute h, \ 19 13 code + lit branch h, \ 20 14 code + lit ?branch h, \ 21 15 code + lit negate h, \ 22 16 + lit + h, \ 23 17 + lit 0= h, \ 24 18 + lit ?dup h, \ 25 19 + lit cells h, \ 26 1A + lit +! h, \ 27 1B + lit h@ h, \ 28 1C + lit h, h, \ 29 1D + lit here h, \ 30 1E + lit allot h, \ 31 1F + lit , h, \ 32 20 + lit c, h, \ 33 21 + lit fun h, \ 34 22 + lit interpreter h, \ 35 23 + lit compiler h, \ 36 24 + lit create h, \ 37 25 + lit does> h, \ 38 26 + lit cold h, \ 39 27 + lit depth h, \ 40 28 code + lit compile, h, \ 41 29 + lit new h, \ 42 2A + lit couple h, \ 43 2B + lit and h, \ 44 2C code + lit or h, \ 45 2D code + lit sp@ h, \ 46 2E code + lit sp! h, \ 47 2F code + lit rp@ h, \ 48 30 code + lit rp! h, \ 49 31 code + lit $lit h, \ 50 32 + lit num h, \ 51 33 + lit um* h, \ 52 34 code + lit um/mod h, \ 53 35 code + lit unused h, \ 54 36 + lit key? h, \ 55 37 + lit token h, \ 56 38 + lit usleep h, \ 57 39 code + lit hp h, \ 58 40 + interpreter bye ; From f843d0837c0f67f7491a4702e2b6ec8ad86b176b Mon Sep 17 00:00:00 2001 From: Nick Downing Date: Sat, 23 Apr 2022 02:44:02 +1000 Subject: [PATCH 8/9] Split seedforth-i386.pre further into header and body portions --- preForth/Makefile | 4 ++-- preForth/seedForth-i386-header.pre | 22 ++++++++++++++++++++++ preForth/seedForth-i386.pre | 11 ----------- 3 files changed, 24 insertions(+), 13 deletions(-) create mode 100644 preForth/seedForth-i386-header.pre diff --git a/preForth/Makefile b/preForth/Makefile index a07d51c..47532b6 100644 --- a/preForth/Makefile +++ b/preForth/Makefile @@ -103,8 +103,8 @@ rundocker: docker-image # ------------------------------------------------------------------------ # seedForth # ------------------------------------------------------------------------ -seedForth.$(EXT): seedForth-i386.pre seedForth.pre preForth - cat seedForth-i386.pre seedForth.pre |./preForth >seedForth.$(EXT) +seedForth.$(EXT): seedForth-i386-header.pre seedForth-i386.pre seedForth.pre preForth + cat seedForth-i386-header.pre seedForth-i386.pre seedForth.pre |./preForth >seedForth.$(EXT) %.seed: %.seedsource seedForth-tokenizer.fs gforth seedForth-tokenizer.fs $< diff --git a/preForth/seedForth-i386-header.pre b/preForth/seedForth-i386-header.pre new file mode 100644 index 0000000..a7022ec --- /dev/null +++ b/preForth/seedForth-i386-header.pre @@ -0,0 +1,22 @@ +\ seedForth: machine dependent header portion + +\ this contains only definitions we want at the top of the file +\ it is then followed by preForth-i386-rts.pre (primitive asm words) +\ and then by seedForth-i386.pre (additional primitive asm words) +\ and then by seedForth.pre (high level words and the interpreter) + +pre +;;; This is seedForth - a small potentially interactive Forth, that dynamically +;;; bootstraps from a minimal kernel. +;;; +;;; cat seedForth.seed - | ./seedForth +;;; +;;; .seed files are in byte-tokenized source code format. +;;; +;;; Use the seedForth tokenizer to convert human readable source code to +;;; byte-token form. + +HEAD_SIZE = 40000 +MEM_SIZE = 400000 + +; diff --git a/preForth/seedForth-i386.pre b/preForth/seedForth-i386.pre index 1c59965..9aa56c6 100644 --- a/preForth/seedForth-i386.pre +++ b/preForth/seedForth-i386.pre @@ -10,19 +10,8 @@ \ ESP data stack pointer pre -;;; This is seedForth - a small,potentially interactive Forth, that dynamically -;;; bootstraps from a minimal kernel. -;;; -;;; cat seedForth.seed - | ./seedForth -;;; -;;; .seed-files are in byte-tokenized source code format. -;;; -;;; Use the seedForth tokenizer to convert human readable source code to byte-token form. - DATA_STACK_SIZE = 40000 RETURN_STACK_SIZE = 40000 -HEAD_SIZE = 40000 -MEM_SIZE = 400000 format ELF From cdd868665dc06148e0d0c0b149bab6ac8b05770f Mon Sep 17 00:00:00 2001 From: Nick Downing Date: Sat, 23 Apr 2022 02:55:09 +1000 Subject: [PATCH 9/9] Remove duplicated code in seedForth-i386.pre, take from preForth-i386-rts.pre --- preForth/Makefile | 15 ++- preForth/preForth-i386-rts.pre | 1 + preForth/seedForth-i386.pre | 169 ++------------------------------- 3 files changed, 20 insertions(+), 165 deletions(-) diff --git a/preForth/Makefile b/preForth/Makefile index 47532b6..945cac0 100644 --- a/preForth/Makefile +++ b/preForth/Makefile @@ -103,13 +103,22 @@ rundocker: docker-image # ------------------------------------------------------------------------ # seedForth # ------------------------------------------------------------------------ -seedForth.$(EXT): seedForth-i386-header.pre seedForth-i386.pre seedForth.pre preForth - cat seedForth-i386-header.pre seedForth-i386.pre seedForth.pre |./preForth >seedForth.$(EXT) +seedForth.$(EXT): \ +seedForth-i386-header.pre \ +preForth-i386-rts.pre \ +seedForth-i386.pre \ +seedForth.pre \ +preForth + cat \ +seedForth-i386-header.pre \ +preForth-i386-rts.pre \ +seedForth-i386.pre \ +seedForth.pre \ +|./preForth >seedForth.$(EXT) %.seed: %.seedsource seedForth-tokenizer.fs gforth seedForth-tokenizer.fs $< - .PHONY=clean clean: rm -f *.asm *.o *.seed preForthdemo preForth seedForth diff --git a/preForth/preForth-i386-rts.pre b/preForth/preForth-i386-rts.pre index 9adda37..f54a123 100644 --- a/preForth/preForth-i386-rts.pre +++ b/preForth/preForth-i386-rts.pre @@ -171,4 +171,5 @@ return_stack: db RETURN_STACK_SIZE dup (0) section '.text' executable + ; diff --git a/preForth/seedForth-i386.pre b/preForth/seedForth-i386.pre index 9aa56c6..03a6b37 100644 --- a/preForth/seedForth-i386.pre +++ b/preForth/seedForth-i386.pre @@ -1,51 +1,13 @@ \ seedForth: machine dependent portion -\ seedForth - seed it, feed it, grow it - i386 (32 bit) ITC flavour uho 2018-04-13 -\ ---------------------------------------------------------------------------------- -\ -\ - registers: -\ EAX, EDX general purpose -\ ESI instruction pointer -\ EBP return stack pointer -\ ESP data stack pointer +\ interpreter and basic asm primitives are taken from preForth-i386-rts.pre, +\ and then this file defines additional primitives (arithmetic, memory, etc) pre -DATA_STACK_SIZE = 40000 -RETURN_STACK_SIZE = 40000 - -format ELF - -section '.text' executable - -public main -extrn putchar -extrn getchar -extrn fflush -extrn exit extrn ioctl extrn usleep -macro next { - lodsd - jmp dword [eax] -} - -origin: - -main: cld - mov esp,data_stack + DATA_STACK_SIZE - mov ebp,return_stack + RETURN_STACK_SIZE - mov esi,main1 - next - -main1: dd _cold - dd _bye - -_nest: -_enter: lea ebp,[ebp-4] - mov [ebp],esi - lea esi,[eax+4] - next +_enter = _nest _dodoes: ; ( -- addr ) lea ebp,[ebp-4] ; push IP @@ -57,50 +19,6 @@ _dovar: ; ( -- addr ) next ; -code bye ( -- ) - push ebp - mov ebp,esp - and esp,0xfffffff0 - mov eax,0 - mov [esp],eax - call exit -; - -code emit ( c -- ) - pop eax - - push ebp - mov ebp,esp - push eax - and esp,0xfffffff0 - - mov dword [esp],eax - call putchar - - mov eax,0 - mov [esp],eax - call fflush ; flush all output streams - - mov esp,ebp - pop ebp - next -; - -code key ( -- c ) - push ebp - mov ebp,esp - and esp,0xfffffff0 - - call getchar - mov esp,ebp - pop ebp - cmp eax,-1 - jnz key1 - mov eax,4 ; eof: return Ctrl-D -key1: push eax - next -; - code key? ( -- f ) push ebp mov ebp,esp @@ -125,65 +43,7 @@ keyq1: push eax next ; -code dup ( x -- x x ) - pop eax - push eax - push eax - next -; - -code swap ( x y -- y x ) - pop edx - pop eax - push edx - push eax - next -; - -code drop ( x -- ) - pop eax - next -; - -code 0< ( x -- flag ) - pop eax - sar eax,31 - push eax - next -; - -code ?exit ( f -- ) \ high level: IF exit THEN - pop eax - or eax,eax - jz qexit1 - mov esi,[ebp] - lea ebp,[ebp+4] -qexit1: next -; - -code >r ( x -- ) ( R -- x ) - pop ebx - lea ebp,[ebp-4] - mov [ebp],ebx - next -; - -code r> ( R x -- ) ( -- x ) - mov eax,[ebp] - lea ebp,[ebp+4] - push eax - next -; - -code - ( x1 x2 -- x3 ) - pop edx - pop eax - sub eax,edx - push eax - next -; - -code or ( x1 x2 -- x3 ) +code or ( x1 x2 -- x3 ) pop edx pop eax or eax,edx @@ -191,7 +51,7 @@ code or ( x1 x2 -- x3 ) next ; -code and ( x1 x2 -- x3 ) +code and ( x1 x2 -- x3 ) pop edx pop eax and eax,edx @@ -200,18 +60,7 @@ code and ( x1 x2 -- x3 ) ; pre -_unnest: -; -code exit ( -- ) - mov esi,[ebp] - lea ebp,[ebp+4] - next -; - -code lit ( -- ) - lodsd - push eax - next +_exit = _unnest ; code @ ( addr -- x ) @@ -334,11 +183,6 @@ code usleep ( c -- ) pre section '.bss' writeable -data_stack: - db DATA_STACK_SIZE dup (0) -return_stack: - db RETURN_STACK_SIZE dup (0) - ; dictionary pointer: points to next free location in memory _dp: dd _mem @@ -351,4 +195,5 @@ _mem: db MEM_SIZE dup (0) _memtop: section '.text' executable + ;