1 /* Disassemble V850 instructions.
2    Copyright (C) 1996-2016 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 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 v850_prefop_codes[] =
86 { 0x00, 0x04, -1};
87 
88 static void
print_value(int flags,bfd_vma memaddr,struct disassemble_info * info,long value)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 
98       if (flags & V850_INVERSE_PCREL)
99 	addr = memaddr - value;
100       info->print_address_func (addr, info);
101     }
102   else if (flags & V850_OPERAND_DISP)
103     {
104       if (flags & V850_OPERAND_SIGNED)
105         {
106           info->fprintf_func (info->stream, "%ld", value);
107         }
108       else
109         {
110           info->fprintf_func (info->stream, "%lu", value);
111         }
112     }
113   else if ((flags & V850E_IMMEDIATE32)
114 	   || (flags & V850E_IMMEDIATE16HI))
115     {
116       info->fprintf_func (info->stream, "0x%lx", value);
117     }
118   else
119     {
120       if (flags & V850_OPERAND_SIGNED)
121 	{
122 	  info->fprintf_func (info->stream, "%ld", value);
123 	}
124       else
125 	{
126 	  info->fprintf_func (info->stream, "%lu", value);
127 	}
128     }
129 }
130 
131 static long
get_operand_value(const struct v850_operand * operand,unsigned long insn,int bytes_read,bfd_vma memaddr,struct disassemble_info * info,bfd_boolean noerror,int * invalid)132 get_operand_value (const struct v850_operand *operand,
133 		   unsigned long insn,
134 		   int bytes_read,
135 		   bfd_vma memaddr,
136 		   struct disassemble_info * info,
137 		   bfd_boolean noerror,
138 		   int *invalid)
139 {
140   long value;
141   bfd_byte buffer[4];
142 
143   if ((operand->flags & V850E_IMMEDIATE16)
144       || (operand->flags & V850E_IMMEDIATE16HI))
145     {
146       int status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info);
147 
148       if (status == 0)
149 	{
150 	  value = bfd_getl16 (buffer);
151 
152 	  if (operand->flags & V850E_IMMEDIATE16HI)
153 	    value <<= 16;
154 	  else if (value & 0x8000)
155 	    value |= (-1UL << 16);
156 
157 	  return value;
158 	}
159 
160       if (!noerror)
161 	info->memory_error_func (status, memaddr + bytes_read, info);
162 
163       return 0;
164     }
165 
166   if (operand->flags & V850E_IMMEDIATE23)
167     {
168       int status = info->read_memory_func (memaddr + 2, buffer, 4, info);
169 
170       if (status == 0)
171 	{
172 	  value = bfd_getl32 (buffer);
173 
174 	  value = (operand->extract) (value, invalid);
175 
176 	  return value;
177 	}
178 
179       if (!noerror)
180 	info->memory_error_func (status, memaddr + bytes_read, info);
181 
182       return 0;
183     }
184 
185   if (operand->flags & V850E_IMMEDIATE32)
186     {
187       int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info);
188 
189       if (status == 0)
190 	{
191 	  bytes_read += 4;
192 	  value = bfd_getl32 (buffer);
193 
194 	  return value;
195 	}
196 
197       if (!noerror)
198 	info->memory_error_func (status, memaddr + bytes_read, info);
199 
200       return 0;
201     }
202 
203   if (operand->extract)
204     value = (operand->extract) (insn, invalid);
205   else
206     {
207       if (operand->bits == -1)
208 	value = (insn & operand->shift);
209       else
210 	value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
211 
212       if (operand->flags & V850_OPERAND_SIGNED)
213 	value = ((long)(value << (sizeof (long)*8 - operand->bits))
214 		 >> (sizeof (long)*8 - operand->bits));
215     }
216 
217   return value;
218 }
219 
220 
221 static int
disassemble(bfd_vma memaddr,struct disassemble_info * info,int bytes_read,unsigned long insn)222 disassemble (bfd_vma memaddr,
223 	     struct disassemble_info *info,
224 	     int bytes_read,
225 	     unsigned long insn)
226 {
227   struct v850_opcode *op = (struct v850_opcode *) v850_opcodes;
228   const struct v850_operand *operand;
229   int match = 0;
230   int target_processor;
231 
232   switch (info->mach)
233     {
234     case 0:
235     default:
236       target_processor = PROCESSOR_V850;
237       break;
238 
239     case bfd_mach_v850e:
240       target_processor = PROCESSOR_V850E;
241       break;
242 
243     case bfd_mach_v850e1:
244       target_processor = PROCESSOR_V850E;
245       break;
246 
247     case bfd_mach_v850e2:
248       target_processor = PROCESSOR_V850E2;
249       break;
250 
251     case bfd_mach_v850e2v3:
252       target_processor = PROCESSOR_V850E2V3;
253       break;
254 
255     case bfd_mach_v850e3v5:
256       target_processor = PROCESSOR_V850E3V5;
257       break;
258     }
259 
260   /* If this is a two byte insn, then mask off the high bits.  */
261   if (bytes_read == 2)
262     insn &= 0xffff;
263 
264   /* Find the opcode.  */
265   while (op->name)
266     {
267       if ((op->mask & insn) == op->opcode
268 	  && (op->processors & target_processor)
269 	  && !(op->processors & PROCESSOR_OPTION_ALIAS))
270 	{
271 	  /* Code check start.  */
272 	  const unsigned char *opindex_ptr;
273 	  unsigned int opnum;
274 	  unsigned int memop;
275 
276 	  for (opindex_ptr = op->operands, opnum = 1;
277 	       *opindex_ptr != 0;
278 	       opindex_ptr++, opnum++)
279 	    {
280 	      int invalid = 0;
281 	      long value;
282 
283 	      operand = &v850_operands[*opindex_ptr];
284 
285 	      value = get_operand_value (operand, insn, bytes_read, memaddr,
286 					 info, 1, &invalid);
287 
288 	      if (invalid)
289 		goto next_opcode;
290 
291               if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2)
292 		goto next_opcode;
293 
294 	      if ((operand->flags & V850_NOT_SA) && value == 0xd)
295 		goto next_opcode;
296 
297 	      if ((operand->flags & V850_NOT_IMM0) && value == 0)
298 		goto next_opcode;
299 	    }
300 
301 	  /* Code check end.  */
302 
303 	  match = 1;
304 	  (*info->fprintf_func) (info->stream, "%s\t", op->name);
305 #if 0
306 	  fprintf (stderr, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n",
307 		   insn, op->mask, op->opcode, op->name );
308 #endif
309 
310 	  memop = op->memop;
311 	  /* Now print the operands.
312 
313 	     MEMOP is the operand number at which a memory
314 	     address specification starts, or zero if this
315 	     instruction has no memory addresses.
316 
317 	     A memory address is always two arguments.
318 
319 	     This information allows us to determine when to
320 	     insert commas into the output stream as well as
321 	     when to insert disp[reg] expressions onto the
322 	     output stream.  */
323 
324 	  for (opindex_ptr = op->operands, opnum = 1;
325 	       *opindex_ptr != 0;
326 	       opindex_ptr++, opnum++)
327 	    {
328 	      bfd_boolean square = FALSE;
329 	      long value;
330 	      int flag;
331 	      char *prefix;
332 
333 	      operand = &v850_operands[*opindex_ptr];
334 
335 	      value = get_operand_value (operand, insn, bytes_read, memaddr,
336 					 info, 0, 0);
337 
338 	      /* The first operand is always output without any
339 		 special handling.
340 
341 		 For the following arguments:
342 
343 		   If memop && opnum == memop + 1, then we need '[' since
344 		   we're about to output the register used in a memory
345 		   reference.
346 
347 		   If memop && opnum == memop + 2, then we need ']' since
348 		   we just finished the register in a memory reference.  We
349 		   also need a ',' before this operand.
350 
351 		   Else we just need a comma.
352 
353 		   We may need to output a trailing ']' if the last operand
354 		   in an instruction is the register for a memory address.
355 
356 		   The exception (and there's always an exception) are the
357 		   "jmp" insn which needs square brackets around it's only
358 		   register argument, and the clr1/not1/set1/tst1 insns
359 		   which [...] around their second register argument.  */
360 
361 	      prefix = "";
362 	      if (operand->flags & V850_OPERAND_BANG)
363 		{
364 		  prefix = "!";
365 		}
366 	      else if (operand->flags & V850_OPERAND_PERCENT)
367 		{
368 		  prefix = "%";
369 		}
370 
371 	      if (opnum == 1 && opnum == memop)
372 		{
373 		  info->fprintf_func (info->stream, "%s[", prefix);
374 		  square = TRUE;
375 		}
376 	      else if (   (strcmp ("stc.w", op->name) == 0
377 			|| strcmp ("cache", op->name) == 0
378 			|| strcmp ("pref",  op->name) == 0)
379 		       && opnum == 2 && opnum == memop)
380 		{
381 		  info->fprintf_func (info->stream, ", [");
382 		  square = TRUE;
383 		}
384 	      else if (   (strcmp (op->name, "pushsp") == 0
385 			|| strcmp (op->name, "popsp") == 0
386 			|| strcmp (op->name, "dbpush" ) == 0)
387 		       && opnum == 2)
388 		{
389 		  info->fprintf_func (info->stream, "-");
390 		}
391 	      else if (opnum > 1
392 		       && (v850_operands[*(opindex_ptr - 1)].flags
393 			   & V850_OPERAND_DISP) != 0
394 		       && opnum == memop)
395 		{
396 		  info->fprintf_func (info->stream, "%s[", prefix);
397 		  square = TRUE;
398 		}
399 	      else if (opnum == 2
400 		       && (   op->opcode == 0x00e407e0 /* clr1 */
401 			   || op->opcode == 0x00e207e0 /* not1 */
402 			   || op->opcode == 0x00e007e0 /* set1 */
403 			   || op->opcode == 0x00e607e0 /* tst1 */
404 			   ))
405 		{
406 		  info->fprintf_func (info->stream, ", %s[", prefix);
407 		  square = TRUE;
408 		}
409 	      else if (opnum > 1)
410 		info->fprintf_func (info->stream, ", %s", prefix);
411 
412  	      /* Extract the flags, ignoring ones which do not
413 		 effect disassembly output.  */
414 	      flag = operand->flags & (V850_OPERAND_REG
415 				       | V850_REG_EVEN
416 				       | V850_OPERAND_EP
417 				       | V850_OPERAND_SRG
418 				       | V850E_OPERAND_REG_LIST
419 				       | V850_OPERAND_CC
420 				       | V850_OPERAND_VREG
421 				       | V850_OPERAND_CACHEOP
422 				       | V850_OPERAND_PREFOP
423 				       | V850_OPERAND_FLOAT_CC);
424 
425 	      switch (flag)
426 		{
427 		case V850_OPERAND_REG:
428 		  info->fprintf_func (info->stream, "%s", v850_reg_names[value]);
429 		  break;
430 		case (V850_OPERAND_REG|V850_REG_EVEN):
431 		  info->fprintf_func (info->stream, "%s", v850_reg_names[value * 2]);
432 		  break;
433 		case V850_OPERAND_EP:
434 		  info->fprintf_func (info->stream, "ep");
435 		  break;
436 		case V850_OPERAND_SRG:
437 		  info->fprintf_func (info->stream, "%s", v850_sreg_names[value]);
438 		  break;
439 		case V850E_OPERAND_REG_LIST:
440 		  {
441 		    static int list12_regs[32]   = { 30, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
442 						     0,  0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
443 		    int *regs;
444 		    int i;
445 		    unsigned long int mask = 0;
446 		    int pc = 0;
447 
448 		    switch (operand->shift)
449 		      {
450 		      case 0xffe00001: regs = list12_regs; break;
451 		      default:
452 			/* xgettext:c-format */
453 			fprintf (stderr, _("unknown operand shift: %x\n"), operand->shift);
454 			abort ();
455 		      }
456 
457 		    for (i = 0; i < 32; i++)
458 		      {
459 			if (value & (1 << i))
460 			  {
461 			    switch (regs[ i ])
462 			      {
463 			      default: mask |= (1 << regs[ i ]); break;
464 				/* xgettext:c-format */
465 			      case 0:  fprintf (stderr, _("unknown reg: %d\n"), i ); abort ();
466 			      case -1: pc = 1; break;
467 			      }
468 			  }
469 		      }
470 
471 		    info->fprintf_func (info->stream, "{");
472 
473 		    if (mask || pc)
474 		      {
475 			if (mask)
476 			  {
477 			    unsigned int bit;
478 			    int shown_one = 0;
479 
480 			    for (bit = 0; bit < 32; bit++)
481 			      if (mask & (1 << bit))
482 				{
483 				  unsigned long int first = bit;
484 				  unsigned long int last;
485 
486 				  if (shown_one)
487 				    info->fprintf_func (info->stream, ", ");
488 				  else
489 				    shown_one = 1;
490 
491 				  info->fprintf_func (info->stream, "%s", v850_reg_names[first]);
492 
493 				  for (bit++; bit < 32; bit++)
494 				    if ((mask & (1 << bit)) == 0)
495 				      break;
496 
497 				  last = bit;
498 
499 				  if (last > first + 1)
500 				    {
501 				      info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]);
502 				    }
503 				}
504 			  }
505 
506 			if (pc)
507 			  info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
508 		      }
509 
510 		    info->fprintf_func (info->stream, "}");
511 		  }
512 		  break;
513 
514 		case V850_OPERAND_CC:
515 		  info->fprintf_func (info->stream, "%s", v850_cc_names[value]);
516 		  break;
517 
518 		case V850_OPERAND_FLOAT_CC:
519 		  info->fprintf_func (info->stream, "%s", v850_float_cc_names[value]);
520 		  break;
521 
522 		case V850_OPERAND_CACHEOP:
523 		  {
524 		    int idx;
525 
526 		    for (idx = 0; v850_cacheop_codes[idx] != -1; idx++)
527 		      {
528 			if (value == v850_cacheop_codes[idx])
529 			  {
530 			    info->fprintf_func (info->stream, "%s",
531 						v850_cacheop_names[idx]);
532 			    goto MATCH_CACHEOP_CODE;
533 			  }
534 		      }
535 		    info->fprintf_func (info->stream, "%d", (int) value);
536 		  }
537 		MATCH_CACHEOP_CODE:
538 		  break;
539 
540 		case V850_OPERAND_PREFOP:
541 		  {
542 		    int idx;
543 
544 		    for (idx = 0; v850_prefop_codes[idx] != -1; idx++)
545 		      {
546 			if (value == v850_prefop_codes[idx])
547 			  {
548 			    info->fprintf_func (info->stream, "%s",
549 			      v850_prefop_names[idx]);
550 			    goto MATCH_PREFOP_CODE;
551 			  }
552 		      }
553 		    info->fprintf_func (info->stream, "%d", (int) value);
554 		  }
555 		MATCH_PREFOP_CODE:
556 		  break;
557 
558 		case V850_OPERAND_VREG:
559 		  info->fprintf_func (info->stream, "%s", v850_vreg_names[value]);
560 		  break;
561 
562 		default:
563 		  print_value (operand->flags, memaddr, info, value);
564 		  break;
565 		}
566 
567 	      if (square)
568 		(*info->fprintf_func) (info->stream, "]");
569 	    }
570 
571 	  /* All done. */
572 	  break;
573 	}
574     next_opcode:
575       op++;
576     }
577 
578   return match;
579 }
580 
581 int
print_insn_v850(bfd_vma memaddr,struct disassemble_info * info)582 print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
583 {
584   int status, status2, match;
585   bfd_byte buffer[8];
586   int length = 0, code_length = 0;
587   unsigned long insn = 0, insn2 = 0;
588   int target_processor;
589 
590   switch (info->mach)
591     {
592     case 0:
593     default:
594       target_processor = PROCESSOR_V850;
595       break;
596 
597     case bfd_mach_v850e:
598       target_processor = PROCESSOR_V850E;
599       break;
600 
601     case bfd_mach_v850e1:
602       target_processor = PROCESSOR_V850E;
603       break;
604 
605     case bfd_mach_v850e2:
606       target_processor = PROCESSOR_V850E2;
607       break;
608 
609     case bfd_mach_v850e2v3:
610       target_processor = PROCESSOR_V850E2V3;
611       break;
612 
613     case bfd_mach_v850e3v5:
614       target_processor = PROCESSOR_V850E3V5;
615       break;
616     }
617 
618   status = info->read_memory_func (memaddr, buffer, 2, info);
619 
620   if (status)
621     {
622       info->memory_error_func (status, memaddr, info);
623       return -1;
624     }
625 
626   insn = bfd_getl16 (buffer);
627 
628   status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
629 
630   if (!status2)
631     {
632       insn2 = bfd_getl16 (buffer);
633       /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
634     }
635 
636   /* Special case.  */
637   if (length == 0
638       && ((target_processor & PROCESSOR_V850E2_UP) != 0))
639     {
640       if ((insn & 0xffff) == 0x02e0		/* jr 32bit */
641 	  && !status2 && (insn2 & 0x1) == 0)
642 	{
643 	  length = 2;
644 	  code_length = 6;
645 	}
646       else if ((insn & 0xffe0) == 0x02e0	/* jarl 32bit */
647 	       && !status2 && (insn2 & 0x1) == 0)
648 	{
649 	  length = 2;
650 	  code_length = 6;
651 	}
652       else if ((insn & 0xffe0) == 0x06e0	/* jmp 32bit */
653 	       && !status2 && (insn2 & 0x1) == 0)
654 	{
655 	  length = 2;
656 	  code_length = 6;
657 	}
658     }
659 
660   if (length == 0
661       && ((target_processor & PROCESSOR_V850E3V5_UP) != 0))
662     {
663       if (   ((insn & 0xffe0) == 0x07a0		/* ld.dw 23bit (v850e3v5) */
664 	      && !status2 && (insn2 & 0x000f) == 0x0009)
665 	  || ((insn & 0xffe0) == 0x07a0		/* st.dw 23bit (v850e3v5) */
666 	      && !status2 && (insn2 & 0x000f) == 0x000f))
667 	{
668 	  length = 4;
669 	  code_length = 6;
670 	}
671     }
672 
673   if (length == 0
674       && ((target_processor & PROCESSOR_V850E2V3_UP) != 0))
675     {
676       if (((insn & 0xffe0) == 0x0780		/* ld.b 23bit */
677 	   && !status2 && (insn2 & 0x000f) == 0x0005)
678 	  || ((insn & 0xffe0) == 0x07a0		/* ld.bu 23bit */
679 	      && !status2 && (insn2 & 0x000f) == 0x0005)
680 	  || ((insn & 0xffe0) == 0x0780		/* ld.h 23bit */
681 	      && !status2 && (insn2 & 0x000f) == 0x0007)
682 	  || ((insn & 0xffe0) == 0x07a0		/* ld.hu 23bit */
683 	      && !status2 && (insn2 & 0x000f) == 0x0007)
684 	  || ((insn & 0xffe0) == 0x0780		/* ld.w 23bit */
685 	      && !status2 && (insn2 & 0x000f) == 0x0009))
686 	{
687 	  length = 4;
688 	  code_length = 6;
689 	}
690       else if (((insn & 0xffe0) == 0x0780	/* st.b 23bit */
691 	       && !status2 && (insn2 & 0x000f) == 0x000d)
692 	      || ((insn & 0xffe0) == 0x07a0	/* st.h 23bit */
693 		  && !status2 && (insn2 & 0x000f) == 0x000d)
694 	      || ((insn & 0xffe0) == 0x0780	/* st.w 23bit */
695 		  && !status2 && (insn2 & 0x000f) == 0x000f))
696 	{
697 	  length = 4;
698 	  code_length = 6;
699 	}
700     }
701 
702   if (length == 0
703       && target_processor != PROCESSOR_V850)
704     {
705       if ((insn & 0xffe0) == 0x0620)		/* 32 bit MOV */
706 	{
707 	  length = 2;
708 	  code_length = 6;
709 	}
710       else if ((insn & 0xffc0) == 0x0780	/* prepare {list}, imm5, imm16<<16 */
711 	       && !status2 && (insn2 & 0x001f) == 0x0013)
712 	{
713 	  length = 4;
714 	  code_length = 6;
715 	}
716       else if ((insn & 0xffc0) == 0x0780	/* prepare {list}, imm5, imm16 */
717 	       && !status2 && (insn2 & 0x001f) == 0x000b)
718 	{
719 	  length = 4;
720 	  code_length = 6;
721 	}
722       else if ((insn & 0xffc0) == 0x0780	/* prepare {list}, imm5, imm32 */
723 	       && !status2 && (insn2 & 0x001f) == 0x001b)
724 	{
725 	  length = 4;
726 	  code_length = 8;
727 	}
728     }
729 
730   if (length == 4
731       || (length == 0
732 	  && (insn & 0x0600) == 0x0600))
733     {
734       /* This is a 4 byte insn.  */
735       status = info->read_memory_func (memaddr, buffer, 4, info);
736       if (!status)
737 	{
738 	  insn = bfd_getl32 (buffer);
739 
740 	  if (!length)
741 	    length = code_length = 4;
742 	}
743     }
744 
745   if (code_length > length)
746     {
747       status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
748       if (status)
749 	length = 0;
750     }
751 
752   if (length == 0 && !status)
753     length = code_length = 2;
754 
755   if (length == 2)
756     insn &= 0xffff;
757 
758   /* when the last 2 bytes of section is 0xffff, length will be 0 and cause infinitive loop */
759   if (length == 0)
760     return -1;
761 
762   match = disassemble (memaddr, info, length, insn);
763 
764   if (!match)
765     {
766       int l = 0;
767 
768       status = info->read_memory_func (memaddr, buffer, code_length, info);
769 
770       while (l < code_length)
771 	{
772 	  if (code_length - l == 2)
773 	    {
774 	      insn = bfd_getl16 (buffer + l) & 0xffff;
775 	      info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
776 	      l += 2;
777 	    }
778 	  else
779 	    {
780 	      insn = bfd_getl32 (buffer + l);
781 	      info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
782 	      l += 4;
783 	    }
784 	}
785     }
786 
787   return code_length;
788 }
789