xref: /openbsd-src/gnu/usr.bin/binutils-2.17/opcodes/h8300-dis.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
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