Merge from vendor branch NTPD:
[dragonfly.git] / contrib / binutils / 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, ", #%d]", 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, "], #%d", 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, #%d]\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 'A':
394                       func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
395                       if ((given & 0x01000000) != 0)
396                         {
397                           int offset = given & 0xff;
398                           if (offset)
399                             func (stream, ", %s#%d]%s",
400                                   ((given & 0x00800000) == 0 ? "-" : ""),
401                                   offset * 4,
402                                   ((given & 0x00200000) != 0 ? "!" : ""));
403                           else
404                             func (stream, "]");
405                         }
406                       else
407                         {
408                           int offset = given & 0xff;
409                           if (offset)
410                             func (stream, "], %s#%d",
411                                   ((given & 0x00800000) == 0 ? "-" : ""),
412                                   offset * 4);
413                           else
414                             func (stream, "]");
415                         }
416                       break;
417
418                     case 'B':
419                       /* Print ARM V5 BLX(1) address: pc+25 bits.  */
420                       {
421                         bfd_vma address;
422                         bfd_vma offset = 0;
423                         
424                         if (given & 0x00800000)
425                           /* Is signed, hi bits should be ones.  */
426                           offset = (-1) ^ 0x00ffffff;
427
428                         /* Offset is (SignExtend(offset field)<<2).  */
429                         offset += given & 0x00ffffff;
430                         offset <<= 2;
431                         address = offset + pc + 8;
432                         
433                         if (given & 0x01000000)
434                           /* H bit allows addressing to 2-byte boundaries.  */
435                           address += 2;
436
437                         info->print_address_func (address, info);
438                       }
439                       break;
440
441                     case 'I':
442                       /* Print a Cirrus/DSP shift immediate.  */
443                       /* Immediates are 7bit signed ints with bits 0..3 in
444                          bits 0..3 of opcode and bits 4..6 in bits 5..7
445                          of opcode.  */
446                       {
447                         int imm;
448
449                         imm = (given & 0xf) | ((given & 0xe0) >> 1);
450
451                         /* Is ``imm'' a negative number?  */
452                         if (imm & 0x40)
453                           imm |= (-1 << 7);
454
455                         func (stream, "%d", imm);
456                       }
457
458                       break;
459
460                     case 'C':
461                       func (stream, "_");
462                       if (given & 0x80000)
463                         func (stream, "f");
464                       if (given & 0x40000)
465                         func (stream, "s");
466                       if (given & 0x20000)
467                         func (stream, "x");
468                       if (given & 0x10000)
469                         func (stream, "c");
470                       break;
471
472                     case 'F':
473                       switch (given & 0x00408000)
474                         {
475                         case 0:
476                           func (stream, "4");
477                           break;
478                         case 0x8000:
479                           func (stream, "1");
480                           break;
481                         case 0x00400000:
482                           func (stream, "2");
483                           break;
484                         default:
485                           func (stream, "3");
486                         }
487                       break;
488                         
489                     case 'P':
490                       switch (given & 0x00080080)
491                         {
492                         case 0:
493                           func (stream, "s");
494                           break;
495                         case 0x80:
496                           func (stream, "d");
497                           break;
498                         case 0x00080000:
499                           func (stream, "e");
500                           break;
501                         default:
502                           func (stream, _("<illegal precision>"));
503                           break;
504                         }
505                       break;
506                     case 'Q':
507                       switch (given & 0x00408000)
508                         {
509                         case 0:
510                           func (stream, "s");
511                           break;
512                         case 0x8000:
513                           func (stream, "d");
514                           break;
515                         case 0x00400000:
516                           func (stream, "e");
517                           break;
518                         default:
519                           func (stream, "p");
520                           break;
521                         }
522                       break;
523                     case 'R':
524                       switch (given & 0x60)
525                         {
526                         case 0:
527                           break;
528                         case 0x20:
529                           func (stream, "p");
530                           break;
531                         case 0x40:
532                           func (stream, "m");
533                           break;
534                         default:
535                           func (stream, "z");
536                           break;
537                         }
538                       break;
539
540                     case '0': case '1': case '2': case '3': case '4': 
541                     case '5': case '6': case '7': case '8': case '9':
542                       {
543                         int bitstart = *c++ - '0';
544                         int bitend = 0;
545                         while (*c >= '0' && *c <= '9')
546                           bitstart = (bitstart * 10) + *c++ - '0';
547
548                         switch (*c)
549                           {
550                           case '-':
551                             c++;
552                             
553                             while (*c >= '0' && *c <= '9')
554                               bitend = (bitend * 10) + *c++ - '0';
555                             
556                             if (!bitend)
557                               abort ();
558                             
559                             switch (*c)
560                               {
561                               case 'r':
562                                 {
563                                   long reg;
564                                   
565                                   reg = given >> bitstart;
566                                   reg &= (2 << (bitend - bitstart)) - 1;
567                                   
568                                   func (stream, "%s", arm_regnames[reg]);
569                                 }
570                                 break;
571                               case 'd':
572                                 {
573                                   long reg;
574                                   
575                                   reg = given >> bitstart;
576                                   reg &= (2 << (bitend - bitstart)) - 1;
577                                   
578                                   func (stream, "%d", reg);
579                                 }
580                                 break;
581                               case 'x':
582                                 {
583                                   long reg;
584                                   
585                                   reg = given >> bitstart;
586                                   reg &= (2 << (bitend - bitstart)) - 1;
587                                   
588                                   func (stream, "0x%08x", reg);
589                                   
590                                   /* Some SWI instructions have special
591                                      meanings.  */
592                                   if ((given & 0x0fffffff) == 0x0FF00000)
593                                     func (stream, "\t; IMB");
594                                   else if ((given & 0x0fffffff) == 0x0FF00001)
595                                     func (stream, "\t; IMBRange");
596                                 }
597                                 break;
598                               case 'X':
599                                 {
600                                   long reg;
601                                   
602                                   reg = given >> bitstart;
603                                   reg &= (2 << (bitend - bitstart)) - 1;
604                                   
605                                   func (stream, "%01x", reg & 0xf);
606                                 }
607                                 break;
608                               case 'f':
609                                 {
610                                   long reg;
611                                   
612                                   reg = given >> bitstart;
613                                   reg &= (2 << (bitend - bitstart)) - 1;
614                                   
615                                   if (reg > 7)
616                                     func (stream, "#%s",
617                                           arm_fp_const[reg & 7]);
618                                   else
619                                     func (stream, "f%d", reg);
620                                 }
621                                 break;
622                               default:
623                                 abort ();
624                               }
625                             break;
626
627                           case 'y':
628                           case 'z':
629                             {
630                               int single = *c == 'y';
631                               int regno;
632
633                               switch (bitstart)
634                                 {
635                                 case 4: /* Sm pair */
636                                   func (stream, "{");
637                                   /* Fall through.  */
638                                 case 0: /* Sm, Dm */
639                                   regno = given & 0x0000000f;
640                                   if (single)
641                                     {
642                                       regno <<= 1;
643                                       regno += (given >> 5) & 1;
644                                     }
645                                   break;
646
647                                 case 1: /* Sd, Dd */
648                                   regno = (given >> 12) & 0x0000000f;
649                                   if (single)
650                                     {
651                                       regno <<= 1;
652                                       regno += (given >> 22) & 1;
653                                     }
654                                   break;
655
656                                 case 2: /* Sn, Dn */
657                                   regno = (given >> 16) & 0x0000000f;
658                                   if (single)
659                                     {
660                                       regno <<= 1;
661                                       regno += (given >> 7) & 1;
662                                     }
663                                   break;
664
665                                 case 3: /* List */
666                                   func (stream, "{");
667                                   regno = (given >> 12) & 0x0000000f;
668                                   if (single)
669                                     {
670                                       regno <<= 1;
671                                       regno += (given >> 22) & 1;
672                                     }
673                                   break;
674
675                                   
676                                 default:
677                                   abort ();
678                                 }
679
680                               func (stream, "%c%d", single ? 's' : 'd', regno);
681
682                               if (bitstart == 3)
683                                 {
684                                   int count = given & 0xff;
685
686                                   if (single == 0)
687                                     count >>= 1;
688
689                                   if (--count)
690                                     {
691                                       func (stream, "-%c%d",
692                                             single ? 's' : 'd',
693                                             regno + count);
694                                     }
695
696                                   func (stream, "}");
697                                 }
698                               else if (bitstart == 4)
699                                 func (stream, ", %c%d}", single ? 's' : 'd',
700                                       regno + 1);
701
702                               break;
703                             }
704
705                           case '`':
706                             c++;
707                             if ((given & (1 << bitstart)) == 0)
708                               func (stream, "%c", *c);
709                             break;
710                           case '\'':
711                             c++;
712                             if ((given & (1 << bitstart)) != 0)
713                               func (stream, "%c", *c);
714                             break;
715                           case '?':
716                             ++c;
717                             if ((given & (1 << bitstart)) != 0)
718                               func (stream, "%c", *c++);
719                             else
720                               func (stream, "%c", *++c);
721                             break;
722                           default:
723                             abort ();
724                           }
725                         break;
726
727                       default:
728                         abort ();
729                       }
730                     }
731                 }
732               else
733                 func (stream, "%c", *c);
734             }
735           return 4;
736         }
737     }
738   abort ();
739 }
740
741 /* Print one instruction from PC on INFO->STREAM.
742    Return the size of the instruction. */
743 static int
744 print_insn_thumb (pc, info, given)
745      bfd_vma                   pc;
746      struct disassemble_info * info;
747      long                      given;
748 {
749   struct thumb_opcode * insn;
750   void *                stream = info->stream;
751   fprintf_ftype         func = info->fprintf_func;
752
753   for (insn = thumb_opcodes; insn->assembler; insn++)
754     {
755       if ((given & insn->mask) == insn->value)
756         {
757           char * c = insn->assembler;
758
759           /* Special processing for Thumb 2 instruction BL sequence:  */
760           if (!*c) /* Check for empty (not NULL) assembler string.  */
761             {
762               long offset;
763               
764               info->bytes_per_chunk = 4;
765               info->bytes_per_line  = 4;
766
767               offset = BDISP23 (given);
768               
769               if ((given & 0x10000000) == 0)
770                 {
771                   func (stream, "blx\t");
772
773                   /* The spec says that bit 1 of the branch's destination
774                      address comes from bit 1 of the instruction's
775                      address and not from the offset in the instruction.  */
776                   if (offset & 0x1)
777                     {
778                       /* func (stream, "*malformed!* "); */
779                       offset &= ~ 0x1;
780                     }
781
782                   offset |= ((pc & 0x2) >> 1);
783                 }
784               else
785                 func (stream, "bl\t");
786
787               info->print_address_func (offset * 2 + pc + 4, info);
788               return 4;
789             }
790           else
791             {
792               info->bytes_per_chunk = 2;
793               info->bytes_per_line  = 4;
794                       
795               given &= 0xffff;
796               
797               for (; *c; c++)
798                 {
799                   if (*c == '%')
800                     {
801                       int domaskpc = 0;
802                       int domasklr = 0;
803                       
804                       switch (*++c)
805                         {
806                         case '%':
807                           func (stream, "%%");
808                           break;
809
810                         case 'S':
811                           {
812                             long reg;
813                             
814                             reg = (given >> 3) & 0x7;
815                             if (given & (1 << 6))
816                               reg += 8;
817                             
818                             func (stream, "%s", arm_regnames[reg]);
819                           }
820                           break;
821
822                         case 'D':
823                           {
824                             long reg;
825                             
826                             reg = given & 0x7;
827                             if (given & (1 << 7))
828                              reg += 8;
829                             
830                             func (stream, "%s", arm_regnames[reg]);
831                           }
832                           break;
833
834                         case 'T':
835                           func (stream, "%s",
836                                 arm_conditional [(given >> 8) & 0xf]);
837                           break;
838
839                         case 'N':
840                           if (given & (1 << 8))
841                             domasklr = 1;
842                           /* Fall through.  */
843                         case 'O':
844                           if (*c == 'O' && (given & (1 << 8)))
845                             domaskpc = 1;
846                           /* Fall through.  */
847                         case 'M':
848                           {
849                             int started = 0;
850                             int reg;
851                             
852                             func (stream, "{");
853                             
854                             /* It would be nice if we could spot
855                                ranges, and generate the rS-rE format: */
856                             for (reg = 0; (reg < 8); reg++)
857                               if ((given & (1 << reg)) != 0)
858                                 {
859                                   if (started)
860                                     func (stream, ", ");
861                                   started = 1;
862                                   func (stream, "%s", arm_regnames[reg]);
863                                 }
864
865                             if (domasklr)
866                               {
867                                 if (started)
868                                   func (stream, ", ");
869                                 started = 1;
870                                 func (stream, arm_regnames[14] /* "lr" */);
871                               }
872
873                             if (domaskpc)
874                               {
875                                 if (started)
876                                   func (stream, ", ");
877                                 func (stream, arm_regnames[15] /* "pc" */);
878                               }
879
880                             func (stream, "}");
881                           }
882                           break;
883
884
885                         case '0': case '1': case '2': case '3': case '4': 
886                         case '5': case '6': case '7': case '8': case '9':
887                           {
888                             int bitstart = *c++ - '0';
889                             int bitend = 0;
890                             
891                             while (*c >= '0' && *c <= '9')
892                               bitstart = (bitstart * 10) + *c++ - '0';
893
894                             switch (*c)
895                               {
896                               case '-':
897                                 {
898                                   long reg;
899                                   
900                                   c++;
901                                   while (*c >= '0' && *c <= '9')
902                                     bitend = (bitend * 10) + *c++ - '0';
903                                   if (!bitend)
904                                     abort ();
905                                   reg = given >> bitstart;
906                                   reg &= (2 << (bitend - bitstart)) - 1;
907                                   switch (*c)
908                                     {
909                                     case 'r':
910                                       func (stream, "%s", arm_regnames[reg]);
911                                       break;
912
913                                     case 'd':
914                                       func (stream, "%d", reg);
915                                       break;
916
917                                     case 'H':
918                                       func (stream, "%d", reg << 1);
919                                       break;
920
921                                     case 'W':
922                                       func (stream, "%d", reg << 2);
923                                       break;
924
925                                     case 'a':
926                                       /* PC-relative address -- the bottom two
927                                          bits of the address are dropped
928                                          before the calculation.  */
929                                       info->print_address_func
930                                         (((pc + 4) & ~3) + (reg << 2), info);
931                                       break;
932
933                                     case 'x':
934                                       func (stream, "0x%04x", reg);
935                                       break;
936
937                                     case 'I':
938                                       reg = ((reg ^ (1 << bitend)) - (1 << bitend));
939                                       func (stream, "%d", reg);
940                                       break;
941
942                                     case 'B':
943                                       reg = ((reg ^ (1 << bitend)) - (1 << bitend));
944                                       (*info->print_address_func)
945                                         (reg * 2 + pc + 4, info);
946                                       break;
947
948                                     default:
949                                       abort ();
950                                     }
951                                 }
952                                 break;
953
954                               case '\'':
955                                 c++;
956                                 if ((given & (1 << bitstart)) != 0)
957                                   func (stream, "%c", *c);
958                                 break;
959
960                               case '?':
961                                 ++c;
962                                 if ((given & (1 << bitstart)) != 0)
963                                   func (stream, "%c", *c++);
964                                 else
965                                   func (stream, "%c", *++c);
966                                 break;
967
968                               default:
969                                  abort ();
970                               }
971                           }
972                           break;
973
974                         default:
975                           abort ();
976                         }
977                     }
978                   else
979                     func (stream, "%c", *c);
980                 }
981              }
982           return 2;
983        }
984     }
985
986   /* No match.  */
987   abort ();
988 }
989
990 /* Parse an individual disassembler option.  */
991 void
992 parse_arm_disassembler_option (option)
993      char * option;
994 {
995   if (option == NULL)
996     return;
997       
998   if (strneq (option, "reg-names-", 10))
999     {
1000       int i;
1001         
1002       option += 10;
1003
1004       for (i = NUM_ARM_REGNAMES; i--;)
1005         if (streq (option, regnames[i].name))
1006           {
1007             regname_selected = i;
1008             break;
1009           }
1010       
1011       if (i < 0)
1012         fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
1013     }
1014   else if (streq (option, "force-thumb"))
1015     force_thumb = 1;
1016   else if (streq (option, "no-force-thumb"))
1017     force_thumb = 0;
1018   else
1019     fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
1020   
1021   return;
1022 }
1023
1024 /* Parse the string of disassembler options, spliting it at whitespaces.  */
1025 static void
1026 parse_disassembler_options (options)
1027      char * options;
1028 {
1029   char * space;
1030   
1031   if (options == NULL)
1032     return;
1033
1034   do
1035     {
1036       space = strchr (options, ' ');
1037
1038       if (space)
1039         {
1040           * space = '\0';
1041           parse_arm_disassembler_option (options);
1042           * space = ' ';
1043           options = space + 1;
1044         }
1045       else
1046         parse_arm_disassembler_option (options);
1047     }
1048   while (space);
1049 }
1050
1051 /* NOTE: There are no checks in these routines that
1052    the relevant number of data bytes exist.  */
1053 static int
1054 print_insn (pc, info, little)
1055      bfd_vma pc;
1056      struct disassemble_info * info;
1057      boolean little;
1058 {
1059   unsigned char      b[4];
1060   long               given;
1061   int                status;
1062   int                is_thumb;
1063
1064   if (info->disassembler_options)
1065     {
1066       parse_disassembler_options (info->disassembler_options);
1067       
1068       /* To avoid repeated parsing of these options, we remove them here.  */
1069       info->disassembler_options = NULL;
1070     }
1071   
1072   is_thumb = force_thumb;
1073   
1074   if (!is_thumb && info->symbols != NULL)
1075     {
1076       if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
1077         {
1078           coff_symbol_type * cs;
1079           
1080           cs = coffsymbol (*info->symbols);
1081           is_thumb = (   cs->native->u.syment.n_sclass == C_THUMBEXT
1082                       || cs->native->u.syment.n_sclass == C_THUMBSTAT
1083                       || cs->native->u.syment.n_sclass == C_THUMBLABEL
1084                       || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
1085                       || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
1086         }
1087       else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
1088         {
1089           elf_symbol_type *  es;
1090           unsigned int       type;
1091           
1092           es = *(elf_symbol_type **)(info->symbols);
1093           type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
1094           
1095           is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
1096         }
1097     }
1098   
1099   info->bytes_per_chunk = 4;
1100   info->display_endian  = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
1101
1102   if (little)
1103     {
1104       status = info->read_memory_func (pc, (bfd_byte *) &b[0], 4, info);
1105       if (status != 0 && is_thumb)
1106         {
1107           info->bytes_per_chunk = 2;
1108           
1109           status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
1110           b[3] = b[2] = 0;
1111         }
1112       
1113       if (status != 0)
1114         {
1115           info->memory_error_func (status, pc, info);
1116           return -1;
1117         }
1118       
1119       given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
1120     }
1121   else
1122     {
1123       status = info->read_memory_func
1124         (pc & ~ 0x3, (bfd_byte *) &b[0], 4, info);
1125       if (status != 0)
1126         {
1127           info->memory_error_func (status, pc, info);
1128           return -1;
1129         }
1130       
1131       if (is_thumb)
1132         {
1133           if (pc & 0x2)
1134             {
1135               given = (b[2] << 8) | b[3];
1136               
1137               status = info->read_memory_func
1138                 ((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
1139               if (status != 0)
1140                 {
1141                   info->memory_error_func (status, pc + 4, info);
1142                   return -1;
1143                 }
1144               
1145               given |= (b[0] << 24) | (b[1] << 16);
1146             }
1147           else
1148             given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16);
1149         }
1150       else
1151         given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
1152     }
1153   
1154   if (info->flags & INSN_HAS_RELOC)
1155     /* If the instruction has a reloc associated with it, then
1156        the offset field in the instruction will actually be the
1157        addend for the reloc.  (We are using REL type relocs).
1158        In such cases, we can ignore the pc when computing
1159        addresses, since the addend is not currently pc-relative.  */
1160     pc = 0;
1161   
1162   if (is_thumb)
1163     status = print_insn_thumb (pc, info, given);
1164   else
1165     status = print_insn_arm (pc, info, given);
1166
1167   return status;
1168 }
1169
1170 int
1171 print_insn_big_arm (pc, info)
1172      bfd_vma pc;
1173      struct disassemble_info * info;
1174 {
1175   return print_insn (pc, info, false);
1176 }
1177
1178 int
1179 print_insn_little_arm (pc, info)
1180      bfd_vma pc;
1181      struct disassemble_info * info;
1182 {
1183   return print_insn (pc, info, true);
1184 }
1185
1186 void
1187 print_arm_disassembler_options (FILE * stream)
1188 {
1189   int i;
1190
1191   fprintf (stream, _("\n\
1192 The following ARM specific disassembler options are supported for use with\n\
1193 the -M switch:\n"));
1194   
1195   for (i = NUM_ARM_REGNAMES; i--;)
1196     fprintf (stream, "  reg-names-%s %*c%s\n",
1197              regnames[i].name,
1198              (int)(14 - strlen (regnames[i].name)), ' ',
1199              regnames[i].description);
1200
1201   fprintf (stream, "  force-thumb              Assume all insns are Thumb insns\n");
1202   fprintf (stream, "  no-force-thumb           Examine preceeding label to determine an insn's type\n\n");
1203 }