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 &params)
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