1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-02 08:30:55 +11:00

Compare commits

...

3 Commits

Author SHA1 Message Date
Virgil Dupras
f605e2d85c Give CASE's default branch access to its input value
ref #97
2020-04-27 20:44:21 -04:00
Virgil Dupras
3b66aefcd1 block editor: fix broken B and N
fixes #97
2020-04-27 18:11:54 -04:00
Virgil Dupras
295b4b6e0a z80a: add BIN( parameter
Will be useful for assembling binaries for the TRS-80 which can't start
at addr 0.
2020-04-27 15:11:38 -04:00
27 changed files with 89 additions and 79 deletions

14
blk/042
View File

@ -1,9 +1,9 @@
Flow Flow
Note about flow words: flow words can only be used in Note that flow words can only be used in definitions. In the
definitions. In the INTERPRET loop, they don't have the desired INTERPRET loop, they don't have the desired effect because each
effect because each word from the input stream is executed word from the input stream is executed immediately. In this
immediately. In this context, branching doesn't work. context, branching doesn't work.
f IF A ELSE B THEN: if f is true, execute A, if false, execute f IF A ELSE B THEN: if f is true, execute A, if false, execute
B. ELSE is optional. B. ELSE is optional.
@ -11,6 +11,6 @@ BEGIN .. f UNTIL: if f is false, branch to BEGIN.
BEGIN .. AGAIN: Always branch to BEGIN. BEGIN .. AGAIN: Always branch to BEGIN.
x y DO .. LOOP: LOOP increments y. if y != x, branch to DO. x y DO .. LOOP: LOOP increments y. if y != x, branch to DO.
x CASE y OF A ENDOF z OF B ENDOF C ENDCASE: If x == y, execute x CASE y OF A ENDOF z OF B ENDOF C ENDCASE: If x == y, execute
A, if x == z, execute B. Otherwise, execute C. A, if x == z, execute B. Otherwise, execute C. x is dropped
in case of an OF match, *but it is kept if it reaches C*. You
(cont.) have to consume it to avoid PSP leak. (cont.)

View File

@ -6,8 +6,8 @@ VARIABLE ACC
ACC ! ACC !
; ;
: L BLK> @ _LIST ; : L BLK> @ _LIST ;
: B BLK> @ 1- BLK> ! L ; : B BLK> @ 1- BLK@ L ;
: N BLK> @ 1+ BLK> ! L ; : N BLK> @ 1+ BLK@ L ;

17
blk/201
View File

@ -3,13 +3,14 @@ Forth words, opcode assembly is a bit different than with a
typical assembler. For example, what would traditionally be typical assembler. For example, what would traditionally be
"ld a, b" would become "A B LDrr,". "ld a, b" would become "A B LDrr,".
H@ offset at which we consider our PC 0. Used to compute PC. To BIN( is the addr at which the compiled binary will live. It is
have a proper PC, call "H@ ORG !" at the beginning of your often 0.
assembly process.
Labels are a convenient way of managing relative jump ORG is H@ offset at which we begin spitting binary. Used to
calculations. Backward labels are easy. It is only a matter or compute PC. To have a proper PC, call "H@ ORG !" at the
recording "HERE" and do subtractions. Forward labels record the beginning of your assembly process. PC is H@ - ORG + BIN(.
place where we should write the offset, and then when we get to
that point later on, the label records the offset there.
(cont.)

17
blk/202
View File

@ -1,13 +1,16 @@
Labels are a convenient way of managing relative jump
calculations. Backward labels are easy. It is only a matter or
recording "HERE" and do subtractions. Forward labels record the
place where we should write the offset, and then when we get to
that point later on, the label records the offset there.
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 limited pre-declare label variables here, which means we have a limited
number of it. For now, 4 ought to be enough. number of it. For now, 4 ought to be enough.
Flow
There are 2 label types: backward and forward. For each type,
there are two actions: set and write. Setting a label is
declaring where it is. It has to be performed at the label's
destination. Writing a label is writing its offset difference
to the binary result. It has to be done right after a relative
jump operation. Yes, labels are only for relative jumps.
(cont.)

18
blk/203
View File

@ -1,14 +1,16 @@
Flow
There are 2 label types: backward and forward. For each type,
there are two actions: set and write. Setting a label is
declaring where it is. It has to be performed at the label's
destination. Writing a label is writing its offset difference
to the binary result. It has to be done right after a relative
jump operation. Yes, labels are only for relative jumps.
For backward labels, set happens before write. For forward For backward labels, set happens before write. For forward
labels, write happen before set. The write operation writes a labels, write happen before set. The write operation writes a
dummy placeholder, and then the set operation writes the offset dummy placeholder, and then the set operation writes the offset
at that placeholder's address. at that placeholder's address.
Variable actions are expected to be called with labels in
front of them. Example, "L2 FSET"
About that "1 -": z80 relative jumps record "e-2", that is,
the offset that *counts the 2 bytes of the jump itself*.
Because we set the label *after* the jump OP1 itself, that's 1
byte that is taken care of. We still need to adjust by another
byte before writing the offset.
(cont.)

10
blk/204 Normal file
View File

@ -0,0 +1,10 @@
Variable actions are expected to be called with labels in
front of them. Example, "L2 FSET"
About that "1 -": z80 relative jumps record "e-2", that is,
the offset that *counts the 2 bytes of the jump itself*.
Because we set the label *after* the jump OP1 itself, that's 1
byte that is taken care of. We still need to adjust by another
byte before writing the offset.

10
blk/212
View File

@ -1,8 +1,2 @@
( 59 == z80a's memory ) 213 LOAD Z80A$
H@ 0x59 RAM+ ! 215 249 LOADR
10 ALLOT
213 LOAD 215 LOAD 216 LOAD 217 LOAD 218 LOAD 219 LOAD
220 LOAD 222 LOAD 223 LOAD 224 LOAD 226 LOAD 228 LOAD
230 LOAD 232 LOAD 234 LOAD 236 LOAD 238 LOAD 240 LOAD
242 LOAD 243 LOAD 246 LOAD 247 LOAD 249 LOAD

View File

@ -1,7 +1,9 @@
: Z80AMEM+ 0x59 RAM+ @ + ; : Z80AMEM+ 0x59 RAM+ @ + ;
: ORG 0 Z80AMEM+ ; : ORG 0 Z80AMEM+ ;
: L1 2 Z80AMEM+ ; : L2 4 Z80AMEM+ ; : BIN( 2 Z80AMEM+ ;
: L3 6 Z80AMEM+ ; : L4 8 Z80AMEM+ ; : L1 4 Z80AMEM+ ; : L2 6 Z80AMEM+ ;
: L3 8 Z80AMEM+ ; : L4 10 Z80AMEM+ ;
: Z80A$ H@ 0x59 RAM+ ! 12 ALLOT 0 BIN( ! ;
: A 7 ; : B 0 ; : C 1 ; : D 2 ; : A 7 ; : B 0 ; : C 1 ; : D 2 ;
: E 3 ; : H 4 ; : L 5 ; : (HL) 6 ; : E 3 ; : H 4 ; : L 5 ; : (HL) 6 ;
: BC 0 ; : DE 1 ; : HL 2 ; : AF 3 ; : SP AF ; : BC 0 ; : DE 1 ; : HL 2 ; : AF 3 ; : SP AF ;

View File

@ -2,7 +2,7 @@
: SPLITB : SPLITB
256 /MOD SWAP 256 /MOD SWAP
; ;
: PC H@ ORG @ - ; : PC H@ ORG @ - BIN( @ + ;
( A, spits an assembled byte, A,, spits an assembled word ( A, spits an assembled byte, A,, spits an assembled word
Both increase PC. To debug, change C, to .X ) Both increase PC. To debug, change C, to .X )
: A, C, ; : A,, SPLITB A, A, ; : A, C, ; : A,, SPLITB A, A, ;

17
blk/243
View File

@ -1,16 +1,15 @@
: JPccnn, SWAP <<3 0xc2 OR A, A,, ; : JPccnn, SWAP <<3 0xc2 OR A, A,, ;
: BCALL, BIN( @ + CALLnn, ;
: BJP, BIN( @ + JPnn, ;
: BJPcc, BIN( @ + JPccnn, ;
( 26 == next ) : JPNEXT, 26 BJP, ; ( 26 == next )
: JPNEXT, 26 JPnn, ;
( 29 == chkPS )
: chkPS, 29 CALLnn, ;
: CODE : chkPS, 29 BCALL, ; ( 29 == chkPS )
( same as CREATE, but with native word )
: CODE ( same as CREATE, but with native word )
(entry) (entry)
( 23 == nativeWord ) 23 C, ( 23 == nativeWord )
23 C,
; ;
: ;CODE JPNEXT, ; : ;CODE JPNEXT, ;

View File

@ -4,3 +4,5 @@
: PUSH0, BC 0 LDddnn, BC PUSHqq, ; : PUSH0, BC 0 LDddnn, BC PUSHqq, ;
: PUSH1, BC 1 LDddnn, BC PUSHqq, ; : PUSH1, BC 1 LDddnn, BC PUSHqq, ;
: PUSHZ, BC 0 LDddnn, IFZ, BC INCss, THEN, BC PUSHqq, ; : PUSHZ, BC 0 LDddnn, IFZ, BC INCss, THEN, BC PUSHqq, ;
: HLZ, A H LDrr, L ORr, ;
: DEZ, A D LDrr, E ORr, ;

View File

@ -6,7 +6,7 @@
4 A, 4 A,
H@ XCURRENT ! ( set current tip of dict, 0x42 ) H@ XCURRENT ! ( set current tip of dict, 0x42 )
0x17 A, ( nativeWord ) 0x17 A, ( nativeWord )
0x14 CALLnn, ( popRS ) 0x14 BCALL, ( popRS )
HL PUSHqq, IY POPqq, ( --> IP ) HL PUSHqq, IY POPqq, ( --> IP )
JPNEXT, JPNEXT,

View File

@ -1,8 +1,7 @@
CODE (?br) ( 0x67 ) CODE (?br) ( 0x67 )
HL POPqq, HL POPqq,
chkPS, chkPS,
A H LDrr, HLZ,
L ORr,
JRZ, L2 BWR ( BR + 2. False, branch ) JRZ, L2 BWR ( BR + 2. False, branch )
( True, skip next 2 bytes and don't branch ) ( True, skip next 2 bytes and don't branch )
IY INCss, IY INCss,

View File

@ -12,5 +12,5 @@ PC ORG @ 1 + ! ( main )
( LATEST is a label to the latest entry of the dict. It is ( LATEST is a label to the latest entry of the dict. It is
written at offset 0x08 by the process or person building written at offset 0x08 by the process or person building
Forth. ) Forth. )
0x08 LDHL(nn), BIN( @ 0x08 + LDHL(nn),
RAMSTART 0x02 + LD(nn)HL, ( RAM+02 == CURRENT cont. ) RAMSTART 0x02 + LD(nn)HL, ( RAM+02 == CURRENT cont. )

View File

@ -1,4 +1,4 @@
EXDEHL, EXDEHL,
HL L1 @ LDddnn, HL L1 @ LDddnn,
0x03 CALLnn, ( 03 == find ) 0x03 BCALL, ( 03 == find )
0x33 JPnn, ( 33 == execute ) 0x33 BJP, ( 33 == execute )

View File

@ -1,8 +1,7 @@
( DE contains prev offset ) ( DE contains prev offset )
HL POPqq, ( <-- lvl 2 ) HL POPqq, ( <-- lvl 2 )
( HL is prev field's addr. Is offset zero? ) ( HL is prev field's addr. Is offset zero? )
A D LDrr, DEZ,
E ORr,
IFNZ, IFNZ,
( get absolute addr from offset ) ( get absolute addr from offset )
( carry cleared from "or e" ) ( carry cleared from "or e" )
@ -13,4 +12,5 @@
JRNZ, AGAIN, ( inner-B292, try to match again ) JRNZ, AGAIN, ( inner-B292, try to match again )
( Z set? end of dict, unset Z ) ( Z set? end of dict, unset Z )
( cont. ) ( cont. )

View File

@ -2,6 +2,6 @@
L2 BSET ( abortUnderflow ) L2 BSET ( abortUnderflow )
HL PC 7 - LDddnn, HL PC 7 - LDddnn,
DE RAMSTART 0x02 + LDdd(nn), ( RAM+02 == CURRENT ) DE RAMSTART 0x02 + LDdd(nn), ( RAM+02 == CURRENT )
0x03 CALLnn, ( find ) 0x03 BCALL, ( find )
0x33 JPnn, ( 33 == execute ) 0x33 BJP, ( 33 == execute )

View File

@ -3,7 +3,7 @@ PC ORG @ 0x1b + ! ( next )
we jump to current IP, but we also take care of increasing we jump to current IP, but we also take care of increasing
it by 2 before jumping. ) it by 2 before jumping. )
( Before we continue: are stacks within bounds? ) ( Before we continue: are stacks within bounds? )
0x1d CALLnn, ( chkPS ) 0x1d BCALL, ( chkPS )
( check RS ) ( check RS )
IX PUSHqq, HL POPqq, IX PUSHqq, HL POPqq,
DE RS_ADDR LDddnn, DE RS_ADDR LDddnn,

View File

@ -3,7 +3,7 @@ PC ORG @ 0x34 + ! ( execute )
( DE points to wordref ) ( DE points to wordref )
EXDEHL, EXDEHL,
E (HL) LDrr, E (HL) LDrr,
D 0 LDrn, D BIN( @ 256 / LDrn,
EXDEHL, EXDEHL,
( HL points to code pointer ) ( HL points to code pointer )
DE INCss, DE INCss,

View File

@ -4,7 +4,7 @@ PC ORG @ 0x0f + ! ( compiledWord )
2. Set new IP to the second atom of the list 2. Set new IP to the second atom of the list
3. Execute the first atom of the list. ) 3. Execute the first atom of the list. )
IY PUSHqq, HL POPqq, ( <-- IP ) IY PUSHqq, HL POPqq, ( <-- IP )
0x11 CALLnn, ( 11 == pushRS ) 0x11 BCALL, ( 11 == pushRS )
EXDEHL, ( HL points to PFA ) EXDEHL, ( HL points to PFA )
( While we increase, dereference into DE for execute call ( While we increase, dereference into DE for execute call
later. ) later. )

View File

@ -1,8 +1,7 @@
CODE NOT CODE NOT
HL POPqq, HL POPqq,
chkPS, chkPS,
A L LDrr, HLZ,
H ORr,
PUSHZ, PUSHZ,
;CODE ;CODE

View File

@ -2,12 +2,12 @@ CODE >R
HL POPqq, HL POPqq,
chkPS, chkPS,
( 17 == pushRS ) ( 17 == pushRS )
17 CALLnn, 17 BCALL,
;CODE ;CODE
CODE R> CODE R>
( 20 == popRS ) ( 20 == popRS )
20 CALLnn, 20 BCALL,
HL PUSHqq, HL PUSHqq,
;CODE ;CODE

View File

@ -3,7 +3,7 @@ CODE _find ( cur w -- a f )
DE POPqq, ( cur ) DE POPqq, ( cur )
chkPS, chkPS,
( 3 == find ) ( 3 == find )
3 CALLnn, 3 BCALL,
IFNZ, IFNZ,
( not found ) ( not found )
HL PUSHqq, HL PUSHqq,

View File

@ -1,10 +1,10 @@
( During a CASE, the stack grows by 1 at each ENDOF so that ( During a CASE, the stack grows by 1 at each ENDOF so that
we can fill all those ENDOF branching addrs. So that we we can fill all those ENDOF branching addrs. So that we
know when to stop, we put a 0 on PSP. That's our stopgap. ) know when to stop, we put a 0 on PSP. That's our stopgap. )
: CASE 0 COMPILE >R ; IMMEDIATE : CASE 0 ; IMMEDIATE
: OF : OF
COMPILE I COMPILE = COMPILE OVER COMPILE =
[COMPILE] IF [COMPILE] IF COMPILE DROP
; IMMEDIATE ; IMMEDIATE
: ENDOF [COMPILE] ELSE ; IMMEDIATE : ENDOF [COMPILE] ELSE ; IMMEDIATE

View File

@ -1,11 +1,9 @@
( At this point, we have something like "0 e1 e2 e3 val". We ( At this point, we have something like "0 e1 e2 e3 val". We
want top drop val, and then call THEN as long as we don't want to drop val, and then call THEN as long as we don't
hit 0. ) hit 0. )
: ENDCASE : ENDCASE
BEGIN BEGIN
DUP NOT IF DUP NOT IF DROP EXIT THEN
DROP COMPILE R> COMPILE DROP EXIT
THEN
[COMPILE] THEN [COMPILE] THEN
AGAIN AGAIN
; IMMEDIATE ; IMMEDIATE

Binary file not shown.

View File

@ -3,11 +3,12 @@
'X' OF 42 ENDOF 'X' OF 42 ENDOF
0x12 OF 43 ENDOF 0x12 OF 43 ENDOF
255 OF 44 ENDOF 255 OF 44 ENDOF
45 1+
ENDCASE ENDCASE
; ;
'X' foo 42 #eq 'X' foo 42 #eq
0x12 foo 43 #eq 0x12 foo 43 #eq
255 foo 44 #eq 255 foo 44 #eq
254 foo 45 #eq 254 foo 255 #eq
'S S0 #eq