OSDN Git Service

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