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