OSDN Git Service

Fix typos in ChangeLogs; fix dates in copyright notices
[pf3gnuchains/pf3gnuchains3x.git] / opcodes / arm-dis.c
1 /* Instruction printing code for the ARM
2    Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
3    Free Software Foundation, Inc.
4    Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5    Modification by James G. Smith (jsmith@cygnus.co.uk)
6
7 This file is part of libopcodes. 
8
9 This program is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 2 of the License, or (at your option)
12 any later version. 
13
14 This program is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
17 more details. 
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
22
23 #include "sysdep.h"
24 #include "dis-asm.h"
25 #define DEFINE_TABLE
26 #include "arm-opc.h"
27 #include "coff/internal.h"
28 #include "libcoff.h"
29 #include "opintl.h"
30
31 /* FIXME: This shouldn't be done here */
32 #include "elf-bfd.h"
33 #include "elf/internal.h"
34 #include "elf/arm.h"
35
36 #ifndef streq
37 #define streq(a,b)      (strcmp ((a), (b)) == 0)
38 #endif
39
40 #ifndef strneq
41 #define strneq(a,b,n)   (strncmp ((a), (b), (n)) == 0)
42 #endif
43
44 #ifndef NUM_ELEM
45 #define NUM_ELEM(a)     (sizeof (a) / sizeof (a)[0])
46 #endif
47
48 static char * arm_conditional[] =
49 {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
50  "hi", "ls", "ge", "lt", "gt", "le", "", "nv"};
51
52 typedef struct
53 {
54   const char * name;
55   const char * description;
56   const char * reg_names[16];
57 }
58 arm_regname;
59
60 static arm_regname regnames[] =
61 {
62   { "raw" , "Select raw register names",
63     { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}},
64   { "gcc",  "Select register names used by GCC",
65     { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl",  "fp",  "ip",  "sp",  "lr",  "pc" }},
66   { "std",  "Select register names used in ARM's ISA documentation",
67     { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp",  "lr",  "pc" }},
68   { "apcs", "Select register names used in the APCS",
69     { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl",  "fp",  "ip",  "sp",  "lr",  "pc" }},
70   { "atpcs", "Select register names used in the ATPCS",
71     { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7",  "v8",  "IP",  "SP",  "LR",  "PC" }},
72   { "special-atpcs", "Select special register names used in the ATPCS",
73     { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL",  "FP",  "IP",  "SP",  "LR",  "PC" }}
74 };
75
76 /* Default to GCC register name set.  */
77 static unsigned int regname_selected = 1;
78
79 #define NUM_ARM_REGNAMES  NUM_ELEM (regnames)
80 #define arm_regnames      regnames[regname_selected].reg_names
81
82 static boolean force_thumb = false;
83
84 static char * arm_fp_const[] =
85 {"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
86
87 static char * arm_shift[] = 
88 {"lsl", "lsr", "asr", "ror"};
89 \f
90 /* Forward declarations.  */
91 static void arm_decode_shift PARAMS ((long, fprintf_ftype, void *));
92 static int  print_insn_arm   PARAMS ((bfd_vma, struct disassemble_info *, long));
93 static int  print_insn_thumb PARAMS ((bfd_vma, struct disassemble_info *, long));
94 static void parse_disassembler_options PARAMS ((char *));
95 static int  print_insn       PARAMS ((bfd_vma, struct disassemble_info *, boolean));
96 int get_arm_regname_num_options (void);
97 int set_arm_regname_option (int option);
98 int get_arm_regnames (int option, const char **setname,
99                       const char **setdescription,
100                       const char ***register_names);
101 \f
102 /* Functions. */
103 int
104 get_arm_regname_num_options (void)
105 {
106   return NUM_ARM_REGNAMES;
107 }
108
109 int
110 set_arm_regname_option (int option)
111 {
112   int old = regname_selected;
113   regname_selected = option;
114   return old;
115 }
116
117 int
118 get_arm_regnames (int option, const char **setname,
119                   const char **setdescription,
120                   const char ***register_names)
121 {
122   *setname = regnames[option].name;
123   *setdescription = regnames[option].description;
124   *register_names = regnames[option].reg_names;
125   return 16;
126 }
127
128 static void
129 arm_decode_shift (given, func, stream)
130      long given;
131      fprintf_ftype func;
132      void * stream;
133 {
134   func (stream, "%s", arm_regnames[given & 0xf]);
135   
136   if ((given & 0xff0) != 0)
137     {
138       if ((given & 0x10) == 0)
139         {
140           int amount = (given & 0xf80) >> 7;
141           int shift = (given & 0x60) >> 5;
142           
143           if (amount == 0)
144             {
145               if (shift == 3)
146                 {
147                   func (stream, ", rrx");
148                   return;
149                 }
150               
151               amount = 32;
152             }
153           
154           func (stream, ", %s #%d", arm_shift[shift], amount);
155         }
156       else
157         func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5],
158               arm_regnames[(given & 0xf00) >> 8]);
159     }
160 }
161
162 /* Print one instruction from PC on INFO->STREAM.
163    Return the size of the instruction (always 4 on ARM). */
164 static int
165 print_insn_arm (pc, info, given)
166      bfd_vma                   pc;
167      struct disassemble_info * info;
168      long                      given;
169 {
170   struct arm_opcode *  insn;
171   void *               stream = info->stream;
172   fprintf_ftype        func   = info->fprintf_func;
173
174   for (insn = arm_opcodes; insn->assembler; insn++)
175     {
176       if ((given & insn->mask) == insn->value)
177         {
178           char * c;
179           
180           for (c = insn->assembler; *c; c++)
181             {
182               if (*c == '%')
183                 {
184                   switch (*++c)
185                     {
186                     case '%':
187                       func (stream, "%%");
188                       break;
189
190                     case 'a':
191                       if (((given & 0x000f0000) == 0x000f0000)
192                           && ((given & 0x02000000) == 0))
193                         {
194                           int offset = given & 0xfff;
195                           
196                           func (stream, "[pc");
197  
198                           if (given & 0x01000000)
199                             {
200                               if ((given & 0x00800000) == 0)
201                                 offset = - offset;
202                           
203                               /* pre-indexed */
204                               func (stream, ", #%x]", offset);
205
206                               offset += pc + 8;
207
208                               /* Cope with the possibility of write-back
209                                  being used.  Probably a very dangerous thing
210                                  for the programmer to do, but who are we to
211                                  argue ?  */
212                               if (given & 0x00200000)
213                                 func (stream, "!");
214                             }
215                           else
216                             {
217                               /* Post indexed.  */
218                               func (stream, "], #%x", offset);
219
220                               offset = pc + 8;  /* ie ignore the offset.  */
221                             }
222                           
223                           func (stream, "\t; ");
224                           info->print_address_func (offset, info);
225                         }
226                       else
227                         {
228                           func (stream, "[%s", 
229                                 arm_regnames[(given >> 16) & 0xf]);
230                           if ((given & 0x01000000) != 0)
231                             {
232                               if ((given & 0x02000000) == 0)
233                                 {
234                                   int offset = given & 0xfff;
235                                   if (offset)
236                                     func (stream, ", %s#%d",
237                                           (((given & 0x00800000) == 0)
238                                            ? "-" : ""), offset);
239                                 }
240                               else
241                                 {
242                                   func (stream, ", %s",
243                                         (((given & 0x00800000) == 0)
244                                          ? "-" : ""));
245                                   arm_decode_shift (given, func, stream);
246                                 }
247
248                               func (stream, "]%s", 
249                                     ((given & 0x00200000) != 0) ? "!" : "");
250                             }
251                           else
252                             {
253                               if ((given & 0x02000000) == 0)
254                                 {
255                                   int offset = given & 0xfff;
256                                   if (offset)
257                                     func (stream, "], %s#%d",
258                                           (((given & 0x00800000) == 0)
259                                            ? "-" : ""), offset);
260                                   else 
261                                     func (stream, "]");
262                                 }
263                               else
264                                 {
265                                   func (stream, "], %s",
266                                         (((given & 0x00800000) == 0) 
267                                          ? "-" : ""));
268                                   arm_decode_shift (given, func, stream);
269                                 }
270                             }
271                         }
272                       break;
273
274                     case 's':
275                       if ((given & 0x004f0000) == 0x004f0000)
276                         {
277                           /* PC relative with immediate offset.  */
278                           int offset = ((given & 0xf00) >> 4) | (given & 0xf);
279                           
280                           if ((given & 0x00800000) == 0)
281                             offset = -offset;
282                           
283                           func (stream, "[pc, #%x]\t; ", offset);
284                           
285                           (*info->print_address_func)
286                             (offset + pc + 8, info);
287                         }
288                       else
289                         {
290                           func (stream, "[%s", 
291                                 arm_regnames[(given >> 16) & 0xf]);
292                           if ((given & 0x01000000) != 0)
293                             {
294                               /* Pre-indexed.  */
295                               if ((given & 0x00400000) == 0x00400000)
296                                 {
297                                   /* Immediate.  */
298                                   int offset = ((given & 0xf00) >> 4) | (given & 0xf);
299                                   if (offset)
300                                     func (stream, ", %s#%d",
301                                           (((given & 0x00800000) == 0)
302                                            ? "-" : ""), offset);
303                                 }
304                               else
305                                 {
306                                   /* Register.  */
307                                   func (stream, ", %s%s",
308                                         (((given & 0x00800000) == 0)
309                                          ? "-" : ""),
310                                         arm_regnames[given & 0xf]);
311                                 }
312
313                               func (stream, "]%s", 
314                                     ((given & 0x00200000) != 0) ? "!" : "");
315                             }
316                           else
317                             {
318                               /* Post-indexed.  */
319                               if ((given & 0x00400000) == 0x00400000)
320                                 {
321                                   /* Immediate.  */
322                                   int offset = ((given & 0xf00) >> 4) | (given & 0xf);
323                                   if (offset)
324                                     func (stream, "], %s#%d",
325                                           (((given & 0x00800000) == 0)
326                                            ? "-" : ""), offset);
327                                   else 
328                                     func (stream, "]");
329                                 }
330                               else
331                                 {
332                                   /* Register.  */
333                                   func (stream, "], %s%s",
334                                         (((given & 0x00800000) == 0)
335                                          ? "-" : ""),
336                                         arm_regnames[given & 0xf]);
337                                 }
338                             }
339                         }
340                       break;
341                           
342                     case 'b':
343                       (*info->print_address_func)
344                         (BDISP (given) * 4 + pc + 8, info);
345                       break;
346
347                     case 'c':
348                       func (stream, "%s",
349                             arm_conditional [(given >> 28) & 0xf]);
350                       break;
351
352                     case 'm':
353                       {
354                         int started = 0;
355                         int reg;
356
357                         func (stream, "{");
358                         for (reg = 0; reg < 16; reg++)
359                           if ((given & (1 << reg)) != 0)
360                             {
361                               if (started)
362                                 func (stream, ", ");
363                               started = 1;
364                               func (stream, "%s", arm_regnames[reg]);
365                             }
366                         func (stream, "}");
367                       }
368                       break;
369
370                     case 'o':
371                       if ((given & 0x02000000) != 0)
372                         {
373                           int rotate = (given & 0xf00) >> 7;
374                           int immed = (given & 0xff);
375                           immed = (((immed << (32 - rotate))
376                                     | (immed >> rotate)) & 0xffffffff);
377                           func (stream, "#%d\t; 0x%x", immed, immed);
378                         }
379                       else
380                         arm_decode_shift (given, func, stream);
381                       break;
382
383                     case 'p':
384                       if ((given & 0x0000f000) == 0x0000f000)
385                         func (stream, "p");
386                       break;
387
388                     case 't':
389                       if ((given & 0x01200000) == 0x00200000)
390                         func (stream, "t");
391                       break;
392
393                     case 'h':
394                       if ((given & 0x00000020) == 0x00000020)
395                         func (stream, "h");
396                       else
397                         func (stream, "b");
398                       break;
399
400                     case 'A':
401                       func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
402                       if ((given & 0x01000000) != 0)
403                         {
404                           int offset = given & 0xff;
405                           if (offset)
406                             func (stream, ", %s#%d]%s",
407                                   ((given & 0x00800000) == 0 ? "-" : ""),
408                                   offset * 4,
409                                   ((given & 0x00200000) != 0 ? "!" : ""));
410                           else
411                             func (stream, "]");
412                         }
413                       else
414                         {
415                           int offset = given & 0xff;
416                           if (offset)
417                             func (stream, "], %s#%d",
418                                   ((given & 0x00800000) == 0 ? "-" : ""),
419                                   offset * 4);
420                           else
421                             func (stream, "]");
422                         }
423                       break;
424
425                     case 'B':
426                       /* Print ARM V5 BLX(1) address: pc+25 bits.  */
427                       {
428                         bfd_vma address;
429                         bfd_vma offset = 0;
430                         
431                         if (given & 0x00800000)
432                           /* Is signed, hi bits should be ones.  */
433                           offset = (-1) ^ 0x00ffffff;
434
435                         /* Offset is (SignExtend(offset field)<<2).  */
436                         offset += given & 0x00ffffff;
437                         offset <<= 2;
438                         address = offset + pc + 8;
439                         
440                         if (given & 0x01000000)
441                           /* H bit allows addressing to 2-byte boundaries.  */
442                           address += 2;
443
444                         info->print_address_func (address, info);
445                       }
446                       break;
447
448                     case 'C':
449                       func (stream, "_");
450                       if (given & 0x80000)
451                         func (stream, "f");
452                       if (given & 0x40000)
453                         func (stream, "s");
454                       if (given & 0x20000)
455                         func (stream, "x");
456                       if (given & 0x10000)
457                         func (stream, "c");
458                       break;
459
460                     case 'F':
461                       switch (given & 0x00408000)
462                         {
463                         case 0:
464                           func (stream, "4");
465                           break;
466                         case 0x8000:
467                           func (stream, "1");
468                           break;
469                         case 0x00400000:
470                           func (stream, "2");
471                           break;
472                         default:
473                           func (stream, "3");
474                         }
475                       break;
476                         
477                     case 'P':
478                       switch (given & 0x00080080)
479                         {
480                         case 0:
481                           func (stream, "s");
482                           break;
483                         case 0x80:
484                           func (stream, "d");
485                           break;
486                         case 0x00080000:
487                           func (stream, "e");
488                           break;
489                         default:
490                           func (stream, _("<illegal precision>"));
491                           break;
492                         }
493                       break;
494                     case 'Q':
495                       switch (given & 0x00408000)
496                         {
497                         case 0:
498                           func (stream, "s");
499                           break;
500                         case 0x8000:
501                           func (stream, "d");
502                           break;
503                         case 0x00400000:
504                           func (stream, "e");
505                           break;
506                         default:
507                           func (stream, "p");
508                           break;
509                         }
510                       break;
511                     case 'R':
512                       switch (given & 0x60)
513                         {
514                         case 0:
515                           break;
516                         case 0x20:
517                           func (stream, "p");
518                           break;
519                         case 0x40:
520                           func (stream, "m");
521                           break;
522                         default:
523                           func (stream, "z");
524                           break;
525                         }
526                       break;
527
528                     case '0': case '1': case '2': case '3': case '4': 
529                     case '5': case '6': case '7': case '8': case '9':
530                       {
531                         int bitstart = *c++ - '0';
532                         int bitend = 0;
533                         while (*c >= '0' && *c <= '9')
534                           bitstart = (bitstart * 10) + *c++ - '0';
535
536                         switch (*c)
537                           {
538                           case '-':
539                             c++;
540                             
541                             while (*c >= '0' && *c <= '9')
542                               bitend = (bitend * 10) + *c++ - '0';
543                             
544                             if (!bitend)
545                               abort ();
546                             
547                             switch (*c)
548                               {
549                               case 'r':
550                                 {
551                                   long reg;
552                                   
553                                   reg = given >> bitstart;
554                                   reg &= (2 << (bitend - bitstart)) - 1;
555                                   
556                                   func (stream, "%s", arm_regnames[reg]);
557                                 }
558                                 break;
559                               case 'd':
560                                 {
561                                   long reg;
562                                   
563                                   reg = given >> bitstart;
564                                   reg &= (2 << (bitend - bitstart)) - 1;
565                                   
566                                   func (stream, "%d", reg);
567                                 }
568                                 break;
569                               case 'x':
570                                 {
571                                   long reg;
572                                   
573                                   reg = given >> bitstart;
574                                   reg &= (2 << (bitend - bitstart)) - 1;
575                                   
576                                   func (stream, "0x%08x", reg);
577                                   
578                                   /* Some SWI instructions have special
579                                      meanings.  */
580                                   if ((given & 0x0fffffff) == 0x0FF00000)
581                                     func (stream, "\t; IMB");
582                                   else if ((given & 0x0fffffff) == 0x0FF00001)
583                                     func (stream, "\t; IMBRange");
584                                 }
585                                 break;
586                               case 'X':
587                                 {
588                                   long reg;
589                                   
590                                   reg = given >> bitstart;
591                                   reg &= (2 << (bitend - bitstart)) - 1;
592                                   
593                                   func (stream, "%01x", reg & 0xf);
594                                 }
595                                 break;
596                               case 'f':
597                                 {
598                                   long reg;
599                                   
600                                   reg = given >> bitstart;
601                                   reg &= (2 << (bitend - bitstart)) - 1;
602                                   
603                                   if (reg > 7)
604                                     func (stream, "#%s",
605                                           arm_fp_const[reg & 7]);
606                                   else
607                                     func (stream, "f%d", reg);
608                                 }
609                                 break;
610                               default:
611                                 abort ();
612                               }
613                             break;
614                             
615                           case '`':
616                             c++;
617                             if ((given & (1 << bitstart)) == 0)
618                               func (stream, "%c", *c);
619                             break;
620                           case '\'':
621                             c++;
622                             if ((given & (1 << bitstart)) != 0)
623                               func (stream, "%c", *c);
624                             break;
625                           case '?':
626                             ++c;
627                             if ((given & (1 << bitstart)) != 0)
628                               func (stream, "%c", *c++);
629                             else
630                               func (stream, "%c", *++c);
631                             break;
632                           default:
633                             abort ();
634                           }
635                         break;
636
637                       default:
638                         abort ();
639                       }
640                     }
641                 }
642               else
643                 func (stream, "%c", *c);
644             }
645           return 4;
646         }
647     }
648   abort ();
649 }
650
651 /* Print one instruction from PC on INFO->STREAM.
652    Return the size of the instruction. */
653 static int
654 print_insn_thumb (pc, info, given)
655      bfd_vma                   pc;
656      struct disassemble_info * info;
657      long                      given;
658 {
659   struct thumb_opcode * insn;
660   void *                stream = info->stream;
661   fprintf_ftype         func = info->fprintf_func;
662
663   for (insn = thumb_opcodes; insn->assembler; insn++)
664     {
665       if ((given & insn->mask) == insn->value)
666         {
667           char * c = insn->assembler;
668
669           /* Special processing for Thumb 2 instruction BL sequence:  */
670           if (!*c) /* Check for empty (not NULL) assembler string.  */
671             {
672               long offset;
673               
674               info->bytes_per_chunk = 4;
675               info->bytes_per_line  = 4;
676
677               offset = BDISP23 (given);
678               
679               if ((given & 0x10000000) == 0)
680                 {
681                   func (stream, "blx\t");
682
683                   /* The spec says that bit 1 of the branch's destination
684                      address comes from bit 1 of the instruction's
685                      address and not from the offset in the instruction.  */
686                   if (offset & 0x1)
687                     {
688                       /* func (stream, "*malformed!* "); */
689                       offset &= ~ 0x1;
690                     }
691
692                   offset |= ((pc & 0x2) >> 1);
693                 }
694               else
695                 func (stream, "bl\t");
696
697               info->print_address_func (offset * 2 + pc + 4, info);
698               return 4;
699             }
700           else
701             {
702               info->bytes_per_chunk = 2;
703               info->bytes_per_line  = 4;
704                       
705               given &= 0xffff;
706               
707               for (; *c; c++)
708                 {
709                   if (*c == '%')
710                     {
711                       int domaskpc = 0;
712                       int domasklr = 0;
713                       
714                       switch (*++c)
715                         {
716                         case '%':
717                           func (stream, "%%");
718                           break;
719
720                         case 'S':
721                           {
722                             long reg;
723                             
724                             reg = (given >> 3) & 0x7;
725                             if (given & (1 << 6))
726                               reg += 8;
727                             
728                             func (stream, "%s", arm_regnames[reg]);
729                           }
730                           break;
731
732                         case 'D':
733                           {
734                             long reg;
735                             
736                             reg = given & 0x7;
737                             if (given & (1 << 7))
738                              reg += 8;
739                             
740                             func (stream, "%s", arm_regnames[reg]);
741                           }
742                           break;
743
744                         case 'T':
745                           func (stream, "%s",
746                                 arm_conditional [(given >> 8) & 0xf]);
747                           break;
748
749                         case 'N':
750                           if (given & (1 << 8))
751                             domasklr = 1;
752                           /* Fall through.  */
753                         case 'O':
754                           if (*c == 'O' && (given & (1 << 8)))
755                             domaskpc = 1;
756                           /* Fall through.  */
757                         case 'M':
758                           {
759                             int started = 0;
760                             int reg;
761                             
762                             func (stream, "{");
763                             
764                             /* It would be nice if we could spot
765                                ranges, and generate the rS-rE format: */
766                             for (reg = 0; (reg < 8); reg++)
767                               if ((given & (1 << reg)) != 0)
768                                 {
769                                   if (started)
770                                     func (stream, ", ");
771                                   started = 1;
772                                   func (stream, "%s", arm_regnames[reg]);
773                                 }
774
775                             if (domasklr)
776                               {
777                                 if (started)
778                                   func (stream, ", ");
779                                 started = 1;
780                                 func (stream, arm_regnames[14] /* "lr" */);
781                               }
782
783                             if (domaskpc)
784                               {
785                                 if (started)
786                                   func (stream, ", ");
787                                 func (stream, arm_regnames[15] /* "pc" */);
788                               }
789
790                             func (stream, "}");
791                           }
792                           break;
793
794
795                         case '0': case '1': case '2': case '3': case '4': 
796                         case '5': case '6': case '7': case '8': case '9':
797                           {
798                             int bitstart = *c++ - '0';
799                             int bitend = 0;
800                             
801                             while (*c >= '0' && *c <= '9')
802                               bitstart = (bitstart * 10) + *c++ - '0';
803
804                             switch (*c)
805                               {
806                               case '-':
807                                 {
808                                   long reg;
809                                   
810                                   c++;
811                                   while (*c >= '0' && *c <= '9')
812                                     bitend = (bitend * 10) + *c++ - '0';
813                                   if (!bitend)
814                                     abort ();
815                                   reg = given >> bitstart;
816                                   reg &= (2 << (bitend - bitstart)) - 1;
817                                   switch (*c)
818                                     {
819                                     case 'r':
820                                       func (stream, "%s", arm_regnames[reg]);
821                                       break;
822
823                                     case 'd':
824                                       func (stream, "%d", reg);
825                                       break;
826
827                                     case 'H':
828                                       func (stream, "%d", reg << 1);
829                                       break;
830
831                                     case 'W':
832                                       func (stream, "%d", reg << 2);
833                                       break;
834
835                                     case 'a':
836                                       /* PC-relative address -- the bottom two
837                                          bits of the address are dropped
838                                          before the calculation.  */
839                                       info->print_address_func
840                                         (((pc + 4) & ~3) + (reg << 2), info);
841                                       break;
842
843                                     case 'x':
844                                       func (stream, "0x%04x", reg);
845                                       break;
846
847                                     case 'I':
848                                       reg = ((reg ^ (1 << bitend)) - (1 << bitend));
849                                       func (stream, "%d", reg);
850                                       break;
851
852                                     case 'B':
853                                       reg = ((reg ^ (1 << bitend)) - (1 << bitend));
854                                       (*info->print_address_func)
855                                         (reg * 2 + pc + 4, info);
856                                       break;
857
858                                     default:
859                                       abort ();
860                                     }
861                                 }
862                                 break;
863
864                               case '\'':
865                                 c++;
866                                 if ((given & (1 << bitstart)) != 0)
867                                   func (stream, "%c", *c);
868                                 break;
869
870                               case '?':
871                                 ++c;
872                                 if ((given & (1 << bitstart)) != 0)
873                                   func (stream, "%c", *c++);
874                                 else
875                                   func (stream, "%c", *++c);
876                                 break;
877
878                               default:
879                                  abort ();
880                               }
881                           }
882                           break;
883
884                         default:
885                           abort ();
886                         }
887                     }
888                   else
889                     func (stream, "%c", *c);
890                 }
891              }
892           return 2;
893        }
894     }
895
896   /* No match.  */
897   abort ();
898 }
899
900 /* Parse an individual disassembler option.  */
901 void
902 parse_arm_disassembler_option (option)
903      char * option;
904 {
905   if (option == NULL)
906     return;
907       
908   if (strneq (option, "reg-names-", 10))
909     {
910       int i;
911         
912       option += 10;
913
914       for (i = NUM_ARM_REGNAMES; i--;)
915         if (streq (option, regnames[i].name))
916           {
917             regname_selected = i;
918             break;
919           }
920       
921       if (i < 0)
922         fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
923     }
924   else if (streq (option, "force-thumb"))
925     force_thumb = 1;
926   else if (streq (option, "no-force-thumb"))
927     force_thumb = 0;
928   else
929     fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
930   
931   return;
932 }
933
934 /* Parse the string of disassembler options, spliting it at whitespaces.  */
935 static void
936 parse_disassembler_options (options)
937      char * options;
938 {
939   char * space;
940   
941   if (options == NULL)
942     return;
943
944   do
945     {
946       space = strchr (options, ' ');
947
948       if (space)
949         {
950           * space = '\0';
951           parse_arm_disassembler_option (options);
952           * space = ' ';
953           options = space + 1;
954         }
955       else
956         parse_arm_disassembler_option (options);
957     }
958   while (space);
959 }
960
961 /* NOTE: There are no checks in these routines that
962    the relevant number of data bytes exist.  */
963 static int
964 print_insn (pc, info, little)
965      bfd_vma pc;
966      struct disassemble_info * info;
967      boolean little;
968 {
969   unsigned char      b[4];
970   long               given;
971   int                status;
972   int                is_thumb;
973
974   if (info->disassembler_options)
975     {
976       parse_disassembler_options (info->disassembler_options);
977       
978       /* To avoid repeated parsing of these options, we remove them here.  */
979       info->disassembler_options = NULL;
980     }
981   
982   is_thumb = force_thumb;
983   
984   if (!is_thumb && info->symbols != NULL)
985     {
986       if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
987         {
988           coff_symbol_type * cs;
989           
990           cs = coffsymbol (*info->symbols);
991           is_thumb = (   cs->native->u.syment.n_sclass == C_THUMBEXT
992                       || cs->native->u.syment.n_sclass == C_THUMBSTAT
993                       || cs->native->u.syment.n_sclass == C_THUMBLABEL
994                       || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
995                       || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
996         }
997       else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
998         {
999           elf_symbol_type *  es;
1000           unsigned int       type;
1001           
1002           es = *(elf_symbol_type **)(info->symbols);
1003           type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
1004           
1005           is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
1006         }
1007     }
1008   
1009   info->bytes_per_chunk = 4;
1010   info->display_endian  = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
1011
1012   if (little)
1013     {
1014       status = info->read_memory_func (pc, (bfd_byte *) &b[0], 4, info);
1015       if (status != 0 && is_thumb)
1016         {
1017           info->bytes_per_chunk = 2;
1018           
1019           status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
1020           b[3] = b[2] = 0;
1021         }
1022       
1023       if (status != 0)
1024         {
1025           info->memory_error_func (status, pc, info);
1026           return -1;
1027         }
1028       
1029       given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
1030     }
1031   else
1032     {
1033       status = info->read_memory_func
1034         (pc & ~ 0x3, (bfd_byte *) &b[0], 4, info);
1035       if (status != 0)
1036         {
1037           info->memory_error_func (status, pc, info);
1038           return -1;
1039         }
1040       
1041       if (is_thumb)
1042         {
1043           if (pc & 0x2)
1044             {
1045               given = (b[2] << 8) | b[3];
1046               
1047               status = info->read_memory_func
1048                 ((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
1049               if (status != 0)
1050                 {
1051                   info->memory_error_func (status, pc + 4, info);
1052                   return -1;
1053                 }
1054               
1055               given |= (b[0] << 24) | (b[1] << 16);
1056             }
1057           else
1058             given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16);
1059         }
1060       else
1061         given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
1062     }
1063   
1064   if (info->flags & INSN_HAS_RELOC)
1065     /* If the instruction has a reloc associated with it, then
1066        the offset field in the instruction will actually be the
1067        addend for the reloc.  (We are using REL type relocs).
1068        In such cases, we can ignore the pc when computing
1069        addresses, since the addend is not currently pc-relative.  */
1070     pc = 0;
1071   
1072   if (is_thumb)
1073     status = print_insn_thumb (pc, info, given);
1074   else
1075     status = print_insn_arm (pc, info, given);
1076
1077   return status;
1078 }
1079
1080 int
1081 print_insn_big_arm (pc, info)
1082      bfd_vma pc;
1083      struct disassemble_info * info;
1084 {
1085   return print_insn (pc, info, false);
1086 }
1087
1088 int
1089 print_insn_little_arm (pc, info)
1090      bfd_vma pc;
1091      struct disassemble_info * info;
1092 {
1093   return print_insn (pc, info, true);
1094 }
1095
1096 void
1097 print_arm_disassembler_options (FILE * stream)
1098 {
1099   int i;
1100
1101   fprintf (stream, _("\n\
1102 The following ARM specific disassembler options are supported for use with\n\
1103 the -M switch:\n"));
1104   
1105   for (i = NUM_ARM_REGNAMES; i--;)
1106     fprintf (stream, "  reg-names-%s %*c%s\n",
1107              regnames[i].name,
1108              14 - strlen (regnames[i].name), ' ',
1109              regnames[i].description);
1110
1111   fprintf (stream, "  force-thumb              Assume all insns are Thumb insns\n");
1112   fprintf (stream, "  no-force-thumb           Examine preceeding label to determine an insn's type\n\n");
1113 }