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