2 $DEFINE UFO
-ZXDISASM
-INCLUDED
4 HERE \
for size reports
17 0 value
(zxdis
-ixiy
) \ contains
0, [char
] x or
[char
] y
21 0 value
(zxdis
-opcode
)
23 create (zxdis-ixydisp-table)
24 0x00 C
, 0x00 C
, 0x00 C
, 0x00 C
,
25 0x00 C
, 0x00 C
, 0x70 C
, 0x00 C
,
26 0x40 C
, 0x40 C
, 0x40 C
, 0x40 C
,
27 0x40 C
, 0x40 C
, 0xBF C
, 0x40 C
,
28 0x40 C
, 0x40 C
, 0x40 C
, 0x40 C
,
29 0x40 C
, 0x40 C
, 0x40 C
, 0x40 C
,
30 0x00 C
, 0x08 C
, 0x00 C
, 0x00 C
,
31 0x00 C
, 0x00 C
, 0x00 C
, 0x00 C
,
35 \
////////////////////////////////////////////////////////////////////////// //
36 : (zxdis
-draw
-str
) ( -- ) (zxdis
-dptr
) 1+ (zxdis
-dofs
) xtype cr
;
38 : (zxdis
-put
-char
) ( ch
-- )
39 (zxdis
-dptr
) (zxdis
-dofs
) + 1+ C
!
40 (zxdis
-dofs
) 1+ to (zxdis
-dofs
)
43 : (zxdis
-put
-str
) ( addr len
-- )
53 : (zxdis
-put
-space
) ( -- ) bl
(zxdis
-put
-char
) ;
54 : (zxdis
-put
-comma
) ( -- ) [char
] , (zxdis
-put
-char
) ;
55 : (zxdis
-put
-lpar
) ( -- ) [char
] ( (zxdis
-put
-char
) ;
56 : (zxdis
-put
-rpar
) ( -- ) [char
] ) (zxdis
-put
-char
) ;
59 : (zxdis
-put
-str
-2) ( addr
-- ) 2 (zxdis
-put
-str
) ;
60 : (zxdis
-put
-str
-4) ( addr
-- ) drop
+ 4 (zxdis
-put
-str
) ;
61 : (zxdis
-put
-str
-4x
) ( addr
-- ) dup
3 + C@ bl
= if 3 else 4 endif (zxdis
-put
-str
) ;
64 \
////////////////////////////////////////////////////////////////////////// //
65 : (zxdis
-put
-n8
) ( n
-- )
69 hex
<#n # #
[char
] # hold
74 (zxdis
-put
-str
) r
> base
!
77 : (zxdis
-put
-n16
) ( n
-- )
81 hex
<#n # # # #
[char
] # hold
86 (zxdis
-put
-str
) r
> base
!
89 : (zxdis
-put
-disp
) ( -- )
90 (zxdis
-disp
) 0< if [char
] - else [char
] + endif (zxdis
-put
-char
)
92 base @
>r decimal
<#n #s #
>
93 (zxdis
-put
-str
) r
> base
!
97 \
////////////////////////////////////////////////////////////////////////// //
99 : (zxdis
-get
-byte
) ( -- b
)
101 zxdis
-pc
1+ 0xFFFF and
to zxdis
-pc
106 : (zxdis
-get
-word
) ( -- b
)
107 (zxdis
-get
-byte
) (zxdis
-get
-byte
) 8 lshift or
111 : (zxdis
-byte
-to-signed
) ( b
-- n
) dup
0x80 >= if 0x100 - endif ;
114 \
////////////////////////////////////////////////////////////////////////// //
115 : (zxdis
-put
-ixy
-mem
) ( -- )
116 " (i" (zxdis
-put
-str
)
117 (zxdis
-ixiy
) (zxdis
-put
-char
)
123 : (zxdis
-put
-r8
) ( r8
-- )
124 7 and
" bcdehl.a" drop
+ c@
131 " (hl)" (zxdis
-put
-str
)
134 \ undocumented IX
/IY
8-bit part access
136 dup
[char
] h
= over
[char
] l
= or
if
137 \
[char
] i
(zxdis
-put
-char
)
138 (zxdis
-ixiy
) (zxdis
-put
-char
)
146 : (zxdis
-put
-r16
-hl
-ixy
) ( -- )
150 (zxdis
-ixiy
) (zxdis
-put
-char
)
152 " hl" (zxdis
-put
-str
)
156 : (zxdis
-put
-v16
) ( -- ) (zxdis
-get
-word
) (zxdis
-put
-n16
) ;
157 : (zxdis
-put
-m16
) ( -- ) (zxdis
-put
-lpar
) (zxdis
-put
-v16
) (zxdis
-put
-rpar
) ;
159 : (zxdis
-put
-r16
-common) ( r16 addr count
-- )
160 drop swap
3 and
2u* +
162 drop
(zxdis
-put
-r16
-hl
-ixy
)
168 : (zxdis
-put
-r16
-sp
) ( r16
-- )
169 (zxdis
-opcode
) 4 rshift
170 " bcdehlsp" (zxdis
-put
-r16
-common)
174 : (zxdis
-put
-r16
-af
) ( r16
-- )
175 (zxdis
-opcode
) 4 rshift
176 " bcdehlaf" (zxdis
-put
-r16
-common)
180 : (zxdis
-put
-cc
) ( cc
-- )
181 7 and
2u* " nzz ncc popep m " drop
+
182 dup c@
(zxdis
-put
-char
)
183 1+ c@ dup
32 <> if (zxdis
-put
-char
) else drop
endif
187 \
////////////////////////////////////////////////////////////////////////// //
188 : (zxdis
-decode
-cb
-unixy
) ( -- )
189 \ special undocumented thing
191 \ `bit` doesn
't need undoc ixy
192 (zxdis-opcode) 0x80 and if
193 (zxdis-opcode) 7 and 6 <> if
201 : (zxdis-decode-cb) ( -- )
202 (zxdis-opcode) 0xc0 and
204 (zxdis-opcode) 4 rshift 0x0c and 4- " bit res set " (zxdis-put-str-4)
206 (zxdis-opcode) 3 rshift 7 and [char] 0 + (zxdis-put-char)
209 (zxdis-opcode) 2u/ 0x1c and
210 " rlc rrc rl rr sla sra sll srl " (zxdis-put-str-4)
213 (zxdis-opcode) (zxdis-put-r8)
214 (zxdis-decode-cb-unixy)
218 \ ////////////////////////////////////////////////////////////////////////// //
219 : (zxdis-decode-ed-xrep) ( -- )
220 \ two instructions with the wrong mnemonic length
221 (zxdis-opcode) 0xa3 = if " outi" (zxdis-put-str) exit endif
222 (zxdis-opcode) 0xab = if " outd" (zxdis-put-str) exit endif
224 (zxdis-opcode) 3 and 2u* " ldcpinot" drop + (zxdis-put-str-2)
225 (zxdis-opcode) 0x08 and if [char] d else [char] i endif (zxdis-put-char)
226 (zxdis-opcode) 0x10 and if [char] r (zxdis-put-char) endif
229 : (zxdis-decode-ed) ( -- )
230 (zxdis-opcode) 0xa4 and 0xa0 = if (zxdis-decode-ed-xrep) exit endif
231 (zxdis-opcode) 0xc0 and 0x40 <> if " nope" (zxdis-put-str) exit endif
232 (zxdis-opcode) 0x04 and if
233 (zxdis-opcode) 7 and case
234 0x04 of " neg" (zxdis-put-str) endof
235 0x05 of " ret" (zxdis-put-str) (zxdis-opcode) 0x08 and if [char] i else [char] n endif (zxdis-put-char) endof
237 " im " (zxdis-put-str)
238 (zxdis-opcode) 0x47 = if " 0/1" (zxdis-put-str) exit endif
239 (zxdis-opcode) 0x10 and if
240 (zxdis-opcode) 0x08 and if [char] 2 else [char] 1 endif
248 0x47 of " ld i,a" endof
249 0x4f of " ld r,a" endof
250 0x57 of " ld a,i" endof
251 0x5f of " ld a,r" endof
254 otherwise drop " nope"
258 otherwise drop " nope" (zxdis-put-str)
261 (zxdis-opcode) 0x02 and if
263 (zxdis-opcode) 0x01 and if
264 " ld " (zxdis-put-str)
266 (zxdis-opcode) 0x08 and if
278 (zxdis-opcode) 2u/ 4 and " sbc adc " (zxdis-put-str-4)
279 " hl," (zxdis-put-str)
283 (zxdis-opcode) 0x01 and if
284 " out (c)," (zxdis-put-str)
285 (zxdis-opcode) 3 rshift
286 \ check for `(hl)`, it is special here
288 drop [char] 0 (zxdis-put-char)
293 " in " (zxdis-put-str)
294 (zxdis-opcode) 3 rshift
295 \ check for `(hl)`, it is special here
302 " (c)" (zxdis-put-str)
309 \ ////////////////////////////////////////////////////////////////////////// //
310 \ ld r8,r8 (and halt)
311 : (zxdis-decode-norm-grp1) ( -- )
312 (zxdis-opcode) 0x76 = if " halt" (zxdis-put-str) exit endif
313 " ld " (zxdis-put-str)
314 (zxdis-opcode) 3 rshift (zxdis-put-r8)
316 (zxdis-opcode) (zxdis-put-r8)
319 : (zxdis-put-alu-str) ( -- )
320 (zxdis-opcode) 2u/ 0x1c and " add adc sub sbc and xor or cp " (zxdis-put-str-4)
322 \ two special opcodes
323 (zxdis-opcode) 0x38 and dup 0x08 = over 0x18 = or swap 0x00 = or if " a," (zxdis-put-str) endif
327 \ call,ret,push,pop,etc.
328 : (zxdis-decode-norm-grp3) ( -- )
329 (zxdis-opcode) 7 and case
330 0x00 of " ret " (zxdis-put-str) (zxdis-opcode) 3 rshift (zxdis-put-cc) endof
332 (zxdis-opcode) 0x08 and if
333 (zxdis-opcode) 0x30 and case
334 0x00 of " ret" (zxdis-put-str) endof
335 0x10 of " exx" (zxdis-put-str) endof
336 0x20 of " jp (" (zxdis-put-str) (zxdis-put-r16-hl-ixy) (zxdis-put-rpar) endof
337 0x30 of " ld sp," (zxdis-put-str) (zxdis-put-r16-hl-ixy) endof
340 " pop " (zxdis-put-str)
344 0x02 of " jp " (zxdis-put-str) (zxdis-opcode) 3 rshift (zxdis-put-cc) (zxdis-put-comma) (zxdis-put-v16) endof
346 (zxdis-opcode) 0x38 and case
347 0x00 of " jp " (zxdis-put-str) (zxdis-put-v16) endof
349 0x10 of " out (" (zxdis-put-str) (zxdis-get-byte) (zxdis-put-n8) " ),a" (zxdis-put-str) endof
350 0x18 of " in a,(" (zxdis-put-str) (zxdis-get-byte) (zxdis-put-n8) (zxdis-put-rpar) endof
351 0x20 of " ex (sp)," (zxdis-put-str) (zxdis-put-r16-hl-ixy) endof
352 0x28 of " ex de,hl" (zxdis-put-str) endof
353 0x30 of " di" (zxdis-put-str) endof
354 0x38 of " ei" (zxdis-put-str) endof
357 0x04 of " call " (zxdis-put-str) (zxdis-opcode) 3 rshift (zxdis-put-cc) (zxdis-put-comma) (zxdis-put-v16) endof
359 (zxdis-opcode) 0x08 and if
360 \ prefixes already done, so only call is left
361 " call " (zxdis-put-str)
364 " push " (zxdis-put-str)
370 (zxdis-get-byte) (zxdis-put-n8)
373 " rst " (zxdis-put-str)
374 (zxdis-opcode) 0x38 and (zxdis-put-n8)
379 : (zxdis-decode-norm-grp0) ( -- )
380 (zxdis-opcode) 0x06 and case
382 (zxdis-opcode) 1 and if
383 (zxdis-opcode) 0x08 and if
384 " add " (zxdis-put-str)
385 (zxdis-put-r16-hl-ixy)
389 " ld " (zxdis-put-str)
395 (zxdis-opcode) 0x20 and if
396 " jr " (zxdis-put-str)
397 (zxdis-opcode) 3 rshift 3 and (zxdis-put-cc)
399 (zxdis-get-byte) dup 0x80 >= if 0x100 - endif
400 zxdis-pc + (zxdis-put-n16)
403 (zxdis-opcode) 0x10 and if
404 (zxdis-opcode) 2u/ 4 and " djnzjr " (zxdis-put-str-4)
406 (zxdis-get-byte) dup 0x80 >= if 0x100 - endif
407 zxdis-pc + (zxdis-put-n16)
410 (zxdis-opcode) 0x08 and if " ex af,af'" else " nop
" endif (zxdis-put-str)
414 (zxdis-opcode) 1 and if
415 (zxdis-opcode) 2u/ 4 and " inc dec
" (zxdis-put-str-4)
419 " ld
" (zxdis-put-str)
420 (zxdis-opcode) 0x3c and case
421 0x00 of " (bc
),a
" (zxdis-put-str) endof
422 0x08 of " a
,(bc
)" (zxdis-put-str) endof
423 0x10 of " (de
),a
" (zxdis-put-str) endof
424 0x18 of " a
,(de
)" (zxdis-put-str) endof
425 0x20 of (zxdis-put-m16) (zxdis-put-comma) (zxdis-put-r16-hl-ixy) endof
426 0x28 of (zxdis-put-r16-hl-ixy) (zxdis-put-comma) (zxdis-put-m16) endof
427 0x30 of (zxdis-put-m16) " ,a
" (zxdis-put-str) endof
428 0x38 of " a
," (zxdis-put-str) (zxdis-put-m16) endof
433 (zxdis-opcode) 0x01 and 2 lshift " inc dec
" (zxdis-put-str-4)
435 (zxdis-opcode) 3 rshift (zxdis-put-r8)
438 (zxdis-opcode) 1 and if
439 (zxdis-opcode) 2u/ 0x1c and " rlcarrcarla rra daa cpl scf ccf
" drop + (zxdis-put-str-4x)
441 " ld
" (zxdis-put-str)
442 (zxdis-opcode) 3 rshift (zxdis-put-r8)
444 (zxdis-get-byte) (zxdis-put-n8)
450 : (zxdis-decode-norm) ( -- )
451 (zxdis-opcode) 0xc0 and case
452 0x00 of (zxdis-decode-norm-grp0) endof
453 0x40 of (zxdis-decode-norm-grp1) endof
454 0x80 of (zxdis-put-alu-str) (zxdis-opcode) (zxdis-put-r8) endof \ alu a,r8
455 otherwise drop (zxdis-decode-norm-grp3)
460 \ ////////////////////////////////////////////////////////////////////////// //
463 \ returns disassembled test (only command, no address or bytes )
464 : zx-disasm-one ( addr -- saddr slen )
467 PAD 420 + to (zxdis-dptr)
472 \ check if I<X|Y> prefix
473 dup 0xdd = if [char] x to (zxdis-ixiy) endif
474 dup 0xfd = if [char] y to (zxdis-ixiy) endif
476 drop (zxdis-get-byte) dup to (zxdis-opcode)
477 dup 0xdd = over 0xfd = or if
478 drop " nopx
" (zxdis-put-str)
480 zxdis-pc 1- 0xFFFF and to zxdis-pc
483 \ check if we have disp here
484 dup 3 rshift (zxdis-ixydisp-table) + c@
485 1 rot 7 and lshift and
488 (zxdis-get-byte) (zxdis-byte-to-signed) to (zxdis-disp)
495 0xcb of (zxdis-get-byte) to (zxdis-opcode) (zxdis-decode-cb) endof
496 0xed of (zxdis-get-byte) to (zxdis-opcode) (zxdis-decode-ed) endof
497 otherwise drop (zxdis-decode-norm)
499 (zxdis-dofs) (zxdis-dptr) C!
500 (zxdis-dptr) 1+ (zxdis-dofs)
506 \ DUP ." Z80 disasm size
: " . ." bytes
" CR
517 \ zx-disasm-one \ ( staddr addr count )
519 \ base @ over hex <#n # # # # #> type base ! ." : "
523 \ base @ i asm-c@ hex <#n bl hold # # #> type base !