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.
This commit is contained in:
Virgil Dupras 2020-09-21 17:51:08 -04:00
parent a348ee9106
commit 91f79d1131
44 changed files with 163 additions and 135 deletions

View File

@ -1,9 +1,8 @@
MASTER INDEX MASTER INDEX
5-99 unused 005 Z80 assembler 30-99 unused
100 Block editor 120 Visual Editor 100 Block editor 120 Visual Editor
160-199 unused 160-259 unused 260 Cross compilation
200 Z80 assembler 260 Cross compilation
280 Z80 boot code 350 Core words 280 Z80 boot code 350 Core words
410 PS/2 keyboard subsystem 420 SD Card subsystem 410 PS/2 keyboard subsystem 420 SD Card subsystem
440-519 unused 520 Fonts 440-519 unused 520 Fonts

13
blk/005 Normal file
View File

@ -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+

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

13
blk/200
View File

@ -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

16
blk/201
View File

@ -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.)

16
blk/202
View File

@ -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.)

16
blk/203
View File

@ -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.)

16
blk/204
View File

@ -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.)

16
blk/205
View File

@ -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.)

View File

@ -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,

16
blk/208
View File

@ -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.)

11
blk/209
View File

@ -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

View File

@ -1 +0,0 @@
1 37 LOADR+

140
doc/asm.txt Normal file
View File

@ -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

View File

@ -2,7 +2,7 @@
0xfffa CONSTANT PS_ADDR 0xfffa CONSTANT PS_ADDR
RS_ADDR 0x80 - CONSTANT SYSVARS RS_ADDR 0x80 - CONSTANT SYSVARS
0 CONSTANT HERESTART 0 CONSTANT HERESTART
212 LOAD ( z80 assembler ) 5 LOAD ( z80 assembler )
262 LOAD ( xcomp ) 262 LOAD ( xcomp )
282 LOAD ( boot.z80.decl ) 282 LOAD ( boot.z80.decl )
270 LOAD ( xcomp overrides ) 270 LOAD ( xcomp overrides )

View File

@ -2,7 +2,7 @@
RS_ADDR 0x80 - CONSTANT SYSVARS RS_ADDR 0x80 - CONSTANT SYSVARS
0x8000 CONSTANT HERESTART 0x8000 CONSTANT HERESTART
602 LOAD ( acia decl ) 602 LOAD ( acia decl )
212 LOAD ( z80 assembler ) 5 LOAD ( z80 assembler )
262 LOAD ( xcomp ) 282 LOAD ( boot.z80.decl ) 262 LOAD ( xcomp ) 282 LOAD ( boot.z80.decl )
270 LOAD ( xcomp overrides ) 283 335 LOADR ( boot.z80 ) 270 LOAD ( xcomp overrides ) 283 335 LOADR ( boot.z80 )
353 LOAD ( xcomp core low ) 603 605 LOADR ( acia ) 353 LOAD ( xcomp core low ) 603 605 LOADR ( acia )

View File

@ -12,7 +12,7 @@ SYSVARS 0x70 + CONSTANT VDP_MEM
SYSVARS 0x72 + CONSTANT PAD_MEM SYSVARS 0x72 + CONSTANT PAD_MEM
0x3f CONSTANT PAD_CTLPORT 0x3f CONSTANT PAD_CTLPORT
0xdc CONSTANT PAD_D1PORT 0xdc CONSTANT PAD_D1PORT
212 LOAD ( z80 assembler ) 5 LOAD ( z80 assembler )
: ZFILL, ( u ) 0 DO 0 A, LOOP ; : ZFILL, ( u ) 0 DO 0 A, LOOP ;
262 LOAD ( xcomp ) 262 LOAD ( xcomp )
524 LOAD ( font compiler ) 524 LOAD ( font compiler )

View File

@ -5,7 +5,7 @@ RS_ADDR 0x80 - CONSTANT SYSVARS
SYSVARS 0x70 + CONSTANT LCD_MEM SYSVARS 0x70 + CONSTANT LCD_MEM
SYSVARS 0x72 + CONSTANT KBD_MEM SYSVARS 0x72 + CONSTANT KBD_MEM
0x01 CONSTANT KBD_PORT 0x01 CONSTANT KBD_PORT
212 LOAD ( z80 assembler ) 5 LOAD ( z80 assembler )
: ZFILL, ( u ) 0 DO 0 A, LOOP ; : ZFILL, ( u ) 0 DO 0 A, LOOP ;
262 LOAD ( xcomp ) 262 LOAD ( xcomp )
522 LOAD ( font compiler ) 522 LOAD ( font compiler )

View File

@ -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're in luck: that program has already been written. It's in B502 and B503.
You can compile it with: You can compile it with:
212 LOAD ( z80 assembler ) 5 LOAD ( z80 assembler )
0x0238 CONSTANT COM_DRV_ADDR 0x0238 CONSTANT COM_DRV_ADDR
0x3000 CONSTANT DEST_ADDR 0x3000 CONSTANT DEST_ADDR
502 LOAD 502 LOAD

View File

@ -2,7 +2,7 @@
0xfffa CONSTANT PS_ADDR 0xfffa CONSTANT PS_ADDR
RS_ADDR 0x80 - CONSTANT SYSVARS RS_ADDR 0x80 - CONSTANT SYSVARS
0 CONSTANT HERESTART 0 CONSTANT HERESTART
212 LOAD ( z80 assembler ) 5 LOAD ( z80 assembler )
262 LOAD ( xcomp ) 262 LOAD ( xcomp )
282 LOAD ( boot.z80.decl ) 282 LOAD ( boot.z80.decl )
270 LOAD ( xcomp overrides ) 270 LOAD ( xcomp overrides )

View File

@ -1,7 +1,7 @@
0xff00 CONSTANT RS_ADDR 0xfffa CONSTANT PS_ADDR 0xff00 CONSTANT RS_ADDR 0xfffa CONSTANT PS_ADDR
RS_ADDR 0x80 - CONSTANT SYSVARS RS_ADDR 0x80 - CONSTANT SYSVARS
0 CONSTANT HERESTART 0 CONSTANT HERESTART
212 LOAD ( z80 assembler ) 5 LOAD ( z80 assembler )
262 LOAD ( xcomp ) 262 LOAD ( xcomp )
282 LOAD ( boot.z80.decl ) 282 LOAD ( boot.z80.decl )
270 LOAD ( xcomp overrides ) 270 LOAD ( xcomp overrides )

View File

@ -1,4 +1,4 @@
212 LOAD ( z80a ) 5 LOAD ( z80a )
423 LOAD ( sdc's _crc16 ) 423 LOAD ( sdc's _crc16 )
0x0000 0x00 _crc16 0x0000 #eq 0x0000 0x00 _crc16 0x0000 #eq