Home | History | Annotate | Download | only in opcodes
      1 /* Disassemble V850 instructions.
      2    Copyright (C) 1996-2014 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
     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 |= (-1L << 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 			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
    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