Home | History | Annotate | Line # | Download | only in opcodes
arc-dis.c revision 1.1
      1  1.1  christos /* Instruction printing code for the ARC.
      2  1.1  christos    Copyright 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2005, 2007, 2009,
      3  1.1  christos    2010, 2012 Free Software Foundation, Inc.
      4  1.1  christos    Contributed by Doug Evans (dje (at) cygnus.com).
      5  1.1  christos 
      6  1.1  christos    This file is part of libopcodes.
      7  1.1  christos 
      8  1.1  christos    This library is free software; you can redistribute it and/or modify
      9  1.1  christos    it under the terms of the GNU General Public License as published by
     10  1.1  christos    the Free Software Foundation; either version 3, or (at your option)
     11  1.1  christos    any later version.
     12  1.1  christos 
     13  1.1  christos    It is distributed in the hope that it will be useful, but WITHOUT
     14  1.1  christos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     15  1.1  christos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     16  1.1  christos    License for more details.
     17  1.1  christos 
     18  1.1  christos    You should have received a copy of the GNU General Public License
     19  1.1  christos    along with this program; if not, write to the Free Software
     20  1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     21  1.1  christos    MA 02110-1301, USA.  */
     22  1.1  christos 
     23  1.1  christos #include "sysdep.h"
     24  1.1  christos #include "libiberty.h"
     25  1.1  christos #include "dis-asm.h"
     26  1.1  christos #include "opcode/arc.h"
     27  1.1  christos #include "elf-bfd.h"
     28  1.1  christos #include "elf/arc.h"
     29  1.1  christos #include "opintl.h"
     30  1.1  christos 
     31  1.1  christos #include <stdarg.h>
     32  1.1  christos #include "arc-dis.h"
     33  1.1  christos #include "arc-ext.h"
     34  1.1  christos 
     35  1.1  christos #ifndef dbg
     36  1.1  christos #define dbg (0)
     37  1.1  christos #endif
     38  1.1  christos 
     39  1.1  christos /* Classification of the opcodes for the decoder to print
     40  1.1  christos    the instructions.  */
     41  1.1  christos 
     42  1.1  christos typedef enum
     43  1.1  christos {
     44  1.1  christos   CLASS_A4_ARITH,
     45  1.1  christos   CLASS_A4_OP3_GENERAL,
     46  1.1  christos   CLASS_A4_FLAG,
     47  1.1  christos   /* All branches other than JC.  */
     48  1.1  christos   CLASS_A4_BRANCH,
     49  1.1  christos   CLASS_A4_JC ,
     50  1.1  christos   /* All loads other than immediate
     51  1.1  christos      indexed loads.  */
     52  1.1  christos   CLASS_A4_LD0,
     53  1.1  christos   CLASS_A4_LD1,
     54  1.1  christos   CLASS_A4_ST,
     55  1.1  christos   CLASS_A4_SR,
     56  1.1  christos   /* All single operand instructions.  */
     57  1.1  christos   CLASS_A4_OP3_SUBOPC3F,
     58  1.1  christos   CLASS_A4_LR
     59  1.1  christos } a4_decoding_class;
     60  1.1  christos 
     61  1.1  christos #define BIT(word,n)	((word) & (1 << n))
     62  1.1  christos #define BITS(word,s,e)  (((word) >> s) & ((1 << (e + 1 - s)) - 1))
     63  1.1  christos #define OPCODE(word)	(BITS ((word), 27, 31))
     64  1.1  christos #define FIELDA(word)	(BITS ((word), 21, 26))
     65  1.1  christos #define FIELDB(word)	(BITS ((word), 15, 20))
     66  1.1  christos #define FIELDC(word)	(BITS ((word),  9, 14))
     67  1.1  christos 
     68  1.1  christos /* FIELD D is signed.  */
     69  1.1  christos #define FIELDD(word)	((BITS ((word), 0, 8) ^ 0x100) - 0x100)
     70  1.1  christos 
     71  1.1  christos #define PUT_NEXT_WORD_IN(a)						\
     72  1.1  christos   do									\
     73  1.1  christos     {									\
     74  1.1  christos       if (is_limm == 1 && !NEXT_WORD (1))				\
     75  1.1  christos         mwerror (state, _("Illegal limm reference in last instruction!\n")); \
     76  1.1  christos       a = state->words[1];						\
     77  1.1  christos     }									\
     78  1.1  christos   while (0)
     79  1.1  christos 
     80  1.1  christos #define CHECK_FLAG_COND_NULLIFY()				\
     81  1.1  christos   do								\
     82  1.1  christos     {								\
     83  1.1  christos       if (is_shimm == 0)					\
     84  1.1  christos         {							\
     85  1.1  christos           flag = BIT (state->words[0], 8);			\
     86  1.1  christos           state->nullifyMode = BITS (state->words[0], 5, 6);	\
     87  1.1  christos           cond = BITS (state->words[0], 0, 4);			\
     88  1.1  christos         }							\
     89  1.1  christos     }								\
     90  1.1  christos   while (0)
     91  1.1  christos 
     92  1.1  christos #define CHECK_COND()				\
     93  1.1  christos   do						\
     94  1.1  christos     {						\
     95  1.1  christos       if (is_shimm == 0)			\
     96  1.1  christos         cond = BITS (state->words[0], 0, 4);	\
     97  1.1  christos     }						\
     98  1.1  christos   while (0)
     99  1.1  christos 
    100  1.1  christos #define CHECK_FIELD(field)			\
    101  1.1  christos   do						\
    102  1.1  christos     {						\
    103  1.1  christos       if (field == 62)				\
    104  1.1  christos         {					\
    105  1.1  christos           is_limm++;				\
    106  1.1  christos 	  field##isReg = 0;			\
    107  1.1  christos 	  PUT_NEXT_WORD_IN (field);		\
    108  1.1  christos 	  limm_value = field;			\
    109  1.1  christos 	}					\
    110  1.1  christos       else if (field > 60)			\
    111  1.1  christos         {					\
    112  1.1  christos 	  field##isReg = 0;			\
    113  1.1  christos 	  is_shimm++;				\
    114  1.1  christos 	  flag = (field == 61);			\
    115  1.1  christos 	  field = FIELDD (state->words[0]);	\
    116  1.1  christos 	}					\
    117  1.1  christos     }						\
    118  1.1  christos   while (0)
    119  1.1  christos 
    120  1.1  christos #define CHECK_FIELD_A()				\
    121  1.1  christos   do						\
    122  1.1  christos     {						\
    123  1.1  christos       fieldA = FIELDA (state->words[0]);	\
    124  1.1  christos       if (fieldA > 60)				\
    125  1.1  christos         {					\
    126  1.1  christos 	  fieldAisReg = 0;			\
    127  1.1  christos 	  fieldA = 0;				\
    128  1.1  christos 	}					\
    129  1.1  christos     }						\
    130  1.1  christos   while (0)
    131  1.1  christos 
    132  1.1  christos #define CHECK_FIELD_B()				\
    133  1.1  christos   do						\
    134  1.1  christos     {						\
    135  1.1  christos       fieldB = FIELDB (state->words[0]);	\
    136  1.1  christos       CHECK_FIELD (fieldB);			\
    137  1.1  christos     }						\
    138  1.1  christos   while (0)
    139  1.1  christos 
    140  1.1  christos #define CHECK_FIELD_C()				\
    141  1.1  christos   do						\
    142  1.1  christos     {						\
    143  1.1  christos       fieldC = FIELDC (state->words[0]);	\
    144  1.1  christos       CHECK_FIELD (fieldC);			\
    145  1.1  christos     }						\
    146  1.1  christos   while (0)
    147  1.1  christos 
    148  1.1  christos #define IS_SMALL(x)                 (((field##x) < 256) && ((field##x) > -257))
    149  1.1  christos #define IS_REG(x)                    (field##x##isReg)
    150  1.1  christos #define WRITE_FORMAT_LB_Rx_RB(x)     WRITE_FORMAT (x, "[","]","","")
    151  1.1  christos #define WRITE_FORMAT_x_COMMA_LB(x)   WRITE_FORMAT (x, "",",[","",",[")
    152  1.1  christos #define WRITE_FORMAT_COMMA_x_RB(x)   WRITE_FORMAT (x, ",","]",",","]")
    153  1.1  christos #define WRITE_FORMAT_x_RB(x)         WRITE_FORMAT (x, "","]","","]")
    154  1.1  christos #define WRITE_FORMAT_COMMA_x(x)      WRITE_FORMAT (x, ",","",",","")
    155  1.1  christos #define WRITE_FORMAT_x_COMMA(x)      WRITE_FORMAT (x, "",",","",",")
    156  1.1  christos #define WRITE_FORMAT_x(x)            WRITE_FORMAT (x, "","","","")
    157  1.1  christos #define WRITE_FORMAT(x,cb1,ca1,cb,ca) strcat (formatString,		\
    158  1.1  christos 				     (IS_REG (x) ? cb1"%r"ca1 :		\
    159  1.1  christos 				      usesAuxReg ? cb"%a"ca :		\
    160  1.1  christos 				      IS_SMALL (x) ? cb"%d"ca : cb"%h"ca))
    161  1.1  christos #define WRITE_FORMAT_RB()	strcat (formatString, "]")
    162  1.1  christos #define WRITE_COMMENT(str)	(state->comm[state->commNum++] = (str))
    163  1.1  christos #define WRITE_NOP_COMMENT()	if (!fieldAisReg && !flag) WRITE_COMMENT ("nop");
    164  1.1  christos 
    165  1.1  christos #define NEXT_WORD(x)	(offset += 4, state->words[x])
    166  1.1  christos 
    167  1.1  christos #define add_target(x)	(state->targets[state->tcnt++] = (x))
    168  1.1  christos 
    169  1.1  christos static char comment_prefix[] = "\t; ";
    170  1.1  christos 
    171  1.1  christos static const char *
    172  1.1  christos core_reg_name (struct arcDisState * state, int val)
    173  1.1  christos {
    174  1.1  christos   if (state->coreRegName)
    175  1.1  christos     return (*state->coreRegName)(state->_this, val);
    176  1.1  christos   return 0;
    177  1.1  christos }
    178  1.1  christos 
    179  1.1  christos static const char *
    180  1.1  christos aux_reg_name (struct arcDisState * state, int val)
    181  1.1  christos {
    182  1.1  christos   if (state->auxRegName)
    183  1.1  christos     return (*state->auxRegName)(state->_this, val);
    184  1.1  christos   return 0;
    185  1.1  christos }
    186  1.1  christos 
    187  1.1  christos static const char *
    188  1.1  christos cond_code_name (struct arcDisState * state, int val)
    189  1.1  christos {
    190  1.1  christos   if (state->condCodeName)
    191  1.1  christos     return (*state->condCodeName)(state->_this, val);
    192  1.1  christos   return 0;
    193  1.1  christos }
    194  1.1  christos 
    195  1.1  christos static const char *
    196  1.1  christos instruction_name (struct arcDisState * state,
    197  1.1  christos 		  int    op1,
    198  1.1  christos 		  int    op2,
    199  1.1  christos 		  int *  flags)
    200  1.1  christos {
    201  1.1  christos   if (state->instName)
    202  1.1  christos     return (*state->instName)(state->_this, op1, op2, flags);
    203  1.1  christos   return 0;
    204  1.1  christos }
    205  1.1  christos 
    206  1.1  christos static void
    207  1.1  christos mwerror (struct arcDisState * state, const char * msg)
    208  1.1  christos {
    209  1.1  christos   if (state->err != 0)
    210  1.1  christos     (*state->err)(state->_this, (msg));
    211  1.1  christos }
    212  1.1  christos 
    213  1.1  christos static const char *
    214  1.1  christos post_address (struct arcDisState * state, int addr)
    215  1.1  christos {
    216  1.1  christos   static char id[3 * ARRAY_SIZE (state->addresses)];
    217  1.1  christos   int j, i = state->acnt;
    218  1.1  christos 
    219  1.1  christos   if (i < ((int) ARRAY_SIZE (state->addresses)))
    220  1.1  christos     {
    221  1.1  christos       state->addresses[i] = addr;
    222  1.1  christos       ++state->acnt;
    223  1.1  christos       j = i*3;
    224  1.1  christos       id[j+0] = '@';
    225  1.1  christos       id[j+1] = '0'+i;
    226  1.1  christos       id[j+2] = 0;
    227  1.1  christos 
    228  1.1  christos       return id + j;
    229  1.1  christos     }
    230  1.1  christos   return "";
    231  1.1  christos }
    232  1.1  christos 
    233  1.1  christos static void
    234  1.1  christos arc_sprintf (struct arcDisState *state, char *buf, const char *format, ...)
    235  1.1  christos {
    236  1.1  christos   char *bp;
    237  1.1  christos   const char *p;
    238  1.1  christos   int size, leading_zero, regMap[2];
    239  1.1  christos   va_list ap;
    240  1.1  christos 
    241  1.1  christos   va_start (ap, format);
    242  1.1  christos 
    243  1.1  christos   bp = buf;
    244  1.1  christos   *bp = 0;
    245  1.1  christos   p = format;
    246  1.1  christos   regMap[0] = 0;
    247  1.1  christos   regMap[1] = 0;
    248  1.1  christos 
    249  1.1  christos   while (1)
    250  1.1  christos     switch (*p++)
    251  1.1  christos       {
    252  1.1  christos       case 0:
    253  1.1  christos 	goto DOCOMM; /* (return)  */
    254  1.1  christos       default:
    255  1.1  christos 	*bp++ = p[-1];
    256  1.1  christos 	break;
    257  1.1  christos       case '%':
    258  1.1  christos 	size = 0;
    259  1.1  christos 	leading_zero = 0;
    260  1.1  christos       RETRY: ;
    261  1.1  christos 	switch (*p++)
    262  1.1  christos 	  {
    263  1.1  christos 	  case '0':
    264  1.1  christos 	  case '1':
    265  1.1  christos 	  case '2':
    266  1.1  christos 	  case '3':
    267  1.1  christos 	  case '4':
    268  1.1  christos 	  case '5':
    269  1.1  christos 	  case '6':
    270  1.1  christos 	  case '7':
    271  1.1  christos 	  case '8':
    272  1.1  christos 	  case '9':
    273  1.1  christos 	    {
    274  1.1  christos 	      /* size.  */
    275  1.1  christos 	      size = p[-1] - '0';
    276  1.1  christos 	      if (size == 0)
    277  1.1  christos 		leading_zero = 1; /* e.g. %08x  */
    278  1.1  christos 	      while (*p >= '0' && *p <= '9')
    279  1.1  christos 		{
    280  1.1  christos 		  size = size * 10 + *p - '0';
    281  1.1  christos 		  p++;
    282  1.1  christos 		}
    283  1.1  christos 	      goto RETRY;
    284  1.1  christos 	    }
    285  1.1  christos #define inc_bp() bp = bp + strlen (bp)
    286  1.1  christos 
    287  1.1  christos 	  case 'h':
    288  1.1  christos 	    {
    289  1.1  christos 	      unsigned u = va_arg (ap, int);
    290  1.1  christos 
    291  1.1  christos 	      /* Hex.  We can change the format to 0x%08x in
    292  1.1  christos 		 one place, here, if we wish.
    293  1.1  christos 		 We add underscores for easy reading.  */
    294  1.1  christos 	      if (u > 65536)
    295  1.1  christos 		sprintf (bp, "0x%x_%04x", u >> 16, u & 0xffff);
    296  1.1  christos 	      else
    297  1.1  christos 		sprintf (bp, "0x%x", u);
    298  1.1  christos 	      inc_bp ();
    299  1.1  christos 	    }
    300  1.1  christos 	    break;
    301  1.1  christos 	  case 'X': case 'x':
    302  1.1  christos 	    {
    303  1.1  christos 	      int val = va_arg (ap, int);
    304  1.1  christos 
    305  1.1  christos 	      if (size != 0)
    306  1.1  christos 		if (leading_zero)
    307  1.1  christos 		  sprintf (bp, "%0*x", size, val);
    308  1.1  christos 		else
    309  1.1  christos 		  sprintf (bp, "%*x", size, val);
    310  1.1  christos 	      else
    311  1.1  christos 		sprintf (bp, "%x", val);
    312  1.1  christos 	      inc_bp ();
    313  1.1  christos 	    }
    314  1.1  christos 	    break;
    315  1.1  christos 	  case 'd':
    316  1.1  christos 	    {
    317  1.1  christos 	      int val = va_arg (ap, int);
    318  1.1  christos 
    319  1.1  christos 	      if (size != 0)
    320  1.1  christos 		sprintf (bp, "%*d", size, val);
    321  1.1  christos 	      else
    322  1.1  christos 		sprintf (bp, "%d", val);
    323  1.1  christos 	      inc_bp ();
    324  1.1  christos 	    }
    325  1.1  christos 	    break;
    326  1.1  christos 	  case 'r':
    327  1.1  christos 	    {
    328  1.1  christos 	      /* Register.  */
    329  1.1  christos 	      int val = va_arg (ap, int);
    330  1.1  christos 
    331  1.1  christos #define REG2NAME(num, name) case num: sprintf (bp, ""name); \
    332  1.1  christos   regMap[(num < 32) ? 0 : 1] |= 1 << (num - ((num < 32) ? 0 : 32)); break;
    333  1.1  christos 
    334  1.1  christos 	      switch (val)
    335  1.1  christos 		{
    336  1.1  christos 		  REG2NAME (26, "gp");
    337  1.1  christos 		  REG2NAME (27, "fp");
    338  1.1  christos 		  REG2NAME (28, "sp");
    339  1.1  christos 		  REG2NAME (29, "ilink1");
    340  1.1  christos 		  REG2NAME (30, "ilink2");
    341  1.1  christos 		  REG2NAME (31, "blink");
    342  1.1  christos 		  REG2NAME (60, "lp_count");
    343  1.1  christos 		default:
    344  1.1  christos 		  {
    345  1.1  christos 		    const char * ext;
    346  1.1  christos 
    347  1.1  christos 		    ext = core_reg_name (state, val);
    348  1.1  christos 		    if (ext)
    349  1.1  christos 		      sprintf (bp, "%s", ext);
    350  1.1  christos 		    else
    351  1.1  christos 		      sprintf (bp,"r%d",val);
    352  1.1  christos 		  }
    353  1.1  christos 		  break;
    354  1.1  christos 		}
    355  1.1  christos 	      inc_bp ();
    356  1.1  christos 	    } break;
    357  1.1  christos 
    358  1.1  christos 	  case 'a':
    359  1.1  christos 	    {
    360  1.1  christos 	      /* Aux Register.  */
    361  1.1  christos 	      int val = va_arg (ap, int);
    362  1.1  christos 
    363  1.1  christos #define AUXREG2NAME(num, name) case num: sprintf (bp,name); break;
    364  1.1  christos 
    365  1.1  christos 	      switch (val)
    366  1.1  christos 		{
    367  1.1  christos 		  AUXREG2NAME (0x0, "status");
    368  1.1  christos 		  AUXREG2NAME (0x1, "semaphore");
    369  1.1  christos 		  AUXREG2NAME (0x2, "lp_start");
    370  1.1  christos 		  AUXREG2NAME (0x3, "lp_end");
    371  1.1  christos 		  AUXREG2NAME (0x4, "identity");
    372  1.1  christos 		  AUXREG2NAME (0x5, "debug");
    373  1.1  christos 		default:
    374  1.1  christos 		  {
    375  1.1  christos 		    const char *ext;
    376  1.1  christos 
    377  1.1  christos 		    ext = aux_reg_name (state, val);
    378  1.1  christos 		    if (ext)
    379  1.1  christos 		      sprintf (bp, "%s", ext);
    380  1.1  christos 		    else
    381  1.1  christos 		      arc_sprintf (state, bp, "%h", val);
    382  1.1  christos 		  }
    383  1.1  christos 		  break;
    384  1.1  christos 		}
    385  1.1  christos 	      inc_bp ();
    386  1.1  christos 	    }
    387  1.1  christos 	    break;
    388  1.1  christos 
    389  1.1  christos 	  case 's':
    390  1.1  christos 	    {
    391  1.1  christos 	      sprintf (bp, "%s", va_arg (ap, char *));
    392  1.1  christos 	      inc_bp ();
    393  1.1  christos 	    }
    394  1.1  christos 	    break;
    395  1.1  christos 
    396  1.1  christos 	  default:
    397  1.1  christos 	    fprintf (stderr, "?? format %c\n", p[-1]);
    398  1.1  christos 	    break;
    399  1.1  christos 	  }
    400  1.1  christos       }
    401  1.1  christos 
    402  1.1  christos  DOCOMM: *bp = 0;
    403  1.1  christos   va_end (ap);
    404  1.1  christos }
    405  1.1  christos 
    406  1.1  christos static void
    407  1.1  christos write_comments_(struct arcDisState * state,
    408  1.1  christos 		int shimm,
    409  1.1  christos 		int is_limm,
    410  1.1  christos 		long limm_value)
    411  1.1  christos {
    412  1.1  christos   if (state->commentBuffer != 0)
    413  1.1  christos     {
    414  1.1  christos       int i;
    415  1.1  christos 
    416  1.1  christos       if (is_limm)
    417  1.1  christos 	{
    418  1.1  christos 	  const char *name = post_address (state, limm_value + shimm);
    419  1.1  christos 
    420  1.1  christos 	  if (*name != 0)
    421  1.1  christos 	    WRITE_COMMENT (name);
    422  1.1  christos 	}
    423  1.1  christos       for (i = 0; i < state->commNum; i++)
    424  1.1  christos 	{
    425  1.1  christos 	  if (i == 0)
    426  1.1  christos 	    strcpy (state->commentBuffer, comment_prefix);
    427  1.1  christos 	  else
    428  1.1  christos 	    strcat (state->commentBuffer, ", ");
    429  1.1  christos 	  strcat (state->commentBuffer, state->comm[i]);
    430  1.1  christos 	}
    431  1.1  christos     }
    432  1.1  christos }
    433  1.1  christos 
    434  1.1  christos #define write_comments2(x) write_comments_ (state, x, is_limm, limm_value)
    435  1.1  christos #define write_comments()   write_comments2 (0)
    436  1.1  christos 
    437  1.1  christos static const char *condName[] =
    438  1.1  christos {
    439  1.1  christos   /* 0..15.  */
    440  1.1  christos   ""   , "z"  , "nz" , "p"  , "n"  , "c"  , "nc" , "v"  ,
    441  1.1  christos   "nv" , "gt" , "ge" , "lt" , "le" , "hi" , "ls" , "pnz"
    442  1.1  christos };
    443  1.1  christos 
    444  1.1  christos static void
    445  1.1  christos write_instr_name_(struct arcDisState * state,
    446  1.1  christos 		  const char * instrName,
    447  1.1  christos 		  int cond,
    448  1.1  christos 		  int condCodeIsPartOfName,
    449  1.1  christos 		  int flag,
    450  1.1  christos 		  int signExtend,
    451  1.1  christos 		  int addrWriteBack,
    452  1.1  christos 		  int directMem)
    453  1.1  christos {
    454  1.1  christos   strcpy (state->instrBuffer, instrName);
    455  1.1  christos 
    456  1.1  christos   if (cond > 0)
    457  1.1  christos     {
    458  1.1  christos       const char *cc = 0;
    459  1.1  christos 
    460  1.1  christos       if (!condCodeIsPartOfName)
    461  1.1  christos 	strcat (state->instrBuffer, ".");
    462  1.1  christos 
    463  1.1  christos       if (cond < 16)
    464  1.1  christos 	cc = condName[cond];
    465  1.1  christos       else
    466  1.1  christos 	cc = cond_code_name (state, cond);
    467  1.1  christos 
    468  1.1  christos       if (!cc)
    469  1.1  christos 	cc = "???";
    470  1.1  christos 
    471  1.1  christos       strcat (state->instrBuffer, cc);
    472  1.1  christos     }
    473  1.1  christos 
    474  1.1  christos   if (flag)
    475  1.1  christos     strcat (state->instrBuffer, ".f");
    476  1.1  christos 
    477  1.1  christos   switch (state->nullifyMode)
    478  1.1  christos     {
    479  1.1  christos     case BR_exec_always:
    480  1.1  christos       strcat (state->instrBuffer, ".d");
    481  1.1  christos       break;
    482  1.1  christos     case BR_exec_when_jump:
    483  1.1  christos       strcat (state->instrBuffer, ".jd");
    484  1.1  christos       break;
    485  1.1  christos     }
    486  1.1  christos 
    487  1.1  christos   if (signExtend)
    488  1.1  christos     strcat (state->instrBuffer, ".x");
    489  1.1  christos 
    490  1.1  christos   if (addrWriteBack)
    491  1.1  christos     strcat (state->instrBuffer, ".a");
    492  1.1  christos 
    493  1.1  christos   if (directMem)
    494  1.1  christos     strcat (state->instrBuffer, ".di");
    495  1.1  christos }
    496  1.1  christos 
    497  1.1  christos #define write_instr_name()						\
    498  1.1  christos   do									\
    499  1.1  christos     {									\
    500  1.1  christos       write_instr_name_(state, instrName,cond, condCodeIsPartOfName,	\
    501  1.1  christos 			flag, signExtend, addrWriteBack, directMem);	\
    502  1.1  christos       formatString[0] = '\0';						\
    503  1.1  christos     }									\
    504  1.1  christos   while (0)
    505  1.1  christos 
    506  1.1  christos enum
    507  1.1  christos {
    508  1.1  christos   op_LD0 = 0, op_LD1 = 1, op_ST  = 2, op_3   = 3,
    509  1.1  christos   op_BC  = 4, op_BLC = 5, op_LPC = 6, op_JC  = 7,
    510  1.1  christos   op_ADD = 8, op_ADC = 9, op_SUB = 10, op_SBC = 11,
    511  1.1  christos   op_AND = 12, op_OR  = 13, op_BIC = 14, op_XOR = 15
    512  1.1  christos };
    513  1.1  christos 
    514  1.1  christos extern disassemble_info tm_print_insn_info;
    515  1.1  christos 
    516  1.1  christos static int
    517  1.1  christos dsmOneArcInst (bfd_vma addr, struct arcDisState * state)
    518  1.1  christos {
    519  1.1  christos   int condCodeIsPartOfName = 0;
    520  1.1  christos   a4_decoding_class decodingClass;
    521  1.1  christos   const char * instrName;
    522  1.1  christos   int repeatsOp = 0;
    523  1.1  christos   int fieldAisReg = 1;
    524  1.1  christos   int fieldBisReg = 1;
    525  1.1  christos   int fieldCisReg = 1;
    526  1.1  christos   int fieldA;
    527  1.1  christos   int fieldB;
    528  1.1  christos   int fieldC = 0;
    529  1.1  christos   int flag = 0;
    530  1.1  christos   int cond = 0;
    531  1.1  christos   int is_shimm = 0;
    532  1.1  christos   int is_limm = 0;
    533  1.1  christos   long limm_value = 0;
    534  1.1  christos   int signExtend = 0;
    535  1.1  christos   int addrWriteBack = 0;
    536  1.1  christos   int directMem = 0;
    537  1.1  christos   int is_linked = 0;
    538  1.1  christos   int offset = 0;
    539  1.1  christos   int usesAuxReg = 0;
    540  1.1  christos   int flags;
    541  1.1  christos   int ignoreFirstOpd;
    542  1.1  christos   char formatString[60];
    543  1.1  christos 
    544  1.1  christos   state->instructionLen = 4;
    545  1.1  christos   state->nullifyMode = BR_exec_when_no_jump;
    546  1.1  christos   state->opWidth = 12;
    547  1.1  christos   state->isBranch = 0;
    548  1.1  christos 
    549  1.1  christos   state->_mem_load = 0;
    550  1.1  christos   state->_ea_present = 0;
    551  1.1  christos   state->_load_len = 0;
    552  1.1  christos   state->ea_reg1 = no_reg;
    553  1.1  christos   state->ea_reg2 = no_reg;
    554  1.1  christos   state->_offset = 0;
    555  1.1  christos 
    556  1.1  christos   if (! NEXT_WORD (0))
    557  1.1  christos     return 0;
    558  1.1  christos 
    559  1.1  christos   state->_opcode = OPCODE (state->words[0]);
    560  1.1  christos   instrName = 0;
    561  1.1  christos   decodingClass = CLASS_A4_ARITH; /* default!  */
    562  1.1  christos   repeatsOp = 0;
    563  1.1  christos   condCodeIsPartOfName=0;
    564  1.1  christos   state->commNum = 0;
    565  1.1  christos   state->tcnt = 0;
    566  1.1  christos   state->acnt = 0;
    567  1.1  christos   state->flow = noflow;
    568  1.1  christos   ignoreFirstOpd = 0;
    569  1.1  christos 
    570  1.1  christos   if (state->commentBuffer)
    571  1.1  christos     state->commentBuffer[0] = '\0';
    572  1.1  christos 
    573  1.1  christos   switch (state->_opcode)
    574  1.1  christos     {
    575  1.1  christos     case op_LD0:
    576  1.1  christos       switch (BITS (state->words[0],1,2))
    577  1.1  christos 	{
    578  1.1  christos 	case 0:
    579  1.1  christos 	  instrName = "ld";
    580  1.1  christos 	  state->_load_len = 4;
    581  1.1  christos 	  break;
    582  1.1  christos 	case 1:
    583  1.1  christos 	  instrName = "ldb";
    584  1.1  christos 	  state->_load_len = 1;
    585  1.1  christos 	  break;
    586  1.1  christos 	case 2:
    587  1.1  christos 	  instrName = "ldw";
    588  1.1  christos 	  state->_load_len = 2;
    589  1.1  christos 	  break;
    590  1.1  christos 	default:
    591  1.1  christos 	  instrName = "??? (0[3])";
    592  1.1  christos 	  state->flow = invalid_instr;
    593  1.1  christos 	  break;
    594  1.1  christos 	}
    595  1.1  christos       decodingClass = CLASS_A4_LD0;
    596  1.1  christos       break;
    597  1.1  christos 
    598  1.1  christos     case op_LD1:
    599  1.1  christos       if (BIT (state->words[0],13))
    600  1.1  christos 	{
    601  1.1  christos 	  instrName = "lr";
    602  1.1  christos 	  decodingClass = CLASS_A4_LR;
    603  1.1  christos 	}
    604  1.1  christos       else
    605  1.1  christos 	{
    606  1.1  christos 	  switch (BITS (state->words[0], 10, 11))
    607  1.1  christos 	    {
    608  1.1  christos 	    case 0:
    609  1.1  christos 	      instrName = "ld";
    610  1.1  christos 	      state->_load_len = 4;
    611  1.1  christos 	      break;
    612  1.1  christos 	    case 1:
    613  1.1  christos 	      instrName = "ldb";
    614  1.1  christos 	      state->_load_len = 1;
    615  1.1  christos 	      break;
    616  1.1  christos 	    case 2:
    617  1.1  christos 	      instrName = "ldw";
    618  1.1  christos 	      state->_load_len = 2;
    619  1.1  christos 	      break;
    620  1.1  christos 	    default:
    621  1.1  christos 	      instrName = "??? (1[3])";
    622  1.1  christos 	      state->flow = invalid_instr;
    623  1.1  christos 	      break;
    624  1.1  christos 	    }
    625  1.1  christos 	  decodingClass = CLASS_A4_LD1;
    626  1.1  christos 	}
    627  1.1  christos       break;
    628  1.1  christos 
    629  1.1  christos     case op_ST:
    630  1.1  christos       if (BIT (state->words[0], 25))
    631  1.1  christos 	{
    632  1.1  christos 	  instrName = "sr";
    633  1.1  christos 	  decodingClass = CLASS_A4_SR;
    634  1.1  christos 	}
    635  1.1  christos       else
    636  1.1  christos 	{
    637  1.1  christos 	  switch (BITS (state->words[0], 22, 23))
    638  1.1  christos 	    {
    639  1.1  christos 	    case 0:
    640  1.1  christos 	      instrName = "st";
    641  1.1  christos 	      break;
    642  1.1  christos 	    case 1:
    643  1.1  christos 	      instrName = "stb";
    644  1.1  christos 	      break;
    645  1.1  christos 	    case 2:
    646  1.1  christos 	      instrName = "stw";
    647  1.1  christos 	      break;
    648  1.1  christos 	    default:
    649  1.1  christos 	      instrName = "??? (2[3])";
    650  1.1  christos 	      state->flow = invalid_instr;
    651  1.1  christos 	      break;
    652  1.1  christos 	    }
    653  1.1  christos 	  decodingClass = CLASS_A4_ST;
    654  1.1  christos 	}
    655  1.1  christos       break;
    656  1.1  christos 
    657  1.1  christos     case op_3:
    658  1.1  christos       decodingClass = CLASS_A4_OP3_GENERAL;  /* default for opcode 3...  */
    659  1.1  christos       switch (FIELDC (state->words[0]))
    660  1.1  christos 	{
    661  1.1  christos 	case  0:
    662  1.1  christos 	  instrName = "flag";
    663  1.1  christos 	  decodingClass = CLASS_A4_FLAG;
    664  1.1  christos 	  break;
    665  1.1  christos 	case  1:
    666  1.1  christos 	  instrName = "asr";
    667  1.1  christos 	  break;
    668  1.1  christos 	case  2:
    669  1.1  christos 	  instrName = "lsr";
    670  1.1  christos 	  break;
    671  1.1  christos 	case  3:
    672  1.1  christos 	  instrName = "ror";
    673  1.1  christos 	  break;
    674  1.1  christos 	case  4:
    675  1.1  christos 	  instrName = "rrc";
    676  1.1  christos 	  break;
    677  1.1  christos 	case  5:
    678  1.1  christos 	  instrName = "sexb";
    679  1.1  christos 	  break;
    680  1.1  christos 	case  6:
    681  1.1  christos 	  instrName = "sexw";
    682  1.1  christos 	  break;
    683  1.1  christos 	case  7:
    684  1.1  christos 	  instrName = "extb";
    685  1.1  christos 	  break;
    686  1.1  christos 	case  8:
    687  1.1  christos 	  instrName = "extw";
    688  1.1  christos 	  break;
    689  1.1  christos 	case  0x3f:
    690  1.1  christos 	  {
    691  1.1  christos 	    decodingClass = CLASS_A4_OP3_SUBOPC3F;
    692  1.1  christos 	    switch (FIELDD (state->words[0]))
    693  1.1  christos 	      {
    694  1.1  christos 	      case 0:
    695  1.1  christos 		instrName = "brk";
    696  1.1  christos 		break;
    697  1.1  christos 	      case 1:
    698  1.1  christos 		instrName = "sleep";
    699  1.1  christos 		break;
    700  1.1  christos 	      case 2:
    701  1.1  christos 		instrName = "swi";
    702  1.1  christos 		break;
    703  1.1  christos 	      default:
    704  1.1  christos 		instrName = "???";
    705  1.1  christos 		state->flow=invalid_instr;
    706  1.1  christos 		break;
    707  1.1  christos 	      }
    708  1.1  christos 	  }
    709  1.1  christos 	  break;
    710  1.1  christos 
    711  1.1  christos 	  /* ARC Extension Library Instructions
    712  1.1  christos 	     NOTE: We assume that extension codes are these instrs.  */
    713  1.1  christos 	default:
    714  1.1  christos 	  instrName = instruction_name (state,
    715  1.1  christos 					state->_opcode,
    716  1.1  christos 					FIELDC (state->words[0]),
    717  1.1  christos 					&flags);
    718  1.1  christos 	  if (!instrName)
    719  1.1  christos 	    {
    720  1.1  christos 	      instrName = "???";
    721  1.1  christos 	      state->flow = invalid_instr;
    722  1.1  christos 	    }
    723  1.1  christos 	  if (flags & IGNORE_FIRST_OPD)
    724  1.1  christos 	    ignoreFirstOpd = 1;
    725  1.1  christos 	  break;
    726  1.1  christos 	}
    727  1.1  christos       break;
    728  1.1  christos 
    729  1.1  christos     case op_BC:
    730  1.1  christos       instrName = "b";
    731  1.1  christos     case op_BLC:
    732  1.1  christos       if (!instrName)
    733  1.1  christos 	instrName = "bl";
    734  1.1  christos     case op_LPC:
    735  1.1  christos       if (!instrName)
    736  1.1  christos 	instrName = "lp";
    737  1.1  christos     case op_JC:
    738  1.1  christos       if (!instrName)
    739  1.1  christos 	{
    740  1.1  christos 	  if (BITS (state->words[0],9,9))
    741  1.1  christos 	    {
    742  1.1  christos 	      instrName = "jl";
    743  1.1  christos 	      is_linked = 1;
    744  1.1  christos 	    }
    745  1.1  christos 	  else
    746  1.1  christos 	    {
    747  1.1  christos 	      instrName = "j";
    748  1.1  christos 	      is_linked = 0;
    749  1.1  christos 	    }
    750  1.1  christos 	}
    751  1.1  christos       condCodeIsPartOfName = 1;
    752  1.1  christos       decodingClass = ((state->_opcode == op_JC) ? CLASS_A4_JC : CLASS_A4_BRANCH );
    753  1.1  christos       state->isBranch = 1;
    754  1.1  christos       break;
    755  1.1  christos 
    756  1.1  christos     case op_ADD:
    757  1.1  christos     case op_ADC:
    758  1.1  christos     case op_AND:
    759  1.1  christos       repeatsOp = (FIELDC (state->words[0]) == FIELDB (state->words[0]));
    760  1.1  christos 
    761  1.1  christos       switch (state->_opcode)
    762  1.1  christos 	{
    763  1.1  christos 	case op_ADD:
    764  1.1  christos 	  instrName = (repeatsOp ? "asl" : "add");
    765  1.1  christos 	  break;
    766  1.1  christos 	case op_ADC:
    767  1.1  christos 	  instrName = (repeatsOp ? "rlc" : "adc");
    768  1.1  christos 	  break;
    769  1.1  christos 	case op_AND:
    770  1.1  christos 	  instrName = (repeatsOp ? "mov" : "and");
    771  1.1  christos 	  break;
    772  1.1  christos 	}
    773  1.1  christos       break;
    774  1.1  christos 
    775  1.1  christos     case op_SUB: instrName = "sub";
    776  1.1  christos       break;
    777  1.1  christos     case op_SBC: instrName = "sbc";
    778  1.1  christos       break;
    779  1.1  christos     case op_OR:  instrName = "or";
    780  1.1  christos       break;
    781  1.1  christos     case op_BIC: instrName = "bic";
    782  1.1  christos       break;
    783  1.1  christos 
    784  1.1  christos     case op_XOR:
    785  1.1  christos       if (state->words[0] == 0x7fffffff)
    786  1.1  christos 	{
    787  1.1  christos 	  /* NOP encoded as xor -1, -1, -1.   */
    788  1.1  christos 	  instrName = "nop";
    789  1.1  christos 	  decodingClass = CLASS_A4_OP3_SUBOPC3F;
    790  1.1  christos 	}
    791  1.1  christos       else
    792  1.1  christos 	instrName = "xor";
    793  1.1  christos       break;
    794  1.1  christos 
    795  1.1  christos     default:
    796  1.1  christos       instrName = instruction_name (state,state->_opcode,0,&flags);
    797  1.1  christos       /* if (instrName) printf("FLAGS=0x%x\n", flags);  */
    798  1.1  christos       if (!instrName)
    799  1.1  christos 	{
    800  1.1  christos 	  instrName = "???";
    801  1.1  christos 	  state->flow=invalid_instr;
    802  1.1  christos 	}
    803  1.1  christos       if (flags & IGNORE_FIRST_OPD)
    804  1.1  christos 	ignoreFirstOpd = 1;
    805  1.1  christos       break;
    806  1.1  christos     }
    807  1.1  christos 
    808  1.1  christos   fieldAisReg = fieldBisReg = fieldCisReg = 1; /* Assume regs for now.  */
    809  1.1  christos   flag = cond = is_shimm = is_limm = 0;
    810  1.1  christos   state->nullifyMode = BR_exec_when_no_jump;	/* 0  */
    811  1.1  christos   signExtend = addrWriteBack = directMem = 0;
    812  1.1  christos   usesAuxReg = 0;
    813  1.1  christos 
    814  1.1  christos   switch (decodingClass)
    815  1.1  christos     {
    816  1.1  christos     case CLASS_A4_ARITH:
    817  1.1  christos       CHECK_FIELD_A ();
    818  1.1  christos       CHECK_FIELD_B ();
    819  1.1  christos       if (!repeatsOp)
    820  1.1  christos 	CHECK_FIELD_C ();
    821  1.1  christos       CHECK_FLAG_COND_NULLIFY ();
    822  1.1  christos 
    823  1.1  christos       write_instr_name ();
    824  1.1  christos       if (!ignoreFirstOpd)
    825  1.1  christos 	{
    826  1.1  christos 	  WRITE_FORMAT_x (A);
    827  1.1  christos 	  WRITE_FORMAT_COMMA_x (B);
    828  1.1  christos 	  if (!repeatsOp)
    829  1.1  christos 	    WRITE_FORMAT_COMMA_x (C);
    830  1.1  christos 	  WRITE_NOP_COMMENT ();
    831  1.1  christos 	  arc_sprintf (state, state->operandBuffer, formatString,
    832  1.1  christos 		      fieldA, fieldB, fieldC);
    833  1.1  christos 	}
    834  1.1  christos       else
    835  1.1  christos 	{
    836  1.1  christos 	  WRITE_FORMAT_x (B);
    837  1.1  christos 	  if (!repeatsOp)
    838  1.1  christos 	    WRITE_FORMAT_COMMA_x (C);
    839  1.1  christos 	  arc_sprintf (state, state->operandBuffer, formatString,
    840  1.1  christos 		      fieldB, fieldC);
    841  1.1  christos 	}
    842  1.1  christos       write_comments ();
    843  1.1  christos       break;
    844  1.1  christos 
    845  1.1  christos     case CLASS_A4_OP3_GENERAL:
    846  1.1  christos       CHECK_FIELD_A ();
    847  1.1  christos       CHECK_FIELD_B ();
    848  1.1  christos       CHECK_FLAG_COND_NULLIFY ();
    849  1.1  christos 
    850  1.1  christos       write_instr_name ();
    851  1.1  christos       if (!ignoreFirstOpd)
    852  1.1  christos 	{
    853  1.1  christos 	  WRITE_FORMAT_x (A);
    854  1.1  christos 	  WRITE_FORMAT_COMMA_x (B);
    855  1.1  christos 	  WRITE_NOP_COMMENT ();
    856  1.1  christos 	  arc_sprintf (state, state->operandBuffer, formatString,
    857  1.1  christos 		      fieldA, fieldB);
    858  1.1  christos 	}
    859  1.1  christos       else
    860  1.1  christos 	{
    861  1.1  christos 	  WRITE_FORMAT_x (B);
    862  1.1  christos 	  arc_sprintf (state, state->operandBuffer, formatString, fieldB);
    863  1.1  christos 	}
    864  1.1  christos       write_comments ();
    865  1.1  christos       break;
    866  1.1  christos 
    867  1.1  christos     case CLASS_A4_FLAG:
    868  1.1  christos       CHECK_FIELD_B ();
    869  1.1  christos       CHECK_FLAG_COND_NULLIFY ();
    870  1.1  christos       flag = 0; /* This is the FLAG instruction -- it's redundant.  */
    871  1.1  christos 
    872  1.1  christos       write_instr_name ();
    873  1.1  christos       WRITE_FORMAT_x (B);
    874  1.1  christos       arc_sprintf (state, state->operandBuffer, formatString, fieldB);
    875  1.1  christos       write_comments ();
    876  1.1  christos       break;
    877  1.1  christos 
    878  1.1  christos     case CLASS_A4_BRANCH:
    879  1.1  christos       fieldA = BITS (state->words[0],7,26) << 2;
    880  1.1  christos       fieldA = (fieldA << 10) >> 10; /* Make it signed.  */
    881  1.1  christos       fieldA += addr + 4;
    882  1.1  christos       CHECK_FLAG_COND_NULLIFY ();
    883  1.1  christos       flag = 0;
    884  1.1  christos 
    885  1.1  christos       write_instr_name ();
    886  1.1  christos       /* This address could be a label we know. Convert it.  */
    887  1.1  christos       if (state->_opcode != op_LPC /* LP  */)
    888  1.1  christos 	{
    889  1.1  christos 	  add_target (fieldA); /* For debugger.  */
    890  1.1  christos 	  state->flow = state->_opcode == op_BLC /* BL  */
    891  1.1  christos 	    ? direct_call
    892  1.1  christos 	    : direct_jump;
    893  1.1  christos 	  /* indirect calls are achieved by "lr blink,[status];
    894  1.1  christos 	     lr dest<- func addr; j [dest]"  */
    895  1.1  christos 	}
    896  1.1  christos 
    897  1.1  christos       strcat (formatString, "%s"); /* Address/label name.  */
    898  1.1  christos       arc_sprintf (state, state->operandBuffer, formatString,
    899  1.1  christos 		  post_address (state, fieldA));
    900  1.1  christos       write_comments ();
    901  1.1  christos       break;
    902  1.1  christos 
    903  1.1  christos     case CLASS_A4_JC:
    904  1.1  christos       /* For op_JC -- jump to address specified.
    905  1.1  christos 	 Also covers jump and link--bit 9 of the instr. word
    906  1.1  christos 	 selects whether linked, thus "is_linked" is set above.  */
    907  1.1  christos       fieldA = 0;
    908  1.1  christos       CHECK_FIELD_B ();
    909  1.1  christos       CHECK_FLAG_COND_NULLIFY ();
    910  1.1  christos 
    911  1.1  christos       if (!fieldBisReg)
    912  1.1  christos 	{
    913  1.1  christos 	  fieldAisReg = 0;
    914  1.1  christos 	  fieldA = (fieldB >> 25) & 0x7F; /* Flags.  */
    915  1.1  christos 	  fieldB = (fieldB & 0xFFFFFF) << 2;
    916  1.1  christos 	  state->flow = is_linked ? direct_call : direct_jump;
    917  1.1  christos 	  add_target (fieldB);
    918  1.1  christos 	  /* Screwy JLcc requires .jd mode to execute correctly
    919  1.1  christos 	     but we pretend it is .nd (no delay slot).  */
    920  1.1  christos 	  if (is_linked && state->nullifyMode == BR_exec_when_jump)
    921  1.1  christos 	    state->nullifyMode = BR_exec_when_no_jump;
    922  1.1  christos 	}
    923  1.1  christos       else
    924  1.1  christos 	{
    925  1.1  christos 	  state->flow = is_linked ? indirect_call : indirect_jump;
    926  1.1  christos 	  /* We should also treat this as indirect call if NOT linked
    927  1.1  christos 	     but the preceding instruction was a "lr blink,[status]"
    928  1.1  christos 	     and we have a delay slot with "add blink,blink,2".
    929  1.1  christos 	     For now we can't detect such.  */
    930  1.1  christos 	  state->register_for_indirect_jump = fieldB;
    931  1.1  christos 	}
    932  1.1  christos 
    933  1.1  christos       write_instr_name ();
    934  1.1  christos       strcat (formatString,
    935  1.1  christos 	      IS_REG (B) ? "[%r]" : "%s"); /* Address/label name.  */
    936  1.1  christos       if (fieldA != 0)
    937  1.1  christos 	{
    938  1.1  christos 	  fieldAisReg = 0;
    939  1.1  christos 	  WRITE_FORMAT_COMMA_x (A);
    940  1.1  christos 	}
    941  1.1  christos       if (IS_REG (B))
    942  1.1  christos 	arc_sprintf (state, state->operandBuffer, formatString, fieldB, fieldA);
    943  1.1  christos       else
    944  1.1  christos 	arc_sprintf (state, state->operandBuffer, formatString,
    945  1.1  christos 		    post_address (state, fieldB), fieldA);
    946  1.1  christos       write_comments ();
    947  1.1  christos       break;
    948  1.1  christos 
    949  1.1  christos     case CLASS_A4_LD0:
    950  1.1  christos       /* LD instruction.
    951  1.1  christos 	 B and C can be regs, or one (both?) can be limm.  */
    952  1.1  christos       CHECK_FIELD_A ();
    953  1.1  christos       CHECK_FIELD_B ();
    954  1.1  christos       CHECK_FIELD_C ();
    955  1.1  christos       if (dbg)
    956  1.1  christos 	printf ("5:b reg %d %d c reg %d %d  \n",
    957  1.1  christos 		fieldBisReg,fieldB,fieldCisReg,fieldC);
    958  1.1  christos       state->_offset = 0;
    959  1.1  christos       state->_ea_present = 1;
    960  1.1  christos       if (fieldBisReg)
    961  1.1  christos 	state->ea_reg1 = fieldB;
    962  1.1  christos       else
    963  1.1  christos 	state->_offset += fieldB;
    964  1.1  christos       if (fieldCisReg)
    965  1.1  christos 	state->ea_reg2 = fieldC;
    966  1.1  christos       else
    967  1.1  christos 	state->_offset += fieldC;
    968  1.1  christos       state->_mem_load = 1;
    969  1.1  christos 
    970  1.1  christos       directMem     = BIT (state->words[0], 5);
    971  1.1  christos       addrWriteBack = BIT (state->words[0], 3);
    972  1.1  christos       signExtend    = BIT (state->words[0], 0);
    973  1.1  christos 
    974  1.1  christos       write_instr_name ();
    975  1.1  christos       WRITE_FORMAT_x_COMMA_LB(A);
    976  1.1  christos       if (fieldBisReg || fieldB != 0)
    977  1.1  christos 	WRITE_FORMAT_x_COMMA (B);
    978  1.1  christos       else
    979  1.1  christos 	fieldB = fieldC;
    980  1.1  christos 
    981  1.1  christos       WRITE_FORMAT_x_RB (C);
    982  1.1  christos       arc_sprintf (state, state->operandBuffer, formatString,
    983  1.1  christos 		  fieldA, fieldB, fieldC);
    984  1.1  christos       write_comments ();
    985  1.1  christos       break;
    986  1.1  christos 
    987  1.1  christos     case CLASS_A4_LD1:
    988  1.1  christos       /* LD instruction.  */
    989  1.1  christos       CHECK_FIELD_B ();
    990  1.1  christos       CHECK_FIELD_A ();
    991  1.1  christos       fieldC = FIELDD (state->words[0]);
    992  1.1  christos 
    993  1.1  christos       if (dbg)
    994  1.1  christos 	printf ("6:b reg %d %d c 0x%x  \n",
    995  1.1  christos 		fieldBisReg, fieldB, fieldC);
    996  1.1  christos       state->_ea_present = 1;
    997  1.1  christos       state->_offset = fieldC;
    998  1.1  christos       state->_mem_load = 1;
    999  1.1  christos       if (fieldBisReg)
   1000  1.1  christos 	state->ea_reg1 = fieldB;
   1001  1.1  christos       /* Field B is either a shimm (same as fieldC) or limm (different!)
   1002  1.1  christos 	 Say ea is not present, so only one of us will do the name lookup.  */
   1003  1.1  christos       else
   1004  1.1  christos 	state->_offset += fieldB, state->_ea_present = 0;
   1005  1.1  christos 
   1006  1.1  christos       directMem     = BIT (state->words[0],14);
   1007  1.1  christos       addrWriteBack = BIT (state->words[0],12);
   1008  1.1  christos       signExtend    = BIT (state->words[0],9);
   1009  1.1  christos 
   1010  1.1  christos       write_instr_name ();
   1011  1.1  christos       WRITE_FORMAT_x_COMMA_LB (A);
   1012  1.1  christos       if (!fieldBisReg)
   1013  1.1  christos 	{
   1014  1.1  christos 	  fieldB = state->_offset;
   1015  1.1  christos 	  WRITE_FORMAT_x_RB (B);
   1016  1.1  christos 	}
   1017  1.1  christos       else
   1018  1.1  christos 	{
   1019  1.1  christos 	  WRITE_FORMAT_x (B);
   1020  1.1  christos 	  if (fieldC != 0 && !BIT (state->words[0],13))
   1021  1.1  christos 	    {
   1022  1.1  christos 	      fieldCisReg = 0;
   1023  1.1  christos 	      WRITE_FORMAT_COMMA_x_RB (C);
   1024  1.1  christos 	    }
   1025  1.1  christos 	  else
   1026  1.1  christos 	    WRITE_FORMAT_RB ();
   1027  1.1  christos 	}
   1028  1.1  christos       arc_sprintf (state, state->operandBuffer, formatString,
   1029  1.1  christos 		  fieldA, fieldB, fieldC);
   1030  1.1  christos       write_comments ();
   1031  1.1  christos       break;
   1032  1.1  christos 
   1033  1.1  christos     case CLASS_A4_ST:
   1034  1.1  christos       /* ST instruction.  */
   1035  1.1  christos       CHECK_FIELD_B();
   1036  1.1  christos       CHECK_FIELD_C();
   1037  1.1  christos       fieldA = FIELDD(state->words[0]); /* shimm  */
   1038  1.1  christos 
   1039  1.1  christos       /* [B,A offset]  */
   1040  1.1  christos       if (dbg) printf("7:b reg %d %x off %x\n",
   1041  1.1  christos 		      fieldBisReg,fieldB,fieldA);
   1042  1.1  christos       state->_ea_present = 1;
   1043  1.1  christos       state->_offset = fieldA;
   1044  1.1  christos       if (fieldBisReg)
   1045  1.1  christos 	state->ea_reg1 = fieldB;
   1046  1.1  christos       /* Field B is either a shimm (same as fieldA) or limm (different!)
   1047  1.1  christos 	 Say ea is not present, so only one of us will do the name lookup.
   1048  1.1  christos 	 (for is_limm we do the name translation here).  */
   1049  1.1  christos       else
   1050  1.1  christos 	state->_offset += fieldB, state->_ea_present = 0;
   1051  1.1  christos 
   1052  1.1  christos       directMem     = BIT (state->words[0], 26);
   1053  1.1  christos       addrWriteBack = BIT (state->words[0], 24);
   1054  1.1  christos 
   1055  1.1  christos       write_instr_name ();
   1056  1.1  christos       WRITE_FORMAT_x_COMMA_LB(C);
   1057  1.1  christos 
   1058  1.1  christos       if (!fieldBisReg)
   1059  1.1  christos 	{
   1060  1.1  christos 	  fieldB = state->_offset;
   1061  1.1  christos 	  WRITE_FORMAT_x_RB (B);
   1062  1.1  christos 	}
   1063  1.1  christos       else
   1064  1.1  christos 	{
   1065  1.1  christos 	  WRITE_FORMAT_x (B);
   1066  1.1  christos 	  if (fieldBisReg && fieldA != 0)
   1067  1.1  christos 	    {
   1068  1.1  christos 	      fieldAisReg = 0;
   1069  1.1  christos 	      WRITE_FORMAT_COMMA_x_RB(A);
   1070  1.1  christos 	    }
   1071  1.1  christos 	  else
   1072  1.1  christos 	    WRITE_FORMAT_RB();
   1073  1.1  christos 	}
   1074  1.1  christos       arc_sprintf (state, state->operandBuffer, formatString,
   1075  1.1  christos 		  fieldC, fieldB, fieldA);
   1076  1.1  christos       write_comments2 (fieldA);
   1077  1.1  christos       break;
   1078  1.1  christos 
   1079  1.1  christos     case CLASS_A4_SR:
   1080  1.1  christos       /* SR instruction  */
   1081  1.1  christos       CHECK_FIELD_B();
   1082  1.1  christos       CHECK_FIELD_C();
   1083  1.1  christos 
   1084  1.1  christos       write_instr_name ();
   1085  1.1  christos       WRITE_FORMAT_x_COMMA_LB(C);
   1086  1.1  christos       /* Try to print B as an aux reg if it is not a core reg.  */
   1087  1.1  christos       usesAuxReg = 1;
   1088  1.1  christos       WRITE_FORMAT_x (B);
   1089  1.1  christos       WRITE_FORMAT_RB ();
   1090  1.1  christos       arc_sprintf (state, state->operandBuffer, formatString, fieldC, fieldB);
   1091  1.1  christos       write_comments ();
   1092  1.1  christos       break;
   1093  1.1  christos 
   1094  1.1  christos     case CLASS_A4_OP3_SUBOPC3F:
   1095  1.1  christos       write_instr_name ();
   1096  1.1  christos       state->operandBuffer[0] = '\0';
   1097  1.1  christos       break;
   1098  1.1  christos 
   1099  1.1  christos     case CLASS_A4_LR:
   1100  1.1  christos       /* LR instruction */
   1101  1.1  christos       CHECK_FIELD_A ();
   1102  1.1  christos       CHECK_FIELD_B ();
   1103  1.1  christos 
   1104  1.1  christos       write_instr_name ();
   1105  1.1  christos       WRITE_FORMAT_x_COMMA_LB (A);
   1106  1.1  christos       /* Try to print B as an aux reg if it is not a core reg. */
   1107  1.1  christos       usesAuxReg = 1;
   1108  1.1  christos       WRITE_FORMAT_x (B);
   1109  1.1  christos       WRITE_FORMAT_RB ();
   1110  1.1  christos       arc_sprintf (state, state->operandBuffer, formatString, fieldA, fieldB);
   1111  1.1  christos       write_comments ();
   1112  1.1  christos       break;
   1113  1.1  christos 
   1114  1.1  christos     default:
   1115  1.1  christos       mwerror (state, "Bad decoding class in ARC disassembler");
   1116  1.1  christos       break;
   1117  1.1  christos     }
   1118  1.1  christos 
   1119  1.1  christos   state->_cond = cond;
   1120  1.1  christos   return state->instructionLen = offset;
   1121  1.1  christos }
   1122  1.1  christos 
   1123  1.1  christos 
   1124  1.1  christos /* Returns the name the user specified core extension register.  */
   1125  1.1  christos 
   1126  1.1  christos static const char *
   1127  1.1  christos _coreRegName(void * arg ATTRIBUTE_UNUSED, int regval)
   1128  1.1  christos {
   1129  1.1  christos   return arcExtMap_coreRegName (regval);
   1130  1.1  christos }
   1131  1.1  christos 
   1132  1.1  christos /* Returns the name the user specified AUX extension register.  */
   1133  1.1  christos 
   1134  1.1  christos static const char *
   1135  1.1  christos _auxRegName(void *_this ATTRIBUTE_UNUSED, int regval)
   1136  1.1  christos {
   1137  1.1  christos   return arcExtMap_auxRegName(regval);
   1138  1.1  christos }
   1139  1.1  christos 
   1140  1.1  christos /* Returns the name the user specified condition code name.  */
   1141  1.1  christos 
   1142  1.1  christos static const char *
   1143  1.1  christos _condCodeName(void *_this ATTRIBUTE_UNUSED, int regval)
   1144  1.1  christos {
   1145  1.1  christos   return arcExtMap_condCodeName(regval);
   1146  1.1  christos }
   1147  1.1  christos 
   1148  1.1  christos /* Returns the name the user specified extension instruction.  */
   1149  1.1  christos 
   1150  1.1  christos static const char *
   1151  1.1  christos _instName (void *_this ATTRIBUTE_UNUSED, int majop, int minop, int *flags)
   1152  1.1  christos {
   1153  1.1  christos   return arcExtMap_instName(majop, minop, flags);
   1154  1.1  christos }
   1155  1.1  christos 
   1156  1.1  christos /* Decode an instruction returning the size of the instruction
   1157  1.1  christos    in bytes or zero if unrecognized.  */
   1158  1.1  christos 
   1159  1.1  christos static int
   1160  1.1  christos decodeInstr (bfd_vma            address, /* Address of this instruction.  */
   1161  1.1  christos 	     disassemble_info * info)
   1162  1.1  christos {
   1163  1.1  christos   int status;
   1164  1.1  christos   bfd_byte buffer[4];
   1165  1.1  christos   struct arcDisState s;		/* ARC Disassembler state.  */
   1166  1.1  christos   void *stream = info->stream; 	/* Output stream.  */
   1167  1.1  christos   fprintf_ftype func = info->fprintf_func;
   1168  1.1  christos 
   1169  1.1  christos   memset (&s, 0, sizeof(struct arcDisState));
   1170  1.1  christos 
   1171  1.1  christos   /* read first instruction  */
   1172  1.1  christos   status = (*info->read_memory_func) (address, buffer, 4, info);
   1173  1.1  christos   if (status != 0)
   1174  1.1  christos     {
   1175  1.1  christos       (*info->memory_error_func) (status, address, info);
   1176  1.1  christos       return 0;
   1177  1.1  christos     }
   1178  1.1  christos   if (info->endian == BFD_ENDIAN_LITTLE)
   1179  1.1  christos     s.words[0] = bfd_getl32(buffer);
   1180  1.1  christos   else
   1181  1.1  christos     s.words[0] = bfd_getb32(buffer);
   1182  1.1  christos   /* Always read second word in case of limm.  */
   1183  1.1  christos 
   1184  1.1  christos   /* We ignore the result since last insn may not have a limm.  */
   1185  1.1  christos   status = (*info->read_memory_func) (address + 4, buffer, 4, info);
   1186  1.1  christos   if (info->endian == BFD_ENDIAN_LITTLE)
   1187  1.1  christos     s.words[1] = bfd_getl32(buffer);
   1188  1.1  christos   else
   1189  1.1  christos     s.words[1] = bfd_getb32(buffer);
   1190  1.1  christos 
   1191  1.1  christos   s._this = &s;
   1192  1.1  christos   s.coreRegName = _coreRegName;
   1193  1.1  christos   s.auxRegName = _auxRegName;
   1194  1.1  christos   s.condCodeName = _condCodeName;
   1195  1.1  christos   s.instName = _instName;
   1196  1.1  christos 
   1197  1.1  christos   /* Disassemble.  */
   1198  1.1  christos   dsmOneArcInst (address, & s);
   1199  1.1  christos 
   1200  1.1  christos   /* Display the disassembly instruction.  */
   1201  1.1  christos   (*func) (stream, "%08lx ", s.words[0]);
   1202  1.1  christos   (*func) (stream, "    ");
   1203  1.1  christos   (*func) (stream, "%-10s ", s.instrBuffer);
   1204  1.1  christos 
   1205  1.1  christos   if (__TRANSLATION_REQUIRED (s))
   1206  1.1  christos     {
   1207  1.1  christos       bfd_vma addr = s.addresses[s.operandBuffer[1] - '0'];
   1208  1.1  christos 
   1209  1.1  christos       (*info->print_address_func) ((bfd_vma) addr, info);
   1210  1.1  christos       (*func) (stream, "\n");
   1211  1.1  christos     }
   1212  1.1  christos   else
   1213  1.1  christos     (*func) (stream, "%s",s.operandBuffer);
   1214  1.1  christos 
   1215  1.1  christos   return s.instructionLen;
   1216  1.1  christos }
   1217  1.1  christos 
   1218  1.1  christos /* Return the print_insn function to use.
   1219  1.1  christos    Side effect: load (possibly empty) extension section  */
   1220  1.1  christos 
   1221  1.1  christos disassembler_ftype
   1222  1.1  christos arc_get_disassembler (void *ptr)
   1223  1.1  christos {
   1224  1.1  christos   if (ptr)
   1225  1.1  christos     build_ARC_extmap ((struct bfd *) ptr);
   1226  1.1  christos   return decodeInstr;
   1227  1.1  christos }
   1228