From 91f79d113123030033e9ac9d386795c3d567eaf7 Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Mon, 21 Sep 2020 17:51:08 -0400 Subject: [PATCH] Move z80a from B200 to B5 The idea is to consider assemblers as "runtime" apps instead of placing them in the "bootstrap" section of the blocks. These apps will be used for much more than bootstrapping. Moved its documentation to doc/asm.txt and made its code blocks more compact. --- blk/001 | 5 +- blk/005 | 13 ++++ blk/{213 => 006} | 0 blk/{215 => 007} | 0 blk/{216 => 008} | 0 blk/{217 => 009} | 0 blk/{218 => 010} | 0 blk/{219 => 011} | 0 blk/{220 => 012} | 0 blk/{222 => 013} | 0 blk/{223 => 014} | 0 blk/{224 => 015} | 0 blk/{226 => 016} | 0 blk/{228 => 017} | 0 blk/{230 => 018} | 0 blk/{232 => 019} | 0 blk/{234 => 020} | 0 blk/{236 => 021} | 0 blk/{238 => 022} | 0 blk/{240 => 023} | 0 blk/{242 => 024} | 0 blk/{243 => 025} | 0 blk/{246 => 026} | 0 blk/{247 => 027} | 0 blk/{249 => 028} | 0 blk/200 | 13 ---- blk/201 | 16 ----- blk/202 | 16 ----- blk/203 | 16 ----- blk/204 | 16 ----- blk/205 | 16 ----- blk/206 | 3 - blk/208 | 16 ----- blk/209 | 11 --- blk/212 | 1 - doc/asm.txt | 140 +++++++++++++++++++++++++++++++++++++++ emul/xcomp.fs | 2 +- recipes/rc2014/blk/619 | 2 +- recipes/sms/xcomp.fs | 2 +- recipes/ti84/xcomp.fs | 2 +- recipes/trs80/README.md | 2 +- recipes/trs80/xcomp.fs | 2 +- recipes/z80mbc2/xcomp.fs | 2 +- tests/z80/test_sdc.fs | 2 +- 44 files changed, 163 insertions(+), 135 deletions(-) create mode 100644 blk/005 rename blk/{213 => 006} (100%) rename blk/{215 => 007} (100%) rename blk/{216 => 008} (100%) rename blk/{217 => 009} (100%) rename blk/{218 => 010} (100%) rename blk/{219 => 011} (100%) rename blk/{220 => 012} (100%) rename blk/{222 => 013} (100%) rename blk/{223 => 014} (100%) rename blk/{224 => 015} (100%) rename blk/{226 => 016} (100%) rename blk/{228 => 017} (100%) rename blk/{230 => 018} (100%) rename blk/{232 => 019} (100%) rename blk/{234 => 020} (100%) rename blk/{236 => 021} (100%) rename blk/{238 => 022} (100%) rename blk/{240 => 023} (100%) rename blk/{242 => 024} (100%) rename blk/{243 => 025} (100%) rename blk/{246 => 026} (100%) rename blk/{247 => 027} (100%) rename blk/{249 => 028} (100%) delete mode 100644 blk/200 delete mode 100644 blk/201 delete mode 100644 blk/202 delete mode 100644 blk/203 delete mode 100644 blk/204 delete mode 100644 blk/205 delete mode 100644 blk/206 delete mode 100644 blk/208 delete mode 100644 blk/209 delete mode 100644 blk/212 create mode 100644 doc/asm.txt diff --git a/blk/001 b/blk/001 index fe6cc65..7ae197a 100644 --- a/blk/001 +++ b/blk/001 @@ -1,9 +1,8 @@ MASTER INDEX -5-99 unused +005 Z80 assembler 30-99 unused 100 Block editor 120 Visual Editor -160-199 unused -200 Z80 assembler 260 Cross compilation +160-259 unused 260 Cross compilation 280 Z80 boot code 350 Core words 410 PS/2 keyboard subsystem 420 SD Card subsystem 440-519 unused 520 Fonts diff --git a/blk/005 b/blk/005 new file mode 100644 index 0000000..4f2da2e --- /dev/null +++ b/blk/005 @@ -0,0 +1,13 @@ +( Z80 Assembler + +006 Variables & consts +007 Utils 008 OP1 +010 OP1r 012 OP1d +013 OP1rr 015 OP2 +016 OP2i 017 OP2ri +018 OP2br 019 OProt +020 OP2r 021 OP2d +022 OP3di 023 OP3i +024 Specials 025 Flow +028 Macros ) +1 23 LOADR+ diff --git a/blk/213 b/blk/006 similarity index 100% rename from blk/213 rename to blk/006 diff --git a/blk/215 b/blk/007 similarity index 100% rename from blk/215 rename to blk/007 diff --git a/blk/216 b/blk/008 similarity index 100% rename from blk/216 rename to blk/008 diff --git a/blk/217 b/blk/009 similarity index 100% rename from blk/217 rename to blk/009 diff --git a/blk/218 b/blk/010 similarity index 100% rename from blk/218 rename to blk/010 diff --git a/blk/219 b/blk/011 similarity index 100% rename from blk/219 rename to blk/011 diff --git a/blk/220 b/blk/012 similarity index 100% rename from blk/220 rename to blk/012 diff --git a/blk/222 b/blk/013 similarity index 100% rename from blk/222 rename to blk/013 diff --git a/blk/223 b/blk/014 similarity index 100% rename from blk/223 rename to blk/014 diff --git a/blk/224 b/blk/015 similarity index 100% rename from blk/224 rename to blk/015 diff --git a/blk/226 b/blk/016 similarity index 100% rename from blk/226 rename to blk/016 diff --git a/blk/228 b/blk/017 similarity index 100% rename from blk/228 rename to blk/017 diff --git a/blk/230 b/blk/018 similarity index 100% rename from blk/230 rename to blk/018 diff --git a/blk/232 b/blk/019 similarity index 100% rename from blk/232 rename to blk/019 diff --git a/blk/234 b/blk/020 similarity index 100% rename from blk/234 rename to blk/020 diff --git a/blk/236 b/blk/021 similarity index 100% rename from blk/236 rename to blk/021 diff --git a/blk/238 b/blk/022 similarity index 100% rename from blk/238 rename to blk/022 diff --git a/blk/240 b/blk/023 similarity index 100% rename from blk/240 rename to blk/023 diff --git a/blk/242 b/blk/024 similarity index 100% rename from blk/242 rename to blk/024 diff --git a/blk/243 b/blk/025 similarity index 100% rename from blk/243 rename to blk/025 diff --git a/blk/246 b/blk/026 similarity index 100% rename from blk/246 rename to blk/026 diff --git a/blk/247 b/blk/027 similarity index 100% rename from blk/247 rename to blk/027 diff --git a/blk/249 b/blk/028 similarity index 100% rename from blk/249 rename to blk/028 diff --git a/blk/200 b/blk/200 deleted file mode 100644 index 6779a11..0000000 --- a/blk/200 +++ /dev/null @@ -1,13 +0,0 @@ -Z80 Assembler - -201 Guide 208 Instructions list -212 Loader 213 Variables & consts -215 Utils 216 OP1 -218 OP1r 220 OP1d -222 OP1rr 224 OP2 -226 OP2i 228 OP2ri -230 OP2br 232 OProt -234 OP2r 236 OP2d -238 OP3di 240 OP3i -242 Specials 246 Flow -249 Macros diff --git a/blk/201 b/blk/201 deleted file mode 100644 index c895e02..0000000 --- a/blk/201 +++ /dev/null @@ -1,16 +0,0 @@ -The following words allow you to assemble z80 binaries. Being -Forth words, opcode assembly is a bit different than with a -typical assembler. For example, what would traditionally be -"ld a, b" would become "A B LDrr,". - -The "argtype" suffix after each mnemonic is needed because the -assembler doesn't auto-detect the op's form based on arguments. -It has to be explicitly specified. "r" is for 8-bit registers, -"d" for 16-bit ones, "i" for immediate, "c" is for conditions. -Be aware that "SP" and "AF" refer to the same value: some 16- -bit ops can affect SP, others, AF. If you use the wrong argu- -ment on the wrong op, you will affect the wrong register. - -Mnemonics having only a single form, such as PUSH and POP, -don't have argtype suffixes. - (cont.) diff --git a/blk/202 b/blk/202 deleted file mode 100644 index af2bbf5..0000000 --- a/blk/202 +++ /dev/null @@ -1,16 +0,0 @@ -BIN( is the addr at which the compiled binary will live. It is -often 0. - -ORG is H@ offset at which we begin spitting binary. Used to -compute PC. To have a proper PC, call "H@ ORG !" at the -beginning of your assembly process. PC is H@ - ORG + BIN(. - -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 -pre-declare label variables here, which means we have a limited -number of it. For now, 4 ought to be enough. (cont.) diff --git a/blk/203 b/blk/203 deleted file mode 100644 index 1500cbb..0000000 --- a/blk/203 +++ /dev/null @@ -1,16 +0,0 @@ -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. - - - (cont.) diff --git a/blk/204 b/blk/204 deleted file mode 100644 index 5a1e462..0000000 --- a/blk/204 +++ /dev/null @@ -1,16 +0,0 @@ -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.) diff --git a/blk/205 b/blk/205 deleted file mode 100644 index 46a587a..0000000 --- a/blk/205 +++ /dev/null @@ -1,16 +0,0 @@ -Structured flow - -z80a also has words that behave similarly to IF..THEN and -BEGIN..UNTIL. - -On the IF side, we have IFZ, IFNZ, IFC, IFNC, and THEN,. When -the opposite condition is met, a relative jump is made to -THEN,'s PC. For example, if you have IFZ, a jump is made when -Z is unset. - -On the BEGIN,..AGAIN, side, it's a bit different. You start -with your BEGIN, instruction, and then later you issue a -JRxx, instr followed by AGAIN,. Exactly like you would do -with a label. - - (cont.) diff --git a/blk/206 b/blk/206 deleted file mode 100644 index 8480c6b..0000000 --- a/blk/206 +++ /dev/null @@ -1,3 +0,0 @@ -On top of that, you have the very nice BREAK, instruction, -which must also be preceded by a JRxx, and will jump to the -PC following the next AGAIN, diff --git a/blk/208 b/blk/208 deleted file mode 100644 index da7f2fb..0000000 --- a/blk/208 +++ /dev/null @@ -1,16 +0,0 @@ -Instructions list - -r => A B C D E H L (HL) -d => BC DE HL AF/SP -c => CNZ CZ CNC CC CPO CPE CP CM - -LD [rr, ri, di, (i)HL, HL(i), d(i), (i)d, rIXY, IXYr, - (DE)A, A(DE), (i)A, A(i)] -ADD [r, i, HLd, IXd, IXIX, IYd, IYIY] -ADC [r, HLd] -CP [r, i, (IXY+)] -SBC [r, HLd] -SUB [r, i] -PUSH POP -INC [r, d, (IXY+)] DEC [r, d, (IXY+)] -AND [r, i] OR [r, i] XOR [r, i] (cont.) diff --git a/blk/209 b/blk/209 deleted file mode 100644 index c26d8f0..0000000 --- a/blk/209 +++ /dev/null @@ -1,11 +0,0 @@ -(cont.) -OUT [iA, (C)r] IN [Ai, r(C)] -SET RES BIT -RL RLC SLA RLA RLCA -RR RRC SRL RRA RRCA -CALL RST DJNZ -JP [i, (HL), (IX), (IY)] -JR [, Z, NZ, C, NC] - -DI EI EXDEHL EXX HALT -NOP RET [,c] RETI RETN SCF diff --git a/blk/212 b/blk/212 deleted file mode 100644 index 09d3733..0000000 --- a/blk/212 +++ /dev/null @@ -1 +0,0 @@ -1 37 LOADR+ diff --git a/doc/asm.txt b/doc/asm.txt new file mode 100644 index 0000000..d32ce8c --- /dev/null +++ b/doc/asm.txt @@ -0,0 +1,140 @@ +# Assembling Z80 binaries + +(All assembers in Collapse OS follow the same basic principles. +There are sections, below, for each supported architectures, but +you should read this first section first to be familiar with +those common, basic principles) + +Words in the Z80 assembler (B5) allow you to assemble z80 bin- +aries. Being Forth words, opcode assembly is a bit different +than with a typical assembler. For example, what would tradi- +tionally be "ld a, b" would become "A B LDrr,". + +Those opcode words, of which there is a complete list below, end +with "," to indicate that their effect is to write (,) the cor- +responding opcode. + +The "argtype" suffix after each mnemonic is needed because the +assembler doesn't auto-detect the op's form based on arguments. +It has to be explicitly specified. "r" is for 8-bit registers, +"d" for 16-bit ones, "i" for immediate, "c" is for conditions. +Be aware that "SP" and "AF" refer to the same value: some 16- +bit ops can affect SP, others, AF. If you use the wrong argu- +ment on the wrong op, you will affect the wrong register. + +Mnemonics having only a single form, such as PUSH and POP, +don't have argtype suffixes. + +In addition to opcode words, some variables are also defined by +this program: + +BIN( is the addr at which the compiled binary will live. It is +often 0. + +ORG is H@ offset at which we begin spitting binary. Used to +compute PC. To have a proper PC, call "H@ ORG !" at the +beginning of your assembly process. PC is H@ - ORG + BIN(. + +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 +pre-declare label variables here, which means we have a limited +number of it. We have 4: L1, L2, L3, L4. + +# 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. Words for this are BSET and FSET. 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. Word for this are +BWR and FWR. Yes, those words 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. Examples: + +L1 BSET NOP, JR, L1 BWR ( backward jump ) +JR, L1 FWR NOP, L1 FSET ( forward jump ) + +If you look at the code for those words, you'll notice a mys- +terious "1-". z80 relative jumps receives "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. + +Can you use labels with JP, and CALL,? Yes, but only backwards +jumps, and in that case, you use the label's value directly. +Example: L2 @ CALL, + +# Structured flow + +z80a also has words that behave similarly to IF..THEN and +BEGIN..UNTIL. + +On the IF side, we have IFZ, IFNZ, IFC, IFNC, and THEN,. When +the opposite condition is met, a relative jump is made to +THEN,'s PC. For example, if you have IFZ, a jump is made when +Z is unset. + +On the BEGIN,..AGAIN, side, it's a bit different. You start +with your BEGIN, instruction, and then later you issue a +JRxx, instr followed by AGAIN,. Exactly like you would do +with a label. + +On top of that, you have the very nice BREAK, instruction, +which must also be preceded by a JRxx, and will jump to the +PC following the next AGAIN,. Examples: + +IFZ, NOP, THEN, +BEGIN, NOP, JR, AGAIN, ( unconditional ) +BEGIN, NOP, JRZ, AGAIN, ( conditional ) +BEGIN, NOP, JRZ, BREAK, JR, AGAIN, ( break off the loop ) + +# Z80 Instructions list + +Letters in [] brackets indicate "argtype" variants. When the +bracket starts with ",", it means that a "plain" mnemonic is +available. For example, "RET," and "RETc," exist. + +Note that assemblers in Collapse OS are incomplete and opcode +words were implemented in a "just-in-time" fashion, when needed. + +r => A B C D E H L (HL) +d => BC DE HL AF/SP +c => CNZ CZ CNC CC CPO CPE CP CM + +LD [rr, ri, di, (i)HL, HL(i), d(i), (i)d, rIXY, IXYr, + (DE)A, A(DE), (i)A, A(i)] +ADD [r, i, HLd, IXd, IXIX, IYd, IYIY] +ADC [r, HLd] +CP [r, i, (IXY+)] +SBC [r, HLd] +SUB [r, i] +INC [r, d, (IXY+)] +DEC [r, d, (IXY+)] +AND [r, i] +OR [r, i] +XOR [r, i] +OUT [iA, (C)r] +IN [Ai, r(C)] +JP [i, (HL), (IX), (IY)] +JR [, Z, NZ, C, NC] + +PUSH POP +SET RES BIT +RL RLC SLA RLA RLCA +RR RRC SRL RRA RRCA +CALL RST DJNZ +DI EI EXDEHL EXX HALT +NOP RET [,c] RETI RETN SCF diff --git a/emul/xcomp.fs b/emul/xcomp.fs index 8a143f2..fd401b0 100644 --- a/emul/xcomp.fs +++ b/emul/xcomp.fs @@ -2,7 +2,7 @@ 0xfffa CONSTANT PS_ADDR RS_ADDR 0x80 - CONSTANT SYSVARS 0 CONSTANT HERESTART -212 LOAD ( z80 assembler ) +5 LOAD ( z80 assembler ) 262 LOAD ( xcomp ) 282 LOAD ( boot.z80.decl ) 270 LOAD ( xcomp overrides ) diff --git a/recipes/rc2014/blk/619 b/recipes/rc2014/blk/619 index c1ab969..49ac04b 100644 --- a/recipes/rc2014/blk/619 +++ b/recipes/rc2014/blk/619 @@ -2,7 +2,7 @@ RS_ADDR 0x80 - CONSTANT SYSVARS 0x8000 CONSTANT HERESTART 602 LOAD ( acia decl ) -212 LOAD ( z80 assembler ) +5 LOAD ( z80 assembler ) 262 LOAD ( xcomp ) 282 LOAD ( boot.z80.decl ) 270 LOAD ( xcomp overrides ) 283 335 LOADR ( boot.z80 ) 353 LOAD ( xcomp core low ) 603 605 LOADR ( acia ) diff --git a/recipes/sms/xcomp.fs b/recipes/sms/xcomp.fs index d8db458..d66a66f 100644 --- a/recipes/sms/xcomp.fs +++ b/recipes/sms/xcomp.fs @@ -12,7 +12,7 @@ SYSVARS 0x70 + CONSTANT VDP_MEM SYSVARS 0x72 + CONSTANT PAD_MEM 0x3f CONSTANT PAD_CTLPORT 0xdc CONSTANT PAD_D1PORT -212 LOAD ( z80 assembler ) +5 LOAD ( z80 assembler ) : ZFILL, ( u ) 0 DO 0 A, LOOP ; 262 LOAD ( xcomp ) 524 LOAD ( font compiler ) diff --git a/recipes/ti84/xcomp.fs b/recipes/ti84/xcomp.fs index af1cfd7..b632c6d 100644 --- a/recipes/ti84/xcomp.fs +++ b/recipes/ti84/xcomp.fs @@ -5,7 +5,7 @@ RS_ADDR 0x80 - CONSTANT SYSVARS SYSVARS 0x70 + CONSTANT LCD_MEM SYSVARS 0x72 + CONSTANT KBD_MEM 0x01 CONSTANT KBD_PORT -212 LOAD ( z80 assembler ) +5 LOAD ( z80 assembler ) : ZFILL, ( u ) 0 DO 0 A, LOOP ; 262 LOAD ( xcomp ) 522 LOAD ( font compiler ) diff --git a/recipes/trs80/README.md b/recipes/trs80/README.md index a35810f..fbc9a30 100644 --- a/recipes/trs80/README.md +++ b/recipes/trs80/README.md @@ -106,7 +106,7 @@ As stated in the overview, we need a program on the TRS-80 that: You're in luck: that program has already been written. It's in B502 and B503. You can compile it with: - 212 LOAD ( z80 assembler ) + 5 LOAD ( z80 assembler ) 0x0238 CONSTANT COM_DRV_ADDR 0x3000 CONSTANT DEST_ADDR 502 LOAD diff --git a/recipes/trs80/xcomp.fs b/recipes/trs80/xcomp.fs index 5a61f9c..40943f7 100644 --- a/recipes/trs80/xcomp.fs +++ b/recipes/trs80/xcomp.fs @@ -2,7 +2,7 @@ 0xfffa CONSTANT PS_ADDR RS_ADDR 0x80 - CONSTANT SYSVARS 0 CONSTANT HERESTART -212 LOAD ( z80 assembler ) +5 LOAD ( z80 assembler ) 262 LOAD ( xcomp ) 282 LOAD ( boot.z80.decl ) 270 LOAD ( xcomp overrides ) diff --git a/recipes/z80mbc2/xcomp.fs b/recipes/z80mbc2/xcomp.fs index 4400598..0d1ac84 100644 --- a/recipes/z80mbc2/xcomp.fs +++ b/recipes/z80mbc2/xcomp.fs @@ -1,7 +1,7 @@ 0xff00 CONSTANT RS_ADDR 0xfffa CONSTANT PS_ADDR RS_ADDR 0x80 - CONSTANT SYSVARS 0 CONSTANT HERESTART -212 LOAD ( z80 assembler ) +5 LOAD ( z80 assembler ) 262 LOAD ( xcomp ) 282 LOAD ( boot.z80.decl ) 270 LOAD ( xcomp overrides ) diff --git a/tests/z80/test_sdc.fs b/tests/z80/test_sdc.fs index 5903bd3..00e682c 100644 --- a/tests/z80/test_sdc.fs +++ b/tests/z80/test_sdc.fs @@ -1,4 +1,4 @@ -212 LOAD ( z80a ) +5 LOAD ( z80a ) 423 LOAD ( sdc's _crc16 ) 0x0000 0x00 _crc16 0x0000 #eq