1*3d8817e4Smiod /* Print Z80 and R800 instructions
2*3d8817e4Smiod Copyright 2005 Free Software Foundation, Inc.
3*3d8817e4Smiod Contributed by Arnold Metselaar <arnold_m@operamail.com>
4*3d8817e4Smiod
5*3d8817e4Smiod This file is free software; you can redistribute it and/or modify
6*3d8817e4Smiod it under the terms of the GNU General Public License as published by
7*3d8817e4Smiod the Free Software Foundation; either version 2 of the License, or
8*3d8817e4Smiod (at your option) any later version.
9*3d8817e4Smiod
10*3d8817e4Smiod This program is distributed in the hope that it will be useful,
11*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
12*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*3d8817e4Smiod GNU General Public License for more details.
14*3d8817e4Smiod
15*3d8817e4Smiod You should have received a copy of the GNU General Public License
16*3d8817e4Smiod along with this program; if not, write to the Free Software
17*3d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
18*3d8817e4Smiod MA 02110-1301, USA. */
19*3d8817e4Smiod
20*3d8817e4Smiod #include "sysdep.h"
21*3d8817e4Smiod #include "dis-asm.h"
22*3d8817e4Smiod #include <stdio.h>
23*3d8817e4Smiod
24*3d8817e4Smiod struct buffer
25*3d8817e4Smiod {
26*3d8817e4Smiod bfd_vma base;
27*3d8817e4Smiod int n_fetch;
28*3d8817e4Smiod int n_used;
29*3d8817e4Smiod signed char data[4];
30*3d8817e4Smiod } ;
31*3d8817e4Smiod
32*3d8817e4Smiod typedef int (*func)(struct buffer *, disassemble_info *, char *);
33*3d8817e4Smiod
34*3d8817e4Smiod struct tab_elt
35*3d8817e4Smiod {
36*3d8817e4Smiod unsigned char val;
37*3d8817e4Smiod unsigned char mask;
38*3d8817e4Smiod func fp;
39*3d8817e4Smiod char * text;
40*3d8817e4Smiod } ;
41*3d8817e4Smiod
42*3d8817e4Smiod #define TXTSIZ 24
43*3d8817e4Smiod /* Names of 16-bit registers. */
44*3d8817e4Smiod static char * rr_str[] = { "bc", "de", "hl", "sp" };
45*3d8817e4Smiod /* Names of 8-bit registers. */
46*3d8817e4Smiod static char * r_str[] = { "b", "c", "d", "e", "h", "l", "(hl)", "a" };
47*3d8817e4Smiod /* Texts for condition codes. */
48*3d8817e4Smiod static char * cc_str[] = { "nz", "z", "nc", "c", "po", "pe", "p", "m" };
49*3d8817e4Smiod /* Instruction names for 8-bit arithmetic, operand "a" is often implicit */
50*3d8817e4Smiod static char * arit_str[] =
51*3d8817e4Smiod {
52*3d8817e4Smiod "add a,", "adc a,", "sub ", "sbc a,", "and ", "xor ", "or ", "cp "
53*3d8817e4Smiod } ;
54*3d8817e4Smiod
55*3d8817e4Smiod static int
fetch_data(struct buffer * buf,disassemble_info * info,int n)56*3d8817e4Smiod fetch_data (struct buffer *buf, disassemble_info * info, int n)
57*3d8817e4Smiod {
58*3d8817e4Smiod int r;
59*3d8817e4Smiod
60*3d8817e4Smiod if (buf->n_fetch + n > 4)
61*3d8817e4Smiod abort ();
62*3d8817e4Smiod
63*3d8817e4Smiod r = info->read_memory_func (buf->base + buf->n_fetch,
64*3d8817e4Smiod (unsigned char*) buf->data + buf->n_fetch,
65*3d8817e4Smiod n, info);
66*3d8817e4Smiod if (r == 0)
67*3d8817e4Smiod buf->n_fetch += n;
68*3d8817e4Smiod return !r;
69*3d8817e4Smiod }
70*3d8817e4Smiod
71*3d8817e4Smiod static int
prt(struct buffer * buf,disassemble_info * info,char * txt)72*3d8817e4Smiod prt (struct buffer *buf, disassemble_info * info, char *txt)
73*3d8817e4Smiod {
74*3d8817e4Smiod info->fprintf_func (info->stream, "%s", txt);
75*3d8817e4Smiod buf->n_used = buf->n_fetch;
76*3d8817e4Smiod return 1;
77*3d8817e4Smiod }
78*3d8817e4Smiod
79*3d8817e4Smiod static int
prt_e(struct buffer * buf,disassemble_info * info,char * txt)80*3d8817e4Smiod prt_e (struct buffer *buf, disassemble_info * info, char *txt)
81*3d8817e4Smiod {
82*3d8817e4Smiod char e;
83*3d8817e4Smiod int target_addr;
84*3d8817e4Smiod
85*3d8817e4Smiod if (fetch_data (buf, info, 1))
86*3d8817e4Smiod {
87*3d8817e4Smiod e = buf->data[1];
88*3d8817e4Smiod target_addr = (buf->base + 2 + e) & 0xffff;
89*3d8817e4Smiod buf->n_used = buf->n_fetch;
90*3d8817e4Smiod info->fprintf_func (info->stream, "%s0x%04x", txt, target_addr);
91*3d8817e4Smiod }
92*3d8817e4Smiod else
93*3d8817e4Smiod buf->n_used = -1;
94*3d8817e4Smiod
95*3d8817e4Smiod return buf->n_used;
96*3d8817e4Smiod }
97*3d8817e4Smiod
98*3d8817e4Smiod static int
jr_cc(struct buffer * buf,disassemble_info * info,char * txt)99*3d8817e4Smiod jr_cc (struct buffer *buf, disassemble_info * info, char *txt)
100*3d8817e4Smiod {
101*3d8817e4Smiod char mytxt[TXTSIZ];
102*3d8817e4Smiod
103*3d8817e4Smiod snprintf (mytxt, TXTSIZ, txt, cc_str[(buf->data[0] >> 3) & 3]);
104*3d8817e4Smiod return prt_e (buf, info, mytxt);
105*3d8817e4Smiod }
106*3d8817e4Smiod
107*3d8817e4Smiod static int
prt_nn(struct buffer * buf,disassemble_info * info,char * txt)108*3d8817e4Smiod prt_nn (struct buffer *buf, disassemble_info * info, char *txt)
109*3d8817e4Smiod {
110*3d8817e4Smiod int nn;
111*3d8817e4Smiod unsigned char *p;
112*3d8817e4Smiod
113*3d8817e4Smiod p = (unsigned char*) buf->data + buf->n_fetch;
114*3d8817e4Smiod if (fetch_data (buf, info, 2))
115*3d8817e4Smiod {
116*3d8817e4Smiod nn = p[0] + (p[1] << 8);
117*3d8817e4Smiod info->fprintf_func (info->stream, txt, nn);
118*3d8817e4Smiod buf->n_used = buf->n_fetch;
119*3d8817e4Smiod }
120*3d8817e4Smiod else
121*3d8817e4Smiod buf->n_used = -1;
122*3d8817e4Smiod return buf->n_used;
123*3d8817e4Smiod }
124*3d8817e4Smiod
125*3d8817e4Smiod static int
prt_rr_nn(struct buffer * buf,disassemble_info * info,char * txt)126*3d8817e4Smiod prt_rr_nn (struct buffer *buf, disassemble_info * info, char *txt)
127*3d8817e4Smiod {
128*3d8817e4Smiod char mytxt[TXTSIZ];
129*3d8817e4Smiod
130*3d8817e4Smiod snprintf (mytxt, TXTSIZ, txt, rr_str[(buf->data[0] >> 4) & 3]);
131*3d8817e4Smiod return prt_nn (buf, info, mytxt);
132*3d8817e4Smiod }
133*3d8817e4Smiod
134*3d8817e4Smiod static int
prt_rr(struct buffer * buf,disassemble_info * info,char * txt)135*3d8817e4Smiod prt_rr (struct buffer *buf, disassemble_info * info, char *txt)
136*3d8817e4Smiod {
137*3d8817e4Smiod info->fprintf_func (info->stream, "%s%s", txt,
138*3d8817e4Smiod rr_str[(buf->data[buf->n_fetch - 1] >> 4) & 3]);
139*3d8817e4Smiod buf->n_used = buf->n_fetch;
140*3d8817e4Smiod return buf->n_used;
141*3d8817e4Smiod }
142*3d8817e4Smiod
143*3d8817e4Smiod static int
prt_n(struct buffer * buf,disassemble_info * info,char * txt)144*3d8817e4Smiod prt_n (struct buffer *buf, disassemble_info * info, char *txt)
145*3d8817e4Smiod {
146*3d8817e4Smiod int n;
147*3d8817e4Smiod unsigned char *p;
148*3d8817e4Smiod
149*3d8817e4Smiod p = (unsigned char*) buf->data + buf->n_fetch;
150*3d8817e4Smiod
151*3d8817e4Smiod if (fetch_data (buf, info, 1))
152*3d8817e4Smiod {
153*3d8817e4Smiod n = p[0];
154*3d8817e4Smiod info->fprintf_func (info->stream, txt, n);
155*3d8817e4Smiod buf->n_used = buf->n_fetch;
156*3d8817e4Smiod }
157*3d8817e4Smiod else
158*3d8817e4Smiod buf->n_used = -1;
159*3d8817e4Smiod
160*3d8817e4Smiod return buf->n_used;
161*3d8817e4Smiod }
162*3d8817e4Smiod
163*3d8817e4Smiod static int
ld_r_n(struct buffer * buf,disassemble_info * info,char * txt)164*3d8817e4Smiod ld_r_n (struct buffer *buf, disassemble_info * info, char *txt)
165*3d8817e4Smiod {
166*3d8817e4Smiod char mytxt[TXTSIZ];
167*3d8817e4Smiod
168*3d8817e4Smiod snprintf (mytxt, TXTSIZ, txt, r_str[(buf->data[0] >> 3) & 7]);
169*3d8817e4Smiod return prt_n (buf, info, mytxt);
170*3d8817e4Smiod }
171*3d8817e4Smiod
172*3d8817e4Smiod static int
prt_r(struct buffer * buf,disassemble_info * info,char * txt)173*3d8817e4Smiod prt_r (struct buffer *buf, disassemble_info * info, char *txt)
174*3d8817e4Smiod {
175*3d8817e4Smiod info->fprintf_func (info->stream, txt,
176*3d8817e4Smiod r_str[(buf->data[buf->n_fetch - 1] >> 3) & 7]);
177*3d8817e4Smiod buf->n_used = buf->n_fetch;
178*3d8817e4Smiod return buf->n_used;
179*3d8817e4Smiod }
180*3d8817e4Smiod
181*3d8817e4Smiod static int
ld_r_r(struct buffer * buf,disassemble_info * info,char * txt)182*3d8817e4Smiod ld_r_r (struct buffer *buf, disassemble_info * info, char *txt)
183*3d8817e4Smiod {
184*3d8817e4Smiod info->fprintf_func (info->stream, txt,
185*3d8817e4Smiod r_str[(buf->data[buf->n_fetch - 1] >> 3) & 7],
186*3d8817e4Smiod r_str[buf->data[buf->n_fetch - 1] & 7]);
187*3d8817e4Smiod buf->n_used = buf->n_fetch;
188*3d8817e4Smiod return buf->n_used;
189*3d8817e4Smiod }
190*3d8817e4Smiod
191*3d8817e4Smiod static int
arit_r(struct buffer * buf,disassemble_info * info,char * txt)192*3d8817e4Smiod arit_r (struct buffer *buf, disassemble_info * info, char *txt)
193*3d8817e4Smiod {
194*3d8817e4Smiod info->fprintf_func (info->stream, txt,
195*3d8817e4Smiod arit_str[(buf->data[buf->n_fetch - 1] >> 3) & 7],
196*3d8817e4Smiod r_str[buf->data[buf->n_fetch - 1] & 7]);
197*3d8817e4Smiod buf->n_used = buf->n_fetch;
198*3d8817e4Smiod return buf->n_used;
199*3d8817e4Smiod }
200*3d8817e4Smiod
201*3d8817e4Smiod static int
prt_cc(struct buffer * buf,disassemble_info * info,char * txt)202*3d8817e4Smiod prt_cc (struct buffer *buf, disassemble_info * info, char *txt)
203*3d8817e4Smiod {
204*3d8817e4Smiod info->fprintf_func (info->stream, "%s%s", txt,
205*3d8817e4Smiod cc_str[(buf->data[0] >> 3) & 7]);
206*3d8817e4Smiod buf->n_used = buf->n_fetch;
207*3d8817e4Smiod return buf->n_used;
208*3d8817e4Smiod }
209*3d8817e4Smiod
210*3d8817e4Smiod static int
pop_rr(struct buffer * buf,disassemble_info * info,char * txt)211*3d8817e4Smiod pop_rr (struct buffer *buf, disassemble_info * info, char *txt)
212*3d8817e4Smiod {
213*3d8817e4Smiod static char *rr_stack[] = { "bc","de","hl","af"};
214*3d8817e4Smiod
215*3d8817e4Smiod info->fprintf_func (info->stream, "%s %s", txt,
216*3d8817e4Smiod rr_stack[(buf->data[0] >> 4) & 3]);
217*3d8817e4Smiod buf->n_used = buf->n_fetch;
218*3d8817e4Smiod return buf->n_used;
219*3d8817e4Smiod }
220*3d8817e4Smiod
221*3d8817e4Smiod
222*3d8817e4Smiod static int
jp_cc_nn(struct buffer * buf,disassemble_info * info,char * txt)223*3d8817e4Smiod jp_cc_nn (struct buffer *buf, disassemble_info * info, char *txt)
224*3d8817e4Smiod {
225*3d8817e4Smiod char mytxt[TXTSIZ];
226*3d8817e4Smiod
227*3d8817e4Smiod snprintf (mytxt,TXTSIZ,
228*3d8817e4Smiod "%s%s,0x%%04x", txt, cc_str[(buf->data[0] >> 3) & 7]);
229*3d8817e4Smiod return prt_nn (buf, info, mytxt);
230*3d8817e4Smiod }
231*3d8817e4Smiod
232*3d8817e4Smiod static int
arit_n(struct buffer * buf,disassemble_info * info,char * txt)233*3d8817e4Smiod arit_n (struct buffer *buf, disassemble_info * info, char *txt)
234*3d8817e4Smiod {
235*3d8817e4Smiod char mytxt[TXTSIZ];
236*3d8817e4Smiod
237*3d8817e4Smiod snprintf (mytxt,TXTSIZ, txt, arit_str[(buf->data[0] >> 3) & 7]);
238*3d8817e4Smiod return prt_n (buf, info, mytxt);
239*3d8817e4Smiod }
240*3d8817e4Smiod
241*3d8817e4Smiod static int
rst(struct buffer * buf,disassemble_info * info,char * txt)242*3d8817e4Smiod rst (struct buffer *buf, disassemble_info * info, char *txt)
243*3d8817e4Smiod {
244*3d8817e4Smiod info->fprintf_func (info->stream, txt, buf->data[0] & 0x38);
245*3d8817e4Smiod buf->n_used = buf->n_fetch;
246*3d8817e4Smiod return buf->n_used;
247*3d8817e4Smiod }
248*3d8817e4Smiod
249*3d8817e4Smiod
250*3d8817e4Smiod static int
cis(struct buffer * buf,disassemble_info * info,char * txt ATTRIBUTE_UNUSED)251*3d8817e4Smiod cis (struct buffer *buf, disassemble_info * info, char *txt ATTRIBUTE_UNUSED)
252*3d8817e4Smiod {
253*3d8817e4Smiod static char * opar[] = { "ld", "cp", "in", "out" };
254*3d8817e4Smiod char * op;
255*3d8817e4Smiod char c;
256*3d8817e4Smiod
257*3d8817e4Smiod c = buf->data[1];
258*3d8817e4Smiod op = ((0x13 & c) == 0x13) ? "ot" : (opar[c & 3]);
259*3d8817e4Smiod info->fprintf_func (info->stream,
260*3d8817e4Smiod "%s%c%s", op,
261*3d8817e4Smiod (c & 0x08) ? 'd' : 'i',
262*3d8817e4Smiod (c & 0x10) ? "r" : "");
263*3d8817e4Smiod buf->n_used = 2;
264*3d8817e4Smiod return buf->n_used;
265*3d8817e4Smiod }
266*3d8817e4Smiod
267*3d8817e4Smiod static int
dump(struct buffer * buf,disassemble_info * info,char * txt)268*3d8817e4Smiod dump (struct buffer *buf, disassemble_info * info, char *txt)
269*3d8817e4Smiod {
270*3d8817e4Smiod int i;
271*3d8817e4Smiod
272*3d8817e4Smiod info->fprintf_func (info->stream, "defb ");
273*3d8817e4Smiod for (i = 0; txt[i]; ++i)
274*3d8817e4Smiod info->fprintf_func (info->stream, i ? ", 0x%02x" : "0x%02x",
275*3d8817e4Smiod (unsigned char) buf->data[i]);
276*3d8817e4Smiod buf->n_used = i;
277*3d8817e4Smiod return buf->n_used;
278*3d8817e4Smiod }
279*3d8817e4Smiod
280*3d8817e4Smiod /* Table to disassemble machine codes with prefix 0xED. */
281*3d8817e4Smiod struct tab_elt opc_ed[] =
282*3d8817e4Smiod {
283*3d8817e4Smiod { 0x70, 0xFF, prt, "in f,(c)" },
284*3d8817e4Smiod { 0x70, 0xFF, dump, "xx" },
285*3d8817e4Smiod { 0x40, 0xC7, prt_r, "in %s,(c)" },
286*3d8817e4Smiod { 0x71, 0xFF, prt, "out (c),0" },
287*3d8817e4Smiod { 0x70, 0xFF, dump, "xx" },
288*3d8817e4Smiod { 0x41, 0xC7, prt_r, "out (c),%s" },
289*3d8817e4Smiod { 0x42, 0xCF, prt_rr, "sbc hl," },
290*3d8817e4Smiod { 0x43, 0xCF, prt_rr_nn, "ld (0x%%04x),%s" },
291*3d8817e4Smiod { 0x44, 0xFF, prt, "neg" },
292*3d8817e4Smiod { 0x45, 0xFF, prt, "retn" },
293*3d8817e4Smiod { 0x46, 0xFF, prt, "im 0" },
294*3d8817e4Smiod { 0x47, 0xFF, prt, "ld i,a" },
295*3d8817e4Smiod { 0x4A, 0xCF, prt_rr, "adc hl," },
296*3d8817e4Smiod { 0x4B, 0xCF, prt_rr_nn, "ld %s,(0x%%04x)" },
297*3d8817e4Smiod { 0x4D, 0xFF, prt, "reti" },
298*3d8817e4Smiod { 0x56, 0xFF, prt, "im 1" },
299*3d8817e4Smiod { 0x57, 0xFF, prt, "ld a,i" },
300*3d8817e4Smiod { 0x5E, 0xFF, prt, "im 2" },
301*3d8817e4Smiod { 0x67, 0xFF, prt, "rrd" },
302*3d8817e4Smiod { 0x6F, 0xFF, prt, "rld" },
303*3d8817e4Smiod { 0xA0, 0xE4, cis, "" },
304*3d8817e4Smiod { 0xC3, 0xFF, prt, "muluw hl,bc" },
305*3d8817e4Smiod { 0xC5, 0xE7, prt_r, "mulub a,%s" },
306*3d8817e4Smiod { 0xF3, 0xFF, prt, "muluw hl,sp" },
307*3d8817e4Smiod { 0x00, 0x00, dump, "xx" }
308*3d8817e4Smiod };
309*3d8817e4Smiod
310*3d8817e4Smiod static int
pref_ed(struct buffer * buf,disassemble_info * info,char * txt ATTRIBUTE_UNUSED)311*3d8817e4Smiod pref_ed (struct buffer * buf, disassemble_info * info,
312*3d8817e4Smiod char* txt ATTRIBUTE_UNUSED)
313*3d8817e4Smiod {
314*3d8817e4Smiod struct tab_elt *p;
315*3d8817e4Smiod
316*3d8817e4Smiod if (fetch_data(buf, info, 1))
317*3d8817e4Smiod {
318*3d8817e4Smiod for (p = opc_ed; p->val != (buf->data[1] & p->mask); ++p)
319*3d8817e4Smiod ;
320*3d8817e4Smiod p->fp (buf, info, p->text);
321*3d8817e4Smiod }
322*3d8817e4Smiod else
323*3d8817e4Smiod buf->n_used = -1;
324*3d8817e4Smiod
325*3d8817e4Smiod return buf->n_used;
326*3d8817e4Smiod }
327*3d8817e4Smiod
328*3d8817e4Smiod /* Instruction names for the instructions addressing single bits. */
329*3d8817e4Smiod static char *cb1_str[] = { "", "bit", "res", "set"};
330*3d8817e4Smiod /* Instruction names for shifts and rotates. */
331*3d8817e4Smiod static char *cb2_str[] =
332*3d8817e4Smiod {
333*3d8817e4Smiod "rlc", "rrc", "rl", "rr", "sla", "sra", "sli", "srl"
334*3d8817e4Smiod };
335*3d8817e4Smiod
336*3d8817e4Smiod static int
pref_cb(struct buffer * buf,disassemble_info * info,char * txt ATTRIBUTE_UNUSED)337*3d8817e4Smiod pref_cb (struct buffer * buf, disassemble_info * info,
338*3d8817e4Smiod char* txt ATTRIBUTE_UNUSED)
339*3d8817e4Smiod {
340*3d8817e4Smiod if (fetch_data (buf, info, 1))
341*3d8817e4Smiod {
342*3d8817e4Smiod buf->n_used = 2;
343*3d8817e4Smiod if ((buf->data[1] & 0xc0) == 0)
344*3d8817e4Smiod info->fprintf_func (info->stream, "%s %s",
345*3d8817e4Smiod cb2_str[(buf->data[1] >> 3) & 7],
346*3d8817e4Smiod r_str[buf->data[1] & 7]);
347*3d8817e4Smiod else
348*3d8817e4Smiod info->fprintf_func (info->stream, "%s %d,%s",
349*3d8817e4Smiod cb1_str[(buf->data[1] >> 6) & 3],
350*3d8817e4Smiod (buf->data[1] >> 3) & 7,
351*3d8817e4Smiod r_str[buf->data[1] & 7]);
352*3d8817e4Smiod }
353*3d8817e4Smiod else
354*3d8817e4Smiod buf->n_used = -1;
355*3d8817e4Smiod
356*3d8817e4Smiod return buf->n_used;
357*3d8817e4Smiod }
358*3d8817e4Smiod
359*3d8817e4Smiod static int
addvv(struct buffer * buf,disassemble_info * info,char * txt)360*3d8817e4Smiod addvv (struct buffer * buf, disassemble_info * info, char* txt)
361*3d8817e4Smiod {
362*3d8817e4Smiod info->fprintf_func (info->stream, "add %s,%s", txt, txt);
363*3d8817e4Smiod
364*3d8817e4Smiod return buf->n_used = buf->n_fetch;
365*3d8817e4Smiod }
366*3d8817e4Smiod
367*3d8817e4Smiod static int
ld_v_v(struct buffer * buf,disassemble_info * info,char * txt)368*3d8817e4Smiod ld_v_v (struct buffer * buf, disassemble_info * info, char* txt)
369*3d8817e4Smiod {
370*3d8817e4Smiod char mytxt[TXTSIZ];
371*3d8817e4Smiod
372*3d8817e4Smiod snprintf (mytxt, TXTSIZ, "ld %s%%s,%s%%s", txt, txt);
373*3d8817e4Smiod return ld_r_r (buf, info, mytxt);
374*3d8817e4Smiod }
375*3d8817e4Smiod
376*3d8817e4Smiod static int
prt_d(struct buffer * buf,disassemble_info * info,char * txt)377*3d8817e4Smiod prt_d (struct buffer *buf, disassemble_info * info, char *txt)
378*3d8817e4Smiod {
379*3d8817e4Smiod int d;
380*3d8817e4Smiod signed char *p;
381*3d8817e4Smiod
382*3d8817e4Smiod p = buf->data + buf->n_fetch;
383*3d8817e4Smiod
384*3d8817e4Smiod if (fetch_data (buf, info, 1))
385*3d8817e4Smiod {
386*3d8817e4Smiod d = p[0];
387*3d8817e4Smiod info->fprintf_func (info->stream, txt, d);
388*3d8817e4Smiod buf->n_used = buf->n_fetch;
389*3d8817e4Smiod }
390*3d8817e4Smiod else
391*3d8817e4Smiod buf->n_used = -1;
392*3d8817e4Smiod
393*3d8817e4Smiod return buf->n_used;
394*3d8817e4Smiod }
395*3d8817e4Smiod
396*3d8817e4Smiod static int
prt_d_n(struct buffer * buf,disassemble_info * info,char * txt)397*3d8817e4Smiod prt_d_n (struct buffer *buf, disassemble_info * info, char *txt)
398*3d8817e4Smiod {
399*3d8817e4Smiod char mytxt[TXTSIZ];
400*3d8817e4Smiod int d;
401*3d8817e4Smiod signed char *p;
402*3d8817e4Smiod
403*3d8817e4Smiod p = buf->data + buf->n_fetch;
404*3d8817e4Smiod
405*3d8817e4Smiod if (fetch_data (buf, info, 1))
406*3d8817e4Smiod {
407*3d8817e4Smiod d = p[0];
408*3d8817e4Smiod snprintf (mytxt, TXTSIZ, txt, d);
409*3d8817e4Smiod return prt_n (buf, info, mytxt);
410*3d8817e4Smiod }
411*3d8817e4Smiod else
412*3d8817e4Smiod buf->n_used = -1;
413*3d8817e4Smiod
414*3d8817e4Smiod return buf->n_used;
415*3d8817e4Smiod }
416*3d8817e4Smiod
417*3d8817e4Smiod static int
arit_d(struct buffer * buf,disassemble_info * info,char * txt)418*3d8817e4Smiod arit_d (struct buffer *buf, disassemble_info * info, char *txt)
419*3d8817e4Smiod {
420*3d8817e4Smiod char mytxt[TXTSIZ];
421*3d8817e4Smiod signed char c;
422*3d8817e4Smiod
423*3d8817e4Smiod c = buf->data[buf->n_fetch - 1];
424*3d8817e4Smiod snprintf (mytxt, TXTSIZ, txt, arit_str[(c >> 3) & 7]);
425*3d8817e4Smiod return prt_d (buf, info, mytxt);
426*3d8817e4Smiod }
427*3d8817e4Smiod
428*3d8817e4Smiod static int
ld_r_d(struct buffer * buf,disassemble_info * info,char * txt)429*3d8817e4Smiod ld_r_d (struct buffer *buf, disassemble_info * info, char *txt)
430*3d8817e4Smiod {
431*3d8817e4Smiod char mytxt[TXTSIZ];
432*3d8817e4Smiod signed char c;
433*3d8817e4Smiod
434*3d8817e4Smiod c = buf->data[buf->n_fetch - 1];
435*3d8817e4Smiod snprintf (mytxt, TXTSIZ, txt, r_str[(c >> 3) & 7]);
436*3d8817e4Smiod return prt_d (buf, info, mytxt);
437*3d8817e4Smiod }
438*3d8817e4Smiod
439*3d8817e4Smiod static int
ld_d_r(struct buffer * buf,disassemble_info * info,char * txt)440*3d8817e4Smiod ld_d_r(struct buffer *buf, disassemble_info * info, char *txt)
441*3d8817e4Smiod {
442*3d8817e4Smiod char mytxt[TXTSIZ];
443*3d8817e4Smiod signed char c;
444*3d8817e4Smiod
445*3d8817e4Smiod c = buf->data[buf->n_fetch - 1];
446*3d8817e4Smiod snprintf (mytxt, TXTSIZ, txt, r_str[c & 7]);
447*3d8817e4Smiod return prt_d (buf, info, mytxt);
448*3d8817e4Smiod }
449*3d8817e4Smiod
450*3d8817e4Smiod static int
pref_xd_cb(struct buffer * buf,disassemble_info * info,char * txt)451*3d8817e4Smiod pref_xd_cb (struct buffer * buf, disassemble_info * info, char* txt)
452*3d8817e4Smiod {
453*3d8817e4Smiod if (fetch_data (buf, info, 2))
454*3d8817e4Smiod {
455*3d8817e4Smiod int d;
456*3d8817e4Smiod char arg[TXTSIZ];
457*3d8817e4Smiod signed char *p;
458*3d8817e4Smiod
459*3d8817e4Smiod buf->n_used = 4;
460*3d8817e4Smiod p = buf->data;
461*3d8817e4Smiod d = p[2];
462*3d8817e4Smiod
463*3d8817e4Smiod if (((p[3] & 0xC0) == 0x40) || ((p[3] & 7) == 0x06))
464*3d8817e4Smiod snprintf (arg, TXTSIZ, "(%s%+d)", txt, d);
465*3d8817e4Smiod else
466*3d8817e4Smiod snprintf (arg, TXTSIZ, "(%s%+d),%s", txt, d, r_str[p[3] & 7]);
467*3d8817e4Smiod
468*3d8817e4Smiod if ((p[3] & 0xc0) == 0)
469*3d8817e4Smiod info->fprintf_func (info->stream, "%s %s",
470*3d8817e4Smiod cb2_str[(buf->data[3] >> 3) & 7],
471*3d8817e4Smiod arg);
472*3d8817e4Smiod else
473*3d8817e4Smiod info->fprintf_func (info->stream, "%s %d,%s",
474*3d8817e4Smiod cb1_str[(buf->data[3] >> 6) & 3],
475*3d8817e4Smiod (buf->data[3] >> 3) & 7,
476*3d8817e4Smiod arg);
477*3d8817e4Smiod }
478*3d8817e4Smiod else
479*3d8817e4Smiod buf->n_used = -1;
480*3d8817e4Smiod
481*3d8817e4Smiod return buf->n_used;
482*3d8817e4Smiod }
483*3d8817e4Smiod
484*3d8817e4Smiod /* Table to disassemble machine codes with prefix 0xDD or 0xFD. */
485*3d8817e4Smiod static struct tab_elt opc_ind[] =
486*3d8817e4Smiod {
487*3d8817e4Smiod { 0x24, 0xF7, prt_r, "inc %s%%s" },
488*3d8817e4Smiod { 0x25, 0xF7, prt_r, "dec %s%%s" },
489*3d8817e4Smiod { 0x26, 0xF7, ld_r_n, "ld %s%%s,0x%%%%02x" },
490*3d8817e4Smiod { 0x21, 0xFF, prt_nn, "ld %s,0x%%04x" },
491*3d8817e4Smiod { 0x22, 0xFF, prt_nn, "ld (0x%%04x),%s" },
492*3d8817e4Smiod { 0x2A, 0xFF, prt_nn, "ld %s,(0x%%04x)" },
493*3d8817e4Smiod { 0x23, 0xFF, prt, "inc %s" },
494*3d8817e4Smiod { 0x2B, 0xFF, prt, "dec %s" },
495*3d8817e4Smiod { 0x29, 0xFF, addvv, "%s" },
496*3d8817e4Smiod { 0x09, 0xCF, prt_rr, "add %s," },
497*3d8817e4Smiod { 0x34, 0xFF, prt_d, "inc (%s%%+d)" },
498*3d8817e4Smiod { 0x35, 0xFF, prt_d, "dec (%s%%+d)" },
499*3d8817e4Smiod { 0x36, 0xFF, prt_d_n, "ld (%s%%+d),0x%%%%02x" },
500*3d8817e4Smiod
501*3d8817e4Smiod { 0x76, 0xFF, dump, "h" },
502*3d8817e4Smiod { 0x46, 0xC7, ld_r_d, "ld %%s,(%s%%%%+d)" },
503*3d8817e4Smiod { 0x70, 0xF8, ld_d_r, "ld (%s%%%%+d),%%s" },
504*3d8817e4Smiod { 0x64, 0xF6, ld_v_v, "%s" },
505*3d8817e4Smiod { 0x60, 0xF0, ld_r_r, "ld %s%%s,%%s" },
506*3d8817e4Smiod { 0x44, 0xC6, ld_r_r, "ld %%s,%s%%s" },
507*3d8817e4Smiod
508*3d8817e4Smiod { 0x86, 0xC7, arit_d, "%%s(%s%%%%+d)" },
509*3d8817e4Smiod { 0x84, 0xC6, arit_r, "%%s%s%%s" },
510*3d8817e4Smiod
511*3d8817e4Smiod { 0xE1, 0xFF, prt, "pop %s" },
512*3d8817e4Smiod { 0xE5, 0xFF, prt, "push %s" },
513*3d8817e4Smiod { 0xCB, 0xFF, pref_xd_cb, "%s" },
514*3d8817e4Smiod { 0xE3, 0xFF, prt, "ex (sp),%s" },
515*3d8817e4Smiod { 0xE9, 0xFF, prt, "jp (%s)" },
516*3d8817e4Smiod { 0xF9, 0xFF, prt, "ld sp,%s" },
517*3d8817e4Smiod { 0x00, 0x00, dump, "?" },
518*3d8817e4Smiod } ;
519*3d8817e4Smiod
520*3d8817e4Smiod static int
pref_ind(struct buffer * buf,disassemble_info * info,char * txt)521*3d8817e4Smiod pref_ind (struct buffer * buf, disassemble_info * info, char* txt)
522*3d8817e4Smiod {
523*3d8817e4Smiod if (fetch_data (buf, info, 1))
524*3d8817e4Smiod {
525*3d8817e4Smiod char mytxt[TXTSIZ];
526*3d8817e4Smiod struct tab_elt *p;
527*3d8817e4Smiod
528*3d8817e4Smiod for (p = opc_ind; p->val != (buf->data[1] & p->mask); ++p)
529*3d8817e4Smiod ;
530*3d8817e4Smiod snprintf (mytxt, TXTSIZ, p->text, txt);
531*3d8817e4Smiod p->fp (buf, info, mytxt);
532*3d8817e4Smiod }
533*3d8817e4Smiod else
534*3d8817e4Smiod buf->n_used = -1;
535*3d8817e4Smiod
536*3d8817e4Smiod return buf->n_used;
537*3d8817e4Smiod }
538*3d8817e4Smiod
539*3d8817e4Smiod /* Table to disassemble machine codes without prefix. */
540*3d8817e4Smiod static struct tab_elt opc_main[] =
541*3d8817e4Smiod {
542*3d8817e4Smiod { 0x00, 0xFF, prt, "nop" },
543*3d8817e4Smiod { 0x01, 0xCF, prt_rr_nn, "ld %s,0x%%04x" },
544*3d8817e4Smiod { 0x02, 0xFF, prt, "ld (bc),a" },
545*3d8817e4Smiod { 0x03, 0xCF, prt_rr, "inc " },
546*3d8817e4Smiod { 0x04, 0xC7, prt_r, "inc %s" },
547*3d8817e4Smiod { 0x05, 0xC7, prt_r, "dec %s" },
548*3d8817e4Smiod { 0x06, 0xC7, ld_r_n, "ld %s,0x%%02x" },
549*3d8817e4Smiod { 0x07, 0xFF, prt, "rlca" },
550*3d8817e4Smiod { 0x08, 0xFF, prt, "ex af,af'" },
551*3d8817e4Smiod { 0x09, 0xCF, prt_rr, "add hl," },
552*3d8817e4Smiod { 0x0A, 0xFF, prt, "ld a,(bc)" },
553*3d8817e4Smiod { 0x0B, 0xCF, prt_rr, "dec " },
554*3d8817e4Smiod { 0x0F, 0xFF, prt, "rrca" },
555*3d8817e4Smiod { 0x10, 0xFF, prt_e, "djnz " },
556*3d8817e4Smiod { 0x12, 0xFF, prt, "ld (de),a" },
557*3d8817e4Smiod { 0x17, 0xFF, prt, "rla" },
558*3d8817e4Smiod { 0x18, 0xFF, prt_e, "jr "},
559*3d8817e4Smiod { 0x1A, 0xFF, prt, "ld a,(de)" },
560*3d8817e4Smiod { 0x1F, 0xFF, prt, "rra" },
561*3d8817e4Smiod { 0x20, 0xE7, jr_cc, "jr %s,"},
562*3d8817e4Smiod { 0x22, 0xFF, prt_nn, "ld (0x%04x),hl" },
563*3d8817e4Smiod { 0x27, 0xFF, prt, "daa"},
564*3d8817e4Smiod { 0x2A, 0xFF, prt_nn, "ld hl,(0x%04x)" },
565*3d8817e4Smiod { 0x2F, 0xFF, prt, "cpl" },
566*3d8817e4Smiod { 0x32, 0xFF, prt_nn, "ld (0x%04x),a" },
567*3d8817e4Smiod { 0x37, 0xFF, prt, "scf" },
568*3d8817e4Smiod { 0x3A, 0xFF, prt_nn, "ld a,(0x%04x)" },
569*3d8817e4Smiod { 0x3F, 0xFF, prt, "ccf" },
570*3d8817e4Smiod
571*3d8817e4Smiod { 0x76, 0xFF, prt, "halt" },
572*3d8817e4Smiod { 0x40, 0xC0, ld_r_r, "ld %s,%s"},
573*3d8817e4Smiod
574*3d8817e4Smiod { 0x80, 0xC0, arit_r, "%s%s" },
575*3d8817e4Smiod
576*3d8817e4Smiod { 0xC0, 0xC7, prt_cc, "ret " },
577*3d8817e4Smiod { 0xC1, 0xCF, pop_rr, "pop" },
578*3d8817e4Smiod { 0xC2, 0xC7, jp_cc_nn, "jp " },
579*3d8817e4Smiod { 0xC3, 0xFF, prt_nn, "jp 0x%04x" },
580*3d8817e4Smiod { 0xC4, 0xC7, jp_cc_nn, "call " },
581*3d8817e4Smiod { 0xC5, 0xCF, pop_rr, "push" },
582*3d8817e4Smiod { 0xC6, 0xC7, arit_n, "%s0x%%02x" },
583*3d8817e4Smiod { 0xC7, 0xC7, rst, "rst 0x%02x" },
584*3d8817e4Smiod { 0xC9, 0xFF, prt, "ret" },
585*3d8817e4Smiod { 0xCB, 0xFF, pref_cb, "" },
586*3d8817e4Smiod { 0xCD, 0xFF, prt_nn, "call 0x%04x" },
587*3d8817e4Smiod { 0xD3, 0xFF, prt_n, "out (0x%02x),a" },
588*3d8817e4Smiod { 0xD9, 0xFF, prt, "exx" },
589*3d8817e4Smiod { 0xDB, 0xFF, prt_n, "in a,(0x%02x)" },
590*3d8817e4Smiod { 0xDD, 0xFF, pref_ind, "ix" },
591*3d8817e4Smiod { 0xE3, 0xFF, prt, "ex (sp),hl" },
592*3d8817e4Smiod { 0xE9, 0xFF, prt, "jp (hl)" },
593*3d8817e4Smiod { 0xEB, 0xFF, prt, "ex de,hl" },
594*3d8817e4Smiod { 0xED, 0xFF, pref_ed, ""},
595*3d8817e4Smiod { 0xF3, 0xFF, prt, "di" },
596*3d8817e4Smiod { 0xF9, 0xFF, prt, "ld sp,hl" },
597*3d8817e4Smiod { 0xFB, 0xFF, prt, "ei" },
598*3d8817e4Smiod { 0xFD, 0xFF, pref_ind, "iy" },
599*3d8817e4Smiod { 0x00, 0x00, prt, "????" },
600*3d8817e4Smiod } ;
601*3d8817e4Smiod
602*3d8817e4Smiod int
print_insn_z80(bfd_vma addr,disassemble_info * info)603*3d8817e4Smiod print_insn_z80 (bfd_vma addr, disassemble_info * info)
604*3d8817e4Smiod {
605*3d8817e4Smiod struct buffer buf;
606*3d8817e4Smiod struct tab_elt *p;
607*3d8817e4Smiod
608*3d8817e4Smiod buf.base = addr;
609*3d8817e4Smiod buf.n_fetch = 0;
610*3d8817e4Smiod buf.n_used = 0;
611*3d8817e4Smiod
612*3d8817e4Smiod if (! fetch_data (& buf, info, 1))
613*3d8817e4Smiod return -1;
614*3d8817e4Smiod
615*3d8817e4Smiod for (p = opc_main; p->val != (buf.data[0] & p->mask); ++p)
616*3d8817e4Smiod ;
617*3d8817e4Smiod p->fp (& buf, info, p->text);
618*3d8817e4Smiod
619*3d8817e4Smiod return buf.n_used;
620*3d8817e4Smiod }
621