Home | History | Annotate | Line # | Download | only in opcodes
v850-dis.c revision 1.1.1.11
      1 /* Disassemble V850 instructions.
      2    Copyright (C) 1996-2025 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
     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
     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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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
    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
    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