file as.info-9 was initially added on branch binutils-2_11-branch.
[binutils.git] / opcodes / arm-dis.c
blob0681758de99f89ac746e6fb5c80cdae2f0c4912b
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)
6 This file is part of libopcodes.
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.
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.
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. */
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"
30 /* FIXME: This shouldn't be done here */
31 #include "elf-bfd.h"
32 #include "elf/internal.h"
33 #include "elf/arm.h"
35 #ifndef streq
36 #define streq(a,b) (strcmp ((a), (b)) == 0)
37 #endif
39 #ifndef strneq
40 #define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
41 #endif
43 #ifndef NUM_ELEM
44 #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
45 #endif
47 static char * arm_conditional[] =
48 {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
49 "hi", "ls", "ge", "lt", "gt", "le", "", "nv"};
51 typedef struct
53 const char * name;
54 const char * description;
55 const char * reg_names[16];
57 arm_regname;
59 static arm_regname regnames[] =
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" }}
75 /* Default to GCC register name set. */
76 static unsigned int regname_selected = 1;
78 #define NUM_ARM_REGNAMES NUM_ELEM (regnames)
79 #define arm_regnames regnames[regname_selected].reg_names
81 static boolean force_thumb = false;
83 static char * arm_fp_const[] =
84 {"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
86 static char * arm_shift[] =
87 {"lsl", "lsr", "asr", "ror"};
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);
101 /* Functions. */
103 get_arm_regname_num_options (void)
105 return NUM_ARM_REGNAMES;
109 set_arm_regname_option (int option)
111 int old = regname_selected;
112 regname_selected = option;
113 return old;
117 get_arm_regnames (int option, const char **setname,
118 const char **setdescription,
119 const char ***register_names)
121 *setname = regnames[option].name;
122 *setdescription = regnames[option].description;
123 *register_names = regnames[option].reg_names;
124 return 16;
127 static void
128 arm_decode_shift (given, func, stream)
129 long given;
130 fprintf_ftype func;
131 void * stream;
133 func (stream, "%s", arm_regnames[given & 0xf]);
135 if ((given & 0xff0) != 0)
137 if ((given & 0x10) == 0)
139 int amount = (given & 0xf80) >> 7;
140 int shift = (given & 0x60) >> 5;
142 if (amount == 0)
144 if (shift == 3)
146 func (stream, ", rrx");
147 return;
150 amount = 32;
153 func (stream, ", %s #%d", arm_shift[shift], amount);
155 else
156 func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5],
157 arm_regnames[(given & 0xf00) >> 8]);
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;
169 struct arm_opcode * insn;
170 void * stream = info->stream;
171 fprintf_ftype func = info->fprintf_func;
173 for (insn = arm_opcodes; insn->assembler; insn++)
175 if ((given & insn->mask) == insn->value)
177 char * c;
179 for (c = insn->assembler; *c; c++)
181 if (*c == '%')
183 switch (*++c)
185 case '%':
186 func (stream, "%%");
187 break;
189 case 'a':
190 if (((given & 0x000f0000) == 0x000f0000)
191 && ((given & 0x02000000) == 0))
193 int offset = given & 0xfff;
195 func (stream, "[pc");
197 if (given & 0x01000000)
199 if ((given & 0x00800000) == 0)
200 offset = - offset;
202 /* pre-indexed */
203 func (stream, ", #%x]", offset);
205 offset += pc + 8;
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, "!");
214 else
216 /* Post indexed. */
217 func (stream, "], #%x", offset);
219 offset = pc + 8; /* ie ignore the offset. */
222 func (stream, "\t; ");
223 info->print_address_func (offset, info);
225 else
227 func (stream, "[%s",
228 arm_regnames[(given >> 16) & 0xf]);
229 if ((given & 0x01000000) != 0)
231 if ((given & 0x02000000) == 0)
233 int offset = given & 0xfff;
234 if (offset)
235 func (stream, ", %s#%d",
236 (((given & 0x00800000) == 0)
237 ? "-" : ""), offset);
239 else
241 func (stream, ", %s",
242 (((given & 0x00800000) == 0)
243 ? "-" : ""));
244 arm_decode_shift (given, func, stream);
247 func (stream, "]%s",
248 ((given & 0x00200000) != 0) ? "!" : "");
250 else
252 if ((given & 0x02000000) == 0)
254 int offset = given & 0xfff;
255 if (offset)
256 func (stream, "], %s#%d",
257 (((given & 0x00800000) == 0)
258 ? "-" : ""), offset);
259 else
260 func (stream, "]");
262 else
264 func (stream, "], %s",
265 (((given & 0x00800000) == 0)
266 ? "-" : ""));
267 arm_decode_shift (given, func, stream);
271 break;
273 case 's':
274 if ((given & 0x004f0000) == 0x004f0000)
276 /* PC relative with immediate offset. */
277 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
279 if ((given & 0x00800000) == 0)
280 offset = -offset;
282 func (stream, "[pc, #%x]\t; ", offset);
284 (*info->print_address_func)
285 (offset + pc + 8, info);
287 else
289 func (stream, "[%s",
290 arm_regnames[(given >> 16) & 0xf]);
291 if ((given & 0x01000000) != 0)
293 /* Pre-indexed. */
294 if ((given & 0x00400000) == 0x00400000)
296 /* Immediate. */
297 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
298 if (offset)
299 func (stream, ", %s#%d",
300 (((given & 0x00800000) == 0)
301 ? "-" : ""), offset);
303 else
305 /* Register. */
306 func (stream, ", %s%s",
307 (((given & 0x00800000) == 0)
308 ? "-" : ""),
309 arm_regnames[given & 0xf]);
312 func (stream, "]%s",
313 ((given & 0x00200000) != 0) ? "!" : "");
315 else
317 /* Post-indexed. */
318 if ((given & 0x00400000) == 0x00400000)
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, "]");
329 else
331 /* Register. */
332 func (stream, "], %s%s",
333 (((given & 0x00800000) == 0)
334 ? "-" : ""),
335 arm_regnames[given & 0xf]);
339 break;
341 case 'b':
342 (*info->print_address_func)
343 (BDISP (given) * 4 + pc + 8, info);
344 break;
346 case 'c':
347 func (stream, "%s",
348 arm_conditional [(given >> 28) & 0xf]);
349 break;
351 case 'm':
353 int started = 0;
354 int reg;
356 func (stream, "{");
357 for (reg = 0; reg < 16; reg++)
358 if ((given & (1 << reg)) != 0)
360 if (started)
361 func (stream, ", ");
362 started = 1;
363 func (stream, "%s", arm_regnames[reg]);
365 func (stream, "}");
367 break;
369 case 'o':
370 if ((given & 0x02000000) != 0)
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);
378 else
379 arm_decode_shift (given, func, stream);
380 break;
382 case 'p':
383 if ((given & 0x0000f000) == 0x0000f000)
384 func (stream, "p");
385 break;
387 case 't':
388 if ((given & 0x01200000) == 0x00200000)
389 func (stream, "t");
390 break;
392 case 'h':
393 if ((given & 0x00000020) == 0x00000020)
394 func (stream, "h");
395 else
396 func (stream, "b");
397 break;
399 case 'A':
400 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
401 if ((given & 0x01000000) != 0)
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, "]");
412 else
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, "]");
422 break;
424 case 'B':
425 /* Print ARM V5 BLX(1) address: pc+25 bits. */
427 bfd_vma address;
428 bfd_vma offset = 0;
430 if (given & 0x00800000)
431 /* Is signed, hi bits should be ones. */
432 offset = (-1) ^ 0x00ffffff;
434 /* Offset is (SignExtend(offset field)<<2). */
435 offset += given & 0x00ffffff;
436 offset <<= 2;
437 address = offset + pc + 8;
439 if (given & 0x01000000)
440 /* H bit allows addressing to 2-byte boundaries. */
441 address += 2;
443 info->print_address_func (address, info);
445 break;
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;
459 case 'F':
460 switch (given & 0x00408000)
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");
474 break;
476 case 'P':
477 switch (given & 0x00080080)
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;
492 break;
493 case 'Q':
494 switch (given & 0x00408000)
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;
509 break;
510 case 'R':
511 switch (given & 0x60)
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;
525 break;
527 case '0': case '1': case '2': case '3': case '4':
528 case '5': case '6': case '7': case '8': case '9':
530 int bitstart = *c++ - '0';
531 int bitend = 0;
532 while (*c >= '0' && *c <= '9')
533 bitstart = (bitstart * 10) + *c++ - '0';
535 switch (*c)
537 case '-':
538 c++;
540 while (*c >= '0' && *c <= '9')
541 bitend = (bitend * 10) + *c++ - '0';
543 if (!bitend)
544 abort ();
546 switch (*c)
548 case 'r':
550 long reg;
552 reg = given >> bitstart;
553 reg &= (2 << (bitend - bitstart)) - 1;
555 func (stream, "%s", arm_regnames[reg]);
557 break;
558 case 'd':
560 long reg;
562 reg = given >> bitstart;
563 reg &= (2 << (bitend - bitstart)) - 1;
565 func (stream, "%d", reg);
567 break;
568 case 'x':
570 long reg;
572 reg = given >> bitstart;
573 reg &= (2 << (bitend - bitstart)) - 1;
575 func (stream, "0x%08x", reg);
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");
584 break;
585 case 'X':
587 long reg;
589 reg = given >> bitstart;
590 reg &= (2 << (bitend - bitstart)) - 1;
592 func (stream, "%01x", reg & 0xf);
594 break;
595 case 'f':
597 long reg;
599 reg = given >> bitstart;
600 reg &= (2 << (bitend - bitstart)) - 1;
602 if (reg > 7)
603 func (stream, "#%s",
604 arm_fp_const[reg & 7]);
605 else
606 func (stream, "f%d", reg);
608 break;
609 default:
610 abort ();
612 break;
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 ();
634 break;
636 default:
637 abort ();
641 else
642 func (stream, "%c", *c);
644 return 4;
647 abort ();
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;
658 struct thumb_opcode * insn;
659 void * stream = info->stream;
660 fprintf_ftype func = info->fprintf_func;
662 for (insn = thumb_opcodes; insn->assembler; insn++)
664 if ((given & insn->mask) == insn->value)
666 char * c = insn->assembler;
668 /* Special processing for Thumb 2 instruction BL sequence: */
669 if (!*c) /* Check for empty (not NULL) assembler string. */
671 long offset;
673 info->bytes_per_chunk = 4;
674 info->bytes_per_line = 4;
676 offset = BDISP23 (given);
678 if ((given & 0x10000000) == 0)
680 func (stream, "blx\t");
682 /* The spec says that bit 1 of the branch's destination
683 address comes from bit 1 of the instruction's
684 address and not from the offset in the instruction. */
685 if (offset & 0x1)
687 /* func (stream, "*malformed!* "); */
688 offset &= ~ 0x1;
691 offset |= ((pc & 0x2) >> 1);
693 else
694 func (stream, "bl\t");
696 info->print_address_func (offset * 2 + pc + 4, info);
697 return 4;
699 else
701 info->bytes_per_chunk = 2;
702 info->bytes_per_line = 4;
704 given &= 0xffff;
706 for (; *c; c++)
708 if (*c == '%')
710 int domaskpc = 0;
711 int domasklr = 0;
713 switch (*++c)
715 case '%':
716 func (stream, "%%");
717 break;
719 case 'S':
721 long reg;
723 reg = (given >> 3) & 0x7;
724 if (given & (1 << 6))
725 reg += 8;
727 func (stream, "%s", arm_regnames[reg]);
729 break;
731 case 'D':
733 long reg;
735 reg = given & 0x7;
736 if (given & (1 << 7))
737 reg += 8;
739 func (stream, "%s", arm_regnames[reg]);
741 break;
743 case 'T':
744 func (stream, "%s",
745 arm_conditional [(given >> 8) & 0xf]);
746 break;
748 case 'N':
749 if (given & (1 << 8))
750 domasklr = 1;
751 /* Fall through. */
752 case 'O':
753 if (*c == 'O' && (given & (1 << 8)))
754 domaskpc = 1;
755 /* Fall through. */
756 case 'M':
758 int started = 0;
759 int reg;
761 func (stream, "{");
763 /* It would be nice if we could spot
764 ranges, and generate the rS-rE format: */
765 for (reg = 0; (reg < 8); reg++)
766 if ((given & (1 << reg)) != 0)
768 if (started)
769 func (stream, ", ");
770 started = 1;
771 func (stream, "%s", arm_regnames[reg]);
774 if (domasklr)
776 if (started)
777 func (stream, ", ");
778 started = 1;
779 func (stream, arm_regnames[14] /* "lr" */);
782 if (domaskpc)
784 if (started)
785 func (stream, ", ");
786 func (stream, arm_regnames[15] /* "pc" */);
789 func (stream, "}");
791 break;
794 case '0': case '1': case '2': case '3': case '4':
795 case '5': case '6': case '7': case '8': case '9':
797 int bitstart = *c++ - '0';
798 int bitend = 0;
800 while (*c >= '0' && *c <= '9')
801 bitstart = (bitstart * 10) + *c++ - '0';
803 switch (*c)
805 case '-':
807 long reg;
809 c++;
810 while (*c >= '0' && *c <= '9')
811 bitend = (bitend * 10) + *c++ - '0';
812 if (!bitend)
813 abort ();
814 reg = given >> bitstart;
815 reg &= (2 << (bitend - bitstart)) - 1;
816 switch (*c)
818 case 'r':
819 func (stream, "%s", arm_regnames[reg]);
820 break;
822 case 'd':
823 func (stream, "%d", reg);
824 break;
826 case 'H':
827 func (stream, "%d", reg << 1);
828 break;
830 case 'W':
831 func (stream, "%d", reg << 2);
832 break;
834 case 'a':
835 /* PC-relative address -- the bottom two
836 bits of the address are dropped
837 before the calculation. */
838 info->print_address_func
839 (((pc + 4) & ~3) + (reg << 2), info);
840 break;
842 case 'x':
843 func (stream, "0x%04x", reg);
844 break;
846 case 'I':
847 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
848 func (stream, "%d", reg);
849 break;
851 case 'B':
852 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
853 (*info->print_address_func)
854 (reg * 2 + pc + 4, info);
855 break;
857 default:
858 abort ();
861 break;
863 case '\'':
864 c++;
865 if ((given & (1 << bitstart)) != 0)
866 func (stream, "%c", *c);
867 break;
869 case '?':
870 ++c;
871 if ((given & (1 << bitstart)) != 0)
872 func (stream, "%c", *c++);
873 else
874 func (stream, "%c", *++c);
875 break;
877 default:
878 abort ();
881 break;
883 default:
884 abort ();
887 else
888 func (stream, "%c", *c);
891 return 2;
895 /* No match. */
896 abort ();
899 /* Parse an individual disassembler option. */
900 void
901 parse_arm_disassembler_option (option)
902 char * option;
904 if (option == NULL)
905 return;
907 if (strneq (option, "reg-names-", 10))
909 int i;
911 option += 10;
913 for (i = NUM_ARM_REGNAMES; i--;)
914 if (streq (option, regnames[i].name))
916 regname_selected = i;
917 break;
920 if (i < 0)
921 fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
923 else if (streq (option, "force-thumb"))
924 force_thumb = 1;
925 else if (streq (option, "no-force-thumb"))
926 force_thumb = 0;
927 else
928 fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
930 return;
933 /* Parse the string of disassembler options, spliting it at whitespaces. */
934 static void
935 parse_disassembler_options (options)
936 char * options;
938 char * space;
940 if (options == NULL)
941 return;
945 space = strchr (options, ' ');
947 if (space)
949 * space = '\0';
950 parse_arm_disassembler_option (options);
951 * space = ' ';
952 options = space + 1;
954 else
955 parse_arm_disassembler_option (options);
957 while (space);
960 /* NOTE: There are no checks in these routines that
961 the relevant number of data bytes exist. */
962 static int
963 print_insn (pc, info, little)
964 bfd_vma pc;
965 struct disassemble_info * info;
966 boolean little;
968 unsigned char b[4];
969 long given;
970 int status;
971 int is_thumb;
973 if (info->disassembler_options)
975 parse_disassembler_options (info->disassembler_options);
977 /* To avoid repeated parsing of these options, we remove them here. */
978 info->disassembler_options = NULL;
981 is_thumb = force_thumb;
983 if (!is_thumb && info->symbols != NULL)
985 if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
987 coff_symbol_type * cs;
989 cs = coffsymbol (*info->symbols);
990 is_thumb = ( cs->native->u.syment.n_sclass == C_THUMBEXT
991 || cs->native->u.syment.n_sclass == C_THUMBSTAT
992 || cs->native->u.syment.n_sclass == C_THUMBLABEL
993 || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
994 || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
996 else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
998 elf_symbol_type * es;
999 unsigned int type;
1001 es = *(elf_symbol_type **)(info->symbols);
1002 type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
1004 is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
1008 info->bytes_per_chunk = 4;
1009 info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
1011 if (little)
1013 status = info->read_memory_func (pc, (bfd_byte *) &b[0], 4, info);
1014 if (status != 0 && is_thumb)
1016 info->bytes_per_chunk = 2;
1018 status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
1019 b[3] = b[2] = 0;
1022 if (status != 0)
1024 info->memory_error_func (status, pc, info);
1025 return -1;
1028 given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
1030 else
1032 status = info->read_memory_func
1033 (pc & ~ 0x3, (bfd_byte *) &b[0], 4, info);
1034 if (status != 0)
1036 info->memory_error_func (status, pc, info);
1037 return -1;
1040 if (is_thumb)
1042 if (pc & 0x2)
1044 given = (b[2] << 8) | b[3];
1046 status = info->read_memory_func
1047 ((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
1048 if (status != 0)
1050 info->memory_error_func (status, pc + 4, info);
1051 return -1;
1054 given |= (b[0] << 24) | (b[1] << 16);
1056 else
1057 given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16);
1059 else
1060 given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
1063 if (info->flags & INSN_HAS_RELOC)
1064 /* If the instruction has a reloc associated with it, then
1065 the offset field in the instruction will actually be the
1066 addend for the reloc. (We are using REL type relocs).
1067 In such cases, we can ignore the pc when computing
1068 addresses, since the addend is not currently pc-relative. */
1069 pc = 0;
1071 if (is_thumb)
1072 status = print_insn_thumb (pc, info, given);
1073 else
1074 status = print_insn_arm (pc, info, given);
1076 return status;
1080 print_insn_big_arm (pc, info)
1081 bfd_vma pc;
1082 struct disassemble_info * info;
1084 return print_insn (pc, info, false);
1088 print_insn_little_arm (pc, info)
1089 bfd_vma pc;
1090 struct disassemble_info * info;
1092 return print_insn (pc, info, true);
1095 void
1096 print_arm_disassembler_options (FILE * stream)
1098 int i;
1100 fprintf (stream, _("\n\
1101 The following ARM specific disassembler options are supported for use with\n\
1102 the -M switch:\n"));
1104 for (i = NUM_ARM_REGNAMES; i--;)
1105 fprintf (stream, " reg-names-%s %*c%s\n",
1106 regnames[i].name,
1107 14 - strlen (regnames[i].name), ' ',
1108 regnames[i].description);
1110 fprintf (stream, " force-thumb Assume all insns are Thumb insns\n");
1111 fprintf (stream, " no-force-thumb Examine preceeding label to determine an insn's type\n\n");