1*3d8817e4Smiod /* Disassemble h8300 instructions.
2*3d8817e4Smiod Copyright 1993, 1994, 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005
3*3d8817e4Smiod Free Software Foundation, Inc.
4*3d8817e4Smiod
5*3d8817e4Smiod This program 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 #define DEFINE_TABLE
21*3d8817e4Smiod
22*3d8817e4Smiod #include "sysdep.h"
23*3d8817e4Smiod #define h8_opcodes h8ops
24*3d8817e4Smiod #include "opcode/h8300.h"
25*3d8817e4Smiod #include "dis-asm.h"
26*3d8817e4Smiod #include "opintl.h"
27*3d8817e4Smiod #include "libiberty.h"
28*3d8817e4Smiod
29*3d8817e4Smiod struct h8_instruction
30*3d8817e4Smiod {
31*3d8817e4Smiod int length;
32*3d8817e4Smiod const struct h8_opcode *opcode;
33*3d8817e4Smiod };
34*3d8817e4Smiod
35*3d8817e4Smiod struct h8_instruction *h8_instructions;
36*3d8817e4Smiod
37*3d8817e4Smiod /* Run through the opcodes and sort them into order to make them easy
38*3d8817e4Smiod to disassemble. */
39*3d8817e4Smiod
40*3d8817e4Smiod static void
bfd_h8_disassemble_init(void)41*3d8817e4Smiod bfd_h8_disassemble_init (void)
42*3d8817e4Smiod {
43*3d8817e4Smiod unsigned int i;
44*3d8817e4Smiod unsigned int nopcodes;
45*3d8817e4Smiod const struct h8_opcode *p;
46*3d8817e4Smiod struct h8_instruction *pi;
47*3d8817e4Smiod
48*3d8817e4Smiod nopcodes = sizeof (h8_opcodes) / sizeof (struct h8_opcode);
49*3d8817e4Smiod
50*3d8817e4Smiod h8_instructions = xmalloc (nopcodes * sizeof (struct h8_instruction));
51*3d8817e4Smiod
52*3d8817e4Smiod for (p = h8_opcodes, pi = h8_instructions; p->name; p++, pi++)
53*3d8817e4Smiod {
54*3d8817e4Smiod int n1 = 0;
55*3d8817e4Smiod int n2 = 0;
56*3d8817e4Smiod
57*3d8817e4Smiod if ((int) p->data.nib[0] < 16)
58*3d8817e4Smiod n1 = (int) p->data.nib[0];
59*3d8817e4Smiod else
60*3d8817e4Smiod n1 = 0;
61*3d8817e4Smiod
62*3d8817e4Smiod if ((int) p->data.nib[1] < 16)
63*3d8817e4Smiod n2 = (int) p->data.nib[1];
64*3d8817e4Smiod else
65*3d8817e4Smiod n2 = 0;
66*3d8817e4Smiod
67*3d8817e4Smiod /* Just make sure there are an even number of nibbles in it, and
68*3d8817e4Smiod that the count is the same as the length. */
69*3d8817e4Smiod for (i = 0; p->data.nib[i] != (op_type) E; i++)
70*3d8817e4Smiod ;
71*3d8817e4Smiod
72*3d8817e4Smiod if (i & 1)
73*3d8817e4Smiod {
74*3d8817e4Smiod fprintf (stderr, "Internal error, h8_disassemble_init.\n");
75*3d8817e4Smiod abort ();
76*3d8817e4Smiod }
77*3d8817e4Smiod
78*3d8817e4Smiod pi->length = i / 2;
79*3d8817e4Smiod pi->opcode = p;
80*3d8817e4Smiod }
81*3d8817e4Smiod
82*3d8817e4Smiod /* Add entry for the NULL vector terminator. */
83*3d8817e4Smiod pi->length = 0;
84*3d8817e4Smiod pi->opcode = p;
85*3d8817e4Smiod }
86*3d8817e4Smiod
87*3d8817e4Smiod static void
extract_immediate(FILE * stream,op_type looking_for,int thisnib,unsigned char * data,int * cst,int * len,const struct h8_opcode * q)88*3d8817e4Smiod extract_immediate (FILE *stream,
89*3d8817e4Smiod op_type looking_for,
90*3d8817e4Smiod int thisnib,
91*3d8817e4Smiod unsigned char *data,
92*3d8817e4Smiod int *cst,
93*3d8817e4Smiod int *len,
94*3d8817e4Smiod const struct h8_opcode *q)
95*3d8817e4Smiod {
96*3d8817e4Smiod switch (looking_for & SIZE)
97*3d8817e4Smiod {
98*3d8817e4Smiod case L_2:
99*3d8817e4Smiod *len = 2;
100*3d8817e4Smiod *cst = thisnib & 3;
101*3d8817e4Smiod
102*3d8817e4Smiod /* DISP2 special treatment. */
103*3d8817e4Smiod if ((looking_for & MODE) == DISP)
104*3d8817e4Smiod {
105*3d8817e4Smiod if (OP_KIND (q->how) == O_MOVAB
106*3d8817e4Smiod || OP_KIND (q->how) == O_MOVAW
107*3d8817e4Smiod || OP_KIND (q->how) == O_MOVAL)
108*3d8817e4Smiod {
109*3d8817e4Smiod /* Handling for mova insn. */
110*3d8817e4Smiod switch (q->args.nib[0] & MODE)
111*3d8817e4Smiod {
112*3d8817e4Smiod case INDEXB:
113*3d8817e4Smiod default:
114*3d8817e4Smiod break;
115*3d8817e4Smiod case INDEXW:
116*3d8817e4Smiod *cst *= 2;
117*3d8817e4Smiod break;
118*3d8817e4Smiod case INDEXL:
119*3d8817e4Smiod *cst *= 4;
120*3d8817e4Smiod break;
121*3d8817e4Smiod }
122*3d8817e4Smiod }
123*3d8817e4Smiod else
124*3d8817e4Smiod {
125*3d8817e4Smiod /* Handling for non-mova insn. */
126*3d8817e4Smiod switch (OP_SIZE (q->how))
127*3d8817e4Smiod {
128*3d8817e4Smiod default: break;
129*3d8817e4Smiod case SW:
130*3d8817e4Smiod *cst *= 2;
131*3d8817e4Smiod break;
132*3d8817e4Smiod case SL:
133*3d8817e4Smiod *cst *= 4;
134*3d8817e4Smiod break;
135*3d8817e4Smiod }
136*3d8817e4Smiod }
137*3d8817e4Smiod }
138*3d8817e4Smiod break;
139*3d8817e4Smiod case L_8:
140*3d8817e4Smiod *len = 8;
141*3d8817e4Smiod *cst = data[0];
142*3d8817e4Smiod break;
143*3d8817e4Smiod case L_16:
144*3d8817e4Smiod case L_16U:
145*3d8817e4Smiod *len = 16;
146*3d8817e4Smiod *cst = (data[0] << 8) + data [1];
147*3d8817e4Smiod #if 0
148*3d8817e4Smiod if ((looking_for & SIZE) == L_16)
149*3d8817e4Smiod *cst = (short) *cst; /* Sign extend. */
150*3d8817e4Smiod #endif
151*3d8817e4Smiod break;
152*3d8817e4Smiod case L_32:
153*3d8817e4Smiod *len = 32;
154*3d8817e4Smiod *cst = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3];
155*3d8817e4Smiod break;
156*3d8817e4Smiod default:
157*3d8817e4Smiod *len = 0;
158*3d8817e4Smiod *cst = 0;
159*3d8817e4Smiod fprintf (stream, "DISP bad size\n");
160*3d8817e4Smiod break;
161*3d8817e4Smiod }
162*3d8817e4Smiod }
163*3d8817e4Smiod
164*3d8817e4Smiod static const char *regnames[] =
165*3d8817e4Smiod {
166*3d8817e4Smiod "r0h", "r1h", "r2h", "r3h", "r4h", "r5h", "r6h", "r7h",
167*3d8817e4Smiod "r0l", "r1l", "r2l", "r3l", "r4l", "r5l", "r6l", "r7l"
168*3d8817e4Smiod };
169*3d8817e4Smiod static const char *wregnames[] =
170*3d8817e4Smiod {
171*3d8817e4Smiod "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
172*3d8817e4Smiod "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7"
173*3d8817e4Smiod };
174*3d8817e4Smiod static const char *lregnames[] =
175*3d8817e4Smiod {
176*3d8817e4Smiod "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7",
177*3d8817e4Smiod "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7"
178*3d8817e4Smiod };
179*3d8817e4Smiod static const char *cregnames[] =
180*3d8817e4Smiod {
181*3d8817e4Smiod "ccr", "exr", "mach", "macl", "", "", "vbr", "sbr"
182*3d8817e4Smiod };
183*3d8817e4Smiod
184*3d8817e4Smiod static void
print_one_arg(disassemble_info * info,bfd_vma addr,op_type x,int cst,int cstlen,int rdisp_n,int rn,const char ** pregnames,int len)185*3d8817e4Smiod print_one_arg (disassemble_info *info,
186*3d8817e4Smiod bfd_vma addr,
187*3d8817e4Smiod op_type x,
188*3d8817e4Smiod int cst,
189*3d8817e4Smiod int cstlen,
190*3d8817e4Smiod int rdisp_n,
191*3d8817e4Smiod int rn,
192*3d8817e4Smiod const char **pregnames,
193*3d8817e4Smiod int len)
194*3d8817e4Smiod {
195*3d8817e4Smiod void * stream = info->stream;
196*3d8817e4Smiod fprintf_ftype outfn = info->fprintf_func;
197*3d8817e4Smiod
198*3d8817e4Smiod if ((x & SIZE) == L_3 || (x & SIZE) == L_3NZ)
199*3d8817e4Smiod outfn (stream, "#0x%x", (unsigned) cst);
200*3d8817e4Smiod else if ((x & MODE) == IMM)
201*3d8817e4Smiod outfn (stream, "#0x%x", (unsigned) cst);
202*3d8817e4Smiod else if ((x & MODE) == DBIT || (x & MODE) == KBIT)
203*3d8817e4Smiod outfn (stream, "#%d", (unsigned) cst);
204*3d8817e4Smiod else if ((x & MODE) == CONST_2)
205*3d8817e4Smiod outfn (stream, "#2");
206*3d8817e4Smiod else if ((x & MODE) == CONST_4)
207*3d8817e4Smiod outfn (stream, "#4");
208*3d8817e4Smiod else if ((x & MODE) == CONST_8)
209*3d8817e4Smiod outfn (stream, "#8");
210*3d8817e4Smiod else if ((x & MODE) == CONST_16)
211*3d8817e4Smiod outfn (stream, "#16");
212*3d8817e4Smiod else if ((x & MODE) == REG)
213*3d8817e4Smiod {
214*3d8817e4Smiod switch (x & SIZE)
215*3d8817e4Smiod {
216*3d8817e4Smiod case L_8:
217*3d8817e4Smiod outfn (stream, "%s", regnames[rn]);
218*3d8817e4Smiod break;
219*3d8817e4Smiod case L_16:
220*3d8817e4Smiod case L_16U:
221*3d8817e4Smiod outfn (stream, "%s", wregnames[rn]);
222*3d8817e4Smiod break;
223*3d8817e4Smiod case L_P:
224*3d8817e4Smiod case L_32:
225*3d8817e4Smiod outfn (stream, "%s", lregnames[rn]);
226*3d8817e4Smiod break;
227*3d8817e4Smiod }
228*3d8817e4Smiod }
229*3d8817e4Smiod else if ((x & MODE) == LOWREG)
230*3d8817e4Smiod {
231*3d8817e4Smiod switch (x & SIZE)
232*3d8817e4Smiod {
233*3d8817e4Smiod case L_8:
234*3d8817e4Smiod /* Always take low half of reg. */
235*3d8817e4Smiod outfn (stream, "%s.b", regnames[rn < 8 ? rn + 8 : rn]);
236*3d8817e4Smiod break;
237*3d8817e4Smiod case L_16:
238*3d8817e4Smiod case L_16U:
239*3d8817e4Smiod /* Always take low half of reg. */
240*3d8817e4Smiod outfn (stream, "%s.w", wregnames[rn < 8 ? rn : rn - 8]);
241*3d8817e4Smiod break;
242*3d8817e4Smiod case L_P:
243*3d8817e4Smiod case L_32:
244*3d8817e4Smiod outfn (stream, "%s.l", lregnames[rn]);
245*3d8817e4Smiod break;
246*3d8817e4Smiod }
247*3d8817e4Smiod }
248*3d8817e4Smiod else if ((x & MODE) == POSTINC)
249*3d8817e4Smiod outfn (stream, "@%s+", pregnames[rn]);
250*3d8817e4Smiod
251*3d8817e4Smiod else if ((x & MODE) == POSTDEC)
252*3d8817e4Smiod outfn (stream, "@%s-", pregnames[rn]);
253*3d8817e4Smiod
254*3d8817e4Smiod else if ((x & MODE) == PREINC)
255*3d8817e4Smiod outfn (stream, "@+%s", pregnames[rn]);
256*3d8817e4Smiod
257*3d8817e4Smiod else if ((x & MODE) == PREDEC)
258*3d8817e4Smiod outfn (stream, "@-%s", pregnames[rn]);
259*3d8817e4Smiod
260*3d8817e4Smiod else if ((x & MODE) == IND)
261*3d8817e4Smiod outfn (stream, "@%s", pregnames[rn]);
262*3d8817e4Smiod
263*3d8817e4Smiod else if ((x & MODE) == ABS || (x & ABSJMP))
264*3d8817e4Smiod outfn (stream, "@0x%x:%d", (unsigned) cst, cstlen);
265*3d8817e4Smiod
266*3d8817e4Smiod else if ((x & MODE) == MEMIND)
267*3d8817e4Smiod outfn (stream, "@@%d (0x%x)", cst, cst);
268*3d8817e4Smiod
269*3d8817e4Smiod else if ((x & MODE) == VECIND)
270*3d8817e4Smiod {
271*3d8817e4Smiod /* FIXME Multiplier should be 2 or 4, depending on processor mode,
272*3d8817e4Smiod by which is meant "normal" vs. "middle", "advanced", "maximum". */
273*3d8817e4Smiod
274*3d8817e4Smiod int offset = (cst + 0x80) * 4;
275*3d8817e4Smiod outfn (stream, "@@%d (0x%x)", offset, offset);
276*3d8817e4Smiod }
277*3d8817e4Smiod else if ((x & MODE) == PCREL)
278*3d8817e4Smiod {
279*3d8817e4Smiod if ((x & SIZE) == L_16 ||
280*3d8817e4Smiod (x & SIZE) == L_16U)
281*3d8817e4Smiod {
282*3d8817e4Smiod outfn (stream, ".%s%d (0x%lx)",
283*3d8817e4Smiod (short) cst > 0 ? "+" : "",
284*3d8817e4Smiod (short) cst,
285*3d8817e4Smiod (long)(addr + (short) cst + len));
286*3d8817e4Smiod }
287*3d8817e4Smiod else
288*3d8817e4Smiod {
289*3d8817e4Smiod outfn (stream, ".%s%d (0x%lx)",
290*3d8817e4Smiod (char) cst > 0 ? "+" : "",
291*3d8817e4Smiod (char) cst,
292*3d8817e4Smiod (long)(addr + (char) cst + len));
293*3d8817e4Smiod }
294*3d8817e4Smiod }
295*3d8817e4Smiod else if ((x & MODE) == DISP)
296*3d8817e4Smiod outfn (stream, "@(0x%x:%d,%s)", cst, cstlen, pregnames[rdisp_n]);
297*3d8817e4Smiod
298*3d8817e4Smiod else if ((x & MODE) == INDEXB)
299*3d8817e4Smiod /* Always take low half of reg. */
300*3d8817e4Smiod outfn (stream, "@(0x%x:%d,%s.b)", cst, cstlen,
301*3d8817e4Smiod regnames[rdisp_n < 8 ? rdisp_n + 8 : rdisp_n]);
302*3d8817e4Smiod
303*3d8817e4Smiod else if ((x & MODE) == INDEXW)
304*3d8817e4Smiod /* Always take low half of reg. */
305*3d8817e4Smiod outfn (stream, "@(0x%x:%d,%s.w)", cst, cstlen,
306*3d8817e4Smiod wregnames[rdisp_n < 8 ? rdisp_n : rdisp_n - 8]);
307*3d8817e4Smiod
308*3d8817e4Smiod else if ((x & MODE) == INDEXL)
309*3d8817e4Smiod outfn (stream, "@(0x%x:%d,%s.l)", cst, cstlen, lregnames[rdisp_n]);
310*3d8817e4Smiod
311*3d8817e4Smiod else if (x & CTRL)
312*3d8817e4Smiod outfn (stream, cregnames[rn]);
313*3d8817e4Smiod
314*3d8817e4Smiod else if ((x & MODE) == CCR)
315*3d8817e4Smiod outfn (stream, "ccr");
316*3d8817e4Smiod
317*3d8817e4Smiod else if ((x & MODE) == EXR)
318*3d8817e4Smiod outfn (stream, "exr");
319*3d8817e4Smiod
320*3d8817e4Smiod else if ((x & MODE) == MACREG)
321*3d8817e4Smiod outfn (stream, "mac%c", cst ? 'l' : 'h');
322*3d8817e4Smiod
323*3d8817e4Smiod else
324*3d8817e4Smiod /* xgettext:c-format */
325*3d8817e4Smiod outfn (stream, _("Hmmmm 0x%x"), x);
326*3d8817e4Smiod }
327*3d8817e4Smiod
328*3d8817e4Smiod static unsigned int
bfd_h8_disassemble(bfd_vma addr,disassemble_info * info,int mach)329*3d8817e4Smiod bfd_h8_disassemble (bfd_vma addr, disassemble_info *info, int mach)
330*3d8817e4Smiod {
331*3d8817e4Smiod /* Find the first entry in the table for this opcode. */
332*3d8817e4Smiod int regno[3] = { 0, 0, 0 };
333*3d8817e4Smiod int dispregno[3] = { 0, 0, 0 };
334*3d8817e4Smiod int cst[3] = { 0, 0, 0 };
335*3d8817e4Smiod int cstlen[3] = { 0, 0, 0 };
336*3d8817e4Smiod static bfd_boolean init = 0;
337*3d8817e4Smiod const struct h8_instruction *qi;
338*3d8817e4Smiod char const **pregnames = mach != 0 ? lregnames : wregnames;
339*3d8817e4Smiod int status;
340*3d8817e4Smiod unsigned int l;
341*3d8817e4Smiod unsigned char data[MAX_CODE_NIBBLES];
342*3d8817e4Smiod void *stream = info->stream;
343*3d8817e4Smiod fprintf_ftype outfn = info->fprintf_func;
344*3d8817e4Smiod
345*3d8817e4Smiod if (!init)
346*3d8817e4Smiod {
347*3d8817e4Smiod bfd_h8_disassemble_init ();
348*3d8817e4Smiod init = 1;
349*3d8817e4Smiod }
350*3d8817e4Smiod
351*3d8817e4Smiod status = info->read_memory_func (addr, data, 2, info);
352*3d8817e4Smiod if (status != 0)
353*3d8817e4Smiod {
354*3d8817e4Smiod info->memory_error_func (status, addr, info);
355*3d8817e4Smiod return -1;
356*3d8817e4Smiod }
357*3d8817e4Smiod
358*3d8817e4Smiod for (l = 2; status == 0 && l < sizeof (data) / 2; l += 2)
359*3d8817e4Smiod status = info->read_memory_func (addr + l, data + l, 2, info);
360*3d8817e4Smiod
361*3d8817e4Smiod /* Find the exact opcode/arg combo. */
362*3d8817e4Smiod for (qi = h8_instructions; qi->opcode->name; qi++)
363*3d8817e4Smiod {
364*3d8817e4Smiod const struct h8_opcode *q = qi->opcode;
365*3d8817e4Smiod op_type *nib = q->data.nib;
366*3d8817e4Smiod unsigned int len = 0;
367*3d8817e4Smiod
368*3d8817e4Smiod while (1)
369*3d8817e4Smiod {
370*3d8817e4Smiod op_type looking_for = *nib;
371*3d8817e4Smiod int thisnib = data[len / 2];
372*3d8817e4Smiod int opnr;
373*3d8817e4Smiod
374*3d8817e4Smiod thisnib = (len & 1) ? (thisnib & 0xf) : ((thisnib / 16) & 0xf);
375*3d8817e4Smiod opnr = ((looking_for & OP3) == OP3 ? 2
376*3d8817e4Smiod : (looking_for & DST) == DST ? 1 : 0);
377*3d8817e4Smiod
378*3d8817e4Smiod if (looking_for < 16 && looking_for >= 0)
379*3d8817e4Smiod {
380*3d8817e4Smiod if (looking_for != thisnib)
381*3d8817e4Smiod goto fail;
382*3d8817e4Smiod }
383*3d8817e4Smiod else
384*3d8817e4Smiod {
385*3d8817e4Smiod if ((int) looking_for & (int) B31)
386*3d8817e4Smiod {
387*3d8817e4Smiod if (!((thisnib & 0x8) != 0))
388*3d8817e4Smiod goto fail;
389*3d8817e4Smiod
390*3d8817e4Smiod looking_for = (op_type) ((int) looking_for & ~(int) B31);
391*3d8817e4Smiod thisnib &= 0x7;
392*3d8817e4Smiod }
393*3d8817e4Smiod else if ((int) looking_for & (int) B30)
394*3d8817e4Smiod {
395*3d8817e4Smiod if (!((thisnib & 0x8) == 0))
396*3d8817e4Smiod goto fail;
397*3d8817e4Smiod
398*3d8817e4Smiod looking_for = (op_type) ((int) looking_for & ~(int) B30);
399*3d8817e4Smiod }
400*3d8817e4Smiod
401*3d8817e4Smiod if ((int) looking_for & (int) B21)
402*3d8817e4Smiod {
403*3d8817e4Smiod if (!((thisnib & 0x4) != 0))
404*3d8817e4Smiod goto fail;
405*3d8817e4Smiod
406*3d8817e4Smiod looking_for = (op_type) ((int) looking_for & ~(int) B21);
407*3d8817e4Smiod thisnib &= 0xb;
408*3d8817e4Smiod }
409*3d8817e4Smiod else if ((int) looking_for & (int) B20)
410*3d8817e4Smiod {
411*3d8817e4Smiod if (!((thisnib & 0x4) == 0))
412*3d8817e4Smiod goto fail;
413*3d8817e4Smiod
414*3d8817e4Smiod looking_for = (op_type) ((int) looking_for & ~(int) B20);
415*3d8817e4Smiod }
416*3d8817e4Smiod if ((int) looking_for & (int) B11)
417*3d8817e4Smiod {
418*3d8817e4Smiod if (!((thisnib & 0x2) != 0))
419*3d8817e4Smiod goto fail;
420*3d8817e4Smiod
421*3d8817e4Smiod looking_for = (op_type) ((int) looking_for & ~(int) B11);
422*3d8817e4Smiod thisnib &= 0xd;
423*3d8817e4Smiod }
424*3d8817e4Smiod else if ((int) looking_for & (int) B10)
425*3d8817e4Smiod {
426*3d8817e4Smiod if (!((thisnib & 0x2) == 0))
427*3d8817e4Smiod goto fail;
428*3d8817e4Smiod
429*3d8817e4Smiod looking_for = (op_type) ((int) looking_for & ~(int) B10);
430*3d8817e4Smiod }
431*3d8817e4Smiod
432*3d8817e4Smiod if ((int) looking_for & (int) B01)
433*3d8817e4Smiod {
434*3d8817e4Smiod if (!((thisnib & 0x1) != 0))
435*3d8817e4Smiod goto fail;
436*3d8817e4Smiod
437*3d8817e4Smiod looking_for = (op_type) ((int) looking_for & ~(int) B01);
438*3d8817e4Smiod thisnib &= 0xe;
439*3d8817e4Smiod }
440*3d8817e4Smiod else if ((int) looking_for & (int) B00)
441*3d8817e4Smiod {
442*3d8817e4Smiod if (!((thisnib & 0x1) == 0))
443*3d8817e4Smiod goto fail;
444*3d8817e4Smiod
445*3d8817e4Smiod looking_for = (op_type) ((int) looking_for & ~(int) B00);
446*3d8817e4Smiod }
447*3d8817e4Smiod
448*3d8817e4Smiod if (looking_for & IGNORE)
449*3d8817e4Smiod {
450*3d8817e4Smiod /* Hitachi has declared that IGNORE must be zero. */
451*3d8817e4Smiod if (thisnib != 0)
452*3d8817e4Smiod goto fail;
453*3d8817e4Smiod }
454*3d8817e4Smiod else if ((looking_for & MODE) == DATA)
455*3d8817e4Smiod {
456*3d8817e4Smiod ; /* Skip embedded data. */
457*3d8817e4Smiod }
458*3d8817e4Smiod else if ((looking_for & MODE) == DBIT)
459*3d8817e4Smiod {
460*3d8817e4Smiod /* Exclude adds/subs by looking at bit 0 and 2, and
461*3d8817e4Smiod make sure the operand size, either w or l,
462*3d8817e4Smiod matches by looking at bit 1. */
463*3d8817e4Smiod if ((looking_for & 7) != (thisnib & 7))
464*3d8817e4Smiod goto fail;
465*3d8817e4Smiod
466*3d8817e4Smiod cst[opnr] = (thisnib & 0x8) ? 2 : 1;
467*3d8817e4Smiod }
468*3d8817e4Smiod else if ((looking_for & MODE) == DISP
469*3d8817e4Smiod || (looking_for & MODE) == ABS
470*3d8817e4Smiod || (looking_for & MODE) == PCREL
471*3d8817e4Smiod || (looking_for & MODE) == INDEXB
472*3d8817e4Smiod || (looking_for & MODE) == INDEXW
473*3d8817e4Smiod || (looking_for & MODE) == INDEXL)
474*3d8817e4Smiod {
475*3d8817e4Smiod extract_immediate (stream, looking_for, thisnib,
476*3d8817e4Smiod data + len / 2, cst + opnr,
477*3d8817e4Smiod cstlen + opnr, q);
478*3d8817e4Smiod /* Even address == bra, odd == bra/s. */
479*3d8817e4Smiod if (q->how == O (O_BRAS, SB))
480*3d8817e4Smiod cst[opnr] -= 1;
481*3d8817e4Smiod }
482*3d8817e4Smiod else if ((looking_for & MODE) == REG
483*3d8817e4Smiod || (looking_for & MODE) == LOWREG
484*3d8817e4Smiod || (looking_for & MODE) == IND
485*3d8817e4Smiod || (looking_for & MODE) == PREINC
486*3d8817e4Smiod || (looking_for & MODE) == POSTINC
487*3d8817e4Smiod || (looking_for & MODE) == PREDEC
488*3d8817e4Smiod || (looking_for & MODE) == POSTDEC)
489*3d8817e4Smiod {
490*3d8817e4Smiod regno[opnr] = thisnib;
491*3d8817e4Smiod }
492*3d8817e4Smiod else if (looking_for & CTRL) /* Control Register. */
493*3d8817e4Smiod {
494*3d8817e4Smiod thisnib &= 7;
495*3d8817e4Smiod if (((looking_for & MODE) == CCR && (thisnib != C_CCR))
496*3d8817e4Smiod || ((looking_for & MODE) == EXR && (thisnib != C_EXR))
497*3d8817e4Smiod || ((looking_for & MODE) == MACH && (thisnib != C_MACH))
498*3d8817e4Smiod || ((looking_for & MODE) == MACL && (thisnib != C_MACL))
499*3d8817e4Smiod || ((looking_for & MODE) == VBR && (thisnib != C_VBR))
500*3d8817e4Smiod || ((looking_for & MODE) == SBR && (thisnib != C_SBR)))
501*3d8817e4Smiod goto fail;
502*3d8817e4Smiod if (((looking_for & MODE) == CCR_EXR
503*3d8817e4Smiod && (thisnib != C_CCR && thisnib != C_EXR))
504*3d8817e4Smiod || ((looking_for & MODE) == VBR_SBR
505*3d8817e4Smiod && (thisnib != C_VBR && thisnib != C_SBR))
506*3d8817e4Smiod || ((looking_for & MODE) == MACREG
507*3d8817e4Smiod && (thisnib != C_MACH && thisnib != C_MACL)))
508*3d8817e4Smiod goto fail;
509*3d8817e4Smiod if (((looking_for & MODE) == CC_EX_VB_SB
510*3d8817e4Smiod && (thisnib != C_CCR && thisnib != C_EXR
511*3d8817e4Smiod && thisnib != C_VBR && thisnib != C_SBR)))
512*3d8817e4Smiod goto fail;
513*3d8817e4Smiod
514*3d8817e4Smiod regno[opnr] = thisnib;
515*3d8817e4Smiod }
516*3d8817e4Smiod else if ((looking_for & SIZE) == L_5)
517*3d8817e4Smiod {
518*3d8817e4Smiod cst[opnr] = data[len / 2] & 31;
519*3d8817e4Smiod cstlen[opnr] = 5;
520*3d8817e4Smiod }
521*3d8817e4Smiod else if ((looking_for & SIZE) == L_4)
522*3d8817e4Smiod {
523*3d8817e4Smiod cst[opnr] = thisnib;
524*3d8817e4Smiod cstlen[opnr] = 4;
525*3d8817e4Smiod }
526*3d8817e4Smiod else if ((looking_for & SIZE) == L_16
527*3d8817e4Smiod || (looking_for & SIZE) == L_16U)
528*3d8817e4Smiod {
529*3d8817e4Smiod cst[opnr] = (data[len / 2]) * 256 + data[(len + 2) / 2];
530*3d8817e4Smiod cstlen[opnr] = 16;
531*3d8817e4Smiod }
532*3d8817e4Smiod else if ((looking_for & MODE) == MEMIND)
533*3d8817e4Smiod {
534*3d8817e4Smiod cst[opnr] = data[1];
535*3d8817e4Smiod }
536*3d8817e4Smiod else if ((looking_for & MODE) == VECIND)
537*3d8817e4Smiod {
538*3d8817e4Smiod cst[opnr] = data[1] & 0x7f;
539*3d8817e4Smiod }
540*3d8817e4Smiod else if ((looking_for & SIZE) == L_32)
541*3d8817e4Smiod {
542*3d8817e4Smiod int i = len / 2;
543*3d8817e4Smiod
544*3d8817e4Smiod cst[opnr] = ((data[i] << 24)
545*3d8817e4Smiod | (data[i + 1] << 16)
546*3d8817e4Smiod | (data[i + 2] << 8)
547*3d8817e4Smiod | (data[i + 3]));
548*3d8817e4Smiod
549*3d8817e4Smiod cstlen[opnr] = 32;
550*3d8817e4Smiod }
551*3d8817e4Smiod else if ((looking_for & SIZE) == L_24)
552*3d8817e4Smiod {
553*3d8817e4Smiod int i = len / 2;
554*3d8817e4Smiod
555*3d8817e4Smiod cst[opnr] =
556*3d8817e4Smiod (data[i] << 16) | (data[i + 1] << 8) | (data[i + 2]);
557*3d8817e4Smiod cstlen[opnr] = 24;
558*3d8817e4Smiod }
559*3d8817e4Smiod else if (looking_for & IGNORE)
560*3d8817e4Smiod {
561*3d8817e4Smiod ;
562*3d8817e4Smiod }
563*3d8817e4Smiod else if (looking_for & DISPREG)
564*3d8817e4Smiod {
565*3d8817e4Smiod dispregno[opnr] = thisnib & 7;
566*3d8817e4Smiod }
567*3d8817e4Smiod else if ((looking_for & MODE) == KBIT)
568*3d8817e4Smiod {
569*3d8817e4Smiod switch (thisnib)
570*3d8817e4Smiod {
571*3d8817e4Smiod case 9:
572*3d8817e4Smiod cst[opnr] = 4;
573*3d8817e4Smiod break;
574*3d8817e4Smiod case 8:
575*3d8817e4Smiod cst[opnr] = 2;
576*3d8817e4Smiod break;
577*3d8817e4Smiod case 0:
578*3d8817e4Smiod cst[opnr] = 1;
579*3d8817e4Smiod break;
580*3d8817e4Smiod default:
581*3d8817e4Smiod goto fail;
582*3d8817e4Smiod }
583*3d8817e4Smiod }
584*3d8817e4Smiod else if ((looking_for & SIZE) == L_8)
585*3d8817e4Smiod {
586*3d8817e4Smiod cstlen[opnr] = 8;
587*3d8817e4Smiod cst[opnr] = data[len / 2];
588*3d8817e4Smiod }
589*3d8817e4Smiod else if ((looking_for & SIZE) == L_3
590*3d8817e4Smiod || (looking_for & SIZE) == L_3NZ)
591*3d8817e4Smiod {
592*3d8817e4Smiod cst[opnr] = thisnib & 0x7;
593*3d8817e4Smiod if (cst[opnr] == 0 && (looking_for & SIZE) == L_3NZ)
594*3d8817e4Smiod goto fail;
595*3d8817e4Smiod }
596*3d8817e4Smiod else if ((looking_for & SIZE) == L_2)
597*3d8817e4Smiod {
598*3d8817e4Smiod cstlen[opnr] = 2;
599*3d8817e4Smiod cst[opnr] = thisnib & 0x3;
600*3d8817e4Smiod }
601*3d8817e4Smiod else if ((looking_for & MODE) == MACREG)
602*3d8817e4Smiod {
603*3d8817e4Smiod cst[opnr] = (thisnib == 3);
604*3d8817e4Smiod }
605*3d8817e4Smiod else if (looking_for == (op_type) E)
606*3d8817e4Smiod {
607*3d8817e4Smiod outfn (stream, "%s\t", q->name);
608*3d8817e4Smiod
609*3d8817e4Smiod /* Gross. Disgusting. */
610*3d8817e4Smiod if (strcmp (q->name, "ldm.l") == 0)
611*3d8817e4Smiod {
612*3d8817e4Smiod int count, high;
613*3d8817e4Smiod
614*3d8817e4Smiod count = (data[1] / 16) & 0x3;
615*3d8817e4Smiod high = regno[1];
616*3d8817e4Smiod
617*3d8817e4Smiod outfn (stream, "@sp+,er%d-er%d", high - count, high);
618*3d8817e4Smiod return qi->length;
619*3d8817e4Smiod }
620*3d8817e4Smiod
621*3d8817e4Smiod if (strcmp (q->name, "stm.l") == 0)
622*3d8817e4Smiod {
623*3d8817e4Smiod int count, low;
624*3d8817e4Smiod
625*3d8817e4Smiod count = (data[1] / 16) & 0x3;
626*3d8817e4Smiod low = regno[0];
627*3d8817e4Smiod
628*3d8817e4Smiod outfn (stream, "er%d-er%d,@-sp", low, low + count);
629*3d8817e4Smiod return qi->length;
630*3d8817e4Smiod }
631*3d8817e4Smiod if (strcmp (q->name, "rte/l") == 0
632*3d8817e4Smiod || strcmp (q->name, "rts/l") == 0)
633*3d8817e4Smiod {
634*3d8817e4Smiod if (regno[0] == 0)
635*3d8817e4Smiod outfn (stream, "er%d", regno[1]);
636*3d8817e4Smiod else
637*3d8817e4Smiod outfn (stream, "er%d-er%d", regno[1] - regno[0],
638*3d8817e4Smiod regno[1]);
639*3d8817e4Smiod return qi->length;
640*3d8817e4Smiod }
641*3d8817e4Smiod if (strncmp (q->name, "mova", 4) == 0)
642*3d8817e4Smiod {
643*3d8817e4Smiod op_type *args = q->args.nib;
644*3d8817e4Smiod
645*3d8817e4Smiod if (args[1] == (op_type) E)
646*3d8817e4Smiod {
647*3d8817e4Smiod /* Short form. */
648*3d8817e4Smiod print_one_arg (info, addr, args[0], cst[0],
649*3d8817e4Smiod cstlen[0], dispregno[0], regno[0],
650*3d8817e4Smiod pregnames, qi->length);
651*3d8817e4Smiod outfn (stream, ",er%d", dispregno[0]);
652*3d8817e4Smiod }
653*3d8817e4Smiod else
654*3d8817e4Smiod {
655*3d8817e4Smiod outfn (stream, "@(0x%x:%d,", cst[0], cstlen[0]);
656*3d8817e4Smiod print_one_arg (info, addr, args[1], cst[1],
657*3d8817e4Smiod cstlen[1], dispregno[1], regno[1],
658*3d8817e4Smiod pregnames, qi->length);
659*3d8817e4Smiod outfn (stream, ".%c),",
660*3d8817e4Smiod (args[0] & MODE) == INDEXB ? 'b' : 'w');
661*3d8817e4Smiod print_one_arg (info, addr, args[2], cst[2],
662*3d8817e4Smiod cstlen[2], dispregno[2], regno[2],
663*3d8817e4Smiod pregnames, qi->length);
664*3d8817e4Smiod }
665*3d8817e4Smiod return qi->length;
666*3d8817e4Smiod }
667*3d8817e4Smiod /* Fill in the args. */
668*3d8817e4Smiod {
669*3d8817e4Smiod op_type *args = q->args.nib;
670*3d8817e4Smiod int hadone = 0;
671*3d8817e4Smiod int nargs;
672*3d8817e4Smiod
673*3d8817e4Smiod /* Special case handling for the adds and subs instructions
674*3d8817e4Smiod since in H8 mode thay can only take the r0-r7 registers
675*3d8817e4Smiod but in other (higher) modes they can take the er0-er7
676*3d8817e4Smiod registers as well. */
677*3d8817e4Smiod if (strcmp (qi->opcode->name, "adds") == 0
678*3d8817e4Smiod || strcmp (qi->opcode->name, "subs") == 0)
679*3d8817e4Smiod {
680*3d8817e4Smiod outfn (stream, "#%d,%s", cst[0], pregnames[regno[1] & 0x7]);
681*3d8817e4Smiod return qi->length;
682*3d8817e4Smiod }
683*3d8817e4Smiod
684*3d8817e4Smiod for (nargs = 0;
685*3d8817e4Smiod nargs < 3 && args[nargs] != (op_type) E;
686*3d8817e4Smiod nargs++)
687*3d8817e4Smiod {
688*3d8817e4Smiod int x = args[nargs];
689*3d8817e4Smiod
690*3d8817e4Smiod if (hadone)
691*3d8817e4Smiod outfn (stream, ",");
692*3d8817e4Smiod
693*3d8817e4Smiod print_one_arg (info, addr, x,
694*3d8817e4Smiod cst[nargs], cstlen[nargs],
695*3d8817e4Smiod dispregno[nargs], regno[nargs],
696*3d8817e4Smiod pregnames, qi->length);
697*3d8817e4Smiod
698*3d8817e4Smiod hadone = 1;
699*3d8817e4Smiod }
700*3d8817e4Smiod }
701*3d8817e4Smiod
702*3d8817e4Smiod return qi->length;
703*3d8817e4Smiod }
704*3d8817e4Smiod else
705*3d8817e4Smiod /* xgettext:c-format */
706*3d8817e4Smiod outfn (stream, _("Don't understand 0x%x \n"), looking_for);
707*3d8817e4Smiod }
708*3d8817e4Smiod
709*3d8817e4Smiod len++;
710*3d8817e4Smiod nib++;
711*3d8817e4Smiod }
712*3d8817e4Smiod
713*3d8817e4Smiod fail:
714*3d8817e4Smiod ;
715*3d8817e4Smiod }
716*3d8817e4Smiod
717*3d8817e4Smiod /* Fell off the end. */
718*3d8817e4Smiod outfn (stream, ".word\tH'%x,H'%x", data[0], data[1]);
719*3d8817e4Smiod return 2;
720*3d8817e4Smiod }
721*3d8817e4Smiod
722*3d8817e4Smiod int
print_insn_h8300(bfd_vma addr,disassemble_info * info)723*3d8817e4Smiod print_insn_h8300 (bfd_vma addr, disassemble_info *info)
724*3d8817e4Smiod {
725*3d8817e4Smiod return bfd_h8_disassemble (addr, info, 0);
726*3d8817e4Smiod }
727*3d8817e4Smiod
728*3d8817e4Smiod int
print_insn_h8300h(bfd_vma addr,disassemble_info * info)729*3d8817e4Smiod print_insn_h8300h (bfd_vma addr, disassemble_info *info)
730*3d8817e4Smiod {
731*3d8817e4Smiod return bfd_h8_disassemble (addr, info, 1);
732*3d8817e4Smiod }
733*3d8817e4Smiod
734*3d8817e4Smiod int
print_insn_h8300s(bfd_vma addr,disassemble_info * info)735*3d8817e4Smiod print_insn_h8300s (bfd_vma addr, disassemble_info *info)
736*3d8817e4Smiod {
737*3d8817e4Smiod return bfd_h8_disassemble (addr, info, 2);
738*3d8817e4Smiod }
739