2002-06-18 Dave Brolley <brolley@redhat.com>
[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 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.055899 seconds and 4 git commands to generate.