Home | History | Annotate | Line # | Download | only in opcodes
v850-dis.c revision 1.1.1.5.12.2
      1 /* Disassemble V850 instructions.
      2    Copyright (C) 1996-2018 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 
     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
     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
    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
    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 			opcodes_error_handler (_("unknown operand shift: %x"),
    454 					       operand->shift);
    455 			abort ();
    456 		      }
    457 
    458 		    for (i = 0; i < 32; i++)
    459 		      {
    460 			if (value & (1 << i))
    461 			  {
    462 			    switch (regs[ i ])
    463 			      {
    464 			      default:
    465 				mask |= (1 << regs[ i ]);
    466 				break;
    467 			      case 0:
    468 				/* xgettext:c-format */
    469 				opcodes_error_handler (_("unknown reg: %d"), i);
    470 				abort ();
    471 				break;
    472 			      case -1:
    473 				pc = 1;
    474 				break;
    475 			      }
    476 			  }
    477 		      }
    478 
    479 		    info->fprintf_func (info->stream, "{");
    480 
    481 		    if (mask || pc)
    482 		      {
    483 			if (mask)
    484 			  {
    485 			    unsigned int bit;
    486 			    int shown_one = 0;
    487 
    488 			    for (bit = 0; bit < 32; bit++)
    489 			      if (mask & (1 << bit))
    490 				{
    491 				  unsigned long int first = bit;
    492 				  unsigned long int last;
    493 
    494 				  if (shown_one)
    495 				    info->fprintf_func (info->stream, ", ");
    496 				  else
    497 				    shown_one = 1;
    498 
    499 				  info->fprintf_func (info->stream, "%s", v850_reg_names[first]);
    500 
    501 				  for (bit++; bit < 32; bit++)
    502 				    if ((mask & (1 << bit)) == 0)
    503 				      break;
    504 
    505 				  last = bit;
    506 
    507 				  if (last > first + 1)
    508 				    {
    509 				      info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]);
    510 				    }
    511 				}
    512 			  }
    513 
    514 			if (pc)
    515 			  info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
    516 		      }
    517 
    518 		    info->fprintf_func (info->stream, "}");
    519 		  }
    520 		  break;
    521 
    522 		case V850_OPERAND_CC:
    523 		  info->fprintf_func (info->stream, "%s", v850_cc_names[value]);
    524 		  break;
    525 
    526 		case V850_OPERAND_FLOAT_CC:
    527 		  info->fprintf_func (info->stream, "%s", v850_float_cc_names[value]);
    528 		  break;
    529 
    530 		case V850_OPERAND_CACHEOP:
    531 		  {
    532 		    int idx;
    533 
    534 		    for (idx = 0; v850_cacheop_codes[idx] != -1; idx++)
    535 		      {
    536 			if (value == v850_cacheop_codes[idx])
    537 			  {
    538 			    info->fprintf_func (info->stream, "%s",
    539 						v850_cacheop_names[idx]);
    540 			    goto MATCH_CACHEOP_CODE;
    541 			  }
    542 		      }
    543 		    info->fprintf_func (info->stream, "%d", (int) value);
    544 		  }
    545 		MATCH_CACHEOP_CODE:
    546 		  break;
    547 
    548 		case V850_OPERAND_PREFOP:
    549 		  {
    550 		    int idx;
    551 
    552 		    for (idx = 0; v850_prefop_codes[idx] != -1; idx++)
    553 		      {
    554 			if (value == v850_prefop_codes[idx])
    555 			  {
    556 			    info->fprintf_func (info->stream, "%s",
    557 			      v850_prefop_names[idx]);
    558 			    goto MATCH_PREFOP_CODE;
    559 			  }
    560 		      }
    561 		    info->fprintf_func (info->stream, "%d", (int) value);
    562 		  }
    563 		MATCH_PREFOP_CODE:
    564 		  break;
    565 
    566 		case V850_OPERAND_VREG:
    567 		  info->fprintf_func (info->stream, "%s", v850_vreg_names[value]);
    568 		  break;
    569 
    570 		default:
    571 		  print_value (operand->flags, memaddr, info, value);
    572 		  break;
    573 		}
    574 
    575 	      if (square)
    576 		(*info->fprintf_func) (info->stream, "]");
    577 	    }
    578 
    579 	  /* All done. */
    580 	  break;
    581 	}
    582     next_opcode:
    583       op++;
    584     }
    585 
    586   return match;
    587 }
    588 
    589 int
    590 print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
    591 {
    592   int status, status2, match;
    593   bfd_byte buffer[8];
    594   int length = 0, code_length = 0;
    595   unsigned long insn = 0, insn2 = 0;
    596   int target_processor;
    597 
    598   switch (info->mach)
    599     {
    600     case 0:
    601     default:
    602       target_processor = PROCESSOR_V850;
    603       break;
    604 
    605     case bfd_mach_v850e:
    606       target_processor = PROCESSOR_V850E;
    607       break;
    608 
    609     case bfd_mach_v850e1:
    610       target_processor = PROCESSOR_V850E;
    611       break;
    612 
    613     case bfd_mach_v850e2:
    614       target_processor = PROCESSOR_V850E2;
    615       break;
    616 
    617     case bfd_mach_v850e2v3:
    618       target_processor = PROCESSOR_V850E2V3;
    619       break;
    620 
    621     case bfd_mach_v850e3v5:
    622       target_processor = PROCESSOR_V850E3V5;
    623       break;
    624     }
    625 
    626   status = info->read_memory_func (memaddr, buffer, 2, info);
    627 
    628   if (status)
    629     {
    630       info->memory_error_func (status, memaddr, info);
    631       return -1;
    632     }
    633 
    634   insn = bfd_getl16 (buffer);
    635 
    636   status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
    637 
    638   if (!status2)
    639     {
    640       insn2 = bfd_getl16 (buffer);
    641       /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
    642     }
    643 
    644   /* Special case.  */
    645   if (length == 0
    646       && ((target_processor & PROCESSOR_V850E2_UP) != 0))
    647     {
    648       if ((insn & 0xffff) == 0x02e0		/* jr 32bit */
    649 	  && !status2 && (insn2 & 0x1) == 0)
    650 	{
    651 	  length = 2;
    652 	  code_length = 6;
    653 	}
    654       else if ((insn & 0xffe0) == 0x02e0	/* jarl 32bit */
    655 	       && !status2 && (insn2 & 0x1) == 0)
    656 	{
    657 	  length = 2;
    658 	  code_length = 6;
    659 	}
    660       else if ((insn & 0xffe0) == 0x06e0	/* jmp 32bit */
    661 	       && !status2 && (insn2 & 0x1) == 0)
    662 	{
    663 	  length = 2;
    664 	  code_length = 6;
    665 	}
    666     }
    667 
    668   if (length == 0
    669       && ((target_processor & PROCESSOR_V850E3V5_UP) != 0))
    670     {
    671       if (   ((insn & 0xffe0) == 0x07a0		/* ld.dw 23bit (v850e3v5) */
    672 	      && !status2 && (insn2 & 0x000f) == 0x0009)
    673 	  || ((insn & 0xffe0) == 0x07a0		/* st.dw 23bit (v850e3v5) */
    674 	      && !status2 && (insn2 & 0x000f) == 0x000f))
    675 	{
    676 	  length = 4;
    677 	  code_length = 6;
    678 	}
    679     }
    680 
    681   if (length == 0
    682       && ((target_processor & PROCESSOR_V850E2V3_UP) != 0))
    683     {
    684       if (((insn & 0xffe0) == 0x0780		/* ld.b 23bit */
    685 	   && !status2 && (insn2 & 0x000f) == 0x0005)
    686 	  || ((insn & 0xffe0) == 0x07a0		/* ld.bu 23bit */
    687 	      && !status2 && (insn2 & 0x000f) == 0x0005)
    688 	  || ((insn & 0xffe0) == 0x0780		/* ld.h 23bit */
    689 	      && !status2 && (insn2 & 0x000f) == 0x0007)
    690 	  || ((insn & 0xffe0) == 0x07a0		/* ld.hu 23bit */
    691 	      && !status2 && (insn2 & 0x000f) == 0x0007)
    692 	  || ((insn & 0xffe0) == 0x0780		/* ld.w 23bit */
    693 	      && !status2 && (insn2 & 0x000f) == 0x0009))
    694 	{
    695 	  length = 4;
    696 	  code_length = 6;
    697 	}
    698       else if (((insn & 0xffe0) == 0x0780	/* st.b 23bit */
    699 	       && !status2 && (insn2 & 0x000f) == 0x000d)
    700 	      || ((insn & 0xffe0) == 0x07a0	/* st.h 23bit */
    701 		  && !status2 && (insn2 & 0x000f) == 0x000d)
    702 	      || ((insn & 0xffe0) == 0x0780	/* st.w 23bit */
    703 		  && !status2 && (insn2 & 0x000f) == 0x000f))
    704 	{
    705 	  length = 4;
    706 	  code_length = 6;
    707 	}
    708     }
    709 
    710   if (length == 0
    711       && target_processor != PROCESSOR_V850)
    712     {
    713       if ((insn & 0xffe0) == 0x0620)		/* 32 bit MOV */
    714 	{
    715 	  length = 2;
    716 	  code_length = 6;
    717 	}
    718       else if ((insn & 0xffc0) == 0x0780	/* prepare {list}, imm5, imm16<<16 */
    719 	       && !status2 && (insn2 & 0x001f) == 0x0013)
    720 	{
    721 	  length = 4;
    722 	  code_length = 6;
    723 	}
    724       else if ((insn & 0xffc0) == 0x0780	/* prepare {list}, imm5, imm16 */
    725 	       && !status2 && (insn2 & 0x001f) == 0x000b)
    726 	{
    727 	  length = 4;
    728 	  code_length = 6;
    729 	}
    730       else if ((insn & 0xffc0) == 0x0780	/* prepare {list}, imm5, imm32 */
    731 	       && !status2 && (insn2 & 0x001f) == 0x001b)
    732 	{
    733 	  length = 4;
    734 	  code_length = 8;
    735 	}
    736     }
    737 
    738   if (length == 4
    739       || (length == 0
    740 	  && (insn & 0x0600) == 0x0600))
    741     {
    742       /* This is a 4 byte insn.  */
    743       status = info->read_memory_func (memaddr, buffer, 4, info);
    744       if (!status)
    745 	{
    746 	  insn = bfd_getl32 (buffer);
    747 
    748 	  if (!length)
    749 	    length = code_length = 4;
    750 	}
    751     }
    752 
    753   if (code_length > length)
    754     {
    755       status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
    756       if (status)
    757 	length = 0;
    758     }
    759 
    760   if (length == 0 && !status)
    761     length = code_length = 2;
    762 
    763   if (length == 2)
    764     insn &= 0xffff;
    765 
    766   /* when the last 2 bytes of section is 0xffff, length will be 0 and cause infinitive loop */
    767   if (length == 0)
    768     return -1;
    769 
    770   match = disassemble (memaddr, info, length, insn);
    771 
    772   if (!match)
    773     {
    774       int l = 0;
    775 
    776       status = info->read_memory_func (memaddr, buffer, code_length, info);
    777 
    778       while (l < code_length)
    779 	{
    780 	  if (code_length - l == 2)
    781 	    {
    782 	      insn = bfd_getl16 (buffer + l) & 0xffff;
    783 	      info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
    784 	      l += 2;
    785 	    }
    786 	  else
    787 	    {
    788 	      insn = bfd_getl32 (buffer + l);
    789 	      info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
    790 	      l += 4;
    791 	    }
    792 	}
    793     }
    794 
    795   return code_length;
    796 }
    797