link: add "offset" argument to RLDICT

As long as our target was the first word of the "user" dict, using
target's prev to compute offset was fine, but when the target is not
the first word, this system breaks down.

This is the case when, instead of including source code in our boot
binary, we paste it in Collapse OS' prompt.

Also, adjust RC2014 recipe to include stage 3 assembling instructions
with the "paste into prompt" method.
This commit is contained in:
Virgil Dupras 2020-04-19 16:28:40 -04:00
parent 29a6ee128d
commit dfaa1dc101
3 changed files with 55 additions and 27 deletions

View File

@ -110,11 +110,11 @@
( TODO implement RLCELL ) ( TODO implement RLCELL )
( Copy dict from target wordref, including header, up to HERE. ( Copy dict from target wordref, including header, up to HERE.
We're going to compact the space between that word and its We're going relocate those words by specified offset. To do
prev word. To do this, we're copying this whole memory area this, we're copying this whole memory area in HERE and then
in HERE and then iterate through that copied area and call iterate through that copied area and call RLWORD on each
RLWORD on each word. That results in a dict that can be word. That results in a dict that can be concatenated to
concatenated to target's prev entry in a more compact way. target's prev entry in a more compact way.
This copy of data doesn't allocate anything, so H@ doesn't This copy of data doesn't allocate anything, so H@ doesn't
move. Moreover, we reserve 4 bytes at H@ to write our target move. Moreover, we reserve 4 bytes at H@ to write our target
@ -129,19 +129,16 @@
possible to reliably detect its end. If you need that last possible to reliably detect its end. If you need that last
word, define a dummy word before calling RLDICT. word, define a dummy word before calling RLDICT.
) )
( target -- ) ( target offset -- )
: RLDICT : RLDICT
( First of all, let's get our offset. It's easy, it's ( First of all, let's get our offset. It's easy, it's
target's prev field, which is already an offset, minus target's prev field, which is already an offset, minus
its name length. We expect, in RLDICT that a target's its name length. We expect, in RLDICT that a target's
prev word is a "hook word", that is, an empty word. ) prev word is a "hook word", that is, an empty word. )
( H@ == target )
DUP H@ !
DUP 1- C@ 0x7f AND ( t namelen )
SWAP 3 - @ ( namelen po )
-^ ( o )
( H@+2 == offset ) ( H@+2 == offset )
H@ 2+ ! ( ) H@ 2+ ! ( target )
( H@ == target )
H@ ! ( )
( We have our offset, now let's copy our memory chunk ) ( We have our offset, now let's copy our memory chunk )
H@ @ WORD( ( src ) H@ @ WORD( ( src )
DUP H@ -^ ( src u ) DUP H@ -^ ( src u )
@ -180,5 +177,9 @@
( Relink a regular Forth full interpreter. ) ( Relink a regular Forth full interpreter. )
: RLCORE : RLCORE
LIT< H@ (find) DROP RLDICT LIT< H@ (find) DROP ( target )
DUP 3 - @ ( t prevoff )
( subtract H@ name length )
2- ( t o )
RLDICT
; ;

View File

@ -210,22 +210,49 @@ That's it! our binary is ready to run!
../../emul/hw/rc2014/classic stage2r.bin ../../emul/hw/rc2014/classic stage2r.bin
And there you have it, a stage2 binary that you've assembled yourself. Now, And there you have it, a stage2 binary that you've assembled yourself.
here's for your homework: use the same technique to add the contents of
`readln.fs` and `adev.fs` to stage2 so that you have a full-featured
interpreter.
Name it `stage3.bin` (the version without any source code appended and no ### Assembling stage 3
`INIT` word defined), you'll need this binary for sub-recipes written for the
RC2014.
Here's a little cheatsheet, but seriously, you should figure most of it Stage 2 gives you a useable prompt, but bare. Because 8K isn't a lot of space
yourself. Tough love they call it. to cram source code, we're limited in what we can include for this stage.
* `cat stage2.bin ../../forth/readln.fs ../../forth/adev.fs run.fs > stage2r.bin` However, now that we have a usable prompt, we can do a lot (be cautious though:
* Don't forget `RDLN$` and `ADEV$`. there is no `readln` yet, so you have no backspace), for example, build a
* `RLDICT` is like `RLCORE` but with a chosen target. stage 3 with `readln`.
* `stripfc` can help you deal with size constraints.
Copy the unit's source
cat ../../forth/readln.fs | ../../tools/stripfc | xclip
and just paste it in your terminal. If you're doing the real thing and not
using the emulator, pasting so much code at once might freeze up the RC2014, so
it is recommended that you use `/tools/exec` that let the other side enough
time to breathe.
After your pasting, you'll have a compiled dict of that code in memory. You'll
need to relocate it in the same way you did for stage 2, but instead of using
`RLCORE`, which is a convenience word hardcoded for stage 1, we'll parametrize
`RLDICT`, the word doing the real work.
`RLDICT` takes 2 arguments, `target` and `offset`. `target` is the first word
of your relocated dict. In our case, it's going to be `' INBUFSZ`. `offset` is
the offset we'll apply to every eligible word references in our dict. In our
case, that offset is the offset of the *beginning* of the `INBUFSZ` entry (that
is, `' INBUFSZ WORD(` minus the offset of the last word (which should be a hook
word) in the ROM binary.
That offset can be conveniently fetched from code because it is the value of
the `LATEST` constant in stable ABI, which is at offset `0x08`. Therefore, our
offset value is:
' INBUFSZ WORD( 0x08 @ -
You can now run `RLDICT` and proceed with concatenation (and manual adjustments
of course) as you did with stage 2. Don't forget to adjust `run.fs` so that it
initializes `RDLN$` instead of creating a minimal `(c<)`.
Keep that `stage3.bin` around, you will need it for further recipes.
[rc2014]: https://rc2014.co.uk [rc2014]: https://rc2014.co.uk
[romwrite]: https://github.com/hsoft/romwrite [romwrite]: https://github.com/hsoft/romwrite

View File

@ -1,7 +1,7 @@
: (c<) KEY DUP EMIT ; : (c<) KEY DUP EMIT ;
: INIT : INIT
ACIA$ ACIA$
." Collapse OS" CR LF ." Collapse OS" CRLF
( 0c == CINPTR ) ( 0c == CINPTR )
['] (c<) 0x0c RAM+ ! ['] (c<) 0x0c RAM+ !
; ;