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:
parent
a348ee9106
commit
91f79d1131
5
blk/001
5
blk/001
@ -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
13
blk/005
Normal 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+
|
13
blk/200
13
blk/200
@ -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
16
blk/201
@ -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
16
blk/202
@ -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
16
blk/203
@ -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
16
blk/204
@ -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
16
blk/205
@ -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.)
|
|
3
blk/206
3
blk/206
@ -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
16
blk/208
@ -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
11
blk/209
@ -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
|
|
140
doc/asm.txt
Normal file
140
doc/asm.txt
Normal 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
|
@ -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 )
|
||||||
|
@ -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 )
|
||||||
|
@ -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 )
|
||||||
|
@ -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 )
|
||||||
|
@ -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
|
||||||
|
@ -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 )
|
||||||
|
@ -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 )
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user