Home | History | Annotate | Line # | Download | only in opcodes
v850-dis.c revision 1.1
      1  1.1  christos /* Disassemble V850 instructions.
      2  1.1  christos    Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007, 2010
      3  1.1  christos    Free Software Foundation, Inc.
      4  1.1  christos 
      5  1.1  christos    This file is part of the GNU opcodes library.
      6  1.1  christos 
      7  1.1  christos    This library is free software; you can redistribute it and/or modify
      8  1.1  christos    it under the terms of the GNU General Public License as published by
      9  1.1  christos    the Free Software Foundation; either version 3, or (at your option)
     10  1.1  christos    any later version.
     11  1.1  christos 
     12  1.1  christos    It is distributed in the hope that it will be useful, but WITHOUT
     13  1.1  christos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     14  1.1  christos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     15  1.1  christos    License for more details.
     16  1.1  christos 
     17  1.1  christos    You should have received a copy of the GNU General Public License
     18  1.1  christos    along with this program; if not, write to the Free Software
     19  1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     20  1.1  christos    MA 02110-1301, USA.  */
     21  1.1  christos 
     22  1.1  christos 
     23  1.1  christos #include <stdio.h>
     24  1.1  christos 
     25  1.1  christos #include "sysdep.h"
     26  1.1  christos #include "opcode/v850.h"
     27  1.1  christos #include "dis-asm.h"
     28  1.1  christos #include "opintl.h"
     29  1.1  christos 
     30  1.1  christos static const char *const v850_reg_names[] =
     31  1.1  christos {
     32  1.1  christos   "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7",
     33  1.1  christos   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
     34  1.1  christos   "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
     35  1.1  christos   "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp"
     36  1.1  christos };
     37  1.1  christos 
     38  1.1  christos static const char *const v850_sreg_names[] =
     39  1.1  christos {
     40  1.1  christos   "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid",
     41  1.1  christos   "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0",
     42  1.1  christos   "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau",
     43  1.1  christos   "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u",
     44  1.1  christos   "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l",
     45  1.1  christos   "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l",
     46  1.1  christos   "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u",
     47  1.1  christos   "fewr", "dbwr", "bsel"
     48  1.1  christos };
     49  1.1  christos 
     50  1.1  christos static const char *const v850_cc_names[] =
     51  1.1  christos {
     52  1.1  christos   "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
     53  1.1  christos   "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt"
     54  1.1  christos };
     55  1.1  christos 
     56  1.1  christos static const char *const v850_float_cc_names[] =
     57  1.1  christos {
     58  1.1  christos   "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt",
     59  1.1  christos   "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt"
     60  1.1  christos };
     61  1.1  christos 
     62  1.1  christos 
     63  1.1  christos static void
     64  1.1  christos print_value (int flags, bfd_vma memaddr, struct disassemble_info *info, long value)
     65  1.1  christos {
     66  1.1  christos   if (flags & V850_PCREL)
     67  1.1  christos     {
     68  1.1  christos       bfd_vma addr = value + memaddr;
     69  1.1  christos       info->print_address_func (addr, info);
     70  1.1  christos     }
     71  1.1  christos   else if (flags & V850_OPERAND_DISP)
     72  1.1  christos     {
     73  1.1  christos       if (flags & V850_OPERAND_SIGNED)
     74  1.1  christos         {
     75  1.1  christos           info->fprintf_func (info->stream, "%ld", value);
     76  1.1  christos         }
     77  1.1  christos       else
     78  1.1  christos         {
     79  1.1  christos           info->fprintf_func (info->stream, "%lu", value);
     80  1.1  christos         }
     81  1.1  christos     }
     82  1.1  christos   else if (flags & V850E_IMMEDIATE32)
     83  1.1  christos     {
     84  1.1  christos       info->fprintf_func (info->stream, "0x%lx", value);
     85  1.1  christos     }
     86  1.1  christos   else
     87  1.1  christos     {
     88  1.1  christos       if (flags & V850_OPERAND_SIGNED)
     89  1.1  christos 	{
     90  1.1  christos 	  info->fprintf_func (info->stream, "%ld", value);
     91  1.1  christos 	}
     92  1.1  christos       else
     93  1.1  christos 	{
     94  1.1  christos 	  info->fprintf_func (info->stream, "%lu", value);
     95  1.1  christos 	}
     96  1.1  christos     }
     97  1.1  christos }
     98  1.1  christos 
     99  1.1  christos static long
    100  1.1  christos get_operand_value (const struct v850_operand *operand,
    101  1.1  christos 		   unsigned long insn,
    102  1.1  christos 		   int bytes_read,
    103  1.1  christos 		   bfd_vma memaddr,
    104  1.1  christos 		   struct disassemble_info * info,
    105  1.1  christos 		   bfd_boolean noerror,
    106  1.1  christos 		   int *invalid)
    107  1.1  christos {
    108  1.1  christos   long value;
    109  1.1  christos   bfd_byte buffer[4];
    110  1.1  christos 
    111  1.1  christos   if ((operand->flags & V850E_IMMEDIATE16)
    112  1.1  christos       || (operand->flags & V850E_IMMEDIATE16HI))
    113  1.1  christos     {
    114  1.1  christos       int status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info);
    115  1.1  christos 
    116  1.1  christos       if (status == 0)
    117  1.1  christos 	{
    118  1.1  christos 	  value = bfd_getl16 (buffer);
    119  1.1  christos 
    120  1.1  christos 	  if (operand->flags & V850E_IMMEDIATE16HI)
    121  1.1  christos 	    value <<= 16;
    122  1.1  christos 
    123  1.1  christos 	  return value;
    124  1.1  christos 	}
    125  1.1  christos 
    126  1.1  christos       if (!noerror)
    127  1.1  christos 	info->memory_error_func (status, memaddr + bytes_read, info);
    128  1.1  christos 
    129  1.1  christos       return 0;
    130  1.1  christos     }
    131  1.1  christos 
    132  1.1  christos   if (operand->flags & V850E_IMMEDIATE23)
    133  1.1  christos     {
    134  1.1  christos       int status = info->read_memory_func (memaddr + 2, buffer, 4, info);
    135  1.1  christos 
    136  1.1  christos       if (status == 0)
    137  1.1  christos 	{
    138  1.1  christos 	  value = bfd_getl32 (buffer);
    139  1.1  christos 
    140  1.1  christos 	  value = (operand->extract) (value, invalid);
    141  1.1  christos 
    142  1.1  christos 	  return value;
    143  1.1  christos 	}
    144  1.1  christos 
    145  1.1  christos       if (!noerror)
    146  1.1  christos 	info->memory_error_func (status, memaddr + bytes_read, info);
    147  1.1  christos 
    148  1.1  christos       return 0;
    149  1.1  christos     }
    150  1.1  christos 
    151  1.1  christos   if (operand->flags & V850E_IMMEDIATE32)
    152  1.1  christos     {
    153  1.1  christos       int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info);
    154  1.1  christos 
    155  1.1  christos       if (status == 0)
    156  1.1  christos 	{
    157  1.1  christos 	  bytes_read += 4;
    158  1.1  christos 	  value = bfd_getl32 (buffer);
    159  1.1  christos 
    160  1.1  christos 	  return value;
    161  1.1  christos 	}
    162  1.1  christos 
    163  1.1  christos       if (!noerror)
    164  1.1  christos 	info->memory_error_func (status, memaddr + bytes_read, info);
    165  1.1  christos 
    166  1.1  christos       return 0;
    167  1.1  christos     }
    168  1.1  christos 
    169  1.1  christos   if (operand->extract)
    170  1.1  christos     value = (operand->extract) (insn, invalid);
    171  1.1  christos   else
    172  1.1  christos     {
    173  1.1  christos       if (operand->bits == -1)
    174  1.1  christos 	value = (insn & operand->shift);
    175  1.1  christos       else
    176  1.1  christos 	value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
    177  1.1  christos 
    178  1.1  christos       if (operand->flags & V850_OPERAND_SIGNED)
    179  1.1  christos 	value = ((long)(value << (sizeof (long)*8 - operand->bits))
    180  1.1  christos 		 >> (sizeof (long)*8 - operand->bits));
    181  1.1  christos     }
    182  1.1  christos 
    183  1.1  christos   return value;
    184  1.1  christos }
    185  1.1  christos 
    186  1.1  christos 
    187  1.1  christos static int
    188  1.1  christos disassemble (bfd_vma memaddr, struct disassemble_info *info, int bytes_read, unsigned long insn)
    189  1.1  christos {
    190  1.1  christos   struct v850_opcode *op = (struct v850_opcode *)v850_opcodes;
    191  1.1  christos   const struct v850_operand *operand;
    192  1.1  christos   int match = 0;
    193  1.1  christos   int target_processor;
    194  1.1  christos 
    195  1.1  christos   switch (info->mach)
    196  1.1  christos     {
    197  1.1  christos     case 0:
    198  1.1  christos     default:
    199  1.1  christos       target_processor = PROCESSOR_V850;
    200  1.1  christos       break;
    201  1.1  christos 
    202  1.1  christos     case bfd_mach_v850e:
    203  1.1  christos       target_processor = PROCESSOR_V850E;
    204  1.1  christos       break;
    205  1.1  christos 
    206  1.1  christos     case bfd_mach_v850e1:
    207  1.1  christos       target_processor = PROCESSOR_V850E;
    208  1.1  christos       break;
    209  1.1  christos 
    210  1.1  christos     case bfd_mach_v850e2:
    211  1.1  christos       target_processor = PROCESSOR_V850E2;
    212  1.1  christos       break;
    213  1.1  christos 
    214  1.1  christos     case bfd_mach_v850e2v3:
    215  1.1  christos       target_processor = PROCESSOR_V850E2V3;
    216  1.1  christos       break;
    217  1.1  christos     }
    218  1.1  christos 
    219  1.1  christos   /* If this is a two byte insn, then mask off the high bits.  */
    220  1.1  christos   if (bytes_read == 2)
    221  1.1  christos     insn &= 0xffff;
    222  1.1  christos 
    223  1.1  christos   /* Find the opcode.  */
    224  1.1  christos   while (op->name)
    225  1.1  christos     {
    226  1.1  christos       if ((op->mask & insn) == op->opcode
    227  1.1  christos 	  && (op->processors & target_processor)
    228  1.1  christos 	  && !(op->processors & PROCESSOR_OPTION_ALIAS))
    229  1.1  christos 	{
    230  1.1  christos 	  /* Code check start.  */
    231  1.1  christos 	  const unsigned char *opindex_ptr;
    232  1.1  christos 	  unsigned int opnum;
    233  1.1  christos 	  unsigned int memop;
    234  1.1  christos 
    235  1.1  christos 	  for (opindex_ptr = op->operands, opnum = 1;
    236  1.1  christos 	       *opindex_ptr != 0;
    237  1.1  christos 	       opindex_ptr++, opnum++)
    238  1.1  christos 	    {
    239  1.1  christos 	      int invalid = 0;
    240  1.1  christos 	      long value;
    241  1.1  christos 
    242  1.1  christos 	      operand = &v850_operands[*opindex_ptr];
    243  1.1  christos 
    244  1.1  christos 	      value = get_operand_value (operand, insn, bytes_read, memaddr, info, 1, &invalid);
    245  1.1  christos 
    246  1.1  christos 	      if (invalid)
    247  1.1  christos 		goto next_opcode;
    248  1.1  christos 
    249  1.1  christos               if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2)
    250  1.1  christos 		goto next_opcode;
    251  1.1  christos 
    252  1.1  christos 	      if ((operand->flags & V850_NOT_SA) && value == 0xd)
    253  1.1  christos 		goto next_opcode;
    254  1.1  christos 
    255  1.1  christos 	      if ((operand->flags & V850_NOT_IMM0) && value == 0)
    256  1.1  christos 		goto next_opcode;
    257  1.1  christos 	    }
    258  1.1  christos 
    259  1.1  christos 	  /* Code check end.  */
    260  1.1  christos 
    261  1.1  christos 	  match = 1;
    262  1.1  christos 	  (*info->fprintf_func) (info->stream, "%s\t", op->name);
    263  1.1  christos #if 0
    264  1.1  christos 	  fprintf (stderr, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n",
    265  1.1  christos 		   insn, op->mask, op->opcode, op->name );
    266  1.1  christos #endif
    267  1.1  christos 
    268  1.1  christos 	  memop = op->memop;
    269  1.1  christos 	  /* Now print the operands.
    270  1.1  christos 
    271  1.1  christos 	     MEMOP is the operand number at which a memory
    272  1.1  christos 	     address specification starts, or zero if this
    273  1.1  christos 	     instruction has no memory addresses.
    274  1.1  christos 
    275  1.1  christos 	     A memory address is always two arguments.
    276  1.1  christos 
    277  1.1  christos 	     This information allows us to determine when to
    278  1.1  christos 	     insert commas into the output stream as well as
    279  1.1  christos 	     when to insert disp[reg] expressions onto the
    280  1.1  christos 	     output stream.  */
    281  1.1  christos 
    282  1.1  christos 	  for (opindex_ptr = op->operands, opnum = 1;
    283  1.1  christos 	       *opindex_ptr != 0;
    284  1.1  christos 	       opindex_ptr++, opnum++)
    285  1.1  christos 	    {
    286  1.1  christos 	      long value;
    287  1.1  christos 	      int flag;
    288  1.1  christos 	      char *prefix;
    289  1.1  christos 
    290  1.1  christos 	      operand = &v850_operands[*opindex_ptr];
    291  1.1  christos 
    292  1.1  christos 	      value = get_operand_value (operand, insn, bytes_read, memaddr, info, 0, 0);
    293  1.1  christos 
    294  1.1  christos 	      /* The first operand is always output without any
    295  1.1  christos 		 special handling.
    296  1.1  christos 
    297  1.1  christos 		 For the following arguments:
    298  1.1  christos 
    299  1.1  christos 		   If memop && opnum == memop + 1, then we need '[' since
    300  1.1  christos 		   we're about to output the register used in a memory
    301  1.1  christos 		   reference.
    302  1.1  christos 
    303  1.1  christos 		   If memop && opnum == memop + 2, then we need ']' since
    304  1.1  christos 		   we just finished the register in a memory reference.  We
    305  1.1  christos 		   also need a ',' before this operand.
    306  1.1  christos 
    307  1.1  christos 		   Else we just need a comma.
    308  1.1  christos 
    309  1.1  christos 		   We may need to output a trailing ']' if the last operand
    310  1.1  christos 		   in an instruction is the register for a memory address.
    311  1.1  christos 
    312  1.1  christos 		   The exception (and there's always an exception) is the
    313  1.1  christos 		   "jmp" insn which needs square brackets around it's only
    314  1.1  christos 		   register argument.  */
    315  1.1  christos 	      prefix = "";
    316  1.1  christos 	      if (operand->flags & V850_OPERAND_BANG)
    317  1.1  christos 		{
    318  1.1  christos 		  prefix = "!";
    319  1.1  christos 		}
    320  1.1  christos 	      else if (operand->flags & V850_OPERAND_PERCENT)
    321  1.1  christos 		{
    322  1.1  christos 		  prefix = "%";
    323  1.1  christos 		}
    324  1.1  christos 
    325  1.1  christos 	      if (opnum == 1 && opnum == memop)
    326  1.1  christos 		info->fprintf_func (info->stream, "%s[", prefix);
    327  1.1  christos 	      else if (opnum > 1
    328  1.1  christos 		       && (v850_operands[*(opindex_ptr - 1)].flags & V850_OPERAND_DISP) != 0
    329  1.1  christos 		       && opnum == memop)
    330  1.1  christos 		info->fprintf_func (info->stream, "%s[", prefix);
    331  1.1  christos 	      else if (opnum > 1)
    332  1.1  christos 		info->fprintf_func (info->stream, ", %s", prefix);
    333  1.1  christos 
    334  1.1  christos  	      /* Extract the flags, ignoring ones which do not effect disassembly output.  */
    335  1.1  christos 	      flag = operand->flags & (V850_OPERAND_REG
    336  1.1  christos 				       | V850_REG_EVEN
    337  1.1  christos 				       | V850_OPERAND_EP
    338  1.1  christos 				       | V850_OPERAND_SRG
    339  1.1  christos 				       | V850E_OPERAND_REG_LIST
    340  1.1  christos 				       | V850_OPERAND_CC
    341  1.1  christos 				       | V850_OPERAND_FLOAT_CC);
    342  1.1  christos 
    343  1.1  christos 	      switch (flag)
    344  1.1  christos 		{
    345  1.1  christos 		case V850_OPERAND_REG:  info->fprintf_func (info->stream, "%s", v850_reg_names[value]); break;
    346  1.1  christos 		case (V850_OPERAND_REG|V850_REG_EVEN):  info->fprintf_func (info->stream, "%s", v850_reg_names[value*2]); break;
    347  1.1  christos 		case V850_OPERAND_EP:   info->fprintf_func (info->stream, "ep"); break;
    348  1.1  christos 		case V850_OPERAND_SRG:  info->fprintf_func (info->stream, "%s", v850_sreg_names[value]); break;
    349  1.1  christos 
    350  1.1  christos 		case V850E_OPERAND_REG_LIST:
    351  1.1  christos 		  {
    352  1.1  christos 		    static int list12_regs[32]   = { 30, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    353  1.1  christos 						     0,  0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
    354  1.1  christos 		    int *regs;
    355  1.1  christos 		    int i;
    356  1.1  christos 		    unsigned long int mask = 0;
    357  1.1  christos 		    int pc = 0;
    358  1.1  christos 
    359  1.1  christos 
    360  1.1  christos 		    switch (operand->shift)
    361  1.1  christos 		      {
    362  1.1  christos 		      case 0xffe00001: regs = list12_regs; break;
    363  1.1  christos 		      default:
    364  1.1  christos 			/* xgettext:c-format */
    365  1.1  christos 			fprintf (stderr, _("unknown operand shift: %x\n"), operand->shift );
    366  1.1  christos 			abort ();
    367  1.1  christos 		      }
    368  1.1  christos 
    369  1.1  christos 		    for (i = 0; i < 32; i++)
    370  1.1  christos 		      {
    371  1.1  christos 			if (value & (1 << i))
    372  1.1  christos 			  {
    373  1.1  christos 			    switch (regs[ i ])
    374  1.1  christos 			      {
    375  1.1  christos 			      default: mask |= (1 << regs[ i ]); break;
    376  1.1  christos 				/* xgettext:c-format */
    377  1.1  christos 			      case 0:  fprintf (stderr, _("unknown reg: %d\n"), i ); abort ();
    378  1.1  christos 			      case -1: pc = 1; break;
    379  1.1  christos 			      }
    380  1.1  christos 			  }
    381  1.1  christos 		      }
    382  1.1  christos 
    383  1.1  christos 		    info->fprintf_func (info->stream, "{");
    384  1.1  christos 
    385  1.1  christos 		    if (mask || pc)
    386  1.1  christos 		      {
    387  1.1  christos 			if (mask)
    388  1.1  christos 			  {
    389  1.1  christos 			    unsigned int bit;
    390  1.1  christos 			    int shown_one = 0;
    391  1.1  christos 
    392  1.1  christos 			    for (bit = 0; bit < 32; bit++)
    393  1.1  christos 			      if (mask & (1 << bit))
    394  1.1  christos 				{
    395  1.1  christos 				  unsigned long int first = bit;
    396  1.1  christos 				  unsigned long int last;
    397  1.1  christos 
    398  1.1  christos 				  if (shown_one)
    399  1.1  christos 				    info->fprintf_func (info->stream, ", ");
    400  1.1  christos 				  else
    401  1.1  christos 				    shown_one = 1;
    402  1.1  christos 
    403  1.1  christos 				  info->fprintf_func (info->stream, v850_reg_names[first]);
    404  1.1  christos 
    405  1.1  christos 				  for (bit++; bit < 32; bit++)
    406  1.1  christos 				    if ((mask & (1 << bit)) == 0)
    407  1.1  christos 				      break;
    408  1.1  christos 
    409  1.1  christos 				  last = bit;
    410  1.1  christos 
    411  1.1  christos 				  if (last > first + 1)
    412  1.1  christos 				    {
    413  1.1  christos 				      info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]);
    414  1.1  christos 				    }
    415  1.1  christos 				}
    416  1.1  christos 			  }
    417  1.1  christos 
    418  1.1  christos 			if (pc)
    419  1.1  christos 			  info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
    420  1.1  christos 		      }
    421  1.1  christos 
    422  1.1  christos 		    info->fprintf_func (info->stream, "}");
    423  1.1  christos 		  }
    424  1.1  christos 		  break;
    425  1.1  christos 
    426  1.1  christos 		case V850_OPERAND_CC:   info->fprintf_func (info->stream, "%s", v850_cc_names[value]); break;
    427  1.1  christos 		case V850_OPERAND_FLOAT_CC:   info->fprintf_func (info->stream, "%s", v850_float_cc_names[value]); break;
    428  1.1  christos 
    429  1.1  christos 		default:
    430  1.1  christos 		  print_value (operand->flags, memaddr, info, value);
    431  1.1  christos 		  break;
    432  1.1  christos 		}
    433  1.1  christos 
    434  1.1  christos 	      if (opnum == 2 && opnum == memop)
    435  1.1  christos 		(*info->fprintf_func) (info->stream, "]");
    436  1.1  christos 	    }
    437  1.1  christos 
    438  1.1  christos 	  /* All done. */
    439  1.1  christos 	  break;
    440  1.1  christos 	}
    441  1.1  christos     next_opcode:
    442  1.1  christos       op++;
    443  1.1  christos     }
    444  1.1  christos 
    445  1.1  christos   return match;
    446  1.1  christos }
    447  1.1  christos 
    448  1.1  christos int
    449  1.1  christos print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
    450  1.1  christos {
    451  1.1  christos   int status, status2, match;
    452  1.1  christos   bfd_byte buffer[8];
    453  1.1  christos   int length = 0, code_length = 0;
    454  1.1  christos   unsigned long insn = 0, insn2 = 0;
    455  1.1  christos   int target_processor;
    456  1.1  christos 
    457  1.1  christos   switch (info->mach)
    458  1.1  christos     {
    459  1.1  christos     case 0:
    460  1.1  christos     default:
    461  1.1  christos       target_processor = PROCESSOR_V850;
    462  1.1  christos       break;
    463  1.1  christos 
    464  1.1  christos     case bfd_mach_v850e:
    465  1.1  christos       target_processor = PROCESSOR_V850E;
    466  1.1  christos       break;
    467  1.1  christos 
    468  1.1  christos     case bfd_mach_v850e1:
    469  1.1  christos       target_processor = PROCESSOR_V850E;
    470  1.1  christos       break;
    471  1.1  christos 
    472  1.1  christos     case bfd_mach_v850e2:
    473  1.1  christos       target_processor = PROCESSOR_V850E2;
    474  1.1  christos       break;
    475  1.1  christos 
    476  1.1  christos     case bfd_mach_v850e2v3:
    477  1.1  christos       target_processor = PROCESSOR_V850E2V3;
    478  1.1  christos       break;
    479  1.1  christos     }
    480  1.1  christos 
    481  1.1  christos   status = info->read_memory_func (memaddr, buffer, 2, info);
    482  1.1  christos 
    483  1.1  christos   if (status)
    484  1.1  christos     {
    485  1.1  christos       info->memory_error_func (status, memaddr, info);
    486  1.1  christos       return -1;
    487  1.1  christos     }
    488  1.1  christos 
    489  1.1  christos   insn = bfd_getl16 (buffer);
    490  1.1  christos 
    491  1.1  christos   status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
    492  1.1  christos 
    493  1.1  christos   if (!status2)
    494  1.1  christos     {
    495  1.1  christos       insn2 = bfd_getl16 (buffer);
    496  1.1  christos       /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
    497  1.1  christos     }
    498  1.1  christos 
    499  1.1  christos   /* Special case.  */
    500  1.1  christos   if (length == 0
    501  1.1  christos       && (target_processor == PROCESSOR_V850E2
    502  1.1  christos 	  || target_processor == PROCESSOR_V850E2V3))
    503  1.1  christos     {
    504  1.1  christos       if ((insn & 0xffff) == 0x02e0		/* jr 32bit */
    505  1.1  christos 	  && !status2 && (insn2 & 0x1) == 0)
    506  1.1  christos 	{
    507  1.1  christos 	  length = 2;
    508  1.1  christos 	  code_length = 6;
    509  1.1  christos 	}
    510  1.1  christos       else if ((insn & 0xffe0) == 0x02e0	/* jarl 32bit */
    511  1.1  christos 	       && !status2 && (insn2 & 0x1) == 0)
    512  1.1  christos 	{
    513  1.1  christos 	  length = 2;
    514  1.1  christos 	  code_length = 6;
    515  1.1  christos 	}
    516  1.1  christos       else if ((insn & 0xffe0) == 0x06e0	/* jmp 32bit */
    517  1.1  christos 	       && !status2 && (insn2 & 0x1) == 0)
    518  1.1  christos 	{
    519  1.1  christos 	  length = 2;
    520  1.1  christos 	  code_length = 6;
    521  1.1  christos 	}
    522  1.1  christos     }
    523  1.1  christos 
    524  1.1  christos   if (length == 0
    525  1.1  christos       && target_processor == PROCESSOR_V850E2V3)
    526  1.1  christos     {
    527  1.1  christos       if (((insn & 0xffe0) == 0x0780		/* ld.b 23bit */
    528  1.1  christos 	   && !status2 && (insn2 & 0x000f) == 0x0005)
    529  1.1  christos 	  || ((insn & 0xffe0) == 0x07a0		/* ld.bu 23bit */
    530  1.1  christos 	      && !status2 && (insn2 & 0x000f) == 0x0005)
    531  1.1  christos 	  || ((insn & 0xffe0) == 0x0780		/* ld.h 23bit */
    532  1.1  christos 	      && !status2 && (insn2 & 0x000f) == 0x0007)
    533  1.1  christos 	  || ((insn & 0xffe0) == 0x07a0		/* ld.hu 23bit */
    534  1.1  christos 	      && !status2 && (insn2 & 0x000f) == 0x0007)
    535  1.1  christos 	  || ((insn & 0xffe0) == 0x0780		/* ld.w 23bit */
    536  1.1  christos 	      && !status2 && (insn2 & 0x000f) == 0x0009))
    537  1.1  christos 	{
    538  1.1  christos 	  length = 4;
    539  1.1  christos 	  code_length = 6;
    540  1.1  christos 	}
    541  1.1  christos       else if (((insn & 0xffe0) == 0x0780	/* st.b 23bit */
    542  1.1  christos 	       && !status2 && (insn2 & 0x000f) == 0x000d)
    543  1.1  christos 	      || ((insn & 0xffe0) == 0x07a0	/* st.h 23bit */
    544  1.1  christos 		  && !status2 && (insn2 & 0x000f) == 0x000d)
    545  1.1  christos 	      || ((insn & 0xffe0) == 0x0780	/* st.w 23bit */
    546  1.1  christos 		  && !status2 && (insn2 & 0x000f) == 0x000f))
    547  1.1  christos 	{
    548  1.1  christos 	  length = 4;
    549  1.1  christos 	  code_length = 6;
    550  1.1  christos 	}
    551  1.1  christos     }
    552  1.1  christos 
    553  1.1  christos   if (length == 0
    554  1.1  christos       && target_processor != PROCESSOR_V850)
    555  1.1  christos     {
    556  1.1  christos       if ((insn & 0xffe0) == 0x0620)		/* 32 bit MOV */
    557  1.1  christos 	{
    558  1.1  christos 	  length = 2;
    559  1.1  christos 	  code_length = 6;
    560  1.1  christos 	}
    561  1.1  christos       else if ((insn & 0xffc0) == 0x0780	/* prepare {list}, imm5, imm16<<16 */
    562  1.1  christos 	       && !status2 && (insn2 & 0x001f) == 0x0013)
    563  1.1  christos 	{
    564  1.1  christos 	  length = 4;
    565  1.1  christos 	  code_length = 6;
    566  1.1  christos 	}
    567  1.1  christos       else if ((insn & 0xffc0) == 0x0780	/* prepare {list}, imm5, imm16 */
    568  1.1  christos 	       && !status2 && (insn2 & 0x001f) == 0x000b)
    569  1.1  christos 	{
    570  1.1  christos 	  length = 4;
    571  1.1  christos 	  code_length = 6;
    572  1.1  christos 	}
    573  1.1  christos       else if ((insn & 0xffc0) == 0x0780	/* prepare {list}, imm5, imm32 */
    574  1.1  christos 	       && !status2 && (insn2 & 0x001f) == 0x001b)
    575  1.1  christos 	{
    576  1.1  christos 	  length = 4;
    577  1.1  christos 	  code_length = 8;
    578  1.1  christos 	}
    579  1.1  christos     }
    580  1.1  christos 
    581  1.1  christos   if (length == 4
    582  1.1  christos       || (length == 0
    583  1.1  christos 	  && (insn & 0x0600) == 0x0600))
    584  1.1  christos     {
    585  1.1  christos       /* This is a 4 byte insn.  */
    586  1.1  christos       status = info->read_memory_func (memaddr, buffer, 4, info);
    587  1.1  christos       if (!status)
    588  1.1  christos 	{
    589  1.1  christos 	  insn = bfd_getl32 (buffer);
    590  1.1  christos 
    591  1.1  christos 	  if (!length)
    592  1.1  christos 	    length = code_length = 4;
    593  1.1  christos 	}
    594  1.1  christos     }
    595  1.1  christos 
    596  1.1  christos   if (code_length > length)
    597  1.1  christos     {
    598  1.1  christos       status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
    599  1.1  christos       if (status)
    600  1.1  christos 	length = 0;
    601  1.1  christos     }
    602  1.1  christos 
    603  1.1  christos   if (length == 0 && !status)
    604  1.1  christos     length = code_length = 2;
    605  1.1  christos 
    606  1.1  christos   if (length == 2)
    607  1.1  christos     insn &= 0xffff;
    608  1.1  christos 
    609  1.1  christos   match = disassemble (memaddr, info, length, insn);
    610  1.1  christos 
    611  1.1  christos   if (!match)
    612  1.1  christos     {
    613  1.1  christos       int l = 0;
    614  1.1  christos 
    615  1.1  christos       status = info->read_memory_func (memaddr, buffer, code_length, info);
    616  1.1  christos 
    617  1.1  christos       while (l < code_length)
    618  1.1  christos 	{
    619  1.1  christos 	  if (code_length - l == 2)
    620  1.1  christos 	    {
    621  1.1  christos 	      insn = bfd_getl16 (buffer + l) & 0xffff;
    622  1.1  christos 	      info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
    623  1.1  christos 	      l += 2;
    624  1.1  christos 	    }
    625  1.1  christos 	  else
    626  1.1  christos 	    {
    627  1.1  christos 	      insn = bfd_getl32 (buffer + l);
    628  1.1  christos 	      info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
    629  1.1  christos 	      l += 4;
    630  1.1  christos 	    }
    631  1.1  christos 	}
    632  1.1  christos     }
    633  1.1  christos 
    634  1.1  christos   return code_length;
    635  1.1  christos }
    636