]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - contrib/binutils/opcodes/arm-dis.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / contrib / binutils / opcodes / arm-dis.c
1 /* Instruction printing code for the ARM
2    Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
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 #include "safe-ctype.h"
31
32 /* FIXME: This shouldn't be done here.  */
33 #include "elf-bfd.h"
34 #include "elf/internal.h"
35 #include "elf/arm.h"
36
37 #ifndef streq
38 #define streq(a,b)      (strcmp ((a), (b)) == 0)
39 #endif
40
41 #ifndef strneq
42 #define strneq(a,b,n)   (strncmp ((a), (b), (n)) == 0)
43 #endif
44
45 #ifndef NUM_ELEM
46 #define NUM_ELEM(a)     (sizeof (a) / sizeof (a)[0])
47 #endif
48
49 static char * arm_conditional[] =
50 {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
51  "hi", "ls", "ge", "lt", "gt", "le", "", "nv"};
52
53 typedef struct
54 {
55   const char * name;
56   const char * description;
57   const char * reg_names[16];
58 }
59 arm_regname;
60
61 static arm_regname regnames[] =
62 {
63   { "raw" , "Select raw register names",
64     { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}},
65   { "gcc",  "Select register names used by GCC",
66     { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl",  "fp",  "ip",  "sp",  "lr",  "pc" }},
67   { "std",  "Select register names used in ARM's ISA documentation",
68     { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp",  "lr",  "pc" }},
69   { "apcs", "Select register names used in the APCS",
70     { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl",  "fp",  "ip",  "sp",  "lr",  "pc" }},
71   { "atpcs", "Select register names used in the ATPCS",
72     { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7",  "v8",  "IP",  "SP",  "LR",  "PC" }},
73   { "special-atpcs", "Select special register names used in the ATPCS",
74     { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL",  "FP",  "IP",  "SP",  "LR",  "PC" }},
75   { "iwmmxt_regnames", "Select register names used on the Intel Wireless MMX technology coprocessor",
76     { "wr0", "wr1", "wr2", "wr3", "wr4", "wr5", "wr6", "wr7", "wr8", "wr9", "wr10", "wr11", "wr12", "wr13", "wr14", "wr15"}},
77   { "iwmmxt_Cregnames", "Select control register names used on the Intel Wireless MMX technology coprocessor",
78     {"wcid", "wcon", "wcssf", "wcasf", "reserved", "reserved", "reserved", "reserved", "wcgr0", "wcgr1", "wcgr2", "wcgr3", "reserved", "reserved", "reserved", "reserved"}}
79 };
80
81 static char * iwmmxt_wwnames[] =
82 {"b", "h", "w", "d"};
83
84 static char * iwmmxt_wwssnames[] =
85 {"b", "bus", "b", "bss",
86  "h", "hus", "h", "hss",
87  "w", "wus", "w", "wss",
88  "d", "dus", "d", "dss"
89 };
90
91 /* Default to GCC register name set.  */
92 static unsigned int regname_selected = 1;
93
94 #define NUM_ARM_REGNAMES  NUM_ELEM (regnames)
95 #define arm_regnames      regnames[regname_selected].reg_names
96
97 static bfd_boolean force_thumb = FALSE;
98
99 static char * arm_fp_const[] =
100 {"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
101
102 static char * arm_shift[] =
103 {"lsl", "lsr", "asr", "ror"};
104 \f
105 /* Forward declarations.  */
106 static void arm_decode_shift
107   PARAMS ((long, fprintf_ftype, void *));
108 static int  print_insn_arm
109   PARAMS ((bfd_vma, struct disassemble_info *, long));
110 static int  print_insn_thumb
111   PARAMS ((bfd_vma, struct disassemble_info *, long));
112 static void parse_disassembler_options
113   PARAMS ((char *));
114 static int  print_insn
115   PARAMS ((bfd_vma, struct disassemble_info *, bfd_boolean));
116 static int set_iwmmxt_regnames
117   PARAMS ((void));
118
119 int get_arm_regname_num_options
120   PARAMS ((void));
121 int set_arm_regname_option
122   PARAMS ((int));
123 int get_arm_regnames
124   PARAMS ((int, const char **, const char **, const char ***));
125 \f
126 /* Functions.  */
127 int
128 get_arm_regname_num_options ()
129 {
130   return NUM_ARM_REGNAMES;
131 }
132
133 int
134 set_arm_regname_option (option)
135      int option;
136 {
137   int old = regname_selected;
138   regname_selected = option;
139   return old;
140 }
141
142 int
143 get_arm_regnames (option, setname, setdescription, register_names)
144      int option;
145      const char **setname;
146      const char **setdescription;
147      const char ***register_names;
148 {
149   *setname = regnames[option].name;
150   *setdescription = regnames[option].description;
151   *register_names = regnames[option].reg_names;
152   return 16;
153 }
154
155 static void
156 arm_decode_shift (given, func, stream)
157      long given;
158      fprintf_ftype func;
159      void * stream;
160 {
161   func (stream, "%s", arm_regnames[given & 0xf]);
162
163   if ((given & 0xff0) != 0)
164     {
165       if ((given & 0x10) == 0)
166         {
167           int amount = (given & 0xf80) >> 7;
168           int shift = (given & 0x60) >> 5;
169
170           if (amount == 0)
171             {
172               if (shift == 3)
173                 {
174                   func (stream, ", rrx");
175                   return;
176                 }
177
178               amount = 32;
179             }
180
181           func (stream, ", %s #%d", arm_shift[shift], amount);
182         }
183       else
184         func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5],
185               arm_regnames[(given & 0xf00) >> 8]);
186     }
187 }
188
189 static int
190 set_iwmmxt_regnames ()
191 {
192   const char * setname;
193   const char * setdesc;
194   const char ** regnames;
195   int iwmmxt_regnames = 0;
196   int num_regnames = get_arm_regname_num_options ();
197
198   get_arm_regnames (iwmmxt_regnames, &setname,
199                     &setdesc, &regnames);
200   while ((strcmp ("iwmmxt_regnames", setname))
201          && (iwmmxt_regnames < num_regnames))
202     get_arm_regnames (++iwmmxt_regnames, &setname, &setdesc, &regnames);
203
204   return iwmmxt_regnames;
205 }
206                           
207 /* Print one instruction from PC on INFO->STREAM.
208    Return the size of the instruction (always 4 on ARM). */
209
210 static int
211 print_insn_arm (pc, info, given)
212      bfd_vma pc;
213      struct disassemble_info *info;
214      long given;
215 {
216   const struct arm_opcode *insn;
217   void *stream = info->stream;
218   fprintf_ftype func   = info->fprintf_func;
219   static int iwmmxt_regnames = 0;
220
221   for (insn = arm_opcodes; insn->assembler; insn++)
222     {
223       if (insn->value == FIRST_IWMMXT_INSN
224           && info->mach != bfd_mach_arm_XScale
225           && info->mach != bfd_mach_arm_iWMMXt)
226         insn = insn + IWMMXT_INSN_COUNT;
227
228       if ((given & insn->mask) == insn->value)
229         {
230           char * c;
231
232           for (c = insn->assembler; *c; c++)
233             {
234               if (*c == '%')
235                 {
236                   switch (*++c)
237                     {
238                     case '%':
239                       func (stream, "%%");
240                       break;
241
242                     case 'a':
243                       if (((given & 0x000f0000) == 0x000f0000)
244                           && ((given & 0x02000000) == 0))
245                         {
246                           int offset = given & 0xfff;
247
248                           func (stream, "[pc");
249
250                           if (given & 0x01000000)
251                             {
252                               if ((given & 0x00800000) == 0)
253                                 offset = - offset;
254
255                               /* Pre-indexed.  */
256                               func (stream, ", #%d]", offset);
257
258                               offset += pc + 8;
259
260                               /* Cope with the possibility of write-back
261                                  being used.  Probably a very dangerous thing
262                                  for the programmer to do, but who are we to
263                                  argue ?  */
264                               if (given & 0x00200000)
265                                 func (stream, "!");
266                             }
267                           else
268                             {
269                               /* Post indexed.  */
270                               func (stream, "], #%d", offset);
271
272                               /* ie ignore the offset.  */
273                               offset = pc + 8;
274                             }
275
276                           func (stream, "\t; ");
277                           info->print_address_func (offset, info);
278                         }
279                       else
280                         {
281                           func (stream, "[%s",
282                                 arm_regnames[(given >> 16) & 0xf]);
283                           if ((given & 0x01000000) != 0)
284                             {
285                               if ((given & 0x02000000) == 0)
286                                 {
287                                   int offset = given & 0xfff;
288                                   if (offset)
289                                     func (stream, ", #%s%d",
290                                           (((given & 0x00800000) == 0)
291                                            ? "-" : ""), offset);
292                                 }
293                               else
294                                 {
295                                   func (stream, ", %s",
296                                         (((given & 0x00800000) == 0)
297                                          ? "-" : ""));
298                                   arm_decode_shift (given, func, stream);
299                                 }
300
301                               func (stream, "]%s",
302                                     ((given & 0x00200000) != 0) ? "!" : "");
303                             }
304                           else
305                             {
306                               if ((given & 0x02000000) == 0)
307                                 {
308                                   int offset = given & 0xfff;
309                                   if (offset)
310                                     func (stream, "], #%s%d",
311                                           (((given & 0x00800000) == 0)
312                                            ? "-" : ""), offset);
313                                   else
314                                     func (stream, "]");
315                                 }
316                               else
317                                 {
318                                   func (stream, "], %s",
319                                         (((given & 0x00800000) == 0)
320                                          ? "-" : ""));
321                                   arm_decode_shift (given, func, stream);
322                                 }
323                             }
324                         }
325                       break;
326
327                     case 's':
328                       if ((given & 0x004f0000) == 0x004f0000)
329                         {
330                           /* PC relative with immediate offset.  */
331                           int offset = ((given & 0xf00) >> 4) | (given & 0xf);
332
333                           if ((given & 0x00800000) == 0)
334                             offset = -offset;
335
336                           func (stream, "[pc, #%d]\t; ", offset);
337
338                           (*info->print_address_func)
339                             (offset + pc + 8, info);
340                         }
341                       else
342                         {
343                           func (stream, "[%s",
344                                 arm_regnames[(given >> 16) & 0xf]);
345                           if ((given & 0x01000000) != 0)
346                             {
347                               /* Pre-indexed.  */
348                               if ((given & 0x00400000) == 0x00400000)
349                                 {
350                                   /* Immediate.  */
351                                   int offset = ((given & 0xf00) >> 4) | (given & 0xf);
352                                   if (offset)
353                                     func (stream, ", #%s%d",
354                                           (((given & 0x00800000) == 0)
355                                            ? "-" : ""), offset);
356                                 }
357                               else
358                                 {
359                                   /* Register.  */
360                                   func (stream, ", %s%s",
361                                         (((given & 0x00800000) == 0)
362                                          ? "-" : ""),
363                                         arm_regnames[given & 0xf]);
364                                 }
365
366                               func (stream, "]%s",
367                                     ((given & 0x00200000) != 0) ? "!" : "");
368                             }
369                           else
370                             {
371                               /* Post-indexed.  */
372                               if ((given & 0x00400000) == 0x00400000)
373                                 {
374                                   /* Immediate.  */
375                                   int offset = ((given & 0xf00) >> 4) | (given & 0xf);
376                                   if (offset)
377                                     func (stream, "], #%s%d",
378                                           (((given & 0x00800000) == 0)
379                                            ? "-" : ""), offset);
380                                   else
381                                     func (stream, "]");
382                                 }
383                               else
384                                 {
385                                   /* Register.  */
386                                   func (stream, "], %s%s",
387                                         (((given & 0x00800000) == 0)
388                                          ? "-" : ""),
389                                         arm_regnames[given & 0xf]);
390                                 }
391                             }
392                         }
393                       break;
394
395                     case 'b':
396                       (*info->print_address_func)
397                         (BDISP (given) * 4 + pc + 8, info);
398                       break;
399
400                     case 'c':
401                       func (stream, "%s",
402                             arm_conditional [(given >> 28) & 0xf]);
403                       break;
404
405                     case 'm':
406                       {
407                         int started = 0;
408                         int reg;
409
410                         func (stream, "{");
411                         for (reg = 0; reg < 16; reg++)
412                           if ((given & (1 << reg)) != 0)
413                             {
414                               if (started)
415                                 func (stream, ", ");
416                               started = 1;
417                               func (stream, "%s", arm_regnames[reg]);
418                             }
419                         func (stream, "}");
420                       }
421                       break;
422
423                     case 'o':
424                       if ((given & 0x02000000) != 0)
425                         {
426                           int rotate = (given & 0xf00) >> 7;
427                           int immed = (given & 0xff);
428                           immed = (((immed << (32 - rotate))
429                                     | (immed >> rotate)) & 0xffffffff);
430                           func (stream, "#%d\t; 0x%x", immed, immed);
431                         }
432                       else
433                         arm_decode_shift (given, func, stream);
434                       break;
435
436                     case 'p':
437                       if ((given & 0x0000f000) == 0x0000f000)
438                         func (stream, "p");
439                       break;
440
441                     case 't':
442                       if ((given & 0x01200000) == 0x00200000)
443                         func (stream, "t");
444                       break;
445
446                     case 'A':
447                       func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
448
449                       if ((given & (1 << 24)) != 0)
450                         {
451                           int offset = given & 0xff;
452
453                           if (offset)
454                             func (stream, ", #%s%d]%s",
455                                   ((given & 0x00800000) == 0 ? "-" : ""),
456                                   offset * 4,
457                                   ((given & 0x00200000) != 0 ? "!" : ""));
458                           else
459                             func (stream, "]");
460                         }
461                       else
462                         {
463                           int offset = given & 0xff;
464
465                           func (stream, "]");
466
467                           if (given & (1 << 21))
468                             {
469                               if (offset)
470                                 func (stream, ", #%s%d",
471                                       ((given & 0x00800000) == 0 ? "-" : ""),
472                                       offset * 4);
473                             }
474                           else
475                             func (stream, ", {%d}", offset);
476                         }
477                       break;
478
479                     case 'B':
480                       /* Print ARM V5 BLX(1) address: pc+25 bits.  */
481                       {
482                         bfd_vma address;
483                         bfd_vma offset = 0;
484
485                         if (given & 0x00800000)
486                           /* Is signed, hi bits should be ones.  */
487                           offset = (-1) ^ 0x00ffffff;
488
489                         /* Offset is (SignExtend(offset field)<<2).  */
490                         offset += given & 0x00ffffff;
491                         offset <<= 2;
492                         address = offset + pc + 8;
493
494                         if (given & 0x01000000)
495                           /* H bit allows addressing to 2-byte boundaries.  */
496                           address += 2;
497
498                         info->print_address_func (address, info);
499                       }
500                       break;
501
502                     case 'I':
503                       /* Print a Cirrus/DSP shift immediate.  */
504                       /* Immediates are 7bit signed ints with bits 0..3 in
505                          bits 0..3 of opcode and bits 4..6 in bits 5..7
506                          of opcode.  */
507                       {
508                         int imm;
509
510                         imm = (given & 0xf) | ((given & 0xe0) >> 1);
511
512                         /* Is ``imm'' a negative number?  */
513                         if (imm & 0x40)
514                           imm |= (-1 << 7);
515
516                         func (stream, "%d", imm);
517                       }
518
519                       break;
520
521                     case 'C':
522                       func (stream, "_");
523                       if (given & 0x80000)
524                         func (stream, "f");
525                       if (given & 0x40000)
526                         func (stream, "s");
527                       if (given & 0x20000)
528                         func (stream, "x");
529                       if (given & 0x10000)
530                         func (stream, "c");
531                       break;
532
533                     case 'F':
534                       switch (given & 0x00408000)
535                         {
536                         case 0:
537                           func (stream, "4");
538                           break;
539                         case 0x8000:
540                           func (stream, "1");
541                           break;
542                         case 0x00400000:
543                           func (stream, "2");
544                           break;
545                         default:
546                           func (stream, "3");
547                         }
548                       break;
549
550                     case 'P':
551                       switch (given & 0x00080080)
552                         {
553                         case 0:
554                           func (stream, "s");
555                           break;
556                         case 0x80:
557                           func (stream, "d");
558                           break;
559                         case 0x00080000:
560                           func (stream, "e");
561                           break;
562                         default:
563                           func (stream, _("<illegal precision>"));
564                           break;
565                         }
566                       break;
567                     case 'Q':
568                       switch (given & 0x00408000)
569                         {
570                         case 0:
571                           func (stream, "s");
572                           break;
573                         case 0x8000:
574                           func (stream, "d");
575                           break;
576                         case 0x00400000:
577                           func (stream, "e");
578                           break;
579                         default:
580                           func (stream, "p");
581                           break;
582                         }
583                       break;
584                     case 'R':
585                       switch (given & 0x60)
586                         {
587                         case 0:
588                           break;
589                         case 0x20:
590                           func (stream, "p");
591                           break;
592                         case 0x40:
593                           func (stream, "m");
594                           break;
595                         default:
596                           func (stream, "z");
597                           break;
598                         }
599                       break;
600
601                     case '0': case '1': case '2': case '3': case '4':
602                     case '5': case '6': case '7': case '8': case '9':
603                       {
604                         int bitstart = *c++ - '0';
605                         int bitend = 0;
606                         while (*c >= '0' && *c <= '9')
607                           bitstart = (bitstart * 10) + *c++ - '0';
608
609                         switch (*c)
610                           {
611                           case '-':
612                             c++;
613
614                             while (*c >= '0' && *c <= '9')
615                               bitend = (bitend * 10) + *c++ - '0';
616
617                             if (!bitend)
618                               abort ();
619
620                             switch (*c)
621                               {
622                               case 'r':
623                                 {
624                                   long reg;
625
626                                   reg = given >> bitstart;
627                                   reg &= (2 << (bitend - bitstart)) - 1;
628
629                                   func (stream, "%s", arm_regnames[reg]);
630                                 }
631                                 break;
632                               case 'd':
633                                 {
634                                   long reg;
635
636                                   reg = given >> bitstart;
637                                   reg &= (2 << (bitend - bitstart)) - 1;
638
639                                   func (stream, "%d", reg);
640                                 }
641                                 break;
642                               case 'W':
643                                 {
644                                   long reg;
645                                   
646                                   reg = given >> bitstart;
647                                   reg &= (2 << (bitend - bitstart)) - 1;
648                                   
649                                   func (stream, "%d", reg + 1);
650                                 }
651                                 break;
652                               case 'x':
653                                 {
654                                   long reg;
655
656                                   reg = given >> bitstart;
657                                   reg &= (2 << (bitend - bitstart)) - 1;
658
659                                   func (stream, "0x%08x", reg);
660
661                                   /* Some SWI instructions have special
662                                      meanings.  */
663                                   if ((given & 0x0fffffff) == 0x0FF00000)
664                                     func (stream, "\t; IMB");
665                                   else if ((given & 0x0fffffff) == 0x0FF00001)
666                                     func (stream, "\t; IMBRange");
667                                 }
668                                 break;
669                               case 'X':
670                                 {
671                                   long reg;
672
673                                   reg = given >> bitstart;
674                                   reg &= (2 << (bitend - bitstart)) - 1;
675
676                                   func (stream, "%01x", reg & 0xf);
677                                 }
678                                 break;
679                               case 'f':
680                                 {
681                                   long reg;
682
683                                   reg = given >> bitstart;
684                                   reg &= (2 << (bitend - bitstart)) - 1;
685
686                                   if (reg > 7)
687                                     func (stream, "#%s",
688                                           arm_fp_const[reg & 7]);
689                                   else
690                                     func (stream, "f%d", reg);
691                                 }
692                                 break;
693
694                               case 'w':
695                                 {
696                                   long reg;
697
698                                   if (bitstart != bitend)
699                                     {
700                                       reg = given >> bitstart;
701                                       reg &= (2 << (bitend - bitstart)) - 1;
702                                       if (bitend - bitstart == 1)
703                                         func (stream, "%s", iwmmxt_wwnames[reg]);
704                                       else
705                                         func (stream, "%s", iwmmxt_wwssnames[reg]);
706                                     }
707                                   else
708                                     {
709                                       reg = (((given >> 8)  & 0x1) |
710                                              ((given >> 22) & 0x1));
711                                       func (stream, "%s", iwmmxt_wwnames[reg]);
712                                     }
713                                 }
714                                 break;
715
716                               case 'g':
717                                 {
718                                   long reg;
719                                   int current_regnames;
720
721                                   if (! iwmmxt_regnames)
722                                     iwmmxt_regnames = set_iwmmxt_regnames ();
723                                   current_regnames = set_arm_regname_option
724                                     (iwmmxt_regnames);
725
726                                   reg = given >> bitstart;
727                                   reg &= (2 << (bitend - bitstart)) - 1;
728                                   func (stream, "%s", arm_regnames[reg]);
729                                   set_arm_regname_option (current_regnames);
730                                 }
731                                 break;
732
733                               case 'G':
734                                 {
735                                   long reg;
736                                   int current_regnames;
737
738                                   if (! iwmmxt_regnames)
739                                     iwmmxt_regnames = set_iwmmxt_regnames ();
740                                   current_regnames = set_arm_regname_option
741                                     (iwmmxt_regnames + 1);
742
743                                   reg = given >> bitstart;
744                                   reg &= (2 << (bitend - bitstart)) - 1;
745                                   func (stream, "%s", arm_regnames[reg]);
746                                   set_arm_regname_option (current_regnames);
747                                 }
748                                 break;
749
750                               default:
751                                 abort ();
752                               }
753                             break;
754
755                           case 'y':
756                           case 'z':
757                             {
758                               int single = *c == 'y';
759                               int regno;
760
761                               switch (bitstart)
762                                 {
763                                 case 4: /* Sm pair */
764                                   func (stream, "{");
765                                   /* Fall through.  */
766                                 case 0: /* Sm, Dm */
767                                   regno = given & 0x0000000f;
768                                   if (single)
769                                     {
770                                       regno <<= 1;
771                                       regno += (given >> 5) & 1;
772                                     }
773                                   break;
774
775                                 case 1: /* Sd, Dd */
776                                   regno = (given >> 12) & 0x0000000f;
777                                   if (single)
778                                     {
779                                       regno <<= 1;
780                                       regno += (given >> 22) & 1;
781                                     }
782                                   break;
783
784                                 case 2: /* Sn, Dn */
785                                   regno = (given >> 16) & 0x0000000f;
786                                   if (single)
787                                     {
788                                       regno <<= 1;
789                                       regno += (given >> 7) & 1;
790                                     }
791                                   break;
792
793                                 case 3: /* List */
794                                   func (stream, "{");
795                                   regno = (given >> 12) & 0x0000000f;
796                                   if (single)
797                                     {
798                                       regno <<= 1;
799                                       regno += (given >> 22) & 1;
800                                     }
801                                   break;
802
803
804                                 default:
805                                   abort ();
806                                 }
807
808                               func (stream, "%c%d", single ? 's' : 'd', regno);
809
810                               if (bitstart == 3)
811                                 {
812                                   int count = given & 0xff;
813
814                                   if (single == 0)
815                                     count >>= 1;
816
817                                   if (--count)
818                                     {
819                                       func (stream, "-%c%d",
820                                             single ? 's' : 'd',
821                                             regno + count);
822                                     }
823
824                                   func (stream, "}");
825                                 }
826                               else if (bitstart == 4)
827                                 func (stream, ", %c%d}", single ? 's' : 'd',
828                                       regno + 1);
829
830                               break;
831                             }
832
833                           case '`':
834                             c++;
835                             if ((given & (1 << bitstart)) == 0)
836                               func (stream, "%c", *c);
837                             break;
838                           case '\'':
839                             c++;
840                             if ((given & (1 << bitstart)) != 0)
841                               func (stream, "%c", *c);
842                             break;
843                           case '?':
844                             ++c;
845                             if ((given & (1 << bitstart)) != 0)
846                               func (stream, "%c", *c++);
847                             else
848                               func (stream, "%c", *++c);
849                             break;
850                           default:
851                             abort ();
852                           }
853                         break;
854
855                       case 'L':
856                         switch (given & 0x00400100)
857                           {
858                           case 0x00000000: func (stream, "b"); break;
859                           case 0x00400000: func (stream, "h"); break;
860                           case 0x00000100: func (stream, "w"); break;
861                           case 0x00400100: func (stream, "d"); break;
862                           default:
863                             break;
864                           }
865                         break;
866
867                       case 'Z':
868                         {
869                           int value;
870                           /* given (20, 23) | given (0, 3) */
871                           value = ((given >> 16) & 0xf0) | (given & 0xf);
872                           func (stream, "%d", value);
873                         }
874                         break;
875
876                       case 'l':
877                         /* This is like the 'A' operator, except that if
878                            the width field "M" is zero, then the offset is
879                            *not* multiplied by four.  */
880                         {
881                           int offset = given & 0xff;
882                           int multiplier = (given & 0x00000100) ? 4 : 1;
883
884                           func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
885
886                           if (offset)
887                             {
888                               if ((given & 0x01000000) != 0)
889                                 func (stream, ", #%s%d]%s",
890                                       ((given & 0x00800000) == 0 ? "-" : ""),
891                                       offset * multiplier,
892                                       ((given & 0x00200000) != 0 ? "!" : ""));
893                               else
894                                 func (stream, "], #%s%d",
895                                       ((given & 0x00800000) == 0 ? "-" : ""),
896                                       offset * multiplier);
897                             }
898                           else
899                             func (stream, "]");
900                         }
901                         break;
902
903                       default:
904                         abort ();
905                       }
906                     }
907                 }
908               else
909                 func (stream, "%c", *c);
910             }
911           return 4;
912         }
913     }
914   abort ();
915 }
916
917 /* Print one instruction from PC on INFO->STREAM.
918    Return the size of the instruction. */
919
920 static int
921 print_insn_thumb (pc, info, given)
922      bfd_vma pc;
923      struct disassemble_info *info;
924      long given;
925 {
926   const struct thumb_opcode *insn;
927   void *stream = info->stream;
928   fprintf_ftype func = info->fprintf_func;
929
930   for (insn = thumb_opcodes; insn->assembler; insn++)
931     {
932       if ((given & insn->mask) == insn->value)
933         {
934           char * c = insn->assembler;
935
936           /* Special processing for Thumb 2 instruction BL sequence:  */
937           if (!*c) /* Check for empty (not NULL) assembler string.  */
938             {
939               long offset;
940
941               info->bytes_per_chunk = 4;
942               info->bytes_per_line  = 4;
943
944               offset = BDISP23 (given);
945               offset = offset * 2 + pc + 4;
946
947               if ((given & 0x10000000) == 0)
948                 {
949                   func (stream, "blx\t");
950                   offset &= 0xfffffffc;
951                 }
952               else
953                 func (stream, "bl\t");
954
955               info->print_address_func (offset, info);
956               return 4;
957             }
958           else
959             {
960               info->bytes_per_chunk = 2;
961               info->bytes_per_line  = 4;
962
963               given &= 0xffff;
964
965               for (; *c; c++)
966                 {
967                   if (*c == '%')
968                     {
969                       int domaskpc = 0;
970                       int domasklr = 0;
971
972                       switch (*++c)
973                         {
974                         case '%':
975                           func (stream, "%%");
976                           break;
977
978                         case 'S':
979                           {
980                             long reg;
981
982                             reg = (given >> 3) & 0x7;
983                             if (given & (1 << 6))
984                               reg += 8;
985
986                             func (stream, "%s", arm_regnames[reg]);
987                           }
988                           break;
989
990                         case 'D':
991                           {
992                             long reg;
993
994                             reg = given & 0x7;
995                             if (given & (1 << 7))
996                              reg += 8;
997
998                             func (stream, "%s", arm_regnames[reg]);
999                           }
1000                           break;
1001
1002                         case 'T':
1003                           func (stream, "%s",
1004                                 arm_conditional [(given >> 8) & 0xf]);
1005                           break;
1006
1007                         case 'N':
1008                           if (given & (1 << 8))
1009                             domasklr = 1;
1010                           /* Fall through.  */
1011                         case 'O':
1012                           if (*c == 'O' && (given & (1 << 8)))
1013                             domaskpc = 1;
1014                           /* Fall through.  */
1015                         case 'M':
1016                           {
1017                             int started = 0;
1018                             int reg;
1019
1020                             func (stream, "{");
1021
1022                             /* It would be nice if we could spot
1023                                ranges, and generate the rS-rE format: */
1024                             for (reg = 0; (reg < 8); reg++)
1025                               if ((given & (1 << reg)) != 0)
1026                                 {
1027                                   if (started)
1028                                     func (stream, ", ");
1029                                   started = 1;
1030                                   func (stream, "%s", arm_regnames[reg]);
1031                                 }
1032
1033                             if (domasklr)
1034                               {
1035                                 if (started)
1036                                   func (stream, ", ");
1037                                 started = 1;
1038                                 func (stream, arm_regnames[14] /* "lr" */);
1039                               }
1040
1041                             if (domaskpc)
1042                               {
1043                                 if (started)
1044                                   func (stream, ", ");
1045                                 func (stream, arm_regnames[15] /* "pc" */);
1046                               }
1047
1048                             func (stream, "}");
1049                           }
1050                           break;
1051
1052
1053                         case '0': case '1': case '2': case '3': case '4':
1054                         case '5': case '6': case '7': case '8': case '9':
1055                           {
1056                             int bitstart = *c++ - '0';
1057                             int bitend = 0;
1058
1059                             while (*c >= '0' && *c <= '9')
1060                               bitstart = (bitstart * 10) + *c++ - '0';
1061
1062                             switch (*c)
1063                               {
1064                               case '-':
1065                                 {
1066                                   long reg;
1067
1068                                   c++;
1069                                   while (*c >= '0' && *c <= '9')
1070                                     bitend = (bitend * 10) + *c++ - '0';
1071                                   if (!bitend)
1072                                     abort ();
1073                                   reg = given >> bitstart;
1074                                   reg &= (2 << (bitend - bitstart)) - 1;
1075                                   switch (*c)
1076                                     {
1077                                     case 'r':
1078                                       func (stream, "%s", arm_regnames[reg]);
1079                                       break;
1080
1081                                     case 'd':
1082                                       func (stream, "%d", reg);
1083                                       break;
1084
1085                                     case 'H':
1086                                       func (stream, "%d", reg << 1);
1087                                       break;
1088
1089                                     case 'W':
1090                                       func (stream, "%d", reg << 2);
1091                                       break;
1092
1093                                     case 'a':
1094                                       /* PC-relative address -- the bottom two
1095                                          bits of the address are dropped
1096                                          before the calculation.  */
1097                                       info->print_address_func
1098                                         (((pc + 4) & ~3) + (reg << 2), info);
1099                                       break;
1100
1101                                     case 'x':
1102                                       func (stream, "0x%04x", reg);
1103                                       break;
1104
1105                                     case 'I':
1106                                       reg = ((reg ^ (1 << bitend)) - (1 << bitend));
1107                                       func (stream, "%d", reg);
1108                                       break;
1109
1110                                     case 'B':
1111                                       reg = ((reg ^ (1 << bitend)) - (1 << bitend));
1112                                       (*info->print_address_func)
1113                                         (reg * 2 + pc + 4, info);
1114                                       break;
1115
1116                                     default:
1117                                       abort ();
1118                                     }
1119                                 }
1120                                 break;
1121
1122                               case '\'':
1123                                 c++;
1124                                 if ((given & (1 << bitstart)) != 0)
1125                                   func (stream, "%c", *c);
1126                                 break;
1127
1128                               case '?':
1129                                 ++c;
1130                                 if ((given & (1 << bitstart)) != 0)
1131                                   func (stream, "%c", *c++);
1132                                 else
1133                                   func (stream, "%c", *++c);
1134                                 break;
1135
1136                               default:
1137                                  abort ();
1138                               }
1139                           }
1140                           break;
1141
1142                         default:
1143                           abort ();
1144                         }
1145                     }
1146                   else
1147                     func (stream, "%c", *c);
1148                 }
1149              }
1150           return 2;
1151        }
1152     }
1153
1154   /* No match.  */
1155   abort ();
1156 }
1157
1158 /* Disallow mapping symbols ($a, $b, $d, $t etc) from
1159    being displayed in symbol relative addresses.  */
1160
1161 bfd_boolean
1162 arm_symbol_is_valid (asymbol * sym,
1163                      struct disassemble_info * info ATTRIBUTE_UNUSED)
1164 {
1165   const char * name;
1166   
1167   if (sym == NULL)
1168     return FALSE;
1169
1170   name = bfd_asymbol_name (sym);
1171
1172   return (name && *name != '$');
1173 }
1174
1175 /* Parse an individual disassembler option.  */
1176
1177 void
1178 parse_arm_disassembler_option (option)
1179      char * option;
1180 {
1181   if (option == NULL)
1182     return;
1183
1184   if (strneq (option, "reg-names-", 10))
1185     {
1186       int i;
1187
1188       option += 10;
1189
1190       for (i = NUM_ARM_REGNAMES; i--;)
1191         if (strneq (option, regnames[i].name, strlen (regnames[i].name)))
1192           {
1193             regname_selected = i;
1194             break;
1195           }
1196
1197       if (i < 0)
1198         /* XXX - should break 'option' at following delimiter.  */
1199         fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
1200     }
1201   else if (strneq (option, "force-thumb", 11))
1202     force_thumb = 1;
1203   else if (strneq (option, "no-force-thumb", 14))
1204     force_thumb = 0;
1205   else
1206     /* XXX - should break 'option' at following delimiter.  */
1207     fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
1208
1209   return;
1210 }
1211
1212 /* Parse the string of disassembler options, spliting it at whitespaces
1213    or commas.  (Whitespace separators supported for backwards compatibility).  */
1214
1215 static void
1216 parse_disassembler_options (options)
1217      char * options;
1218 {
1219   if (options == NULL)
1220     return;
1221
1222   while (*options)
1223     {
1224       parse_arm_disassembler_option (options);
1225
1226       /* Skip forward to next seperator.  */
1227       while ((*options) && (! ISSPACE (*options)) && (*options != ','))
1228         ++ options;
1229       /* Skip forward past seperators.  */
1230       while (ISSPACE (*options) || (*options == ','))
1231         ++ options;      
1232     }
1233 }
1234
1235 /* NOTE: There are no checks in these routines that
1236    the relevant number of data bytes exist.  */
1237
1238 static int
1239 print_insn (pc, info, little)
1240      bfd_vma pc;
1241      struct disassemble_info * info;
1242      bfd_boolean little;
1243 {
1244   unsigned char      b[4];
1245   long               given;
1246   int                status;
1247   int                is_thumb;
1248
1249   if (info->disassembler_options)
1250     {
1251       parse_disassembler_options (info->disassembler_options);
1252
1253       /* To avoid repeated parsing of these options, we remove them here.  */
1254       info->disassembler_options = NULL;
1255     }
1256
1257   is_thumb = force_thumb;
1258
1259   if (!is_thumb && info->symbols != NULL)
1260     {
1261       if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
1262         {
1263           coff_symbol_type * cs;
1264
1265           cs = coffsymbol (*info->symbols);
1266           is_thumb = (   cs->native->u.syment.n_sclass == C_THUMBEXT
1267                       || cs->native->u.syment.n_sclass == C_THUMBSTAT
1268                       || cs->native->u.syment.n_sclass == C_THUMBLABEL
1269                       || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
1270                       || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
1271         }
1272       else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
1273         {
1274           elf_symbol_type *  es;
1275           unsigned int       type;
1276
1277           es = *(elf_symbol_type **)(info->symbols);
1278           type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
1279
1280           is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
1281         }
1282     }
1283
1284   info->bytes_per_chunk = 4;
1285   info->display_endian  = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
1286
1287   if (little)
1288     {
1289       status = info->read_memory_func (pc, (bfd_byte *) &b[0], 4, info);
1290       if (status != 0 && is_thumb)
1291         {
1292           info->bytes_per_chunk = 2;
1293
1294           status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
1295           b[3] = b[2] = 0;
1296         }
1297
1298       if (status != 0)
1299         {
1300           info->memory_error_func (status, pc, info);
1301           return -1;
1302         }
1303
1304       given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
1305     }
1306   else
1307     {
1308       status = info->read_memory_func
1309         (pc & ~ 0x3, (bfd_byte *) &b[0], 4, info);
1310       if (status != 0)
1311         {
1312           info->memory_error_func (status, pc, info);
1313           return -1;
1314         }
1315
1316       if (is_thumb)
1317         {
1318           if (pc & 0x2)
1319             {
1320               given = (b[2] << 8) | b[3];
1321
1322               status = info->read_memory_func
1323                 ((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
1324               if (status != 0)
1325                 {
1326                   info->memory_error_func (status, pc + 4, info);
1327                   return -1;
1328                 }
1329
1330               given |= (b[0] << 24) | (b[1] << 16);
1331             }
1332           else
1333             given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16);
1334         }
1335       else
1336         given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
1337     }
1338
1339   if (info->flags & INSN_HAS_RELOC)
1340     /* If the instruction has a reloc associated with it, then
1341        the offset field in the instruction will actually be the
1342        addend for the reloc.  (We are using REL type relocs).
1343        In such cases, we can ignore the pc when computing
1344        addresses, since the addend is not currently pc-relative.  */
1345     pc = 0;
1346
1347   if (is_thumb)
1348     status = print_insn_thumb (pc, info, given);
1349   else
1350     status = print_insn_arm (pc, info, given);
1351
1352   return status;
1353 }
1354
1355 int
1356 print_insn_big_arm (pc, info)
1357      bfd_vma pc;
1358      struct disassemble_info * info;
1359 {
1360   return print_insn (pc, info, FALSE);
1361 }
1362
1363 int
1364 print_insn_little_arm (pc, info)
1365      bfd_vma pc;
1366      struct disassemble_info * info;
1367 {
1368   return print_insn (pc, info, TRUE);
1369 }
1370
1371 void
1372 print_arm_disassembler_options (FILE * stream)
1373 {
1374   int i;
1375
1376   fprintf (stream, _("\n\
1377 The following ARM specific disassembler options are supported for use with\n\
1378 the -M switch:\n"));
1379
1380   for (i = NUM_ARM_REGNAMES; i--;)
1381     fprintf (stream, "  reg-names-%s %*c%s\n",
1382              regnames[i].name,
1383              (int)(14 - strlen (regnames[i].name)), ' ',
1384              regnames[i].description);
1385
1386   fprintf (stream, "  force-thumb              Assume all insns are Thumb insns\n");
1387   fprintf (stream, "  no-force-thumb           Examine preceeding label to determine an insn's type\n\n");
1388 }