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