mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-26 20:38:10 +11:00
Compare commits
No commits in common. "4c7dfe0dfe8b1f4e5aadd1c715b90c3a01a5642d" and "d6c9ab3f32e6e54f23b32b59b32eddff29d814bd" have entirely different histories.
4c7dfe0dfe
...
d6c9ab3f32
@ -21,23 +21,6 @@ directly, but as part of another word.
|
|||||||
|
|
||||||
"*I*" in description indicates an IMMEDIATE word.
|
"*I*" in description indicates an IMMEDIATE word.
|
||||||
|
|
||||||
*** Symbols ***
|
|
||||||
|
|
||||||
Throughout words, different symbols are used in different contexts, but we try
|
|
||||||
to been consistent in their use. Here's their definitions:
|
|
||||||
|
|
||||||
! - Store
|
|
||||||
@ - Fetch
|
|
||||||
$ - Initialize
|
|
||||||
^ - Arguments in their opposite order
|
|
||||||
< - Input
|
|
||||||
> - 1. Pointer in a buffer 2. Opposite of "<".
|
|
||||||
( - Lower boundary
|
|
||||||
) - Upper boundary
|
|
||||||
* - Word indirection (pointer to word)
|
|
||||||
~ - Container for native code. Usually not an executable word.
|
|
||||||
? - Is it ...? (example: IMMED?)
|
|
||||||
|
|
||||||
*** Defining words ***
|
*** Defining words ***
|
||||||
(find) a -- a f Read at a and find it in dict. If found, f=1 and
|
(find) a -- a f Read at a and find it in dict. If found, f=1 and
|
||||||
a = wordref. If not found, f=0 and a = string addr.
|
a = wordref. If not found, f=0 and a = string addr.
|
||||||
@ -122,16 +105,6 @@ HERE -- a Push HERE's address
|
|||||||
H@ -- a HERE @
|
H@ -- a HERE @
|
||||||
MOVE a1 a2 u -- Copy u bytes from a1 to a2, starting with a1, going
|
MOVE a1 a2 u -- Copy u bytes from a1 to a2, starting with a1, going
|
||||||
up.
|
up.
|
||||||
*** Addressed devices ***
|
|
||||||
|
|
||||||
See usage.txt for details.
|
|
||||||
|
|
||||||
ADEV$ -- Initialize adev subsystem
|
|
||||||
A@ a -- c Indirect C@
|
|
||||||
A! c a -- Indirect C!
|
|
||||||
A@* -- a Address for A@ word
|
|
||||||
A!* -- a Address for A! word
|
|
||||||
AMOVE src dst u -- Same as MOVE, but with A@ and A!
|
|
||||||
|
|
||||||
*** Arithmetic / Bits ***
|
*** Arithmetic / Bits ***
|
||||||
|
|
||||||
|
17
drv/at28.fs
17
drv/at28.fs
@ -1,17 +0,0 @@
|
|||||||
( With dst being assumed to be an AT28 EEPROM, perform !
|
|
||||||
operation while doing the right thing. Checks data integrity
|
|
||||||
and ABORT on mismatch.
|
|
||||||
)
|
|
||||||
( a n -- )
|
|
||||||
: AT28!
|
|
||||||
2DUP C! SWAP
|
|
||||||
( as long as writing operation is running, IO/6 will toggle at each
|
|
||||||
read attempt. We know that write is finished when we read the same
|
|
||||||
value twice. )
|
|
||||||
BEGIN ( n1 a )
|
|
||||||
DUP C@ ( n1 a n2 )
|
|
||||||
OVER C@ ( n1 a n2 n3 )
|
|
||||||
= UNTIL
|
|
||||||
( We're finished writing. do we have a mismatch? )
|
|
||||||
C@ = NOT IF ABORT" mismatch" THEN
|
|
||||||
;
|
|
@ -1 +1 @@
|
|||||||
: INIT RDLN$ Z80A$ INTERPRET ;
|
: INIT (c<$) INTERPRET ;
|
||||||
|
Binary file not shown.
@ -1,34 +0,0 @@
|
|||||||
( Addressed devices.
|
|
||||||
|
|
||||||
Abstractions to read and write to devices that allow addressed
|
|
||||||
access. At all times, we have one active "fetch" device and
|
|
||||||
one active "store" device, A@ and A!.
|
|
||||||
|
|
||||||
Those words have the same signature as C@ and C!, and in fact,
|
|
||||||
initially default to proxy of those words.
|
|
||||||
)
|
|
||||||
|
|
||||||
: ADEVMEM+ 0x55 RAM+ @ + ;
|
|
||||||
: A@* 0 ADEVMEM+ ;
|
|
||||||
: A!* 2 ADEVMEM+ ;
|
|
||||||
|
|
||||||
: ADEV$
|
|
||||||
H@ 0x55 RAM+ !
|
|
||||||
4 ALLOT
|
|
||||||
['] C@ A@* !
|
|
||||||
['] C! A!* !
|
|
||||||
;
|
|
||||||
|
|
||||||
: A@ A@* @ EXECUTE ;
|
|
||||||
: A! A!* @ EXECUTE ;
|
|
||||||
|
|
||||||
( Same as MOVE, but with A@ and A! )
|
|
||||||
( src dst u -- )
|
|
||||||
: AMOVE
|
|
||||||
( u ) 0 DO
|
|
||||||
SWAP DUP I + A@ ( dst src x )
|
|
||||||
ROT SWAP OVER I + ( src dst x dst )
|
|
||||||
A! ( src dst )
|
|
||||||
LOOP
|
|
||||||
2DROP
|
|
||||||
;
|
|
@ -8,23 +8,33 @@
|
|||||||
routine. )
|
routine. )
|
||||||
|
|
||||||
64 CONSTANT INBUFSZ
|
64 CONSTANT INBUFSZ
|
||||||
: RDLNMEM+ 0x53 RAM+ @ + ;
|
|
||||||
( current position in INBUF )
|
|
||||||
: IN> 0 RDLNMEM+ ;
|
|
||||||
( points to INBUF )
|
( points to INBUF )
|
||||||
: IN( 2 RDLNMEM+ ;
|
: IN( 0x53 RAM+ ;
|
||||||
( points to INBUF's end )
|
( points to INBUF's end )
|
||||||
: IN) INBUFSZ 2 + RDLNMEM+ ;
|
: IN) 0x55 RAM+ ;
|
||||||
|
( current position in INBUF )
|
||||||
|
: IN> 0x57 RAM+ ;
|
||||||
|
|
||||||
( flush input buffer )
|
( flush input buffer )
|
||||||
( set IN> to IN( and set IN> @ to null )
|
( set IN> to IN( and set IN> @ to null )
|
||||||
: (infl) 0 IN( DUP IN> ! ! ;
|
: (infl) 0 IN( @ DUP IN> ! ! ;
|
||||||
|
|
||||||
|
( Initializes the readln subsystem )
|
||||||
|
: (c<$)
|
||||||
|
H@ IN( !
|
||||||
|
INBUFSZ ALLOT
|
||||||
|
H@ IN) !
|
||||||
|
( We need two extra bytes. 1 for the last typed 0x0a and
|
||||||
|
one for the following NULL. )
|
||||||
|
2 ALLOT
|
||||||
|
(infl)
|
||||||
|
;
|
||||||
|
|
||||||
( handle backspace: go back one char in IN>, if possible, then
|
( handle backspace: go back one char in IN>, if possible, then
|
||||||
emit SPC + BS )
|
emit SPC + BS )
|
||||||
: (inbs)
|
: (inbs)
|
||||||
( already at IN( ? )
|
( already at IN( ? )
|
||||||
IN> @ IN( = IF EXIT THEN
|
IN> @ IN( @ = IF EXIT THEN
|
||||||
IN> @ 1 - IN> !
|
IN> @ 1 - IN> !
|
||||||
SPC BS
|
SPC BS
|
||||||
;
|
;
|
||||||
@ -33,7 +43,7 @@
|
|||||||
should continue, that is, whether CR was not met. )
|
should continue, that is, whether CR was not met. )
|
||||||
: (rdlnc) ( -- f )
|
: (rdlnc) ( -- f )
|
||||||
( buffer overflow? same as if we typed a newline )
|
( buffer overflow? same as if we typed a newline )
|
||||||
IN> @ IN) = IF 0x0a ELSE KEY THEN ( c )
|
IN> @ IN) @ = IF 0x0a ELSE KEY THEN ( c )
|
||||||
( del? same as backspace )
|
( del? same as backspace )
|
||||||
DUP 0x7f = IF DROP 0x8 THEN
|
DUP 0x7f = IF DROP 0x8 THEN
|
||||||
( lf? same as cr )
|
( lf? same as cr )
|
||||||
@ -59,26 +69,14 @@
|
|||||||
FLAGS @ 0x1 AND NOT IF '>' EMIT SPC THEN
|
FLAGS @ 0x1 AND NOT IF '>' EMIT SPC THEN
|
||||||
(infl)
|
(infl)
|
||||||
BEGIN (rdlnc) NOT UNTIL
|
BEGIN (rdlnc) NOT UNTIL
|
||||||
LF IN( IN> !
|
LF IN( @ IN> !
|
||||||
;
|
;
|
||||||
|
|
||||||
( And finally, implement a replacement for the (c<) routine )
|
( And finally, implement a replacement for the (c<) routine )
|
||||||
: (rdln<)
|
: (c<)
|
||||||
IN> @ C@ ( c )
|
IN> @ C@ ( c )
|
||||||
( not EOL? good, inc and return )
|
( not EOL? good, inc and return )
|
||||||
DUP IF 1 IN> +! EXIT THEN ( c )
|
DUP IF 1 IN> +! EXIT THEN ( c )
|
||||||
( EOL ? readline. we still return typed char though )
|
( EOL ? readline. we still return typed char though )
|
||||||
(rdln) ( c )
|
(rdln) ( c )
|
||||||
;
|
;
|
||||||
|
|
||||||
( Initializes the readln subsystem )
|
|
||||||
: RDLN$
|
|
||||||
( 53 == rdln's memory )
|
|
||||||
H@ 0x53 RAM+ !
|
|
||||||
( 2 for IN>, plus 2 for extra bytes after buffer: 1 for
|
|
||||||
the last typed 0x0a and one for the following NULL. )
|
|
||||||
INBUFSZ 4 + ALLOT
|
|
||||||
(infl)
|
|
||||||
['] (rdln<) 0x0c RAM+ !
|
|
||||||
;
|
|
||||||
|
|
||||||
|
@ -1,11 +1,21 @@
|
|||||||
( Z80 assembler )
|
( Z80 assembler )
|
||||||
|
|
||||||
: Z80AMEM+ 0x59 RAM+ @ + ;
|
( Splits word into msb/lsb, lsb being on TOS )
|
||||||
|
: SPLITB
|
||||||
|
256 /MOD SWAP
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
( H@ offset at which we consider our PC 0. Used to compute
|
( H@ offset at which we consider our PC 0. Used to compute
|
||||||
PC. To have a proper PC, call "H@ ORG !" at the beginning
|
PC. To have a proper PC, call "H@ ORG !" at the beginning
|
||||||
of your assembly process. )
|
of your assembly process. )
|
||||||
: ORG 0 Z80AMEM+ ;
|
: ORG 0x59 RAM+ ;
|
||||||
|
: PC H@ ORG @ - ;
|
||||||
|
|
||||||
|
( A, spits an assembled byte, A,, spits an assembled word
|
||||||
|
Both increase PC. To debug, change C, to .X )
|
||||||
|
: A, C, ;
|
||||||
|
: A,, SPLITB A, A, ;
|
||||||
|
|
||||||
( Labels are a convenient way of managing relative jump
|
( Labels are a convenient way of managing relative jump
|
||||||
calculations. Backward labels are easy. It is only a matter
|
calculations. Backward labels are easy. It is only a matter
|
||||||
@ -17,31 +27,13 @@
|
|||||||
To avoid using dict memory in compilation targets, we
|
To avoid using dict memory in compilation targets, we
|
||||||
pre-declare label variables here, which means we have a
|
pre-declare label variables here, which means we have a
|
||||||
limited number of it. For now, 6 ought to be enough. )
|
limited number of it. For now, 6 ought to be enough. )
|
||||||
: L1 2 Z80AMEM+ ;
|
|
||||||
: L2 4 Z80AMEM+ ;
|
|
||||||
: L3 6 Z80AMEM+ ;
|
|
||||||
: L4 8 Z80AMEM+ ;
|
|
||||||
: L5 10 Z80AMEM+ ;
|
|
||||||
: L6 12 Z80AMEM+ ;
|
|
||||||
|
|
||||||
: Z80A$
|
: L1 0x5b RAM+ ;
|
||||||
( 59 == z80a's memory )
|
: L2 0x5d RAM+ ;
|
||||||
H@ 0x59 RAM+ !
|
: L3 0x5f RAM+ ;
|
||||||
14 ALLOT
|
: L4 0x61 RAM+ ;
|
||||||
;
|
: L5 0x63 RAM+ ;
|
||||||
|
: L6 0x65 RAM+ ;
|
||||||
( Splits word into msb/lsb, lsb being on TOS )
|
|
||||||
: SPLITB
|
|
||||||
256 /MOD SWAP
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
: PC H@ ORG @ - ;
|
|
||||||
|
|
||||||
( A, spits an assembled byte, A,, spits an assembled word
|
|
||||||
Both increase PC. To debug, change C, to .X )
|
|
||||||
: A, C, ;
|
|
||||||
: A,, SPLITB A, A, ;
|
|
||||||
|
|
||||||
( There are 2 label types: backward and forward. For each
|
( There are 2 label types: backward and forward. For each
|
||||||
type, there are two actions: set and write. Setting a label
|
type, there are two actions: set and write. Setting a label
|
||||||
|
16
notes.txt
16
notes.txt
@ -89,11 +89,17 @@ RAMSTART INITIAL_SP
|
|||||||
+2e BOOT C< PTR
|
+2e BOOT C< PTR
|
||||||
+4e INTJUMP
|
+4e INTJUMP
|
||||||
+51 CURRENTPTR
|
+51 CURRENTPTR
|
||||||
+53 readln's variables
|
+53 readln's IN(
|
||||||
+55 adev's variables
|
+55 readln's IN)
|
||||||
+57 FUTURE USES
|
+57 readln's IN>
|
||||||
+59 z80a's variables
|
+59 z80a's ORG
|
||||||
+5b FUTURE USES
|
+5b z80a's L1
|
||||||
|
+5d z80a's L2
|
||||||
|
+5f z80a's L3
|
||||||
|
+61 z80a's L4
|
||||||
|
+63 z80a's L5
|
||||||
|
+65 z80a's L6
|
||||||
|
+67 FUTURE USES
|
||||||
+70 DRIVERS
|
+70 DRIVERS
|
||||||
+80 RAMEND
|
+80 RAMEND
|
||||||
|
|
||||||
|
@ -214,17 +214,6 @@ And there you have it, a stage2 binary that you've assembled yourself. Now,
|
|||||||
here's for your homework: use the same technique to add the contents of
|
here's for your homework: use the same technique to add the contents of
|
||||||
`readln.fs` to stage2 so that you have a full-featured interpreter.
|
`readln.fs` to stage2 so that you have a full-featured interpreter.
|
||||||
|
|
||||||
Name it `stage3.bin` (the version without any source code appended and no
|
|
||||||
`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
|
|
||||||
yourself. Tough love they call it.
|
|
||||||
|
|
||||||
* `cat stage2.bin pre.fs ../../forth/readln.fs run.fs > stage2r.bin`
|
|
||||||
* Don't forget `(c<$)`.
|
|
||||||
* `RLDICT` is like `RLCORE` but with a chosen target.
|
|
||||||
|
|
||||||
[rc2014]: https://rc2014.co.uk
|
[rc2014]: https://rc2014.co.uk
|
||||||
[romwrite]: https://github.com/hsoft/romwrite
|
[romwrite]: https://github.com/hsoft/romwrite
|
||||||
[stage2]: ../../emul
|
[stage2]: ../../emul
|
||||||
|
36
usage.txt
36
usage.txt
@ -86,39 +86,3 @@ flag to true. For example, "<>{ <>}" yields true.
|
|||||||
To check whether A is in between B and C inclusively, you would write:
|
To check whether A is in between B and C inclusively, you would write:
|
||||||
|
|
||||||
A <>{ B 1 - &> C 1 + &< <>}
|
A <>{ B 1 - &> C 1 + &< <>}
|
||||||
|
|
||||||
*** Addressed devices
|
|
||||||
|
|
||||||
The adev unit provides a simple but powerful abstraction over C@ and C!: A@ and
|
|
||||||
A!. These work the same way as C@ and C! (but for performance reasons, aren't
|
|
||||||
used in core words), but are indirect calls.
|
|
||||||
|
|
||||||
Upon initialization, the default to C@ and C!, but can be set to any word
|
|
||||||
through A@* and A!*.
|
|
||||||
|
|
||||||
On top of that, it provides a few core-like words such as AMOVE.
|
|
||||||
|
|
||||||
Let's demonstrate its use through a toy example:
|
|
||||||
|
|
||||||
> : F! SWAP 1 + SWAP C! ;
|
|
||||||
> 8 H@ DUMP
|
|
||||||
|
|
||||||
:54 0000 0000 0000 0000 ........
|
|
||||||
> 9 H@ A!
|
|
||||||
> 8 H@ DUMP
|
|
||||||
|
|
||||||
:54 0900 0000 0000 0000 ........
|
|
||||||
> ' F! A!* !
|
|
||||||
> 9 H@ 1 + A!
|
|
||||||
> 8 H@ DUMP
|
|
||||||
|
|
||||||
:54 090a 0000 0000 0000 ........
|
|
||||||
> H@ H@ 2 + 2 AMOVE
|
|
||||||
> 8 H@ DUMP
|
|
||||||
|
|
||||||
:54 090a 0a0b 0000 0000 ........
|
|
||||||
>
|
|
||||||
|
|
||||||
Of course, you might want to end up using adev in this kind of ad-hoc way to
|
|
||||||
have some kind of mapping function, but what you'll mostly want to to is to
|
|
||||||
plug device drivers into those words.
|
|
||||||
|
Loading…
Reference in New Issue
Block a user