2001-02-17 Philip Blundell <philb@gnu.org>
[binutils.git] / opcodes / arm-dis.c
blob686b18a1a919dd83e0e505fd4aa45d7882025f88
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 info->bytes_per_chunk = 4;
672 info->bytes_per_line = 4;
674 if ((given & 0x10000000) == 0)
675 func (stream, "blx\t");
676 else
677 func (stream, "bl\t");
679 info->print_address_func (BDISP23 (given) * 2 + pc + 4, info);
680 return 4;
682 else
684 info->bytes_per_chunk = 2;
685 info->bytes_per_line = 4;
687 given &= 0xffff;
689 for (; *c; c++)
691 if (*c == '%')
693 int domaskpc = 0;
694 int domasklr = 0;
696 switch (*++c)
698 case '%':
699 func (stream, "%%");
700 break;
702 case 'S':
704 long reg;
706 reg = (given >> 3) & 0x7;
707 if (given & (1 << 6))
708 reg += 8;
710 func (stream, "%s", arm_regnames[reg]);
712 break;
714 case 'D':
716 long reg;
718 reg = given & 0x7;
719 if (given & (1 << 7))
720 reg += 8;
722 func (stream, "%s", arm_regnames[reg]);
724 break;
726 case 'T':
727 func (stream, "%s",
728 arm_conditional [(given >> 8) & 0xf]);
729 break;
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':
741 int started = 0;
742 int reg;
744 func (stream, "{");
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)
751 if (started)
752 func (stream, ", ");
753 started = 1;
754 func (stream, "%s", arm_regnames[reg]);
757 if (domasklr)
759 if (started)
760 func (stream, ", ");
761 started = 1;
762 func (stream, arm_regnames[14] /* "lr" */);
765 if (domaskpc)
767 if (started)
768 func (stream, ", ");
769 func (stream, arm_regnames[15] /* "pc" */);
772 func (stream, "}");
774 break;
777 case '0': case '1': case '2': case '3': case '4':
778 case '5': case '6': case '7': case '8': case '9':
780 int bitstart = *c++ - '0';
781 int bitend = 0;
783 while (*c >= '0' && *c <= '9')
784 bitstart = (bitstart * 10) + *c++ - '0';
786 switch (*c)
788 case '-':
790 long reg;
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)
801 case 'r':
802 func (stream, "%s", arm_regnames[reg]);
803 break;
805 case 'd':
806 func (stream, "%d", reg);
807 break;
809 case 'H':
810 func (stream, "%d", reg << 1);
811 break;
813 case 'W':
814 func (stream, "%d", reg << 2);
815 break;
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;
825 case 'x':
826 func (stream, "0x%04x", reg);
827 break;
829 case 'I':
830 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
831 func (stream, "%d", reg);
832 break;
834 case 'B':
835 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
836 (*info->print_address_func)
837 (reg * 2 + pc + 4, info);
838 break;
840 default:
841 abort ();
844 break;
846 case '\'':
847 c++;
848 if ((given & (1 << bitstart)) != 0)
849 func (stream, "%c", *c);
850 break;
852 case '?':
853 ++c;
854 if ((given & (1 << bitstart)) != 0)
855 func (stream, "%c", *c++);
856 else
857 func (stream, "%c", *++c);
858 break;
860 default:
861 abort ();
864 break;
866 default:
867 abort ();
870 else
871 func (stream, "%c", *c);
874 return 2;
878 /* No match. */
879 abort ();
882 /* Parse an individual disassembler option. */
883 void
884 parse_arm_disassembler_option (option)
885 char * option;
887 if (option == NULL)
888 return;
890 if (strneq (option, "reg-names-", 10))
892 int i;
894 option += 10;
896 for (i = NUM_ARM_REGNAMES; i--;)
897 if (streq (option, regnames[i].name))
899 regname_selected = i;
900 break;
903 if (i < 0)
904 fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
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);
913 return;
916 /* Parse the string of disassembler options, spliting it at whitespaces. */
917 static void
918 parse_disassembler_options (options)
919 char * options;
921 char * space;
923 if (options == NULL)
924 return;
928 space = strchr (options, ' ');
930 if (space)
932 * space = '\0';
933 parse_arm_disassembler_option (options);
934 * space = ' ';
935 options = space + 1;
937 else
938 parse_arm_disassembler_option (options);
940 while (space);
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;
951 unsigned char b[4];
952 long given;
953 int status;
954 int is_thumb;
956 if (info->disassembler_options)
958 parse_disassembler_options (info->disassembler_options);
960 /* To avoid repeated parsing of these options, we remove them here. */
961 info->disassembler_options = NULL;
964 is_thumb = force_thumb;
966 if (!is_thumb && info->symbols != NULL)
968 if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
970 coff_symbol_type * cs;
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);
979 else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
981 elf_symbol_type * es;
982 unsigned int type;
984 es = *(elf_symbol_type **)(info->symbols);
985 type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
987 is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
991 info->bytes_per_chunk = 4;
992 info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
994 if (little)
996 status = info->read_memory_func (pc, (bfd_byte *) &b[0], 4, info);
997 if (status != 0 && is_thumb)
999 info->bytes_per_chunk = 2;
1001 status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
1002 b[3] = b[2] = 0;
1005 if (status != 0)
1007 info->memory_error_func (status, pc, info);
1008 return -1;
1011 given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
1013 else
1015 status = info->read_memory_func
1016 (pc & ~ 0x3, (bfd_byte *) &b[0], 4, info);
1017 if (status != 0)
1019 info->memory_error_func (status, pc, info);
1020 return -1;
1023 if (is_thumb)
1025 if (pc & 0x2)
1027 given = (b[2] << 8) | b[3];
1029 status = info->read_memory_func
1030 ((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
1031 if (status != 0)
1033 info->memory_error_func (status, pc + 4, info);
1034 return -1;
1037 given |= (b[0] << 24) | (b[1] << 16);
1039 else
1040 given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16);
1042 else
1043 given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
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;
1054 if (is_thumb)
1055 status = print_insn_thumb (pc, info, given);
1056 else
1057 status = print_insn_arm (pc, info, given);
1059 return status;
1063 print_insn_big_arm (pc, info)
1064 bfd_vma pc;
1065 struct disassemble_info * info;
1067 return print_insn (pc, info, false);
1071 print_insn_little_arm (pc, info)
1072 bfd_vma pc;
1073 struct disassemble_info * info;
1075 return print_insn (pc, info, true);
1078 void
1079 print_arm_disassembler_options (FILE * stream)
1081 int i;
1083 fprintf (stream, _("\n\
1084 The following ARM specific disassembler options are supported for use with\n\
1085 the -M switch:\n"));
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);
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");