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