OSDN Git Service

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