1/* Disassemble MN10300 instructions.
2   Copyright (C) 1996-2017 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
31static void
32disassemble (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
583int
584print_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