home *** CD-ROM | disk | FTP | other *** search
FORTH Source | 2006-10-19 | 12.8 KB | 733 lines |
- \ set level of self-diagnostics to perform on boot.
- 1 constant init-test-level
-
- variable startmem here startmem !
-
- \ get-rom-addr defined in command line as a constant
- get-rom-addr constant ROM-start-addr
-
- create mach-file ," 99config.fs"
- include cross.fs
-
- \ \\\\\\\\\\\\\\\\\\\\\\\\\\\
-
- Warnings on
-
- unlock
-
- 0000 10000 region address-space
- ROM-start-addr 8000 over - region rom-dictionary
- A000 6000 region ram-dictionary
-
- 10000 makekernel
-
- only forth also definitions
-
- \ \\\\\\\\\\\\\\\\\\\\\\\\\
-
- \ also environment also forth
- also cross also target also forth
- : env-has?
- name T environment? H
- IF \ environment variable is present, return its value
- ELSE \ environment variable is not present, return false
- \ !! JAW abort is just for testing
- false true ABORT" arg"
- THEN
- ; immediate
- previous previous previous
- \ previous
-
- \ \\\\\\\\\\\\\\\\\\\\\\\\\\
-
- \ only forth also definitions
-
- \ Machine definitions
-
- \ also minimal definitions
- \ only forth
- \ also minimal
- \ also definitions
- >target
- include 99asm.fs
- include 99equs.fs
-
- only forth also definitions
-
- \ : Asm
- \ also assembler also asm-hidden
- \ ;
-
- \ Asm
-
- variable out-fileid stdout out-fileid !
- variable copy-to-scrn copy-to-scrn off
-
- : my-emit
- dup
- out-fileid @ emit-file drop
- \ write to screen only if it's not the current output
- \ and we want to copy to screen
- stdout out-fileid @ over <>
- copy-to-scrn @ and if
- emit-file drop
- else
- 2drop
- then
- ;
-
- ' my-emit IS emit
-
- : my-type
- 2dup
- out-fileid @ write-file drop
- stdout out-fileid @ over <>
- copy-to-scrn @ and if
- write-file drop
- else
- 2drop drop
- then
- ;
-
- ' my-type IS type
-
- : stdout>file ( caddr u -- )
- r/w create-file throw out-fileid !
- copy-to-scrn off
- ;
-
- : >stdout
- out-fileid @ close-file
- stdout out-fileid !
- ;
-
-
- \ \\\\\\\\\\\\
-
- >minimal also cross also minimal also forth
-
- : -visible
- copy-to-scrn off
- ;
-
- : visible
- copy-to-scrn on
- ;
-
- : error"
- copy-to-scrn @
- s" ERROR: " type
- visible $22 parse type
- cr
- copy-to-scrn !
- ;
-
- \ \\\\\\\\\\\\\\\\\\\
-
- \ Testing words.
- \ Using: test" word ... "
- \ will define a test for "word" that consists of "...".
- \ At runtime, the test will be executed, and leaving "0" on the stack
- \ indicates failure, "1" indicates success. If fails, the name
- \ is printed.
-
- variable test-fileid
- variable test-level init-test-level test-level !
-
- : write"
- test-fileid @ write-file drop
- ;
-
- : cr"
- $a pad c! pad 1 write"
- ;
-
- : write-test-header
- \ init code
- s" : [name. ( xt -- caddr u ) xt>nfa dup 1+ swap c@ $1f and ; " write" cr"
- \ test run: xt is :noname def, txt is word to blame ;)
- s" : (runtest sp0 @ sp! ; " write" cr"
- s" : runtest) ( txt t/f -- ) " write" cr"
- s" swap if ( 2a emit [name. type 2b emit ) drop else ( 5b emit ) [name. type ( 5d emit ) then 2e emit ; " write" cr"
- \ header for test runner
- s" : runtests 5b emit " write" cr"
- ;
-
- : create-test-file
- test-fileid @ 0= if
- s" 99tests.fth" r/w create-file throw test-fileid !
- write-test-header
- then
- ;
-
- \ Add test to tests list.
- : #test" ( level "word test" -- )
- create-test-file
- test-level @ < if
- $20 parse \ write"
- \ clean stack
- s" (runtest " write"
- \ then it's the test
- $22 parse write"
- \ token for blame if error
- s" ['] " write" write"
- \ execute
- s" runtest) " write" cr"
- else
- $20 parse 2drop $22 parse 2drop
- then
- ;
-
- \ force test
- : test" 0 #test" ;
-
- \ various test levels
- : 1test" 1 #test" ;
- : 2test" 2 #test" ;
- : 3test" 3 #test" ;
-
- : close-test-file
- test-fileid @ if
- s" 5d emit ; " write" cr"
- test-fileid @ close-file
- else
- create-test-file
- s" " write"
- recurse
- then
- ;
-
- >minimal
- \ also minimal definitions previous
-
- : append-test-file
- close-test-file
- s" 99tests.fth" included
- ;
-
- previous previous
-
- \ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\
- >cross
- variable tram
- >target
- $2000 tram !
-
- >cross
- \ also cross \ definitions also target
- \ definitions
-
- env-has? standard-threading
- 0= [if]
-
- \ go direct threading!
- \ Overrides for dictionary creating words.
- \ We want a direct threading model instead of
- \ the indirect threading model, for better
- \ performance.
-
- \ for direct threading, the code field contains actual
- \ code, not a pointer to it.
- \ for primitives, assembly starts here.
- \ for colon defs, a BL *DODOES starts here.
- \ for constants, a BL @>DOCON starts here.
- \ for variables, a BL @>DOVAR starts here.
-
- 0 include common.fs
-
- :noname ( tcfa -- ) \ compiles call to tcfa at current position
- \ !!! ugly hack: defer/is words
- \ appear to point to the wrong CFA.
- T dup 1 cells - @ $06A0 = if 1 cells - then H
- T , H \ tcfa -> code
- ; IS colon,
-
- \ for constant/variable references
- :noname
- >tempdp ]comp
- T , H comp[ tempdp>
- ; IS colon-resolve
-
- :noname
- BL-DODOES T , H
- addr,
- ; IS dodoes,
-
- :noname ( -- )
- BL-DOCOL T , H
- ; IS docol,
-
- :noname ( -- )
- ; IS doprim,
-
- \ for dodefer, etc?
- :noname ( ghost -- )
- ." doer," cr
- BL-@ tdp @ T 1 cells - H T ! H addr,
- \ BL-@ , addr,
- $80 flag!
- \ BL-DODOES , addr,
- ; IS doer,
-
-
-
- \ \ EJS 001130 GF0.5.0
- >target
-
- \ DeferROMs MUST BE 'ROMIS'ed at startup!
- BuildSmart: ( -- ) tram @ dup T 1 cells + H tram ! T A, H ; \ [T'] noop swap T ! H ;
- by: :dordefer ( ghost -- ) ABORT" CROSS: Don't execute" ;DO
- Builder DeferROM
-
- : IS
- T ' cell+ ! H
- ;
-
- : ROMIS
- T ' cell+ @ ! H
- ;
- >cross
-
- ." !!! 99doeshandler, is still weird" cr
- :noname
- \ case of "create foo <allot> does> <code> ;"
- \ we have | BL *DODOES | <variable info> | <doesjump> | <code>
- T cfalign H
- \ there tcell - t@ tcell - there tcell - t!
- BL-DOCOL ,
- ; IS doeshandler,
-
- \ don't stick unloop in here -- saves 2 bytes per do/loop
- :noname 1to compile (loop) loop] skiploop] ;
- IS loop, ( target-addr -- )
- :noname 1to compile (+loop) loop] skiploop] ;
- IS +loop, ( target-addr -- )
-
-
- \ also cross definitions
-
- \ Note: don't change this, even though
- \ we don't have the "blank gap" for all
- \ words. Two cells is indeed the gap for
- \ CREATEd words, which is what the Ghost
- \ routines need (to execute a CONSTANT defined
- \ in the ROM, for instance)
- \ cr order
- \ :noname
- \ 2 +
- \ ; T IS >body H
- \ 4 TO xt>body
-
- [else]
- \ abort
- [then]
-
- \ \\\\\\\\\\\\\\\\\\\\
-
- \ Dictionary and hash table maintenance.
-
- \ too damn slow and memory hogging
- 0 [if]
-
- >cross
-
- variable FORTH-wordlis
- \ right circular shift
- \ x n cshift == ( x>>n | x << 16-n )
- : cshift
- >r
- $ffff and
- dup r@ \ .s
- rshift swap $10 r> - \ .s
- lshift
- \ .s
- OR $ffff and
- ;
-
- ." cshift: "
- $000a 5 cshift . cr
-
- 0 include commonhash.fs
-
- \ preallocate buckets for hash table
-
- T here
- hash-buckets hash-bucket-size * cells dup allot
- over swap erase
- dup ." hash buckets start at " . cr
-
- \ .s
- \ save target ptr
- FORTH-wordlis H !
-
- previous
-
- >minimal
- also cross definitions
-
- >cross
-
- create newname $20 allot
-
- \ Our own header routine.
- \ We need to possibly allocate dict
- \ space for hash table expansion --
- \ so, we get the entry for the new name first,
- \ then lay down the header.
-
- \ Read name from input stream and
- \ add it to hash table. Return tptr to
- \ the place we should store the NFA.
-
- variable newcfa
- : add-hash-entry ( "name" -- addr )
- ." add-hash-entry" cr
- forth-wordlis @
- bl word count
-
- T hash>new H \ leaves new entry addr
-
- ;
-
- :noname ( "name" -- )
- >in @
- add-hash-entry
- >r >in ! r>
-
- T align H view,
- tlast @ dup 0> IF T 1 cells - H THEN T A, H there tlast !
-
- \ write NFA to hash table
- T here cfaligned swap ! H
-
- >in @ T name, H >in !
-
- ; IS header,
-
- \ see name,
-
- [then] \ hash table stuff
-
- \ \\\\\\\\\\\\\\\\\\\\
-
-
- T has? profiling H [if]
-
- \ expect maximum 1024 words (for profiling)
- $a800 constant high-ram-start
-
- \ Statistics: we add a field to each word which
- \ points into RAM. Increment this pointer for each
- \ execution of the word.
-
- :noname ( "name" -- )
- T align H view,
- tlast @ dup 0> IF T cell - H THEN T A, H there tlast !
- >in @ T name, H >in !
-
- \ write the address of the profiling word
- tram @ start-grom-image >= if
- abort" out of profiling space, adjust start-grom-image"
- then
- tram @ T A, cell H tram +!
- ; IS header,
-
- [else]
-
- $a000 constant high-ram-start
-
- [then]
-
- \ \\\\\\\\\\\\\\\\\\\\
-
- >cross
- order
-
- $2800 constant low-ram-start
-
- \ move 'there' to module area
- \ if out of CPU ROM space
- \ not too bright -- literal strings make big definitions
-
- \ eat up 0...$2000, then $6000...$7fff, then high-ram-start...$ffff
- \
- \
- : checkmemory ( delta -- )
- >r
- there $0000 $2002 within if
- there $2000 r@ - >= if
- ." Switching to module ROM bank..." cr
- $6000 tdp !
- $aa55 T , H
- then
- else there $6000 $8002 within if
- there $8000 r@ - >= if
- ." Switching to high memory bank..." cr
- high-ram-start 3 cells + tdp !
- then
- else there $10000 >= if
- abort" All ROMable dictionaries full!" cr
- then
- then
- then
- rdrop
- ;
-
- \ These routines are called from the cross compiler
- \ at locations where it's useful to dump a disassembly
- \ or a dictionary header. They assume that the dictionary
- \ is linearly organized (i.e., names are inline with code)
- \ and that 'there' increments linearly.
-
- variable code-start ROM-start-addr code-start !
- variable ended-code 1 ended-code !
-
- \ print all data accumulated since last time
- \ if ended-code, then it's data, else ignore, since it's code
- \
- : (print-data)
- ended-code @ if
- code-start @ \ start
- dup
- there swap -
- dup 4000 > if \ changed banks
- code-start @ dup 1fff or 1+ over - T tdump H cr
- 2drop there e000 and dup there swap -
- then
- T tdump H cr
- then
- $40 checkmemory
- ;
-
- : (doc-code)
- also cross also assembler \ also asm-hidden
- (print-data)
- ended-code @ if
- ." Assembling at @>" there dup code-start ! . cr
- 0 ended-code !
- then
- ;
-
- : (print-code)
- cr code-start @ there over - T dis H cr
- there code-start !
- ;
-
- : (doc-end-code)
- previous previous \ previous
- $40 checkmemory
- (print-code)
- 1 ended-code !
- ;
-
-
-
- ' (doc-code) IS (code)
- ' (doc-end-code) IS (end-code)
-
- : (doc-end-colon)
- (fini,)
- $40 checkmemory
-
- (print-data)
- 1 ended-code !
- there code-start !
- ;
-
- ' (doc-end-colon) IS fini,
-
- \ only forth also cross
- previous previous \ no more asm
-
- s" list.lst" stdout>file
-
-
- \ \\\\\\\\\\\\\\\\\\\\\\\\\\
-
- 0 [if]
-
- \ only forth
- \ also target
- \ also cross
- \ also ghosts
- \ >target H
- \ order
- \ also target
-
- only forth also target definitions also forth also cross definitions
-
- \ A word to prevent redefintions
- \ (i.e., we define a primitive, and only load the high-
- \ level version if not found)
-
- \ ." LOOK:"
- \ order cr
- \ ??? what the hell is wrong with the vocabularies?
-
- \ : old; compile ; ; immediate
-
- \ : ; .S compile ; old; immediate
- here .
- H : :
- \ .S
- \ order
- >in @ \ store original
- 20 word \ parse the name
- swap >in ! \ restore pointer
-
- dup >r 1+ r> c@ \ convert C" to S"
- 2dup \ .S
- context @ search-wordlist
- if
- drop cr ." Note: " type ." is already defined, ignoring new definition" cr
- else
- cr ." Defining new word " type cr
- then
- T : H
- \ .S
- ; \ IS created?
-
- \ : old: : ;
- \ : old; compile ; ;
-
- \ : ; [compile] dup; old; immediate
- \ : dup: old;
-
-
- \ >target
- \ ' dup-created? IS created?
- \ ' dup; IS ;
-
- [then]
-
- \ \\\\\\\\\\\
-
- include 99memory.fs
-
- \ \\\\\\\\\\\\\\\\\\\\\\\\\\\
-
- lock
-
- >rom
-
- [[ NoHeaderFlag on ]]
- \ \EJS 001130 GF0.5.0
- : T ; immediate
- [[ NoHeaderFlag on ]]
- \ \ EJS 001130 GF0.5.0
- : H ; immediate
-
- \ include defer.fs
-
- include user.fs
-
- include 99prims.fs
-
- unlock
-
- \ [[ $6000 tdp ! ]]
- \ $6000 tdp !
-
- lock
-
- \ $aa55 ,
-
- include constant.fs
- include kernel.fs
- include interp.fs
- include dict.fs
- include compile.fs
- include files.fs
- include init.fs
-
- \ \\\\\\\\\\\\\\\\\
-
- User >latest \ latest definition
-
- \ Return latest definition's nfa
- : latest
- >latest @
- ;
-
-
- \ [[ there $7e00 > [if] $c000 tdp ! [then] ]]
-
- append-test-file
-
- \ The RAM dictionary is copied from GROM to $a000.
- \ We use 'tram' to keep track of whatever stuff
- \ is chosen to reside in RAM.
-
- 0 [if]
-
- [[ tram @ ]] constant dp0 \ start of first user dict
- dp0 constant (dp0
- StartRAM constant dp0) \ end of first user dict
-
- \ $20: reserve space for defns for (dp1 and fence!
- [[ high-ram-start there $20 + max ]] constant (dp1 \ start of second user dict
-
- [else]
-
- [[ high-ram-start there $20 + max ]] constant dp0
-
- [then]
-
- here constant fence
-
- unlock
-
- \ \\\\\\\\\\\\\\\\\\\\\\
-
- \ finish off memory dump
-
- (print-data)
-
- visible
-
- .regions
-
- turnkey
-
-
- .stats
- .unresolved
-
- unlock
-
-
- \ Write module ROM to disk...
- \ rom-dictionary extent save-region nforthc.bin
-
- \ Write end of ROM to end of nforth.rom
- ROM-start-addr $2000 over - save-region nforth.prm
- $6000 $2000 save-region nforthc.bin
-
- \ Write high RAM dictionary...
- \ in GROM, the memory is stored as repeating <$aa55> <start> <stop> <data...>
- \ where <start>/<stop> are the ranges of RAM to copy the following data to.
-
- there high-ram-start $10000 within
- [if]
- $aa55 high-ram-start T ! H \ magic
- high-ram-start dup T cell+ ! H \ start addr in RAM
- there high-ram-start T cell+ cell+ ! H \ last addr in RAM
- high-ram-start
- there high-ram-start - \ 1fff or
- save-region nforthg.bin
- [else]
- high-ram-start 0 save-region nforthg.bin
- [then]
-
- there ." HERE is " . cr
- tram @ $a000 - ." Used " . ." bytes of high RAM space for storage" cr
-
- >stdout
-
-
-
-
-
-
-
-