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