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