xref: /netbsd-src/external/gpl3/binutils.old/dist/opcodes/m10300-dis.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
1 /* Disassemble MN10300 instructions.
2    Copyright (C) 1996-2022 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 "disassemble.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_DREG) != 0
322 		  || (operand->flags & MN10300_OPERAND_AREG) != 0
323 		  || (operand->flags & MN10300_OPERAND_RREG) != 0
324 		  || (operand->flags & MN10300_OPERAND_XRREG) != 0)
325 		value = ((insn >> (operand->shift + extra_shift))
326 			 & ((1 << operand->bits) - 1));
327 	      else if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
328 		{
329 		  unsigned long temp;
330 
331 		  value = insn & ((1 << operand->bits) - 1);
332 		  value <<= (32 - operand->bits);
333 		  temp = extension >> operand->shift;
334 		  temp &= ((1 << (32 - operand->bits)) - 1);
335 		  value |= temp;
336 		  value = ((value ^ (((unsigned long) 1) << 31))
337 			   - (((unsigned long) 1) << 31));
338 		}
339 	      else if ((operand->flags & MN10300_OPERAND_24BIT) != 0)
340 		{
341 		  unsigned long temp;
342 
343 		  value = insn & ((1 << operand->bits) - 1);
344 		  value <<= (24 - operand->bits);
345 		  temp = extension >> operand->shift;
346 		  temp &= ((1 << (24 - operand->bits)) - 1);
347 		  value |= temp;
348 		  if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
349 		    value = ((value & 0xffffff) ^ 0x800000) - 0x800000;
350 		}
351 	      else if ((operand->flags & (MN10300_OPERAND_FSREG
352 					  | MN10300_OPERAND_FDREG)))
353 		{
354 		  /* See m10300-opc.c just before #define FSM0 for an
355 		     explanation of these variables.  Note that
356 		     FMT-implied shifts are not taken into account for
357 		     FP registers.  */
358 		  unsigned long mask_low, mask_high;
359 		  int shl_low, shr_high, shl_high;
360 
361 		  switch (operand->bits)
362 		    {
363 		    case 5:
364 		      /* Handle regular FP registers.  */
365 		      if (operand->shift >= 0)
366 			{
367 			  /* This is an `m' register.  */
368 			  shl_low = operand->shift;
369 			  shl_high = 8 + (8 & shl_low) + (shl_low & 4) / 4;
370 			}
371 		      else
372 			{
373 			  /* This is an `n' register.  */
374 			  shl_low = -operand->shift;
375 			  shl_high = shl_low / 4;
376 			}
377 		      mask_low = 0x0f;
378 		      mask_high = 0x10;
379 		      shr_high = 4;
380 		      break;
381 
382 		    case 3:
383 		      /* Handle accumulators.  */
384 		      shl_low = -operand->shift;
385 		      shl_high = 0;
386 		      mask_low = 0x03;
387 		      mask_high = 0x04;
388 		      shr_high = 2;
389 		      break;
390 
391 		    default:
392 		      abort ();
393 		    }
394 		  value = ((((insn >> shl_high) << shr_high) & mask_high)
395 			   | ((insn >> shl_low) & mask_low));
396 		}
397 	      else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
398 		value = ((extension >> (operand->shift))
399 			 & ((1 << operand->bits) - 1));
400 
401 	      else
402 		value = ((insn >> (operand->shift))
403 			 & ((1 << operand->bits) - 1));
404 
405 	      if ((operand->flags & MN10300_OPERAND_SIGNED) != 0
406 		  /* These are properly extended by the code above.  */
407 		  && ((operand->flags & MN10300_OPERAND_24BIT) == 0))
408 		value = ((value ^ (((unsigned long) 1) << (operand->bits - 1)))
409 			 - (((unsigned long) 1) << (operand->bits - 1)));
410 
411 	      if (!nocomma
412 		  && (!paren
413 		      || ((operand->flags & MN10300_OPERAND_PAREN) == 0)))
414 		(*info->fprintf_func) (info->stream, ",");
415 
416 	      nocomma = 0;
417 
418 	      if ((operand->flags & MN10300_OPERAND_DREG) != 0)
419 		(*info->fprintf_func) (info->stream, "d%d", (int) value);
420 
421 	      else if ((operand->flags & MN10300_OPERAND_AREG) != 0)
422 		(*info->fprintf_func) (info->stream, "a%d", (int) value);
423 
424 	      else if ((operand->flags & MN10300_OPERAND_SP) != 0)
425 		(*info->fprintf_func) (info->stream, "sp");
426 
427 	      else if ((operand->flags & MN10300_OPERAND_PSW) != 0)
428 		(*info->fprintf_func) (info->stream, "psw");
429 
430 	      else if ((operand->flags & MN10300_OPERAND_MDR) != 0)
431 		(*info->fprintf_func) (info->stream, "mdr");
432 
433 	      else if ((operand->flags & MN10300_OPERAND_RREG) != 0)
434 		{
435 		  if (value < 8)
436 		    (*info->fprintf_func) (info->stream, "r%d", (int) value);
437 		  else if (value < 12)
438 		    (*info->fprintf_func) (info->stream, "a%d", (int) value - 8);
439 		  else
440 		    (*info->fprintf_func) (info->stream, "d%d", (int) value - 12);
441 		}
442 
443 	      else if ((operand->flags & MN10300_OPERAND_XRREG) != 0)
444 		{
445 		  if (value == 0)
446 		    (*info->fprintf_func) (info->stream, "sp");
447 		  else
448 		    (*info->fprintf_func) (info->stream, "xr%d", (int) value);
449 		}
450 
451 	      else if ((operand->flags & MN10300_OPERAND_FSREG) != 0)
452 		(*info->fprintf_func) (info->stream, "fs%d", (int) value);
453 
454 	      else if ((operand->flags & MN10300_OPERAND_FDREG) != 0)
455 		(*info->fprintf_func) (info->stream, "fd%d", (int) value);
456 
457 	      else if ((operand->flags & MN10300_OPERAND_FPCR) != 0)
458 		(*info->fprintf_func) (info->stream, "fpcr");
459 
460 	      else if ((operand->flags & MN10300_OPERAND_USP) != 0)
461 		(*info->fprintf_func) (info->stream, "usp");
462 
463 	      else if ((operand->flags & MN10300_OPERAND_SSP) != 0)
464 		(*info->fprintf_func) (info->stream, "ssp");
465 
466 	      else if ((operand->flags & MN10300_OPERAND_MSP) != 0)
467 		(*info->fprintf_func) (info->stream, "msp");
468 
469 	      else if ((operand->flags & MN10300_OPERAND_PC) != 0)
470 		(*info->fprintf_func) (info->stream, "pc");
471 
472 	      else if ((operand->flags & MN10300_OPERAND_EPSW) != 0)
473 		(*info->fprintf_func) (info->stream, "epsw");
474 
475 	      else if ((operand->flags & MN10300_OPERAND_PLUS) != 0)
476 		(*info->fprintf_func) (info->stream, "+");
477 
478 	      else if ((operand->flags & MN10300_OPERAND_PAREN) != 0)
479 		{
480 		  if (paren)
481 		    (*info->fprintf_func) (info->stream, ")");
482 		  else
483 		    {
484 		      (*info->fprintf_func) (info->stream, "(");
485 		      nocomma = 1;
486 		    }
487 		  paren = !paren;
488 		}
489 
490 	      else if ((operand->flags & MN10300_OPERAND_PCREL) != 0)
491 		(*info->print_address_func) ((long) value + memaddr, info);
492 
493 	      else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0)
494 		(*info->print_address_func) (value, info);
495 
496 	      else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0)
497 		{
498 		  int comma = 0;
499 
500 		  (*info->fprintf_func) (info->stream, "[");
501 		  if (value & 0x80)
502 		    {
503 		      (*info->fprintf_func) (info->stream, "d2");
504 		      comma = 1;
505 		    }
506 
507 		  if (value & 0x40)
508 		    {
509 		      if (comma)
510 			(*info->fprintf_func) (info->stream, ",");
511 		      (*info->fprintf_func) (info->stream, "d3");
512 		      comma = 1;
513 		    }
514 
515 		  if (value & 0x20)
516 		    {
517 		      if (comma)
518 			(*info->fprintf_func) (info->stream, ",");
519 		      (*info->fprintf_func) (info->stream, "a2");
520 		      comma = 1;
521 		    }
522 
523 		  if (value & 0x10)
524 		    {
525 		      if (comma)
526 			(*info->fprintf_func) (info->stream, ",");
527 		      (*info->fprintf_func) (info->stream, "a3");
528 		      comma = 1;
529 		    }
530 
531 		  if (value & 0x08)
532 		    {
533 		      if (comma)
534 			(*info->fprintf_func) (info->stream, ",");
535 		      (*info->fprintf_func) (info->stream, "other");
536 		      comma = 1;
537 		    }
538 
539 		  if (value & 0x04)
540 		    {
541 		      if (comma)
542 			(*info->fprintf_func) (info->stream, ",");
543 		      (*info->fprintf_func) (info->stream, "exreg0");
544 		      comma = 1;
545 		    }
546 		  if (value & 0x02)
547 		    {
548 		      if (comma)
549 			(*info->fprintf_func) (info->stream, ",");
550 		      (*info->fprintf_func) (info->stream, "exreg1");
551 		      comma = 1;
552 		    }
553 		  if (value & 0x01)
554 		    {
555 		      if (comma)
556 			(*info->fprintf_func) (info->stream, ",");
557 		      (*info->fprintf_func) (info->stream, "exother");
558 		      comma = 1;
559 		    }
560 		  (*info->fprintf_func) (info->stream, "]");
561 		}
562 
563 	      else
564 		(*info->fprintf_func) (info->stream, "%ld", (long) value);
565 	    }
566 	  /* All done. */
567 	  break;
568 	}
569       op++;
570     }
571 
572   if (!match)
573     /* xgettext:c-format */
574     (*info->fprintf_func) (info->stream, _("unknown\t0x%04lx"), insn);
575 }
576 
577 int
print_insn_mn10300(bfd_vma memaddr,struct disassemble_info * info)578 print_insn_mn10300 (bfd_vma memaddr, struct disassemble_info *info)
579 {
580   int status;
581   bfd_byte buffer[4];
582   unsigned long insn;
583   unsigned int consume;
584 
585   /* First figure out how big the opcode is.  */
586   status = (*info->read_memory_func) (memaddr, buffer, 1, info);
587   if (status != 0)
588     {
589       (*info->memory_error_func) (status, memaddr, info);
590       return -1;
591     }
592   insn = *(unsigned char *) buffer;
593 
594   /* These are one byte insns.  */
595   if ((insn & 0xf3) == 0x00
596       || (insn & 0xf0) == 0x10
597       || (insn & 0xfc) == 0x3c
598       || (insn & 0xf3) == 0x41
599       || (insn & 0xf3) == 0x40
600       || (insn & 0xfc) == 0x50
601       || (insn & 0xfc) == 0x54
602       || (insn & 0xf0) == 0x60
603       || (insn & 0xf0) == 0x70
604       || ((insn & 0xf0) == 0x80
605 	  && (insn & 0x0c) >> 2 != (insn & 0x03))
606       || ((insn & 0xf0) == 0x90
607 	  && (insn & 0x0c) >> 2 != (insn & 0x03))
608       || ((insn & 0xf0) == 0xa0
609 	  && (insn & 0x0c) >> 2 != (insn & 0x03))
610       || ((insn & 0xf0) == 0xb0
611 	  && (insn & 0x0c) >> 2 != (insn & 0x03))
612       || (insn & 0xff) == 0xcb
613       || (insn & 0xfc) == 0xd0
614       || (insn & 0xfc) == 0xd4
615       || (insn & 0xfc) == 0xd8
616       || (insn & 0xf0) == 0xe0
617       || (insn & 0xff) == 0xff)
618     {
619       consume = 1;
620     }
621 
622   /* These are two byte insns.  */
623   else if ((insn & 0xf0) == 0x80
624 	   || (insn & 0xf0) == 0x90
625 	   || (insn & 0xf0) == 0xa0
626 	   || (insn & 0xf0) == 0xb0
627 	   || (insn & 0xfc) == 0x20
628 	   || (insn & 0xfc) == 0x28
629 	   || (insn & 0xf3) == 0x43
630 	   || (insn & 0xf3) == 0x42
631 	   || (insn & 0xfc) == 0x58
632 	   || (insn & 0xfc) == 0x5c
633 	   || ((insn & 0xf0) == 0xc0
634 	       && (insn & 0xff) != 0xcb
635 	       && (insn & 0xff) != 0xcc
636 	       && (insn & 0xff) != 0xcd)
637 	   || (insn & 0xff) == 0xf0
638 	   || (insn & 0xff) == 0xf1
639 	   || (insn & 0xff) == 0xf2
640 	   || (insn & 0xff) == 0xf3
641 	   || (insn & 0xff) == 0xf4
642 	   || (insn & 0xff) == 0xf5
643 	   || (insn & 0xff) == 0xf6)
644     {
645       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
646       if (status != 0)
647 	{
648 	  (*info->memory_error_func) (status, memaddr, info);
649 	  return -1;
650 	}
651       insn = bfd_getb16 (buffer);
652       consume = 2;
653     }
654 
655   /* These are three byte insns.  */
656   else if ((insn & 0xff) == 0xf8
657 	   || (insn & 0xff) == 0xcc
658 	   || (insn & 0xff) == 0xf9
659 	   || (insn & 0xf3) == 0x01
660 	   || (insn & 0xf3) == 0x02
661 	   || (insn & 0xf3) == 0x03
662 	   || (insn & 0xfc) == 0x24
663 	   || (insn & 0xfc) == 0x2c
664 	   || (insn & 0xfc) == 0x30
665 	   || (insn & 0xfc) == 0x34
666 	   || (insn & 0xfc) == 0x38
667 	   || (insn & 0xff) == 0xde
668 	   || (insn & 0xff) == 0xdf
669 	   || (insn & 0xff) == 0xf9
670 	   || (insn & 0xff) == 0xcc)
671     {
672       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
673       if (status != 0)
674 	{
675 	  (*info->memory_error_func) (status, memaddr, info);
676 	  return -1;
677 	}
678       insn = bfd_getb16 (buffer);
679       insn <<= 8;
680       status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
681       if (status != 0)
682 	{
683 	  (*info->memory_error_func) (status, memaddr, info);
684 	  return -1;
685 	}
686       insn |= *(unsigned char *) buffer;
687       consume = 3;
688     }
689 
690   /* These are four byte insns.  */
691   else if ((insn & 0xff) == 0xfa
692 	   || (insn & 0xff) == 0xf7
693 	   || (insn & 0xff) == 0xfb)
694     {
695       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
696       if (status != 0)
697 	{
698 	  (*info->memory_error_func) (status, memaddr, info);
699 	  return -1;
700 	}
701       insn = bfd_getb32 (buffer);
702       consume = 4;
703     }
704 
705   /* These are five byte insns.  */
706   else if ((insn & 0xff) == 0xcd
707 	   || (insn & 0xff) == 0xdc)
708     {
709       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
710       if (status != 0)
711 	{
712 	  (*info->memory_error_func) (status, memaddr, info);
713 	  return -1;
714 	}
715       insn = bfd_getb32 (buffer);
716       consume = 5;
717     }
718 
719   /* These are six byte insns.  */
720   else if ((insn & 0xff) == 0xfd
721 	   || (insn & 0xff) == 0xfc)
722     {
723       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
724       if (status != 0)
725 	{
726 	  (*info->memory_error_func) (status, memaddr, info);
727 	  return -1;
728 	}
729 
730       insn = bfd_getb32 (buffer);
731       consume = 6;
732     }
733 
734   /* Else its a seven byte insns (in theory).  */
735   else
736     {
737       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
738       if (status != 0)
739 	{
740 	  (*info->memory_error_func) (status, memaddr, info);
741 	  return -1;
742 	}
743 
744       insn = bfd_getb32 (buffer);
745       consume = 7;
746       /* Handle the 5-byte extended instruction codes.  */
747       if ((insn & 0xfff80000) == 0xfe800000)
748 	consume = 5;
749     }
750 
751   disassemble (memaddr, info, insn, consume);
752 
753   return consume;
754 }
755