xref: /netbsd-src/external/gpl3/gdb/dist/opcodes/v850-dis.c (revision 413d532bcc3f62d122e56d92e13ac64825a40baf)
1 /* Disassemble V850 instructions.
2    Copyright 1996-2013 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 
22 #include "sysdep.h"
23 #include <stdio.h>
24 #include <string.h>
25 #include "opcode/v850.h"
26 #include "dis-asm.h"
27 #include "opintl.h"
28 
29 static const char *const v850_reg_names[] =
30 {
31   "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7",
32   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
33   "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
34   "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp"
35 };
36 
37 static const char *const v850_sreg_names[] =
38 {
39   "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid",
40   "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0",
41   "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau",
42   "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u",
43   "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l",
44   "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l",
45   "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u",
46   "fewr", "dbwr", "bsel"
47 };
48 
49 static const char *const v850_cc_names[] =
50 {
51   "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
52   "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt"
53 };
54 
55 static const char *const v850_float_cc_names[] =
56 {
57   "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt",
58   "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt"
59 };
60 
61 
62 static const char *const v850_vreg_names[] =
63 {
64   "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", "vr8", "vr9",
65   "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", "vr16", "vr17", "vr18",
66   "vr19", "vr20", "vr21", "vr22", "vr23", "vr24", "vr25", "vr26", "vr27",
67   "vr28", "vr29", "vr30", "vr31"
68 };
69 
70 static const char *const v850_cacheop_names[] =
71 {
72   "chbii", "cibii", "cfali", "cisti", "cildi", "chbid", "chbiwbd",
73   "chbwbd", "cibid", "cibiwbd", "cibwbd", "cfald", "cistd", "cildd"
74 };
75 
76 static const int const v850_cacheop_codes[] =
77 {
78   0x00, 0x20, 0x40, 0x60, 0x61, 0x04, 0x06,
79   0x07, 0x24, 0x26, 0x27, 0x44, 0x64, 0x65, -1
80 };
81 
82 static const char *const v850_prefop_names[] =
83 { "prefi", "prefd" };
84 
85 static const int const v850_prefop_codes[] =
86 { 0x00, 0x04, -1};
87 
88 static void
89 print_value (int flags,
90 	     bfd_vma memaddr,
91 	     struct disassemble_info *info,
92 	     long value)
93 {
94   if (flags & V850_PCREL)
95     {
96       bfd_vma addr = value + memaddr;
97       info->print_address_func (addr, info);
98     }
99   else if (flags & V850_OPERAND_DISP)
100     {
101       if (flags & V850_OPERAND_SIGNED)
102         {
103           info->fprintf_func (info->stream, "%ld", value);
104         }
105       else
106         {
107           info->fprintf_func (info->stream, "%lu", value);
108         }
109     }
110   else if ((flags & V850E_IMMEDIATE32)
111 	   || (flags & V850E_IMMEDIATE16HI))
112     {
113       info->fprintf_func (info->stream, "0x%lx", value);
114     }
115   else
116     {
117       if (flags & V850_OPERAND_SIGNED)
118 	{
119 	  info->fprintf_func (info->stream, "%ld", value);
120 	}
121       else
122 	{
123 	  info->fprintf_func (info->stream, "%lu", value);
124 	}
125     }
126 }
127 
128 static long
129 get_operand_value (const struct v850_operand *operand,
130 		   unsigned long insn,
131 		   int bytes_read,
132 		   bfd_vma memaddr,
133 		   struct disassemble_info * info,
134 		   bfd_boolean noerror,
135 		   int *invalid)
136 {
137   long value;
138   bfd_byte buffer[4];
139 
140   if ((operand->flags & V850E_IMMEDIATE16)
141       || (operand->flags & V850E_IMMEDIATE16HI))
142     {
143       int status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info);
144 
145       if (status == 0)
146 	{
147 	  value = bfd_getl16 (buffer);
148 
149 	  if (operand->flags & V850E_IMMEDIATE16HI)
150 	    value <<= 16;
151 	  else if (value & 0x8000)
152 	    value |= (-1L << 16);
153 
154 	  return value;
155 	}
156 
157       if (!noerror)
158 	info->memory_error_func (status, memaddr + bytes_read, info);
159 
160       return 0;
161     }
162 
163   if (operand->flags & V850E_IMMEDIATE23)
164     {
165       int status = info->read_memory_func (memaddr + 2, buffer, 4, info);
166 
167       if (status == 0)
168 	{
169 	  value = bfd_getl32 (buffer);
170 
171 	  value = (operand->extract) (value, invalid);
172 
173 	  return value;
174 	}
175 
176       if (!noerror)
177 	info->memory_error_func (status, memaddr + bytes_read, info);
178 
179       return 0;
180     }
181 
182   if (operand->flags & V850E_IMMEDIATE32)
183     {
184       int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info);
185 
186       if (status == 0)
187 	{
188 	  bytes_read += 4;
189 	  value = bfd_getl32 (buffer);
190 
191 	  return value;
192 	}
193 
194       if (!noerror)
195 	info->memory_error_func (status, memaddr + bytes_read, info);
196 
197       return 0;
198     }
199 
200   if (operand->extract)
201     value = (operand->extract) (insn, invalid);
202   else
203     {
204       if (operand->bits == -1)
205 	value = (insn & operand->shift);
206       else
207 	value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
208 
209       if (operand->flags & V850_OPERAND_SIGNED)
210 	value = ((long)(value << (sizeof (long)*8 - operand->bits))
211 		 >> (sizeof (long)*8 - operand->bits));
212     }
213 
214   return value;
215 }
216 
217 
218 static int
219 disassemble (bfd_vma memaddr,
220 	     struct disassemble_info *info,
221 	     int bytes_read,
222 	     unsigned long insn)
223 {
224   struct v850_opcode *op = (struct v850_opcode *) v850_opcodes;
225   const struct v850_operand *operand;
226   int match = 0;
227   int target_processor;
228 
229   switch (info->mach)
230     {
231     case 0:
232     default:
233       target_processor = PROCESSOR_V850;
234       break;
235 
236     case bfd_mach_v850e:
237       target_processor = PROCESSOR_V850E;
238       break;
239 
240     case bfd_mach_v850e1:
241       target_processor = PROCESSOR_V850E;
242       break;
243 
244     case bfd_mach_v850e2:
245       target_processor = PROCESSOR_V850E2;
246       break;
247 
248     case bfd_mach_v850e2v3:
249       target_processor = PROCESSOR_V850E2V3;
250       break;
251 
252     case bfd_mach_v850e3v5:
253       target_processor = PROCESSOR_V850E3V5;
254       break;
255     }
256 
257   /* If this is a two byte insn, then mask off the high bits.  */
258   if (bytes_read == 2)
259     insn &= 0xffff;
260 
261   /* Find the opcode.  */
262   while (op->name)
263     {
264       if ((op->mask & insn) == op->opcode
265 	  && (op->processors & target_processor)
266 	  && !(op->processors & PROCESSOR_OPTION_ALIAS))
267 	{
268 	  /* Code check start.  */
269 	  const unsigned char *opindex_ptr;
270 	  unsigned int opnum;
271 	  unsigned int memop;
272 
273 	  for (opindex_ptr = op->operands, opnum = 1;
274 	       *opindex_ptr != 0;
275 	       opindex_ptr++, opnum++)
276 	    {
277 	      int invalid = 0;
278 	      long value;
279 
280 	      operand = &v850_operands[*opindex_ptr];
281 
282 	      value = get_operand_value (operand, insn, bytes_read, memaddr,
283 					 info, 1, &invalid);
284 
285 	      if (invalid)
286 		goto next_opcode;
287 
288               if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2)
289 		goto next_opcode;
290 
291 	      if ((operand->flags & V850_NOT_SA) && value == 0xd)
292 		goto next_opcode;
293 
294 	      if ((operand->flags & V850_NOT_IMM0) && value == 0)
295 		goto next_opcode;
296 	    }
297 
298 	  /* Code check end.  */
299 
300 	  match = 1;
301 	  (*info->fprintf_func) (info->stream, "%s\t", op->name);
302 #if 0
303 	  fprintf (stderr, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n",
304 		   insn, op->mask, op->opcode, op->name );
305 #endif
306 
307 	  memop = op->memop;
308 	  /* Now print the operands.
309 
310 	     MEMOP is the operand number at which a memory
311 	     address specification starts, or zero if this
312 	     instruction has no memory addresses.
313 
314 	     A memory address is always two arguments.
315 
316 	     This information allows us to determine when to
317 	     insert commas into the output stream as well as
318 	     when to insert disp[reg] expressions onto the
319 	     output stream.  */
320 
321 	  for (opindex_ptr = op->operands, opnum = 1;
322 	       *opindex_ptr != 0;
323 	       opindex_ptr++, opnum++)
324 	    {
325 	      bfd_boolean square = FALSE;
326 	      long value;
327 	      int flag;
328 	      char *prefix;
329 
330 	      operand = &v850_operands[*opindex_ptr];
331 
332 	      value = get_operand_value (operand, insn, bytes_read, memaddr,
333 					 info, 0, 0);
334 
335 	      /* The first operand is always output without any
336 		 special handling.
337 
338 		 For the following arguments:
339 
340 		   If memop && opnum == memop + 1, then we need '[' since
341 		   we're about to output the register used in a memory
342 		   reference.
343 
344 		   If memop && opnum == memop + 2, then we need ']' since
345 		   we just finished the register in a memory reference.  We
346 		   also need a ',' before this operand.
347 
348 		   Else we just need a comma.
349 
350 		   We may need to output a trailing ']' if the last operand
351 		   in an instruction is the register for a memory address.
352 
353 		   The exception (and there's always an exception) are the
354 		   "jmp" insn which needs square brackets around it's only
355 		   register argument, and the clr1/not1/set1/tst1 insns
356 		   which [...] around their second register argument.  */
357 
358 	      prefix = "";
359 	      if (operand->flags & V850_OPERAND_BANG)
360 		{
361 		  prefix = "!";
362 		}
363 	      else if (operand->flags & V850_OPERAND_PERCENT)
364 		{
365 		  prefix = "%";
366 		}
367 
368 	      if (opnum == 1 && opnum == memop)
369 		{
370 		  info->fprintf_func (info->stream, "%s[", prefix);
371 		  square = TRUE;
372 		}
373 	      else if (   (strcmp ("stc.w", op->name) == 0
374 			|| strcmp ("cache", op->name) == 0
375 			|| strcmp ("pref",  op->name) == 0)
376 		       && opnum == 2 && opnum == memop)
377 		{
378 		  info->fprintf_func (info->stream, ", [");
379 		  square = TRUE;
380 		}
381 	      else if (   (strcmp (op->name, "pushsp") == 0
382 			|| strcmp (op->name, "popsp") == 0
383 			|| strcmp (op->name, "dbpush" ) == 0)
384 		       && opnum == 2)
385 		{
386 		  info->fprintf_func (info->stream, "-");
387 		}
388 	      else if (opnum > 1
389 		       && (v850_operands[*(opindex_ptr - 1)].flags
390 			   & V850_OPERAND_DISP) != 0
391 		       && opnum == memop)
392 		{
393 		  info->fprintf_func (info->stream, "%s[", prefix);
394 		  square = TRUE;
395 		}
396 	      else if (opnum == 2
397 		       && (   op->opcode == 0x00e407e0 /* clr1 */
398 			   || op->opcode == 0x00e207e0 /* not1 */
399 			   || op->opcode == 0x00e007e0 /* set1 */
400 			   || op->opcode == 0x00e607e0 /* tst1 */
401 			   ))
402 		{
403 		  info->fprintf_func (info->stream, ", %s[", prefix);
404 		  square = TRUE;
405 		}
406 	      else if (opnum > 1)
407 		info->fprintf_func (info->stream, ", %s", prefix);
408 
409  	      /* Extract the flags, ignoring ones which do not
410 		 effect disassembly output.  */
411 	      flag = operand->flags & (V850_OPERAND_REG
412 				       | V850_REG_EVEN
413 				       | V850_OPERAND_EP
414 				       | V850_OPERAND_SRG
415 				       | V850E_OPERAND_REG_LIST
416 				       | V850_OPERAND_CC
417 				       | V850_OPERAND_VREG
418 				       | V850_OPERAND_CACHEOP
419 				       | V850_OPERAND_PREFOP
420 				       | V850_OPERAND_FLOAT_CC);
421 
422 	      switch (flag)
423 		{
424 		case V850_OPERAND_REG:
425 		  info->fprintf_func (info->stream, "%s", v850_reg_names[value]);
426 		  break;
427 		case (V850_OPERAND_REG|V850_REG_EVEN):
428 		  info->fprintf_func (info->stream, "%s", v850_reg_names[value * 2]);
429 		  break;
430 		case V850_OPERAND_EP:
431 		  info->fprintf_func (info->stream, "ep");
432 		  break;
433 		case V850_OPERAND_SRG:
434 		  info->fprintf_func (info->stream, "%s", v850_sreg_names[value]);
435 		  break;
436 		case V850E_OPERAND_REG_LIST:
437 		  {
438 		    static int list12_regs[32]   = { 30, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
439 						     0,  0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
440 		    int *regs;
441 		    int i;
442 		    unsigned long int mask = 0;
443 		    int pc = 0;
444 
445 		    switch (operand->shift)
446 		      {
447 		      case 0xffe00001: regs = list12_regs; break;
448 		      default:
449 			/* xgettext:c-format */
450 			fprintf (stderr, _("unknown operand shift: %x\n"), operand->shift);
451 			abort ();
452 		      }
453 
454 		    for (i = 0; i < 32; i++)
455 		      {
456 			if (value & (1 << i))
457 			  {
458 			    switch (regs[ i ])
459 			      {
460 			      default: mask |= (1 << regs[ i ]); break;
461 				/* xgettext:c-format */
462 			      case 0:  fprintf (stderr, _("unknown reg: %d\n"), i ); abort ();
463 			      case -1: pc = 1; break;
464 			      }
465 			  }
466 		      }
467 
468 		    info->fprintf_func (info->stream, "{");
469 
470 		    if (mask || pc)
471 		      {
472 			if (mask)
473 			  {
474 			    unsigned int bit;
475 			    int shown_one = 0;
476 
477 			    for (bit = 0; bit < 32; bit++)
478 			      if (mask & (1 << bit))
479 				{
480 				  unsigned long int first = bit;
481 				  unsigned long int last;
482 
483 				  if (shown_one)
484 				    info->fprintf_func (info->stream, ", ");
485 				  else
486 				    shown_one = 1;
487 
488 				  info->fprintf_func (info->stream, "%s", v850_reg_names[first]);
489 
490 				  for (bit++; bit < 32; bit++)
491 				    if ((mask & (1 << bit)) == 0)
492 				      break;
493 
494 				  last = bit;
495 
496 				  if (last > first + 1)
497 				    {
498 				      info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]);
499 				    }
500 				}
501 			  }
502 
503 			if (pc)
504 			  info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
505 		      }
506 
507 		    info->fprintf_func (info->stream, "}");
508 		  }
509 		  break;
510 
511 		case V850_OPERAND_CC:
512 		  info->fprintf_func (info->stream, "%s", v850_cc_names[value]);
513 		  break;
514 
515 		case V850_OPERAND_FLOAT_CC:
516 		  info->fprintf_func (info->stream, "%s", v850_float_cc_names[value]);
517 		  break;
518 
519 		case V850_OPERAND_CACHEOP:
520 		  {
521 		    int idx;
522 
523 		    for (idx = 0; v850_cacheop_codes[idx] != -1; idx++)
524 		      {
525 			if (value == v850_cacheop_codes[idx])
526 			  {
527 			    info->fprintf_func (info->stream, "%s",
528 						v850_cacheop_names[idx]);
529 			    goto MATCH_CACHEOP_CODE;
530 			  }
531 		      }
532 		    info->fprintf_func (info->stream, "%d", (int) value);
533 		  }
534 		MATCH_CACHEOP_CODE:
535 		  break;
536 
537 		case V850_OPERAND_PREFOP:
538 		  {
539 		    int idx;
540 
541 		    for (idx = 0; v850_prefop_codes[idx] != -1; idx++)
542 		      {
543 			if (value == v850_prefop_codes[idx])
544 			  {
545 			    info->fprintf_func (info->stream, "%s",
546 			      v850_prefop_names[idx]);
547 			    goto MATCH_PREFOP_CODE;
548 			  }
549 		      }
550 		    info->fprintf_func (info->stream, "%d", (int) value);
551 		  }
552 		MATCH_PREFOP_CODE:
553 		  break;
554 
555 		case V850_OPERAND_VREG:
556 		  info->fprintf_func (info->stream, "%s", v850_vreg_names[value]);
557 		  break;
558 
559 		default:
560 		  print_value (operand->flags, memaddr, info, value);
561 		  break;
562 		}
563 
564 	      if (square)
565 		(*info->fprintf_func) (info->stream, "]");
566 	    }
567 
568 	  /* All done. */
569 	  break;
570 	}
571     next_opcode:
572       op++;
573     }
574 
575   return match;
576 }
577 
578 int
579 print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
580 {
581   int status, status2, match;
582   bfd_byte buffer[8];
583   int length = 0, code_length = 0;
584   unsigned long insn = 0, insn2 = 0;
585   int target_processor;
586 
587   switch (info->mach)
588     {
589     case 0:
590     default:
591       target_processor = PROCESSOR_V850;
592       break;
593 
594     case bfd_mach_v850e:
595       target_processor = PROCESSOR_V850E;
596       break;
597 
598     case bfd_mach_v850e1:
599       target_processor = PROCESSOR_V850E;
600       break;
601 
602     case bfd_mach_v850e2:
603       target_processor = PROCESSOR_V850E2;
604       break;
605 
606     case bfd_mach_v850e2v3:
607       target_processor = PROCESSOR_V850E2V3;
608       break;
609 
610     case bfd_mach_v850e3v5:
611       target_processor = PROCESSOR_V850E3V5;
612       break;
613     }
614 
615   status = info->read_memory_func (memaddr, buffer, 2, info);
616 
617   if (status)
618     {
619       info->memory_error_func (status, memaddr, info);
620       return -1;
621     }
622 
623   insn = bfd_getl16 (buffer);
624 
625   status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
626 
627   if (!status2)
628     {
629       insn2 = bfd_getl16 (buffer);
630       /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
631     }
632 
633   /* Special case.  */
634   if (length == 0
635       && ((target_processor & PROCESSOR_V850E2_UP) != 0))
636     {
637       if ((insn & 0xffff) == 0x02e0		/* jr 32bit */
638 	  && !status2 && (insn2 & 0x1) == 0)
639 	{
640 	  length = 2;
641 	  code_length = 6;
642 	}
643       else if ((insn & 0xffe0) == 0x02e0	/* jarl 32bit */
644 	       && !status2 && (insn2 & 0x1) == 0)
645 	{
646 	  length = 2;
647 	  code_length = 6;
648 	}
649       else if ((insn & 0xffe0) == 0x06e0	/* jmp 32bit */
650 	       && !status2 && (insn2 & 0x1) == 0)
651 	{
652 	  length = 2;
653 	  code_length = 6;
654 	}
655     }
656 
657   if (length == 0
658       && ((target_processor & PROCESSOR_V850E3V5_UP) != 0))
659     {
660       if (   ((insn & 0xffe0) == 0x07a0		/* ld.dw 23bit (v850e3v5) */
661 	      && !status2 && (insn2 & 0x000f) == 0x0009)
662 	  || ((insn & 0xffe0) == 0x07a0		/* st.dw 23bit (v850e3v5) */
663 	      && !status2 && (insn2 & 0x000f) == 0x000f))
664 	{
665 	  length = 4;
666 	  code_length = 6;
667 	}
668     }
669 
670   if (length == 0
671       && ((target_processor & PROCESSOR_V850E2V3_UP) != 0))
672     {
673       if (((insn & 0xffe0) == 0x0780		/* ld.b 23bit */
674 	   && !status2 && (insn2 & 0x000f) == 0x0005)
675 	  || ((insn & 0xffe0) == 0x07a0		/* ld.bu 23bit */
676 	      && !status2 && (insn2 & 0x000f) == 0x0005)
677 	  || ((insn & 0xffe0) == 0x0780		/* ld.h 23bit */
678 	      && !status2 && (insn2 & 0x000f) == 0x0007)
679 	  || ((insn & 0xffe0) == 0x07a0		/* ld.hu 23bit */
680 	      && !status2 && (insn2 & 0x000f) == 0x0007)
681 	  || ((insn & 0xffe0) == 0x0780		/* ld.w 23bit */
682 	      && !status2 && (insn2 & 0x000f) == 0x0009))
683 	{
684 	  length = 4;
685 	  code_length = 6;
686 	}
687       else if (((insn & 0xffe0) == 0x0780	/* st.b 23bit */
688 	       && !status2 && (insn2 & 0x000f) == 0x000d)
689 	      || ((insn & 0xffe0) == 0x07a0	/* st.h 23bit */
690 		  && !status2 && (insn2 & 0x000f) == 0x000d)
691 	      || ((insn & 0xffe0) == 0x0780	/* st.w 23bit */
692 		  && !status2 && (insn2 & 0x000f) == 0x000f))
693 	{
694 	  length = 4;
695 	  code_length = 6;
696 	}
697     }
698 
699   if (length == 0
700       && target_processor != PROCESSOR_V850)
701     {
702       if ((insn & 0xffe0) == 0x0620)		/* 32 bit MOV */
703 	{
704 	  length = 2;
705 	  code_length = 6;
706 	}
707       else if ((insn & 0xffc0) == 0x0780	/* prepare {list}, imm5, imm16<<16 */
708 	       && !status2 && (insn2 & 0x001f) == 0x0013)
709 	{
710 	  length = 4;
711 	  code_length = 6;
712 	}
713       else if ((insn & 0xffc0) == 0x0780	/* prepare {list}, imm5, imm16 */
714 	       && !status2 && (insn2 & 0x001f) == 0x000b)
715 	{
716 	  length = 4;
717 	  code_length = 6;
718 	}
719       else if ((insn & 0xffc0) == 0x0780	/* prepare {list}, imm5, imm32 */
720 	       && !status2 && (insn2 & 0x001f) == 0x001b)
721 	{
722 	  length = 4;
723 	  code_length = 8;
724 	}
725     }
726 
727   if (length == 4
728       || (length == 0
729 	  && (insn & 0x0600) == 0x0600))
730     {
731       /* This is a 4 byte insn.  */
732       status = info->read_memory_func (memaddr, buffer, 4, info);
733       if (!status)
734 	{
735 	  insn = bfd_getl32 (buffer);
736 
737 	  if (!length)
738 	    length = code_length = 4;
739 	}
740     }
741 
742   if (code_length > length)
743     {
744       status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
745       if (status)
746 	length = 0;
747     }
748 
749   if (length == 0 && !status)
750     length = code_length = 2;
751 
752   if (length == 2)
753     insn &= 0xffff;
754 
755   /* when the last 2 bytes of section is 0xffff, length will be 0 and cause infinitive loop */
756   if (length == 0)
757     return -1;
758 
759   match = disassemble (memaddr, info, length, insn);
760 
761   if (!match)
762     {
763       int l = 0;
764 
765       status = info->read_memory_func (memaddr, buffer, code_length, info);
766 
767       while (l < code_length)
768 	{
769 	  if (code_length - l == 2)
770 	    {
771 	      insn = bfd_getl16 (buffer + l) & 0xffff;
772 	      info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
773 	      l += 2;
774 	    }
775 	  else
776 	    {
777 	      insn = bfd_getl32 (buffer + l);
778 	      info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
779 	      l += 4;
780 	    }
781 	}
782     }
783 
784   return code_length;
785 }
786