xref: /netbsd-src/external/gpl3/binutils/dist/opcodes/m10300-dis.c (revision f89f6560d453f5e37386cc7938c072d2f528b9fa)
1 /* Disassemble MN10300 instructions.
2    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2005, 2007, 2012
3    Free Software Foundation, Inc.
4 
5    This file is part of the GNU opcodes library.
6 
7    This library is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3, or (at your option)
10    any later version.
11 
12    It is distributed in the hope that it will be useful, but WITHOUT
13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15    License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21 
22 #include "sysdep.h"
23 #include <stdio.h>
24 #include "opcode/mn10300.h"
25 #include "dis-asm.h"
26 #include "opintl.h"
27 
28 #define HAVE_AM33_2 (info->mach == AM33_2)
29 #define HAVE_AM33   (info->mach == AM33 || HAVE_AM33_2)
30 #define HAVE_AM30   (info->mach == AM30)
31 
32 static void
33 disassemble (bfd_vma memaddr,
34 	     struct disassemble_info *info,
35 	     unsigned long insn,
36 	     unsigned int size)
37 {
38   struct mn10300_opcode *op = (struct mn10300_opcode *) mn10300_opcodes;
39   const struct mn10300_operand *operand;
40   bfd_byte buffer[4];
41   unsigned long extension = 0;
42   int status, match = 0;
43 
44   /* Find the opcode.  */
45   while (op->name)
46     {
47       int mysize, extra_shift;
48 
49       if (op->format == FMT_S0)
50 	mysize = 1;
51       else if (op->format == FMT_S1
52 	       || op->format == FMT_D0)
53 	mysize = 2;
54       else if (op->format == FMT_S2
55 	       || op->format == FMT_D1)
56 	mysize = 3;
57       else if (op->format == FMT_S4)
58 	mysize = 5;
59       else if (op->format == FMT_D2)
60 	mysize = 4;
61       else if (op->format == FMT_D3)
62 	mysize = 5;
63       else if (op->format == FMT_D4)
64 	mysize = 6;
65       else if (op->format == FMT_D6)
66 	mysize = 3;
67       else if (op->format == FMT_D7 || op->format == FMT_D10)
68 	mysize = 4;
69       else if (op->format == FMT_D8)
70 	mysize = 6;
71       else if (op->format == FMT_D9)
72 	mysize = 7;
73       else
74 	mysize = 7;
75 
76       if ((op->mask & insn) == op->opcode
77 	  && size == (unsigned int) mysize
78 	  && (op->machine == 0
79 	      || (op->machine == AM33_2 && HAVE_AM33_2)
80 	      || (op->machine == AM33 && HAVE_AM33)
81 	      || (op->machine == AM30 && HAVE_AM30)))
82 	{
83 	  const unsigned char *opindex_ptr;
84 	  unsigned int nocomma;
85 	  int paren = 0;
86 
87 	  if (op->format == FMT_D1 || op->format == FMT_S1)
88 	    extra_shift = 8;
89 	  else if (op->format == FMT_D2 || op->format == FMT_D4
90 		   || op->format == FMT_S2 || op->format == FMT_S4
91 		   || op->format == FMT_S6 || op->format == FMT_D5)
92 	    extra_shift = 16;
93 	  else if (op->format == FMT_D7
94 		   || op->format == FMT_D8
95 		   || op->format == FMT_D9)
96 	    extra_shift = 8;
97 	  else
98 	    extra_shift = 0;
99 
100 	  if (size == 1 || size == 2)
101 	    extension = 0;
102 
103 	  else if (size == 3
104 		   && (op->format == FMT_D1
105 		       || op->opcode == 0xdf0000
106 		       || op->opcode == 0xde0000))
107 	    extension = 0;
108 
109 	  else if (size == 3
110 		   && op->format == FMT_D6)
111 	    extension = 0;
112 
113 	  else if (size == 3)
114 	    {
115 	      insn &= 0xff0000;
116 	      status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
117 	      if (status != 0)
118 		{
119 		  (*info->memory_error_func) (status, memaddr, info);
120 		  return;
121 		}
122 
123 	      insn |= bfd_getl16 (buffer);
124 	      extension = 0;
125 	    }
126 	  else if (size == 4
127 		   && (op->opcode == 0xfaf80000
128 		       || op->opcode == 0xfaf00000
129 		       || op->opcode == 0xfaf40000))
130 	    extension = 0;
131 
132 	  else if (size == 4
133 		   && (op->format == FMT_D7
134 		       || op->format == FMT_D10))
135 	    extension = 0;
136 
137 	  else if (size == 4)
138 	    {
139 	      insn &= 0xffff0000;
140 	      status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
141 	      if (status != 0)
142 		{
143 		  (*info->memory_error_func) (status, memaddr, info);
144 		  return;
145 		}
146 
147 	      insn |= bfd_getl16 (buffer);
148 	      extension = 0;
149 	    }
150 	  else if (size == 5 && op->opcode == 0xdc000000)
151 	    {
152 	      unsigned long temp = 0;
153 
154 	      status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
155 	      if (status != 0)
156 		{
157 		  (*info->memory_error_func) (status, memaddr, info);
158 		  return;
159 		}
160 	      temp |= bfd_getl32 (buffer);
161 
162 	      insn &= 0xff000000;
163 	      insn |= (temp & 0xffffff00) >> 8;
164 	      extension = temp & 0xff;
165 	    }
166 	  else if (size == 5 && op->format == FMT_D3)
167 	    {
168 	      status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
169 	      if (status != 0)
170 		{
171 		  (*info->memory_error_func) (status, memaddr, info);
172 		  return;
173 		}
174 	      insn &= 0xffff0000;
175 	      insn |= bfd_getl16 (buffer);
176 
177 	      status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
178 	      if (status != 0)
179 		{
180 		  (*info->memory_error_func) (status, memaddr, info);
181 		  return;
182 		}
183 	      extension = *(unsigned char *) buffer;
184 	    }
185 	  else if (size == 5)
186 	    {
187 	      unsigned long temp = 0;
188 
189 	      status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
190 	      if (status != 0)
191 		{
192 		  (*info->memory_error_func) (status, memaddr, info);
193 		  return;
194 		}
195 	      temp |= bfd_getl16 (buffer);
196 
197 	      insn &= 0xff0000ff;
198 	      insn |= temp << 8;
199 
200 	      status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
201 	      if (status != 0)
202 		{
203 		  (*info->memory_error_func) (status, memaddr, info);
204 		  return;
205 		}
206 	      extension = *(unsigned char *) buffer;
207 	    }
208 	  else if (size == 6 && op->format == FMT_D8)
209 	    {
210 	      insn &= 0xffffff00;
211 	      status = (*info->read_memory_func) (memaddr + 5, buffer, 1, info);
212 	      if (status != 0)
213 		{
214 		  (*info->memory_error_func) (status, memaddr, info);
215 		  return;
216 		}
217 	      insn |= *(unsigned char *) buffer;
218 
219 	      status = (*info->read_memory_func) (memaddr + 3, buffer, 2, info);
220 	      if (status != 0)
221 		{
222 		  (*info->memory_error_func) (status, memaddr, info);
223 		  return;
224 		}
225 	      extension = bfd_getl16 (buffer);
226 	    }
227 	  else if (size == 6)
228 	    {
229 	      unsigned long temp = 0;
230 
231 	      status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
232 	      if (status != 0)
233 		{
234 		  (*info->memory_error_func) (status, memaddr, info);
235 		  return;
236 		}
237 	      temp |= bfd_getl32 (buffer);
238 
239 	      insn &= 0xffff0000;
240 	      insn |= (temp >> 16) & 0xffff;
241 	      extension = temp & 0xffff;
242 	    }
243 	  else if (size == 7 && op->format == FMT_D9)
244 	    {
245 	      insn &= 0xffffff00;
246 	      status = (*info->read_memory_func) (memaddr + 3, buffer, 4, info);
247 	      if (status != 0)
248 		{
249 		  (*info->memory_error_func) (status, memaddr, info);
250 		  return;
251 		}
252 	      extension = bfd_getl32 (buffer);
253 	      insn |= (extension & 0xff000000) >> 24;
254 	      extension &= 0xffffff;
255 	    }
256 	  else if (size == 7 && op->opcode == 0xdd000000)
257 	    {
258 	      unsigned long temp = 0;
259 
260 	      status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
261 	      if (status != 0)
262 		{
263 		  (*info->memory_error_func) (status, memaddr, info);
264 		  return;
265 		}
266 	      temp |= bfd_getl32 (buffer);
267 
268 	      insn &= 0xff000000;
269 	      insn |= (temp >> 8) & 0xffffff;
270 	      extension = (temp & 0xff) << 16;
271 
272 	      status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info);
273 	      if (status != 0)
274 		{
275 		  (*info->memory_error_func) (status, memaddr, info);
276 		  return;
277 		}
278 	      extension |= bfd_getb16 (buffer);
279 	    }
280 	  else if (size == 7)
281 	    {
282 	      unsigned long temp = 0;
283 
284 	      status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
285 	      if (status != 0)
286 		{
287 		  (*info->memory_error_func) (status, memaddr, info);
288 		  return;
289 		}
290 	      temp |= bfd_getl32 (buffer);
291 
292 	      insn &= 0xffff0000;
293 	      insn |= (temp >> 16) & 0xffff;
294 	      extension = (temp & 0xffff) << 8;
295 
296 	      status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info);
297 	      if (status != 0)
298 		{
299 		  (*info->memory_error_func) (status, memaddr, info);
300 		  return;
301 		}
302 	      extension |= *(unsigned char *) buffer;
303 	    }
304 
305 	  match = 1;
306 	  (*info->fprintf_func) (info->stream, "%s\t", op->name);
307 
308 	  /* Now print the operands.  */
309 	  for (opindex_ptr = op->operands, nocomma = 1;
310 	       *opindex_ptr != 0;
311 	       opindex_ptr++)
312 	    {
313 	      unsigned long value;
314 
315 	      operand = &mn10300_operands[*opindex_ptr];
316 
317 	      /* If this operand is a PLUS (autoincrement), then do not emit
318 		 a comma before emitting the plus.  */
319 	      if ((operand->flags & MN10300_OPERAND_PLUS) != 0)
320 		nocomma = 1;
321 
322 	      if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
323 		{
324 		  unsigned long temp;
325 
326 		  value = insn & ((1 << operand->bits) - 1);
327 		  value <<= (32 - operand->bits);
328 		  temp = extension >> operand->shift;
329 		  temp &= ((1 << (32 - operand->bits)) - 1);
330 		  value |= temp;
331 		  value = ((value ^ (((unsigned long) 1) << 31))
332 			   - (((unsigned long) 1) << 31));
333 		}
334 	      else if ((operand->flags & MN10300_OPERAND_24BIT) != 0)
335 		{
336 		  unsigned long temp;
337 
338 		  value = insn & ((1 << operand->bits) - 1);
339 		  value <<= (24 - operand->bits);
340 		  temp = extension >> operand->shift;
341 		  temp &= ((1 << (24 - operand->bits)) - 1);
342 		  value |= temp;
343 		  if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
344 		    value = ((value & 0xffffff) ^ 0x800000) - 0x800000;
345 		}
346 	      else if ((operand->flags & (MN10300_OPERAND_FSREG
347 					  | MN10300_OPERAND_FDREG)))
348 		{
349 		  /* See m10300-opc.c just before #define FSM0 for an
350 		     explanation of these variables.  Note that
351 		     FMT-implied shifts are not taken into account for
352 		     FP registers.  */
353 		  unsigned long mask_low, mask_high;
354 		  int shl_low, shr_high, shl_high;
355 
356 		  switch (operand->bits)
357 		    {
358 		    case 5:
359 		      /* Handle regular FP registers.  */
360 		      if (operand->shift >= 0)
361 			{
362 			  /* This is an `m' register.  */
363 			  shl_low = operand->shift;
364 			  shl_high = 8 + (8 & shl_low) + (shl_low & 4) / 4;
365 			}
366 		      else
367 			{
368 			  /* This is an `n' register.  */
369 			  shl_low = -operand->shift;
370 			  shl_high = shl_low / 4;
371 			}
372 		      mask_low = 0x0f;
373 		      mask_high = 0x10;
374 		      shr_high = 4;
375 		      break;
376 
377 		    case 3:
378 		      /* Handle accumulators.  */
379 		      shl_low = -operand->shift;
380 		      shl_high = 0;
381 		      mask_low = 0x03;
382 		      mask_high = 0x04;
383 		      shr_high = 2;
384 		      break;
385 
386 		    default:
387 		      abort ();
388 		    }
389 		  value = ((((insn >> shl_high) << shr_high) & mask_high)
390 			   | ((insn >> shl_low) & mask_low));
391 		}
392 	      else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
393 		value = ((extension >> (operand->shift))
394 			 & ((1 << operand->bits) - 1));
395 
396 	      else
397 		value = ((insn >> (operand->shift))
398 			 & ((1 << operand->bits) - 1));
399 
400 	      if ((operand->flags & MN10300_OPERAND_SIGNED) != 0
401 		  /* These are properly extended by the code above.  */
402 		  && ((operand->flags & MN10300_OPERAND_24BIT) == 0))
403 		value = ((value ^ (((unsigned long) 1) << (operand->bits - 1)))
404 			 - (((unsigned long) 1) << (operand->bits - 1)));
405 
406 	      if (!nocomma
407 		  && (!paren
408 		      || ((operand->flags & MN10300_OPERAND_PAREN) == 0)))
409 		(*info->fprintf_func) (info->stream, ",");
410 
411 	      nocomma = 0;
412 
413 	      if ((operand->flags & MN10300_OPERAND_DREG) != 0)
414 		{
415 		  value = ((insn >> (operand->shift + extra_shift))
416 			   & ((1 << operand->bits) - 1));
417 		  (*info->fprintf_func) (info->stream, "d%d", (int) value);
418 		}
419 
420 	      else if ((operand->flags & MN10300_OPERAND_AREG) != 0)
421 		{
422 		  value = ((insn >> (operand->shift + extra_shift))
423 			   & ((1 << operand->bits) - 1));
424 		  (*info->fprintf_func) (info->stream, "a%d", (int) value);
425 		}
426 
427 	      else if ((operand->flags & MN10300_OPERAND_SP) != 0)
428 		(*info->fprintf_func) (info->stream, "sp");
429 
430 	      else if ((operand->flags & MN10300_OPERAND_PSW) != 0)
431 		(*info->fprintf_func) (info->stream, "psw");
432 
433 	      else if ((operand->flags & MN10300_OPERAND_MDR) != 0)
434 		(*info->fprintf_func) (info->stream, "mdr");
435 
436 	      else if ((operand->flags & MN10300_OPERAND_RREG) != 0)
437 		{
438 		  value = ((insn >> (operand->shift + extra_shift))
439 			   & ((1 << operand->bits) - 1));
440 		  if (value < 8)
441 		    (*info->fprintf_func) (info->stream, "r%d", (int) value);
442 		  else if (value < 12)
443 		    (*info->fprintf_func) (info->stream, "a%d", (int) value - 8);
444 		  else
445 		    (*info->fprintf_func) (info->stream, "d%d", (int) value - 12);
446 		}
447 
448 	      else if ((operand->flags & MN10300_OPERAND_XRREG) != 0)
449 		{
450 		  value = ((insn >> (operand->shift + extra_shift))
451 			   & ((1 << operand->bits) - 1));
452 		  if (value == 0)
453 		    (*info->fprintf_func) (info->stream, "sp");
454 		  else
455 		    (*info->fprintf_func) (info->stream, "xr%d", (int) value);
456 		}
457 
458 	      else if ((operand->flags & MN10300_OPERAND_FSREG) != 0)
459 		(*info->fprintf_func) (info->stream, "fs%d", (int) value);
460 
461 	      else if ((operand->flags & MN10300_OPERAND_FDREG) != 0)
462 		(*info->fprintf_func) (info->stream, "fd%d", (int) value);
463 
464 	      else if ((operand->flags & MN10300_OPERAND_FPCR) != 0)
465 		(*info->fprintf_func) (info->stream, "fpcr");
466 
467 	      else if ((operand->flags & MN10300_OPERAND_USP) != 0)
468 		(*info->fprintf_func) (info->stream, "usp");
469 
470 	      else if ((operand->flags & MN10300_OPERAND_SSP) != 0)
471 		(*info->fprintf_func) (info->stream, "ssp");
472 
473 	      else if ((operand->flags & MN10300_OPERAND_MSP) != 0)
474 		(*info->fprintf_func) (info->stream, "msp");
475 
476 	      else if ((operand->flags & MN10300_OPERAND_PC) != 0)
477 		(*info->fprintf_func) (info->stream, "pc");
478 
479 	      else if ((operand->flags & MN10300_OPERAND_EPSW) != 0)
480 		(*info->fprintf_func) (info->stream, "epsw");
481 
482 	      else if ((operand->flags & MN10300_OPERAND_PLUS) != 0)
483 		(*info->fprintf_func) (info->stream, "+");
484 
485 	      else if ((operand->flags & MN10300_OPERAND_PAREN) != 0)
486 		{
487 		  if (paren)
488 		    (*info->fprintf_func) (info->stream, ")");
489 		  else
490 		    {
491 		      (*info->fprintf_func) (info->stream, "(");
492 		      nocomma = 1;
493 		    }
494 		  paren = !paren;
495 		}
496 
497 	      else if ((operand->flags & MN10300_OPERAND_PCREL) != 0)
498 		(*info->print_address_func) ((long) value + memaddr, info);
499 
500 	      else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0)
501 		(*info->print_address_func) (value, info);
502 
503 	      else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0)
504 		{
505 		  int comma = 0;
506 
507 		  (*info->fprintf_func) (info->stream, "[");
508 		  if (value & 0x80)
509 		    {
510 		      (*info->fprintf_func) (info->stream, "d2");
511 		      comma = 1;
512 		    }
513 
514 		  if (value & 0x40)
515 		    {
516 		      if (comma)
517 			(*info->fprintf_func) (info->stream, ",");
518 		      (*info->fprintf_func) (info->stream, "d3");
519 		      comma = 1;
520 		    }
521 
522 		  if (value & 0x20)
523 		    {
524 		      if (comma)
525 			(*info->fprintf_func) (info->stream, ",");
526 		      (*info->fprintf_func) (info->stream, "a2");
527 		      comma = 1;
528 		    }
529 
530 		  if (value & 0x10)
531 		    {
532 		      if (comma)
533 			(*info->fprintf_func) (info->stream, ",");
534 		      (*info->fprintf_func) (info->stream, "a3");
535 		      comma = 1;
536 		    }
537 
538 		  if (value & 0x08)
539 		    {
540 		      if (comma)
541 			(*info->fprintf_func) (info->stream, ",");
542 		      (*info->fprintf_func) (info->stream, "other");
543 		      comma = 1;
544 		    }
545 
546 		  if (value & 0x04)
547 		    {
548 		      if (comma)
549 			(*info->fprintf_func) (info->stream, ",");
550 		      (*info->fprintf_func) (info->stream, "exreg0");
551 		      comma = 1;
552 		    }
553 		  if (value & 0x02)
554 		    {
555 		      if (comma)
556 			(*info->fprintf_func) (info->stream, ",");
557 		      (*info->fprintf_func) (info->stream, "exreg1");
558 		      comma = 1;
559 		    }
560 		  if (value & 0x01)
561 		    {
562 		      if (comma)
563 			(*info->fprintf_func) (info->stream, ",");
564 		      (*info->fprintf_func) (info->stream, "exother");
565 		      comma = 1;
566 		    }
567 		  (*info->fprintf_func) (info->stream, "]");
568 		}
569 
570 	      else
571 		(*info->fprintf_func) (info->stream, "%ld", (long) value);
572 	    }
573 	  /* All done. */
574 	  break;
575 	}
576       op++;
577     }
578 
579   if (!match)
580     /* xgettext:c-format */
581     (*info->fprintf_func) (info->stream, _("unknown\t0x%04lx"), insn);
582 }
583 
584 int
585 print_insn_mn10300 (bfd_vma memaddr, struct disassemble_info *info)
586 {
587   int status;
588   bfd_byte buffer[4];
589   unsigned long insn;
590   unsigned int consume;
591 
592   /* First figure out how big the opcode is.  */
593   status = (*info->read_memory_func) (memaddr, buffer, 1, info);
594   if (status != 0)
595     {
596       (*info->memory_error_func) (status, memaddr, info);
597       return -1;
598     }
599   insn = *(unsigned char *) buffer;
600 
601   /* These are one byte insns.  */
602   if ((insn & 0xf3) == 0x00
603       || (insn & 0xf0) == 0x10
604       || (insn & 0xfc) == 0x3c
605       || (insn & 0xf3) == 0x41
606       || (insn & 0xf3) == 0x40
607       || (insn & 0xfc) == 0x50
608       || (insn & 0xfc) == 0x54
609       || (insn & 0xf0) == 0x60
610       || (insn & 0xf0) == 0x70
611       || ((insn & 0xf0) == 0x80
612 	  && (insn & 0x0c) >> 2 != (insn & 0x03))
613       || ((insn & 0xf0) == 0x90
614 	  && (insn & 0x0c) >> 2 != (insn & 0x03))
615       || ((insn & 0xf0) == 0xa0
616 	  && (insn & 0x0c) >> 2 != (insn & 0x03))
617       || ((insn & 0xf0) == 0xb0
618 	  && (insn & 0x0c) >> 2 != (insn & 0x03))
619       || (insn & 0xff) == 0xcb
620       || (insn & 0xfc) == 0xd0
621       || (insn & 0xfc) == 0xd4
622       || (insn & 0xfc) == 0xd8
623       || (insn & 0xf0) == 0xe0
624       || (insn & 0xff) == 0xff)
625     {
626       consume = 1;
627     }
628 
629   /* These are two byte insns.  */
630   else if ((insn & 0xf0) == 0x80
631 	   || (insn & 0xf0) == 0x90
632 	   || (insn & 0xf0) == 0xa0
633 	   || (insn & 0xf0) == 0xb0
634 	   || (insn & 0xfc) == 0x20
635 	   || (insn & 0xfc) == 0x28
636 	   || (insn & 0xf3) == 0x43
637 	   || (insn & 0xf3) == 0x42
638 	   || (insn & 0xfc) == 0x58
639 	   || (insn & 0xfc) == 0x5c
640 	   || ((insn & 0xf0) == 0xc0
641 	       && (insn & 0xff) != 0xcb
642 	       && (insn & 0xff) != 0xcc
643 	       && (insn & 0xff) != 0xcd)
644 	   || (insn & 0xff) == 0xf0
645 	   || (insn & 0xff) == 0xf1
646 	   || (insn & 0xff) == 0xf2
647 	   || (insn & 0xff) == 0xf3
648 	   || (insn & 0xff) == 0xf4
649 	   || (insn & 0xff) == 0xf5
650 	   || (insn & 0xff) == 0xf6)
651     {
652       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
653       if (status != 0)
654 	{
655 	  (*info->memory_error_func) (status, memaddr, info);
656 	  return -1;
657 	}
658       insn = bfd_getb16 (buffer);
659       consume = 2;
660     }
661 
662   /* These are three byte insns.  */
663   else if ((insn & 0xff) == 0xf8
664 	   || (insn & 0xff) == 0xcc
665 	   || (insn & 0xff) == 0xf9
666 	   || (insn & 0xf3) == 0x01
667 	   || (insn & 0xf3) == 0x02
668 	   || (insn & 0xf3) == 0x03
669 	   || (insn & 0xfc) == 0x24
670 	   || (insn & 0xfc) == 0x2c
671 	   || (insn & 0xfc) == 0x30
672 	   || (insn & 0xfc) == 0x34
673 	   || (insn & 0xfc) == 0x38
674 	   || (insn & 0xff) == 0xde
675 	   || (insn & 0xff) == 0xdf
676 	   || (insn & 0xff) == 0xf9
677 	   || (insn & 0xff) == 0xcc)
678     {
679       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
680       if (status != 0)
681 	{
682 	  (*info->memory_error_func) (status, memaddr, info);
683 	  return -1;
684 	}
685       insn = bfd_getb16 (buffer);
686       insn <<= 8;
687       status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
688       if (status != 0)
689 	{
690 	  (*info->memory_error_func) (status, memaddr, info);
691 	  return -1;
692 	}
693       insn |= *(unsigned char *) buffer;
694       consume = 3;
695     }
696 
697   /* These are four byte insns.  */
698   else if ((insn & 0xff) == 0xfa
699 	   || (insn & 0xff) == 0xf7
700 	   || (insn & 0xff) == 0xfb)
701     {
702       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
703       if (status != 0)
704 	{
705 	  (*info->memory_error_func) (status, memaddr, info);
706 	  return -1;
707 	}
708       insn = bfd_getb32 (buffer);
709       consume = 4;
710     }
711 
712   /* These are five byte insns.  */
713   else if ((insn & 0xff) == 0xcd
714 	   || (insn & 0xff) == 0xdc)
715     {
716       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
717       if (status != 0)
718 	{
719 	  (*info->memory_error_func) (status, memaddr, info);
720 	  return -1;
721 	}
722       insn = bfd_getb32 (buffer);
723       consume = 5;
724     }
725 
726   /* These are six byte insns.  */
727   else if ((insn & 0xff) == 0xfd
728 	   || (insn & 0xff) == 0xfc)
729     {
730       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
731       if (status != 0)
732 	{
733 	  (*info->memory_error_func) (status, memaddr, info);
734 	  return -1;
735 	}
736 
737       insn = bfd_getb32 (buffer);
738       consume = 6;
739     }
740 
741   /* Else its a seven byte insns (in theory).  */
742   else
743     {
744       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
745       if (status != 0)
746 	{
747 	  (*info->memory_error_func) (status, memaddr, info);
748 	  return -1;
749 	}
750 
751       insn = bfd_getb32 (buffer);
752       consume = 7;
753       /* Handle the 5-byte extended instruction codes.  */
754       if ((insn & 0xfff80000) == 0xfe800000)
755 	consume = 5;
756     }
757 
758   disassemble (memaddr, info, insn, consume);
759 
760   return consume;
761 }
762