OSDN Git Service

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