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