1 // license:BSD-3-Clause
2 // copyright-holders:Juergen Buchmueller
3 /*****************************************************************************
4 *
5 * z80dasm.c
6 * Portable Z80 disassembler
7 *
8 *****************************************************************************/
9
10 #include "emu.h"
11 #include "debugger.h"
12 #include "z80dasm.h"
13
14
15 static const char *const s_mnemonic[] =
16 {
17 "adc" ,"add" ,"and" ,"bit" ,"call","ccf" ,"cp" ,"cpd" ,
18 "cpdr","cpi" ,"cpir","cpl" ,"daa" ,"db" ,"dec" ,"di" ,
19 "djnz","ei" ,"ex" ,"exx" ,"halt","im" ,"in" ,"inc" ,
20 "ind" ,"indr","ini" ,"inir","jp" ,"jr" ,"ld" ,"ldd" ,
21 "lddr","ldi" ,"ldir","neg" ,"nop" ,"or" ,"otdr","otir",
22 "out" ,"outd","outi","pop" ,"push","res" ,"ret" ,"reti",
23 "retn","rl" ,"rla" ,"rlc" ,"rlca","rld" ,"rr" ,"rra" ,
24 "rrc" ,"rrca","rrd" ,"rst" ,"sbc" ,"scf" ,"set" ,"sla" ,
25 "sll" ,"sra" ,"srl" ,"sub" ,"xor "
26 };
27
28 const u32 z80_disassembler::s_flags[] =
29 {
30 0 ,0 ,0 ,0 ,STEP_OVER,0 ,0 ,0 ,
31 STEP_OVER,0 ,STEP_OVER,0 ,0 ,0 ,0 ,0 ,
32 STEP_OVER,0 ,0 ,0 ,STEP_OVER,0 ,0 ,0 ,
33 0 ,STEP_OVER,0 ,STEP_OVER,0 ,0 ,0 ,0 ,
34 STEP_OVER,0 ,STEP_OVER,0 ,0 ,0 ,STEP_OVER,STEP_OVER,
35 0 ,0 ,0 ,0 ,0 ,0 ,STEP_OUT ,STEP_OUT ,
36 STEP_OUT ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
37 0 ,0 ,0 ,STEP_OVER,0 ,0 ,0 ,0 ,
38 0 ,0 ,0 ,0 ,0
39 };
40
41 const z80_disassembler::z80dasm z80_disassembler::mnemonic_xx_cb[256] =
42 {
43 {zRLC,"b=Y"}, {zRLC,"c=Y"}, {zRLC,"d=Y"}, {zRLC,"e=Y"},
44 {zRLC,"h=Y"}, {zRLC,"l=Y"}, {zRLC,"Y"}, {zRLC,"a=Y"},
45 {zRRC,"b=Y"}, {zRRC,"c=Y"}, {zRRC,"d=Y"}, {zRRC,"e=Y"},
46 {zRRC,"h=Y"}, {zRRC,"l=Y"}, {zRRC,"Y"}, {zRRC,"a=Y"},
47 {zRL,"b=Y"}, {zRL,"c=Y"}, {zRL,"d=Y"}, {zRL,"e=Y"},
48 {zRL,"h=Y"}, {zRL,"l=Y"}, {zRL,"Y"}, {zRL,"a=Y"},
49 {zRR,"b=Y"}, {zRR,"c=Y"}, {zRR,"d=Y"}, {zRR,"e=Y"},
50 {zRR,"h=Y"}, {zRR,"l=Y"}, {zRR,"Y"}, {zRR,"a=Y"},
51 {zSLA,"b=Y"}, {zSLA,"c=Y"}, {zSLA,"d=Y"}, {zSLA,"e=Y"},
52 {zSLA,"h=Y"}, {zSLA,"l=Y"}, {zSLA,"Y"}, {zSLA,"a=Y"},
53 {zSRA,"b=Y"}, {zSRA,"c=Y"}, {zSRA,"d=Y"}, {zSRA,"e=Y"},
54 {zSRA,"h=Y"}, {zSRA,"l=Y"}, {zSRA,"Y"}, {zSRA,"a=Y"},
55 {zSLL,"b=Y"}, {zSLL,"c=Y"}, {zSLL,"d=Y"}, {zSLL,"e=Y"},
56 {zSLL,"h=Y"}, {zSLL,"l=Y"}, {zSLL,"Y"}, {zSLL,"a=Y"},
57 {zSRL,"b=Y"}, {zSRL,"c=Y"}, {zSRL,"d=Y"}, {zSRL,"e=Y"},
58 {zSRL,"h=Y"}, {zSRL,"l=Y"}, {zSRL,"Y"}, {zSRL,"a=Y"},
59 {zBIT,"b=0,Y"}, {zBIT,"c=0,Y"}, {zBIT,"d=0,Y"}, {zBIT,"e=0,Y"},
60 {zBIT,"h=0,Y"}, {zBIT,"l=0,Y"}, {zBIT,"0,Y"}, {zBIT,"a=0,Y"},
61 {zBIT,"b=1,Y"}, {zBIT,"c=1,Y"}, {zBIT,"d=1,Y"}, {zBIT,"e=1,Y"},
62 {zBIT,"h=1,Y"}, {zBIT,"l=1,Y"}, {zBIT,"1,Y"}, {zBIT,"a=1,Y"},
63 {zBIT,"b=2,Y"}, {zBIT,"c=2,Y"}, {zBIT,"d=2,Y"}, {zBIT,"e=2,Y"},
64 {zBIT,"h=2,Y"}, {zBIT,"l=2,Y"}, {zBIT,"2,Y"}, {zBIT,"a=2,Y"},
65 {zBIT,"b=3,Y"}, {zBIT,"c=3,Y"}, {zBIT,"d=3,Y"}, {zBIT,"e=3,Y"},
66 {zBIT,"h=3,Y"}, {zBIT,"l=3,Y"}, {zBIT,"3,Y"}, {zBIT,"a=3,Y"},
67 {zBIT,"b=4,Y"}, {zBIT,"c=4,Y"}, {zBIT,"d=4,Y"}, {zBIT,"e=4,Y"},
68 {zBIT,"h=4,Y"}, {zBIT,"l=4,Y"}, {zBIT,"4,Y"}, {zBIT,"a=4,Y"},
69 {zBIT,"b=5,Y"}, {zBIT,"c=5,Y"}, {zBIT,"d=5,Y"}, {zBIT,"e=5,Y"},
70 {zBIT,"h=5,Y"}, {zBIT,"l=5,Y"}, {zBIT,"5,Y"}, {zBIT,"a=5,Y"},
71 {zBIT,"b=6,Y"}, {zBIT,"c=6,Y"}, {zBIT,"d=6,Y"}, {zBIT,"e=6,Y"},
72 {zBIT,"h=6,Y"}, {zBIT,"l=6,Y"}, {zBIT,"6,Y"}, {zBIT,"a=6,Y"},
73 {zBIT,"b=7,Y"}, {zBIT,"c=7,Y"}, {zBIT,"d=7,Y"}, {zBIT,"e=7,Y"},
74 {zBIT,"h=7,Y"}, {zBIT,"l=7,Y"}, {zBIT,"7,Y"}, {zBIT,"a=7,Y"},
75 {zRES,"b=0,Y"}, {zRES,"c=0,Y"}, {zRES,"d=0,Y"}, {zRES,"e=0,Y"},
76 {zRES,"h=0,Y"}, {zRES,"l=0,Y"}, {zRES,"0,Y"}, {zRES,"a=0,Y"},
77 {zRES,"b=1,Y"}, {zRES,"c=1,Y"}, {zRES,"d=1,Y"}, {zRES,"e=1,Y"},
78 {zRES,"h=1,Y"}, {zRES,"l=1,Y"}, {zRES,"1,Y"}, {zRES,"a=1,Y"},
79 {zRES,"b=2,Y"}, {zRES,"c=2,Y"}, {zRES,"d=2,Y"}, {zRES,"e=2,Y"},
80 {zRES,"h=2,Y"}, {zRES,"l=2,Y"}, {zRES,"2,Y"}, {zRES,"a=2,Y"},
81 {zRES,"b=3,Y"}, {zRES,"c=3,Y"}, {zRES,"d=3,Y"}, {zRES,"e=3,Y"},
82 {zRES,"h=3,Y"}, {zRES,"l=3,Y"}, {zRES,"3,Y"}, {zRES,"a=3,Y"},
83 {zRES,"b=4,Y"}, {zRES,"c=4,Y"}, {zRES,"d=4,Y"}, {zRES,"e=4,Y"},
84 {zRES,"h=4,Y"}, {zRES,"l=4,Y"}, {zRES,"4,Y"}, {zRES,"a=4,Y"},
85 {zRES,"b=5,Y"}, {zRES,"c=5,Y"}, {zRES,"d=5,Y"}, {zRES,"e=5,Y"},
86 {zRES,"h=5,Y"}, {zRES,"l=5,Y"}, {zRES,"5,Y"}, {zRES,"a=5,Y"},
87 {zRES,"b=6,Y"}, {zRES,"c=6,Y"}, {zRES,"d=6,Y"}, {zRES,"e=6,Y"},
88 {zRES,"h=6,Y"}, {zRES,"l=6,Y"}, {zRES,"6,Y"}, {zRES,"a=6,Y"},
89 {zRES,"b=7,Y"}, {zRES,"c=7,Y"}, {zRES,"d=7,Y"}, {zRES,"e=7,Y"},
90 {zRES,"h=7,Y"}, {zRES,"l=7,Y"}, {zRES,"7,Y"}, {zRES,"a=7,Y"},
91 {zSET,"b=0,Y"}, {zSET,"c=0,Y"}, {zSET,"d=0,Y"}, {zSET,"e=0,Y"},
92 {zSET,"h=0,Y"}, {zSET,"l=0,Y"}, {zSET,"0,Y"}, {zSET,"a=0,Y"},
93 {zSET,"b=1,Y"}, {zSET,"c=1,Y"}, {zSET,"d=1,Y"}, {zSET,"e=1,Y"},
94 {zSET,"h=1,Y"}, {zSET,"l=1,Y"}, {zSET,"1,Y"}, {zSET,"a=1,Y"},
95 {zSET,"b=2,Y"}, {zSET,"c=2,Y"}, {zSET,"d=2,Y"}, {zSET,"e=2,Y"},
96 {zSET,"h=2,Y"}, {zSET,"l=2,Y"}, {zSET,"2,Y"}, {zSET,"a=2,Y"},
97 {zSET,"b=3,Y"}, {zSET,"c=3,Y"}, {zSET,"d=3,Y"}, {zSET,"e=3,Y"},
98 {zSET,"h=3,Y"}, {zSET,"l=3,Y"}, {zSET,"3,Y"}, {zSET,"a=3,Y"},
99 {zSET,"b=4,Y"}, {zSET,"c=4,Y"}, {zSET,"d=4,Y"}, {zSET,"e=4,Y"},
100 {zSET,"h=4,Y"}, {zSET,"l=4,Y"}, {zSET,"4,Y"}, {zSET,"a=4,Y"},
101 {zSET,"b=5,Y"}, {zSET,"c=5,Y"}, {zSET,"d=5,Y"}, {zSET,"e=5,Y"},
102 {zSET,"h=5,Y"}, {zSET,"l=5,Y"}, {zSET,"5,Y"}, {zSET,"a=5,Y"},
103 {zSET,"b=6,Y"}, {zSET,"c=6,Y"}, {zSET,"d=6,Y"}, {zSET,"e=6,Y"},
104 {zSET,"h=6,Y"}, {zSET,"l=6,Y"}, {zSET,"6,Y"}, {zSET,"a=6,Y"},
105 {zSET,"b=7,Y"}, {zSET,"c=7,Y"}, {zSET,"d=7,Y"}, {zSET,"e=7,Y"},
106 {zSET,"h=7,Y"}, {zSET,"l=7,Y"}, {zSET,"7,Y"}, {zSET,"a=7,Y"}
107 };
108
109 const z80_disassembler::z80dasm z80_disassembler::mnemonic_cb[256] =
110 {
111 {zRLC,"b"}, {zRLC,"c"}, {zRLC,"d"}, {zRLC,"e"},
112 {zRLC,"h"}, {zRLC,"l"}, {zRLC,"(hl)"}, {zRLC,"a"},
113 {zRRC,"b"}, {zRRC,"c"}, {zRRC,"d"}, {zRRC,"e"},
114 {zRRC,"h"}, {zRRC,"l"}, {zRRC,"(hl)"}, {zRRC,"a"},
115 {zRL,"b"}, {zRL,"c"}, {zRL,"d"}, {zRL,"e"},
116 {zRL,"h"}, {zRL,"l"}, {zRL,"(hl)"}, {zRL,"a"},
117 {zRR,"b"}, {zRR,"c"}, {zRR,"d"}, {zRR,"e"},
118 {zRR,"h"}, {zRR,"l"}, {zRR,"(hl)"}, {zRR,"a"},
119 {zSLA,"b"}, {zSLA,"c"}, {zSLA,"d"}, {zSLA,"e"},
120 {zSLA,"h"}, {zSLA,"l"}, {zSLA,"(hl)"}, {zSLA,"a"},
121 {zSRA,"b"}, {zSRA,"c"}, {zSRA,"d"}, {zSRA,"e"},
122 {zSRA,"h"}, {zSRA,"l"}, {zSRA,"(hl)"}, {zSRA,"a"},
123 {zSLL,"b"}, {zSLL,"c"}, {zSLL,"d"}, {zSLL,"e"},
124 {zSLL,"h"}, {zSLL,"l"}, {zSLL,"(hl)"}, {zSLL,"a"},
125 {zSRL,"b"}, {zSRL,"c"}, {zSRL,"d"}, {zSRL,"e"},
126 {zSRL,"h"}, {zSRL,"l"}, {zSRL,"(hl)"}, {zSRL,"a"},
127 {zBIT,"0,b"}, {zBIT,"0,c"}, {zBIT,"0,d"}, {zBIT,"0,e"},
128 {zBIT,"0,h"}, {zBIT,"0,l"}, {zBIT,"0,(hl)"},{zBIT,"0,a"},
129 {zBIT,"1,b"}, {zBIT,"1,c"}, {zBIT,"1,d"}, {zBIT,"1,e"},
130 {zBIT,"1,h"}, {zBIT,"1,l"}, {zBIT,"1,(hl)"},{zBIT,"1,a"},
131 {zBIT,"2,b"}, {zBIT,"2,c"}, {zBIT,"2,d"}, {zBIT,"2,e"},
132 {zBIT,"2,h"}, {zBIT,"2,l"}, {zBIT,"2,(hl)"},{zBIT,"2,a"},
133 {zBIT,"3,b"}, {zBIT,"3,c"}, {zBIT,"3,d"}, {zBIT,"3,e"},
134 {zBIT,"3,h"}, {zBIT,"3,l"}, {zBIT,"3,(hl)"},{zBIT,"3,a"},
135 {zBIT,"4,b"}, {zBIT,"4,c"}, {zBIT,"4,d"}, {zBIT,"4,e"},
136 {zBIT,"4,h"}, {zBIT,"4,l"}, {zBIT,"4,(hl)"},{zBIT,"4,a"},
137 {zBIT,"5,b"}, {zBIT,"5,c"}, {zBIT,"5,d"}, {zBIT,"5,e"},
138 {zBIT,"5,h"}, {zBIT,"5,l"}, {zBIT,"5,(hl)"},{zBIT,"5,a"},
139 {zBIT,"6,b"}, {zBIT,"6,c"}, {zBIT,"6,d"}, {zBIT,"6,e"},
140 {zBIT,"6,h"}, {zBIT,"6,l"}, {zBIT,"6,(hl)"},{zBIT,"6,a"},
141 {zBIT,"7,b"}, {zBIT,"7,c"}, {zBIT,"7,d"}, {zBIT,"7,e"},
142 {zBIT,"7,h"}, {zBIT,"7,l"}, {zBIT,"7,(hl)"},{zBIT,"7,a"},
143 {zRES,"0,b"}, {zRES,"0,c"}, {zRES,"0,d"}, {zRES,"0,e"},
144 {zRES,"0,h"}, {zRES,"0,l"}, {zRES,"0,(hl)"},{zRES,"0,a"},
145 {zRES,"1,b"}, {zRES,"1,c"}, {zRES,"1,d"}, {zRES,"1,e"},
146 {zRES,"1,h"}, {zRES,"1,l"}, {zRES,"1,(hl)"},{zRES,"1,a"},
147 {zRES,"2,b"}, {zRES,"2,c"}, {zRES,"2,d"}, {zRES,"2,e"},
148 {zRES,"2,h"}, {zRES,"2,l"}, {zRES,"2,(hl)"},{zRES,"2,a"},
149 {zRES,"3,b"}, {zRES,"3,c"}, {zRES,"3,d"}, {zRES,"3,e"},
150 {zRES,"3,h"}, {zRES,"3,l"}, {zRES,"3,(hl)"},{zRES,"3,a"},
151 {zRES,"4,b"}, {zRES,"4,c"}, {zRES,"4,d"}, {zRES,"4,e"},
152 {zRES,"4,h"}, {zRES,"4,l"}, {zRES,"4,(hl)"},{zRES,"4,a"},
153 {zRES,"5,b"}, {zRES,"5,c"}, {zRES,"5,d"}, {zRES,"5,e"},
154 {zRES,"5,h"}, {zRES,"5,l"}, {zRES,"5,(hl)"},{zRES,"5,a"},
155 {zRES,"6,b"}, {zRES,"6,c"}, {zRES,"6,d"}, {zRES,"6,e"},
156 {zRES,"6,h"}, {zRES,"6,l"}, {zRES,"6,(hl)"},{zRES,"6,a"},
157 {zRES,"7,b"}, {zRES,"7,c"}, {zRES,"7,d"}, {zRES,"7,e"},
158 {zRES,"7,h"}, {zRES,"7,l"}, {zRES,"7,(hl)"},{zRES,"7,a"},
159 {zSET,"0,b"}, {zSET,"0,c"}, {zSET,"0,d"}, {zSET,"0,e"},
160 {zSET,"0,h"}, {zSET,"0,l"}, {zSET,"0,(hl)"},{zSET,"0,a"},
161 {zSET,"1,b"}, {zSET,"1,c"}, {zSET,"1,d"}, {zSET,"1,e"},
162 {zSET,"1,h"}, {zSET,"1,l"}, {zSET,"1,(hl)"},{zSET,"1,a"},
163 {zSET,"2,b"}, {zSET,"2,c"}, {zSET,"2,d"}, {zSET,"2,e"},
164 {zSET,"2,h"}, {zSET,"2,l"}, {zSET,"2,(hl)"},{zSET,"2,a"},
165 {zSET,"3,b"}, {zSET,"3,c"}, {zSET,"3,d"}, {zSET,"3,e"},
166 {zSET,"3,h"}, {zSET,"3,l"}, {zSET,"3,(hl)"},{zSET,"3,a"},
167 {zSET,"4,b"}, {zSET,"4,c"}, {zSET,"4,d"}, {zSET,"4,e"},
168 {zSET,"4,h"}, {zSET,"4,l"}, {zSET,"4,(hl)"},{zSET,"4,a"},
169 {zSET,"5,b"}, {zSET,"5,c"}, {zSET,"5,d"}, {zSET,"5,e"},
170 {zSET,"5,h"}, {zSET,"5,l"}, {zSET,"5,(hl)"},{zSET,"5,a"},
171 {zSET,"6,b"}, {zSET,"6,c"}, {zSET,"6,d"}, {zSET,"6,e"},
172 {zSET,"6,h"}, {zSET,"6,l"}, {zSET,"6,(hl)"},{zSET,"6,a"},
173 {zSET,"7,b"}, {zSET,"7,c"}, {zSET,"7,d"}, {zSET,"7,e"},
174 {zSET,"7,h"}, {zSET,"7,l"}, {zSET,"7,(hl)"},{zSET,"7,a"}
175 };
176
177 const z80_disassembler::z80dasm z80_disassembler::mnemonic_ed[256] =
178 {
179 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
180 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
181 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
182 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
183 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
184 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
185 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
186 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
187 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
188 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
189 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
190 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
191 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
192 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
193 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
194 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
195 {zIN,"b,(c)"}, {zOUT,"(c),b"}, {zSBC,"hl,bc"}, {zLD,"(W),bc"},
196 {zNEG,nullptr}, {zRETN,nullptr},{zIM,"0"}, {zLD,"i,a"},
197 {zIN,"c,(c)"}, {zOUT,"(c),c"}, {zADC,"hl,bc"}, {zLD,"bc,(W)"},
198 {zNEG,"*"}, {zRETI,nullptr},{zIM,"0"}, {zLD,"r,a"},
199 {zIN,"d,(c)"}, {zOUT,"(c),d"}, {zSBC,"hl,de"}, {zLD,"(W),de"},
200 {zNEG,"*"}, {zRETN,nullptr},{zIM,"1"}, {zLD,"a,i"},
201 {zIN,"e,(c)"}, {zOUT,"(c),e"}, {zADC,"hl,de"}, {zLD,"de,(W)"},
202 {zNEG,"*"}, {zRETI,nullptr},{zIM,"2"}, {zLD,"a,r"},
203 {zIN,"h,(c)"}, {zOUT,"(c),h"}, {zSBC,"hl,hl"}, {zLD,"(W),hl"},
204 {zNEG,"*"}, {zRETN,nullptr},{zIM,"0"}, {zRRD,"(hl)"},
205 {zIN,"l,(c)"}, {zOUT,"(c),l"}, {zADC,"hl,hl"}, {zLD,"hl,(W)"},
206 {zNEG,"*"}, {zRETI,nullptr},{zIM,"0"}, {zRLD,"(hl)"},
207 {zIN,"0,(c)"}, {zOUT,"(c),0"}, {zSBC,"hl,sp"}, {zLD,"(W),sp"},
208 {zNEG,"*"}, {zRETN,nullptr},{zIM,"1"}, {zDB,"?"},
209 {zIN,"a,(c)"}, {zOUT,"(c),a"}, {zADC,"hl,sp"}, {zLD,"sp,(W)"},
210 {zNEG,"*"}, {zRETI,nullptr},{zIM,"2"}, {zDB,"?"},
211 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
212 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
213 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
214 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
215 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
216 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
217 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
218 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
219 {zLDI,nullptr}, {zCPI,nullptr}, {zINI,nullptr}, {zOUTI,nullptr},
220 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
221 {zLDD,nullptr}, {zCPD,nullptr}, {zIND,nullptr}, {zOUTD,nullptr},
222 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
223 {zLDIR,nullptr}, {zCPIR,nullptr}, {zINIR,nullptr}, {zOTIR,nullptr},
224 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
225 {zLDDR,nullptr}, {zCPDR,nullptr}, {zINDR,nullptr}, {zOTDR,nullptr},
226 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
227 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
228 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
229 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
230 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
231 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
232 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
233 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
234 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
235 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
236 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
237 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
238 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
239 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
240 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
241 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
242 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"}
243 };
244
245 const z80_disassembler::z80dasm z80_disassembler::mnemonic_xx[256] =
246 {
247 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
248 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
249 {zDB,"?"}, {zADD,"I,bc"}, {zDB,"?"}, {zDB,"?"},
250 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
251 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
252 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
253 {zDB,"?"}, {zADD,"I,de"}, {zDB,"?"}, {zDB,"?"},
254 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
255 {zDB,"?"}, {zLD,"I,N"}, {zLD,"(W),I"}, {zINC,"I"},
256 {zINC,"Ih"}, {zDEC,"Ih"}, {zLD,"Ih,B"}, {zDB,"?"},
257 {zDB,"?"}, {zADD,"I,I"}, {zLD,"I,(W)"}, {zDEC,"I"},
258 {zINC,"Il"}, {zDEC,"Il"}, {zLD,"Il,B"}, {zDB,"?"},
259 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
260 {zINC,"X"}, {zDEC,"X"}, {zLD,"X,B"}, {zDB,"?"},
261 {zDB,"?"}, {zADD,"I,sp"}, {zDB,"?"}, {zDB,"?"},
262 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
263 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
264 {zLD,"b,Ih"}, {zLD,"b,Il"}, {zLD,"b,X"}, {zDB,"?"},
265 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
266 {zLD,"c,Ih"}, {zLD,"c,Il"}, {zLD,"c,X"}, {zDB,"?"},
267 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
268 {zLD,"d,Ih"}, {zLD,"d,Il"}, {zLD,"d,X"}, {zDB,"?"},
269 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
270 {zLD,"e,Ih"}, {zLD,"e,Il"}, {zLD,"e,X"}, {zDB,"?"},
271 {zLD,"Ih,b"}, {zLD,"Ih,c"}, {zLD,"Ih,d"}, {zLD,"Ih,e"},
272 {zLD,"Ih,Ih"}, {zLD,"Ih,Il"}, {zLD,"h,X"}, {zLD,"Ih,a"},
273 {zLD,"Il,b"}, {zLD,"Il,c"}, {zLD,"Il,d"}, {zLD,"Il,e"},
274 {zLD,"Il,Ih"}, {zLD,"Il,Il"}, {zLD,"l,X"}, {zLD,"Il,a"},
275 {zLD,"X,b"}, {zLD,"X,c"}, {zLD,"X,d"}, {zLD,"X,e"},
276 {zLD,"X,h"}, {zLD,"X,l"}, {zDB,"?"}, {zLD,"X,a"},
277 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
278 {zLD,"a,Ih"}, {zLD,"a,Il"}, {zLD,"a,X"}, {zDB,"?"},
279 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
280 {zADD,"a,Ih"}, {zADD,"a,Il"}, {zADD,"a,X"}, {zDB,"?"},
281 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
282 {zADC,"a,Ih"}, {zADC,"a,Il"}, {zADC,"a,X"}, {zDB,"?"},
283 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
284 {zSUB,"Ih"}, {zSUB,"Il"}, {zSUB,"X"}, {zDB,"?"},
285 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
286 {zSBC,"a,Ih"}, {zSBC,"a,Il"}, {zSBC,"a,X"}, {zDB,"?"},
287 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
288 {zAND,"Ih"}, {zAND,"Il"}, {zAND,"X"}, {zDB,"?"},
289 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
290 {zXOR,"Ih"}, {zXOR,"Il"}, {zXOR,"X"}, {zDB,"?"},
291 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
292 {zOR,"Ih"}, {zOR,"Il"}, {zOR,"X"}, {zDB,"?"},
293 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
294 {zCP,"Ih"}, {zCP,"Il"}, {zCP,"X"}, {zDB,"?"},
295 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
296 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
297 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"cb"},
298 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
299 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
300 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
301 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
302 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
303 {zDB,"?"}, {zPOP,"I"}, {zDB,"?"}, {zEX,"(sp),I"},
304 {zDB,"?"}, {zPUSH,"I"}, {zDB,"?"}, {zDB,"?"},
305 {zDB,"?"}, {zJP,"(I)"}, {zDB,"?"}, {zDB,"?"},
306 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
307 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
308 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
309 {zDB,"?"}, {zLD,"sp,I"}, {zDB,"?"}, {zDB,"?"},
310 {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"}
311 };
312
313 const z80_disassembler::z80dasm z80_disassembler::mnemonic_main[256] =
314 {
315 {zNOP,nullptr}, {zLD,"bc,N"}, {zLD,"(bc),a"}, {zINC,"bc"},
316 {zINC,"b"}, {zDEC,"b"}, {zLD,"b,B"}, {zRLCA,nullptr},
317 {zEX,"af,af'"}, {zADD,"hl,bc"}, {zLD,"a,(bc)"}, {zDEC,"bc"},
318 {zINC,"c"}, {zDEC,"c"}, {zLD,"c,B"}, {zRRCA,nullptr},
319 {zDJNZ,"O"}, {zLD,"de,N"}, {zLD,"(de),a"}, {zINC,"de"},
320 {zINC,"d"}, {zDEC,"d"}, {zLD,"d,B"}, {zRLA,nullptr},
321 {zJR,"O"}, {zADD,"hl,de"}, {zLD,"a,(de)"}, {zDEC,"de"},
322 {zINC,"e"}, {zDEC,"e"}, {zLD,"e,B"}, {zRRA,nullptr},
323 {zJR,"nz,O"}, {zLD,"hl,N"}, {zLD,"(W),hl"}, {zINC,"hl"},
324 {zINC,"h"}, {zDEC,"h"}, {zLD,"h,B"}, {zDAA,nullptr},
325 {zJR,"z,O"}, {zADD,"hl,hl"}, {zLD,"hl,(W)"}, {zDEC,"hl"},
326 {zINC,"l"}, {zDEC,"l"}, {zLD,"l,B"}, {zCPL,nullptr},
327 {zJR,"nc,O"}, {zLD,"sp,N"}, {zLD,"(W),a"}, {zINC,"sp"},
328 {zINC,"(hl)"}, {zDEC,"(hl)"}, {zLD,"(hl),B"}, {zSCF,nullptr},
329 {zJR,"c,O"}, {zADD,"hl,sp"}, {zLD,"a,(W)"}, {zDEC,"sp"},
330 {zINC,"a"}, {zDEC,"a"}, {zLD,"a,B"}, {zCCF,nullptr},
331 {zLD,"b,b"}, {zLD,"b,c"}, {zLD,"b,d"}, {zLD,"b,e"},
332 {zLD,"b,h"}, {zLD,"b,l"}, {zLD,"b,(hl)"}, {zLD,"b,a"},
333 {zLD,"c,b"}, {zLD,"c,c"}, {zLD,"c,d"}, {zLD,"c,e"},
334 {zLD,"c,h"}, {zLD,"c,l"}, {zLD,"c,(hl)"}, {zLD,"c,a"},
335 {zLD,"d,b"}, {zLD,"d,c"}, {zLD,"d,d"}, {zLD,"d,e"},
336 {zLD,"d,h"}, {zLD,"d,l"}, {zLD,"d,(hl)"}, {zLD,"d,a"},
337 {zLD,"e,b"}, {zLD,"e,c"}, {zLD,"e,d"}, {zLD,"e,e"},
338 {zLD,"e,h"}, {zLD,"e,l"}, {zLD,"e,(hl)"}, {zLD,"e,a"},
339 {zLD,"h,b"}, {zLD,"h,c"}, {zLD,"h,d"}, {zLD,"h,e"},
340 {zLD,"h,h"}, {zLD,"h,l"}, {zLD,"h,(hl)"}, {zLD,"h,a"},
341 {zLD,"l,b"}, {zLD,"l,c"}, {zLD,"l,d"}, {zLD,"l,e"},
342 {zLD,"l,h"}, {zLD,"l,l"}, {zLD,"l,(hl)"}, {zLD,"l,a"},
343 {zLD,"(hl),b"}, {zLD,"(hl),c"}, {zLD,"(hl),d"}, {zLD,"(hl),e"},
344 {zLD,"(hl),h"}, {zLD,"(hl),l"}, {zHLT,nullptr}, {zLD,"(hl),a"},
345 {zLD,"a,b"}, {zLD,"a,c"}, {zLD,"a,d"}, {zLD,"a,e"},
346 {zLD,"a,h"}, {zLD,"a,l"}, {zLD,"a,(hl)"}, {zLD,"a,a"},
347 {zADD,"a,b"}, {zADD,"a,c"}, {zADD,"a,d"}, {zADD,"a,e"},
348 {zADD,"a,h"}, {zADD,"a,l"}, {zADD,"a,(hl)"},{zADD,"a,a"},
349 {zADC,"a,b"}, {zADC,"a,c"}, {zADC,"a,d"}, {zADC,"a,e"},
350 {zADC,"a,h"}, {zADC,"a,l"}, {zADC,"a,(hl)"},{zADC,"a,a"},
351 {zSUB,"b"}, {zSUB,"c"}, {zSUB,"d"}, {zSUB,"e"},
352 {zSUB,"h"}, {zSUB,"l"}, {zSUB,"(hl)"}, {zSUB,"a"},
353 {zSBC,"a,b"}, {zSBC,"a,c"}, {zSBC,"a,d"}, {zSBC,"a,e"},
354 {zSBC,"a,h"}, {zSBC,"a,l"}, {zSBC,"a,(hl)"},{zSBC,"a,a"},
355 {zAND,"b"}, {zAND,"c"}, {zAND,"d"}, {zAND,"e"},
356 {zAND,"h"}, {zAND,"l"}, {zAND,"(hl)"}, {zAND,"a"},
357 {zXOR,"b"}, {zXOR,"c"}, {zXOR,"d"}, {zXOR,"e"},
358 {zXOR,"h"}, {zXOR,"l"}, {zXOR,"(hl)"}, {zXOR,"a"},
359 {zOR,"b"}, {zOR,"c"}, {zOR,"d"}, {zOR,"e"},
360 {zOR,"h"}, {zOR,"l"}, {zOR,"(hl)"}, {zOR,"a"},
361 {zCP,"b"}, {zCP,"c"}, {zCP,"d"}, {zCP,"e"},
362 {zCP,"h"}, {zCP,"l"}, {zCP,"(hl)"}, {zCP,"a"},
363 {zRET,"nz"}, {zPOP,"bc"}, {zJP,"nz,A"}, {zJP,"A"},
364 {zCALL,"nz,A"}, {zPUSH,"bc"}, {zADD,"a,B"}, {zRST,"V"},
365 {zRET,"z"}, {zRET,nullptr}, {zJP,"z,A"}, {zDB,"cb"},
366 {zCALL,"z,A"}, {zCALL,"A"}, {zADC,"a,B"}, {zRST,"V"},
367 {zRET,"nc"}, {zPOP,"de"}, {zJP,"nc,A"}, {zOUT,"(P),a"},
368 {zCALL,"nc,A"}, {zPUSH,"de"}, {zSUB,"B"}, {zRST,"V"},
369 {zRET,"c"}, {zEXX,nullptr}, {zJP,"c,A"}, {zIN,"a,(P)"},
370 {zCALL,"c,A"}, {zDB,"dd"}, {zSBC,"a,B"}, {zRST,"V"},
371 {zRET,"po"}, {zPOP,"hl"}, {zJP,"po,A"}, {zEX,"(sp),hl"},
372 {zCALL,"po,A"}, {zPUSH,"hl"}, {zAND,"B"}, {zRST,"V"},
373 {zRET,"pe"}, {zJP,"(hl)"}, {zJP,"pe,A"}, {zEX,"de,hl"},
374 {zCALL,"pe,A"}, {zDB,"ed"}, {zXOR,"B"}, {zRST,"V"},
375 {zRET,"p"}, {zPOP,"af"}, {zJP,"p,A"}, {zDI,nullptr},
376 {zCALL,"p,A"}, {zPUSH,"af"}, {zOR,"B"}, {zRST,"V"},
377 {zRET,"m"}, {zLD,"sp,hl"}, {zJP,"m,A"}, {zEI,nullptr},
378 {zCALL,"m,A"}, {zDB,"fd"}, {zCP,"B"}, {zRST,"V"}
379 };
380
sign(s8 offset)381 char z80_disassembler::sign(s8 offset)
382 {
383 return (offset < 0)? '-':'+';
384 }
385
offs(s8 offset)386 u32 z80_disassembler::offs(s8 offset)
387 {
388 if (offset < 0)
389 return -offset;
390 return offset;
391 }
392
z80_disassembler()393 z80_disassembler::z80_disassembler()
394 {
395 }
396
opcode_alignment() const397 u32 z80_disassembler::opcode_alignment() const
398 {
399 return 1;
400 }
401
disassemble(std::ostream & stream,offs_t pc,const data_buffer & opcodes,const data_buffer & params)402 offs_t z80_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms)
403 {
404 s8 offset = 0;
405
406 offs_t pos = pc;
407 std::string ixy = "oops!!";
408
409 const z80dasm *d = nullptr;
410 u8 op = opcodes.r8(pos++);
411 switch (op)
412 {
413 case 0xcb:
414 op = opcodes.r8(pos++);
415 d = &mnemonic_cb[op];
416 break;
417 case 0xed:
418 d = &mnemonic_ed[opcodes.r8(pos++)];
419 if (d->mnemonic == zDB)
420 pos--;
421 break;
422 case 0xdd:
423 {
424 ixy = "ix";
425 u8 op1 = opcodes.r8(pos++);
426 if( op1 == 0xcb )
427 {
428 offset = params.r8(pos++);
429 op1 = params.r8(pos++);
430 d = &mnemonic_xx_cb[op1];
431 }
432 else
433 {
434 d = &mnemonic_xx[op1];
435 if (d->mnemonic == zDB)
436 pos--;
437 }
438 break;
439 }
440 case 0xfd:
441 {
442 ixy = "iy";
443 u8 op1 = opcodes.r8(pos++);
444 if( op1 == 0xcb )
445 {
446 offset = params.r8(pos++);
447 op1 = params.r8(pos++);
448 d = &mnemonic_xx_cb[op1];
449 }
450 else
451 {
452 d = &mnemonic_xx[op1];
453 if (d->mnemonic == zDB)
454 pos--;
455 }
456 break;
457 }
458 default:
459 d = &mnemonic_main[op];
460 break;
461 }
462
463 if( d->arguments )
464 {
465 util::stream_format(stream, "%-4s ", s_mnemonic[d->mnemonic]);
466 const char *src = d->arguments;
467 while( *src )
468 {
469 switch( *src )
470 {
471 case '?': /* illegal opcode */
472 util::stream_format(stream, "$%02x", op );
473 break;
474 case 'A':
475 util::stream_format(stream, "$%04X", params.r16(pos) );
476 pos += 2;
477 break;
478 case 'B': /* Byte op arg */
479 util::stream_format(stream, "$%02X", params.r8(pos++) );
480 break;
481 case 'N': /* Immediate 16 bit */
482 util::stream_format(stream, "$%04X", params.r16(pos) );
483 pos += 2;
484 break;
485 case 'O': /* Offset relative to PC */
486 util::stream_format(stream, "$%04X", (pc + s8(params.r8(pos++)) + 2) & 0xffff);
487 break;
488 case 'P': /* Port number */
489 util::stream_format(stream, "$%02X", params.r8(pos++) );
490 break;
491 case 'V': /* Restart vector */
492 util::stream_format(stream, "$%02X", op & 0x38 );
493 break;
494 case 'W': /* Memory address word */
495 util::stream_format(stream, "$%04X", params.r16(pos) );
496 pos += 2;
497 break;
498 case 'X':
499 offset = params.r8(pos++);
500 /* fall through */
501 case 'Y':
502 util::stream_format(stream,"(%s%c$%02x)", ixy, sign(offset), offs(offset) );
503 break;
504 case 'I':
505 util::stream_format(stream, "%s", ixy);
506 break;
507 default:
508 stream << *src;
509 }
510 src++;
511 }
512 }
513 else
514 {
515 util::stream_format(stream, "%s", s_mnemonic[d->mnemonic]);
516 }
517
518 return (pos - pc) | s_flags[d->mnemonic] | SUPPORTED;
519 }
520