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
33static void
34disassemble (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
585int
586print_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