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