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