From 7292d486dc3108e316aa1ef2579ad2c71e2da5d3 Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Mon, 13 Apr 2020 20:34:53 -0400 Subject: [PATCH] z80a: add stuctured flow words Allow us to rely a little less on labels. We now only need 4. --- forth/boot.fs | 24 +++++++------- forth/z80a.fs | 91 +++++++++++++++++++++++++++++---------------------- forth/z80c.fs | 64 ++++++++++++++++++------------------ 3 files changed, 95 insertions(+), 84 deletions(-) diff --git a/forth/boot.fs b/forth/boot.fs index 138eda1..df227f7 100644 --- a/forth/boot.fs +++ b/forth/boot.fs @@ -159,7 +159,7 @@ PC ORG @ 4 + ! ( find ) adjust. Because the compare loop pre-decrements, instead of DECing HL twice, we DEC it once. ) HL DECss, -L3 BSET ( inner ) +BEGIN, ( inner ) ( DE is a wordref, first step, do our len correspond? ) HL PUSHqq, ( --> lvl 1 ) DE PUSHqq, ( --> lvl 2 ) @@ -172,15 +172,15 @@ L3 BSET ( inner ) DE DECss, ( Skip prev field. One less because we ) DE DECss, ( pre-decrement ) B C LDrr, ( loop C times ) -L5 BSET ( loop ) +BEGIN, ( loop ) ( pre-decrement for easier Z matching ) DE DECss, HL DECss, LDA(DE), (HL) CPr, - JRNZ, L6 FWR ( loopend ) - DJNZ, L5 BWR ( loop ) -L4 FSET L6 FSET ( loopend ) + JRNZ, L3 FWR ( loopend ) + DJNZ, AGAIN, ( loop ) +L4 FSET L3 FSET ( loopend ) ( At this point, Z is set if we have a match. In all cases, we want to pop HL and DE ) DE POPqq, ( <-- lvl 2 ) @@ -201,14 +201,14 @@ L4 FSET L6 FSET ( loopend ) ( HL is prev field's addr. Is offset zero? ) A D LDrr, E ORr, - JRZ, L6 FWR ( noprev ) - ( get absolute addr from offset ) - ( carry cleared from "or e" ) - DE SBCHLss, - EXDEHL, ( result in DE ) -L6 FSET ( noprev ) + IFZ, ( noprev ) + ( get absolute addr from offset ) + ( carry cleared from "or e" ) + DE SBCHLss, + EXDEHL, ( result in DE ) + THEN, ( noprev ) HL POPqq, ( <-- lvl 1 ) - JRNZ, L3 BWR ( inner, try to match again ) + JRNZ, AGAIN, ( inner, try to match again ) ( Z set? end of dict, unset Z ) L1 FSET ( fail ) A XORr, diff --git a/forth/z80a.fs b/forth/z80a.fs index 6181eb3..0318d26 100644 --- a/forth/z80a.fs +++ b/forth/z80a.fs @@ -16,18 +16,16 @@ To avoid using dict memory in compilation targets, we 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, 4 ought to be enough. ) : L1 2 Z80AMEM+ ; : L2 4 Z80AMEM+ ; : L3 6 Z80AMEM+ ; : L4 8 Z80AMEM+ ; -: L5 10 Z80AMEM+ ; -: L6 12 Z80AMEM+ ; : Z80A$ ( 59 == z80a's memory ) H@ 0x59 RAM+ ! - 14 ALLOT + 10 ALLOT ; ( Splits word into msb/lsb, lsb being on TOS ) @@ -43,42 +41,6 @@ : A, C, ; : A,, SPLITB A, A, ; -( 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 - labels, write happen before set. The write operation writes - a dummy placeholder, and then the set operation writes the - offset 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. -) - -: BSET PC SWAP ! ; -: BWR @ PC - 1 - A, ; -( same as BSET, but we need to write a placeholder ) -: FWR BSET 0 A, ; -: FSET - @ DUP PC ( l l pc ) - -^ 1 - ( l off ) - ( warning: l is a PC offset, not a mem addr! ) - SWAP ORG @ + ( off addr ) - C! -; - - ( "r" register constants ) 7 CONSTANT A 0 CONSTANT B @@ -375,3 +337,52 @@ ( Routines ) ( 29 == chkPS ) : chkPS, 29 CALLnn, ; + +( 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 + labels, write happen before set. The write operation writes + a dummy placeholder, and then the set operation writes the + offset 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. +) + +( Place BEGIN, where you want to jump back and AGAIN after + a relative jump operator. Just like BSET and BWR. ) +: BEGIN, PC ; +: AGAIN, PC - 1 - A, ; + +: BSET PC SWAP ! ; +: BWR @ AGAIN, ; +( same as BSET, but we need to write a placeholder ) +: FJR, PC 0 A, ; +: IFZ, JRZ, FJR, ; +: IFNZ, JRNZ, FJR, ; +: IFC, JRC, FJR, ; +: IFNC, JRNC, FJR, ; +: THEN, + DUP PC ( l l pc ) + -^ 1 - ( l off ) + ( warning: l is a PC offset, not a mem addr! ) + SWAP ORG @ + ( off addr ) + C! +; +: FWR BSET 0 A, ; +: FSET @ THEN, ; + diff --git a/forth/z80c.fs b/forth/z80c.fs index 118f938..8e14c1b 100644 --- a/forth/z80c.fs +++ b/forth/z80c.fs @@ -149,10 +149,10 @@ CODE NOT A L LDrr, H ORr, HL 0 LDddnn, - JRNZ, L1 FWR ( skip ) - ( false, make 1 ) - HL INCss, -L1 FSET ( skip ) + IFNZ, ( skip ) + ( false, make 1 ) + HL INCss, + THEN, ( skip ) HL PUSHqq, ;CODE @@ -203,17 +203,17 @@ CODE /MOD A B LDrr, B 16 LDrn, HL 0 LDddnn, -L1 BSET ( loop ) - SCF, - C RLr, - RLA, - HL ADCHLss, - DE SBCHLss, - JRNC, L2 FWR ( skip ) - DE ADDHLss, - C DECr, -L2 FSET ( skip ) - DJNZ, L1 BWR ( loop ) + BEGIN, ( loop ) + SCF, + C RLr, + RLA, + HL ADCHLss, + DE SBCHLss, + IFNC, ( skip ) + DE ADDHLss, + C DECr, + THEN, ( skip ) + DJNZ, AGAIN, ( loop ) B A LDrr, HL PUSHqq, BC PUSHqq, @@ -315,16 +315,16 @@ CODE SCMP DE POPqq, HL POPqq, chkPS, -L1 BSET ( loop ) - LDA(DE), - (HL) CPr, - JRNZ, L2 FWR ( not equal? break early to "end". - NZ is set. ) - A ORr, ( if our char is null, stop ) - HL INCss, - DE INCss, - JRNZ, L1 BWR ( loop ) -L2 FSET ( end ) + BEGIN, ( loop ) + LDA(DE), + (HL) CPr, + JRNZ, L1 FWR ( not equal? break early to "end". + NZ is set. ) + A ORr, ( if our char is null, stop ) + HL INCss, + DE INCss, + JRNZ, AGAIN, ( loop ) +L1 FSET ( end ) ( 40 == flagsToBC ) 40 CALLnn, BC PUSHqq, @@ -347,13 +347,13 @@ CODE _find chkPS, ( 3 == find ) 3 CALLnn, - JRZ, L1 FWR ( found ) - ( not found ) - HL PUSHqq, - DE 0 LDddnn, - DE PUSHqq, - JPNEXT, -L1 FSET ( found ) + IFZ, ( found ) + ( not found ) + HL PUSHqq, + DE 0 LDddnn, + DE PUSHqq, + JPNEXT, + THEN, ( found ) DE PUSHqq, DE 1 LDddnn, DE PUSHqq,