2 * (C) Copyright 2014,2018 Leo C. <erbl259-lmu@yahoo.de>
8 #include "disas_z180.h"
15 i_
, iNOP
, iLD
, iINC
, iDEC
, iDJNZ
, iJR
, iHALT
, /* 0 .. 7 */
16 iRET
, iPOP
, iJP
, iCALL
, iPUSH
, iRST
, iOUT
, iEXX
, /* 8 .. 15 */
17 iIN
, iEX
, iDI
, iEI
, /* 16 .. 19 */
19 iBIT
, iRES
, iSET
, /* 20 .. 22 */
21 iNEG
, iRETN
, iRETI
, iIM
, iRRD
, iRLD
, /* 23 .. 28 */
23 iIN0
, iOUT0
, iTST
, iMLT
, iTSTIO
,
24 iSLP
, iOTIM
, iOTDM
, iOTIMR
, iOTDMR
, /* 29 .. 38 */
26 //i_opc_alu equ opc_index
28 iADD
, iADC
, iSUB
, iSBC
, iAND
, iXOR
, iOR
, iCP
, /* 39 .. 46 */
29 /* 1-byte no arguments */
30 iRLCA
, iRRCA
, iRLA
, iRRA
, iDAA
, iCPL
, iSCF
, iCCF
, /* 47 .. 54 */
32 iRLC
, iRRC
, iRL
, iRR
, iSLA
, iSRA
, iSLL
, iSRL
, /* 55 .. 62 */
34 //i_opc_bli equ opc_index
35 /* ED Block instr (bli) */
36 iLDI
, iCPI
, iINI
, iOUTI
, iLDD
, iCPD
, iIND
, iOUTD
, /* 63 .. 70 */
37 iLDIR
,iCPIR
,iINIR
,iOTIR
, iLDDR
,iCPDR
,iINDR
,iOTDR
/* 71 .. 78 */
44 const FLASH
uint8_t mnemonics
[] = {
45 '?' + 0x80, /* 1-byte other */
50 'D','J','N','Z' + 0x80,
52 'H','A','L','T' + 0x80,
56 'C','A','L','L' + 0x80,
57 'P','U','S','H' + 0x80,
65 'B','I','T' + 0x80, /* CB bit */
69 'R','E','T','N' + 0x80,
70 'R','E','T','I' + 0x80,
74 'I','N','0' + 0x80, /* Z180 */
75 'O','U','T','0' + 0x80,
78 'T','S','T','I','O' + 0x80,
80 'O','T','I','M' + 0x80,
81 'O','T','D','M' + 0x80,
82 'O','T','I','M','R' + 0x80,
83 'O','T','D','M','R' + 0x80,
84 'A','D','D' + 0x80, /* 1-byte "alu" */
92 'R','L','C','A' + 0x80, /* 1-byte no arguments */
93 'R','R','C','A' + 0x80,
100 'R','L','C' + 0x80, /* CB rot */
108 'L','D','I' + 0x80, /* ED Block instr (bli) */
111 'O','U','T','I' + 0x80,
115 'O','U','T','D' + 0x80,
116 'L','D','I','R' + 0x80,
117 'C','P','I','R' + 0x80,
118 'I','N','I','R' + 0x80,
119 'O','T','I','R' + 0x80,
120 'L','D','D','R' + 0x80,
121 'C','P','D','R' + 0x80,
122 'I','N','D','R' + 0x80,
123 'O','T','D','R' + 0x80,
126 //-------------------------------------------------------------------------------
128 // GROUP2, GROUP1 and GROUP3 are instruction decoding tables and have
129 // the following structure:
131 // [ mask { mode ( match , index ) } 0FFH ] 0.
133 // The repeating group ( match , index ) terminates when the MSB of the
134 // index byte is set. The interpretation of the "mode" byte is
135 // explained in the documentation to datasheet OPRNDZ.
140 //const FLASH uint8_t dec_tab2
143 uint8_t group2
[18]; /* GROUP2: CB group */
144 uint8_t group1
[123]; /* GROUP1: Main group */
145 uint8_t group3
[92]; /* GROUP3, ED group */
146 } __attribute__((__packed__
));
148 const FLASH
struct dec_tab dec_tab
= {
150 0xC0,0x36, //mask, mode
151 0x40,iBIT
, // bit b,g
152 0x80,iRES
, // res b,g
153 0xC0,iSET
+0x80, // set b,g
155 0xF8,0x00, //mask, mode
156 0x30,i_
+0x80, // (sll g)
158 0xC0,0x06, //mask, mode
159 0x00,iRLC
+0x80, // rlc g ... srl g
162 0xFF,0x00, //mask, mode
168 0xFB,iEI
+0x80, // EI //14
200 0xB6, //mode r[y],r[z]
202 0x06, //mode alu[y],r[z]
208 0x04,iINC
, // inc r[y]
209 0x05,iDEC
+0x80, // dec r[y]
211 0x06,iLD
+0x80, // ld r[y],nn
213 0x07,iRLCA
+0x80, // rlca ...
215 0xC0,iRET
+0x80, // ret cc
217 0xC2,iJP
, // jp cc,mn
218 0xC4,iCALL
+0x80, // call cc,mn
220 0xC7,iRST
+0x80, // rst
221 0x02, //mode alu[y] n
222 0xC6,iADD
+0x80, // add ...
227 0x01,iLD
+0x80, // ld ww,mn
230 0x0B,iDEC
+0x80, // dec rp
232 0x09,iADD
+0x80, // add hl,rp
234 0xC1,iPOP
, // pop rp2
235 0xC5,iPUSH
+0x80, // push rp2
240 0x20,iJR
+0x80, //jr cc,
245 0x02,iLD
+0x80, // ld (rp),a //rp=bc,de
247 0x0A,iLD
+0x80, // ld a,(rp) //rp=bc,de //12
259 0x93,iOTIMR
, // otimr
261 0x9B,iOTDMR
, // otdmr
262 0x31,i_
, // (OUT0 (m),0)
263 0x71,i_
+0x80, // (OUT (C),0)
265 0x30,iIN0
+0x80, // in0 (m)
268 0x74,iTSTIO
+0x80, // tstio m
270 0x70,iIN
+0x80, // IN (C)
275 0x04,iTST
+0x80, // tst r
277 0x40,iIN
+0x80, // IN r,(C)
279 0x00,iIN0
+0x80, // IN0 r,(m)
281 0x41,iOUT
+0x80, // OUT (C),r
283 0x01,iOUT0
+0x80, // UT0 (m),r
288 0x42,iSBC
, // sbc hl,rp
289 0x4A,iADC
+0x80, // adc hl,rp
291 0x43,iLD
+0x80, // LD (nn),rp
293 0x4B,iLD
+0x80, // LD rp,(nn)
295 0x4C,iMLT
+0x80, //mlt rp
300 0x46,iIM
+0x80, // IM x
305 0x47,iLD
+0x80, // LD i|r,A
307 0x57,iLD
+0x80, // LD A,i|r
312 0xA0,iLDI
+0x80, // LDI ...
320 //-------------------------------------------------------------------------------
322 // Disassemble and output Z80 machine code operand
324 // Index OPRND1 OPRND2
325 // -----------------------------------------------------------
326 // 1 RST address Relative address
327 // 2 Condition Immediate byte
328 // 3 Bit number Immediate word
329 // 4 Interrupt mode AF,AF'
331 // 6 Register pair 8-bit source
332 // -----------------------------------------------------------
336 // A (Absolute address)
337 // B 8-bit destination
340 // E Address in 16-bit register
346 // DE: Address of next instruction byte
347 // HL: Address of next free byte in output buffer
348 // (iy+0): Bit = 1: Print opcodes
349 // (iy+1): index register flag (1=IX, 2=IY, else 0)
350 // (iy+2): displacement for any indexed instruction
351 // (iy+3): no. of instraction bytes fetched
354 // Operand in output buffer
359 //-------------------------------------------------------------------------------
362 irR8
= 0, irPA
= 6, irRA
= 7, irIR
= 8,
363 irAFAF
= 10, irDEHL
= 11, irR16
= 12, irINDX
= 16,
364 irSP
= 19, irCOND
= 20, irINTMOD
= 28
367 const FLASH
uint8_t op_register
[] = {
374 '(','C',')' + 0x80, // 6
378 'A','F',',','A','F','\'' + 0x80, //10
379 'D','E',',','H','L' + 0x80, //
387 '(','S','P',')' + 0x80, //19
402 //-------------------------------------------------------------------------------
404 typedef struct disas_data_s disas_data_t
;
405 struct disas_data_s
{
408 int8_t opc_displacement
;
410 uint8_t bytes_fetched
;
416 void xtract(uint8_t index
, const FLASH
uint8_t *strlist
, disas_data_t
*dat
)
421 while ((*strlist
++ & 0x80) == 0)
427 dat
->outbuf
[dat
->outbufpos
++] = ch
& 0x7f;
428 } while ((ch
& 0x80) == 0);
432 uint8_t op_fetch(uint32_t addr
)
434 uint8_t op
= z80_read(addr
);
440 uint8_t op_fetch_print(disas_data_t
*dat
)
442 uint8_t opc
= op_fetch(dat
->address
);
444 ++dat
->bytes_fetched
;
445 printf_P(PSTR("%02X "), opc
);
452 void put_char(uint8_t ch
, disas_data_t
*dat
)
454 dat
->outbuf
[dat
->outbufpos
++] = ch
;
458 void put_digit(uint8_t digit
, disas_data_t
*dat
)
462 digit
+= (-10 + 'A'-'0');
465 put_char(digit
, dat
);
471 void put_hex(uint8_t byte
, disas_data_t
*dat
)
473 put_digit(byte
>> 4, dat
);
474 put_digit(byte
, dat
);
478 void put_hex_16(uint16_t word
, disas_data_t
*dat
)
480 put_hex(word
>> 8, dat
);
485 void do_op_reg16(disas_data_t
*dat
)
487 uint8_t op
= dat
->opcode
>> 3;
488 op
= ((op
>> 1) & 0x3) + irR16
;
490 op
= dat
->indexflag
+ irINDX
;
491 xtract(op
, op_register
, dat
);
495 void do_op_8bit_src_dst(uint8_t op
, disas_data_t
*dat
)
500 xtract(dat
->indexflag
+ irINDX
, op_register
, dat
);
501 if (dat
->indexflag
!= 0) {
503 int d
= dat
->opc_displacement
;
509 put_hex (d
& 0xff, dat
);
513 xtract(op
, op_register
, dat
);
517 void do_operand(uint8_t mode
, disas_data_t
*dat
)
524 case 1: /* RST address */
525 put_hex (dat
->opcode
& 0x38, dat
);
527 case 2: /* Op1 i2: Condition */
528 op1
= dat
->opcode
>> 3;
529 if ((op1
& 0x10) == 0) op1
&= 3;
530 op1
= (op1
& 7) + irCOND
;
531 xtract(op1
, op_register
, dat
);
533 case 3: /* Bit number */
534 op1
= dat
->opcode
>> 3;
536 put_digit (op1
, dat
);
538 case 4: /* Int mode */
539 op1
= dat
->opcode
>> 3;
540 op1
= (op1
& 0x03) + irINTMOD
;
541 xtract(op1
, op_register
, dat
);
544 xtract(irSP
, op_register
, dat
);
546 case 6: /* Register pair */
547 op1
= dat
->opcode
>> 3;
548 op1
= (op1
>> 1) & 0x03;
550 op1
= dat
->indexflag
+ irINDX
;
555 xtract(op1
, op_register
, dat
);
558 xtract(irRA
, op_register
, dat
);
561 xtract(irPA
, op_register
, dat
);
563 case 9: /* (port number) */
565 op1
= op_fetch_print(dat
);
569 case 0xA: /* (Absolute address) */
571 uint16_t arg16
= op_fetch_print(dat
)
572 + (op_fetch_print(dat
) << 8);
573 put_hex_16(arg16
, dat
);
576 case 0xB: /* 8-bit destination */
577 op1
= dat
->opcode
>> 3;
578 do_op_8bit_src_dst(op1
,dat
);
580 case 0xC: /* I or R */
581 op1
= dat
->opcode
>> 3;
583 xtract(op1
, op_register
, dat
);
585 case 0xD: /* 16-bit register */
588 case 0xE: /* Address in 16-bit register */
593 case 0xF: /* Index register */
594 op1
= dat
->indexflag
+ irINDX
;
595 xtract(op1
, op_register
, dat
);
599 case 0x11: /* Relative address */
600 op1
= op_fetch_print(dat
);
601 uint16_t dst
= dat
->address
+ (int8_t) op1
;
602 put_hex_16(dst
, dat
);
604 case 0x12: /* Immediate byte */
605 op1
= op_fetch_print(dat
);
608 case 0x13: ; /* Immediate word */
609 uint16_t imm16
= op_fetch_print(dat
)
610 + (op_fetch_print(dat
) << 8);
611 put_hex_16(imm16
, dat
);
613 case 0x14: /* AF,AF' */
614 xtract(irAFAF
, op_register
, dat
);
616 case 0x15: /* DE,HL */
617 xtract(irDEHL
, op_register
, dat
);
619 case 0x16: /* 8-bit source */
620 do_op_8bit_src_dst(dat
->opcode
,dat
);
625 uint32_t dis_decode(uint32_t addr
)
629 memset(&data
, 0, sizeof(data
));
638 printf_P(PSTR("%04X "), data
.address
);
640 const FLASH
uint8_t *decodep
= dec_tab
.group3
;
644 op
= op_fetch_print(&data
);
646 } else if (op
== 0xdd) {
648 } else if (op
== 0xfd) {
653 data
.indexflag
= iflag
;
654 } while (iflag
!= 0);
657 if (data
.indexflag
!= 0) {
658 if ((op
== 0xcb) || ((op
& 0x44) == 0x04) || ((op
& 0xc0) == 0x40)) {
659 data
.opc_displacement
= op_fetch_print(&data
);
663 decodep
= dec_tab
.group1
;
665 decodep
= dec_tab
.group2
;
666 op
= op_fetch_print(&data
);
669 op
= op_fetch_print(&data
);
675 while ((mask
= *decodep
++) != 0) { //NEWMSK
677 uint8_t opmask
= op
& mask
;
679 while ((mode
= *decodep
++) != 0xff) { //NEWMOD
684 opmatch
= *decodep
++;
686 if (opmatch
== opmask
) {
687 mnemi
= imatch
& 0x7f;
690 } while ((imatch
& 0x80) == 0);
695 /* block instruction? */
697 mnemi
= mnemi
+ (op
& 0x03) + ((op
>> 1) & 0x0c);
700 if ((mnemi
>= iADD
) && ((mode
& 0x80) == 0)) {
701 mnemi
= mnemi
+ ((op
>> 3) & 0x07);
704 xtract(mnemi
, mnemonics
, &data
);
705 while (data
.outbufpos
< 6)
706 put_char(' ', &data
);
708 uint8_t w
= (mode
& 0xf0) >> 4;
710 do_operand(w
, &data
);
712 put_char(',', &data
);
718 do_operand(w
, &data
);
720 for (uint8_t i
= data
.bytes_fetched
; i
< 4; i
++)
722 printf_P(PSTR("%s\n"), data
.outbuf
);