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