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