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