2001-03-18 H.J. Lu <hjl@gnu.org>
[binutils.git] / opcodes / arm-dis.c
blob9d280a17b79581d9768d81d7e8f91d0da389f796
1 /* Instruction printing code for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
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)
7 This file is part of libopcodes.
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.
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.
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. */
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"
31 /* FIXME: This shouldn't be done here */
32 #include "elf-bfd.h"
33 #include "elf/internal.h"
34 #include "elf/arm.h"
36 #ifndef streq
37 #define streq(a,b) (strcmp ((a), (b)) == 0)
38 #endif
40 #ifndef strneq
41 #define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
42 #endif
44 #ifndef NUM_ELEM
45 #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
46 #endif
48 static char * arm_conditional[] =
49 {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
50 "hi", "ls", "ge", "lt", "gt", "le", "", "nv"};
52 typedef struct
54 const char * name;
55 const char * description;
56 const char * reg_names[16];
58 arm_regname;
60 static arm_regname regnames[] =
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" }}
76 /* Default to GCC register name set. */
77 static unsigned int regname_selected = 1;
79 #define NUM_ARM_REGNAMES NUM_ELEM (regnames)
80 #define arm_regnames regnames[regname_selected].reg_names
82 static boolean force_thumb = false;
84 static char * arm_fp_const[] =
85 {"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
87 static char * arm_shift[] =
88 {"lsl", "lsr", "asr", "ror"};
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);
102 /* Functions. */
104 get_arm_regname_num_options (void)
106 return NUM_ARM_REGNAMES;
110 set_arm_regname_option (int option)
112 int old = regname_selected;
113 regname_selected = option;
114 return old;
118 get_arm_regnames (int option, const char **setname,
119 const char **setdescription,
120 const char ***register_names)
122 *setname = regnames[option].name;
123 *setdescription = regnames[option].description;
124 *register_names = regnames[option].reg_names;
125 return 16;
128 static void
129 arm_decode_shift (given, func, stream)
130 long given;
131 fprintf_ftype func;
132 void * stream;
134 func (stream, "%s", arm_regnames[given & 0xf]);
136 if ((given & 0xff0) != 0)
138 if ((given & 0x10) == 0)
140 int amount = (given & 0xf80) >> 7;
141 int shift = (given & 0x60) >> 5;
143 if (amount == 0)
145 if (shift == 3)
147 func (stream, ", rrx");
148 return;
151 amount = 32;
154 func (stream, ", %s #%d", arm_shift[shift], amount);
156 else
157 func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5],
158 arm_regnames[(given & 0xf00) >> 8]);
162 /* Print one instruction from PC on INFO->STREAM.
163 Return the size of the instruction (always 4 on ARM). */
164 static int
165 print_insn_arm (pc, info, given)
166 bfd_vma pc;
167 struct disassemble_info * info;
168 long given;
170 struct arm_opcode * insn;
171 void * stream = info->stream;
172 fprintf_ftype func = info->fprintf_func;
174 for (insn = arm_opcodes; insn->assembler; insn++)
176 if ((given & insn->mask) == insn->value)
178 char * c;
180 for (c = insn->assembler; *c; c++)
182 if (*c == '%')
184 switch (*++c)
186 case '%':
187 func (stream, "%%");
188 break;
190 case 'a':
191 if (((given & 0x000f0000) == 0x000f0000)
192 && ((given & 0x02000000) == 0))
194 int offset = given & 0xfff;
196 func (stream, "[pc");
198 if (given & 0x01000000)
200 if ((given & 0x00800000) == 0)
201 offset = - offset;
203 /* pre-indexed */
204 func (stream, ", #%x]", offset);
206 offset += pc + 8;
208 /* Cope with the possibility of write-back
209 being used. Probably a very dangerous thing
210 for the programmer to do, but who are we to
211 argue ? */
212 if (given & 0x00200000)
213 func (stream, "!");
215 else
217 /* Post indexed. */
218 func (stream, "], #%x", offset);
220 offset = pc + 8; /* ie ignore the offset. */
223 func (stream, "\t; ");
224 info->print_address_func (offset, info);
226 else
228 func (stream, "[%s",
229 arm_regnames[(given >> 16) & 0xf]);
230 if ((given & 0x01000000) != 0)
232 if ((given & 0x02000000) == 0)
234 int offset = given & 0xfff;
235 if (offset)
236 func (stream, ", %s#%d",
237 (((given & 0x00800000) == 0)
238 ? "-" : ""), offset);
240 else
242 func (stream, ", %s",
243 (((given & 0x00800000) == 0)
244 ? "-" : ""));
245 arm_decode_shift (given, func, stream);
248 func (stream, "]%s",
249 ((given & 0x00200000) != 0) ? "!" : "");
251 else
253 if ((given & 0x02000000) == 0)
255 int offset = given & 0xfff;
256 if (offset)
257 func (stream, "], %s#%d",
258 (((given & 0x00800000) == 0)
259 ? "-" : ""), offset);
260 else
261 func (stream, "]");
263 else
265 func (stream, "], %s",
266 (((given & 0x00800000) == 0)
267 ? "-" : ""));
268 arm_decode_shift (given, func, stream);
272 break;
274 case 's':
275 if ((given & 0x004f0000) == 0x004f0000)
277 /* PC relative with immediate offset. */
278 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
280 if ((given & 0x00800000) == 0)
281 offset = -offset;
283 func (stream, "[pc, #%x]\t; ", offset);
285 (*info->print_address_func)
286 (offset + pc + 8, info);
288 else
290 func (stream, "[%s",
291 arm_regnames[(given >> 16) & 0xf]);
292 if ((given & 0x01000000) != 0)
294 /* Pre-indexed. */
295 if ((given & 0x00400000) == 0x00400000)
297 /* Immediate. */
298 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
299 if (offset)
300 func (stream, ", %s#%d",
301 (((given & 0x00800000) == 0)
302 ? "-" : ""), offset);
304 else
306 /* Register. */
307 func (stream, ", %s%s",
308 (((given & 0x00800000) == 0)
309 ? "-" : ""),
310 arm_regnames[given & 0xf]);
313 func (stream, "]%s",
314 ((given & 0x00200000) != 0) ? "!" : "");
316 else
318 /* Post-indexed. */
319 if ((given & 0x00400000) == 0x00400000)
321 /* Immediate. */
322 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
323 if (offset)
324 func (stream, "], %s#%d",
325 (((given & 0x00800000) == 0)
326 ? "-" : ""), offset);
327 else
328 func (stream, "]");
330 else
332 /* Register. */
333 func (stream, "], %s%s",
334 (((given & 0x00800000) == 0)
335 ? "-" : ""),
336 arm_regnames[given & 0xf]);
340 break;
342 case 'b':
343 (*info->print_address_func)
344 (BDISP (given) * 4 + pc + 8, info);
345 break;
347 case 'c':
348 func (stream, "%s",
349 arm_conditional [(given >> 28) & 0xf]);
350 break;
352 case 'm':
354 int started = 0;
355 int reg;
357 func (stream, "{");
358 for (reg = 0; reg < 16; reg++)
359 if ((given & (1 << reg)) != 0)
361 if (started)
362 func (stream, ", ");
363 started = 1;
364 func (stream, "%s", arm_regnames[reg]);
366 func (stream, "}");
368 break;
370 case 'o':
371 if ((given & 0x02000000) != 0)
373 int rotate = (given & 0xf00) >> 7;
374 int immed = (given & 0xff);
375 immed = (((immed << (32 - rotate))
376 | (immed >> rotate)) & 0xffffffff);
377 func (stream, "#%d\t; 0x%x", immed, immed);
379 else
380 arm_decode_shift (given, func, stream);
381 break;
383 case 'p':
384 if ((given & 0x0000f000) == 0x0000f000)
385 func (stream, "p");
386 break;
388 case 't':
389 if ((given & 0x01200000) == 0x00200000)
390 func (stream, "t");
391 break;
393 case 'h':
394 if ((given & 0x00000020) == 0x00000020)
395 func (stream, "h");
396 else
397 func (stream, "b");
398 break;
400 case 'A':
401 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
402 if ((given & 0x01000000) != 0)
404 int offset = given & 0xff;
405 if (offset)
406 func (stream, ", %s#%d]%s",
407 ((given & 0x00800000) == 0 ? "-" : ""),
408 offset * 4,
409 ((given & 0x00200000) != 0 ? "!" : ""));
410 else
411 func (stream, "]");
413 else
415 int offset = given & 0xff;
416 if (offset)
417 func (stream, "], %s#%d",
418 ((given & 0x00800000) == 0 ? "-" : ""),
419 offset * 4);
420 else
421 func (stream, "]");
423 break;
425 case 'B':
426 /* Print ARM V5 BLX(1) address: pc+25 bits. */
428 bfd_vma address;
429 bfd_vma offset = 0;
431 if (given & 0x00800000)
432 /* Is signed, hi bits should be ones. */
433 offset = (-1) ^ 0x00ffffff;
435 /* Offset is (SignExtend(offset field)<<2). */
436 offset += given & 0x00ffffff;
437 offset <<= 2;
438 address = offset + pc + 8;
440 if (given & 0x01000000)
441 /* H bit allows addressing to 2-byte boundaries. */
442 address += 2;
444 info->print_address_func (address, info);
446 break;
448 case 'C':
449 func (stream, "_");
450 if (given & 0x80000)
451 func (stream, "f");
452 if (given & 0x40000)
453 func (stream, "s");
454 if (given & 0x20000)
455 func (stream, "x");
456 if (given & 0x10000)
457 func (stream, "c");
458 break;
460 case 'F':
461 switch (given & 0x00408000)
463 case 0:
464 func (stream, "4");
465 break;
466 case 0x8000:
467 func (stream, "1");
468 break;
469 case 0x00400000:
470 func (stream, "2");
471 break;
472 default:
473 func (stream, "3");
475 break;
477 case 'P':
478 switch (given & 0x00080080)
480 case 0:
481 func (stream, "s");
482 break;
483 case 0x80:
484 func (stream, "d");
485 break;
486 case 0x00080000:
487 func (stream, "e");
488 break;
489 default:
490 func (stream, _("<illegal precision>"));
491 break;
493 break;
494 case 'Q':
495 switch (given & 0x00408000)
497 case 0:
498 func (stream, "s");
499 break;
500 case 0x8000:
501 func (stream, "d");
502 break;
503 case 0x00400000:
504 func (stream, "e");
505 break;
506 default:
507 func (stream, "p");
508 break;
510 break;
511 case 'R':
512 switch (given & 0x60)
514 case 0:
515 break;
516 case 0x20:
517 func (stream, "p");
518 break;
519 case 0x40:
520 func (stream, "m");
521 break;
522 default:
523 func (stream, "z");
524 break;
526 break;
528 case '0': case '1': case '2': case '3': case '4':
529 case '5': case '6': case '7': case '8': case '9':
531 int bitstart = *c++ - '0';
532 int bitend = 0;
533 while (*c >= '0' && *c <= '9')
534 bitstart = (bitstart * 10) + *c++ - '0';
536 switch (*c)
538 case '-':
539 c++;
541 while (*c >= '0' && *c <= '9')
542 bitend = (bitend * 10) + *c++ - '0';
544 if (!bitend)
545 abort ();
547 switch (*c)
549 case 'r':
551 long reg;
553 reg = given >> bitstart;
554 reg &= (2 << (bitend - bitstart)) - 1;
556 func (stream, "%s", arm_regnames[reg]);
558 break;
559 case 'd':
561 long reg;
563 reg = given >> bitstart;
564 reg &= (2 << (bitend - bitstart)) - 1;
566 func (stream, "%d", reg);
568 break;
569 case 'x':
571 long reg;
573 reg = given >> bitstart;
574 reg &= (2 << (bitend - bitstart)) - 1;
576 func (stream, "0x%08x", reg);
578 /* Some SWI instructions have special
579 meanings. */
580 if ((given & 0x0fffffff) == 0x0FF00000)
581 func (stream, "\t; IMB");
582 else if ((given & 0x0fffffff) == 0x0FF00001)
583 func (stream, "\t; IMBRange");
585 break;
586 case 'X':
588 long reg;
590 reg = given >> bitstart;
591 reg &= (2 << (bitend - bitstart)) - 1;
593 func (stream, "%01x", reg & 0xf);
595 break;
596 case 'f':
598 long reg;
600 reg = given >> bitstart;
601 reg &= (2 << (bitend - bitstart)) - 1;
603 if (reg > 7)
604 func (stream, "#%s",
605 arm_fp_const[reg & 7]);
606 else
607 func (stream, "f%d", reg);
609 break;
610 default:
611 abort ();
613 break;
615 case '`':
616 c++;
617 if ((given & (1 << bitstart)) == 0)
618 func (stream, "%c", *c);
619 break;
620 case '\'':
621 c++;
622 if ((given & (1 << bitstart)) != 0)
623 func (stream, "%c", *c);
624 break;
625 case '?':
626 ++c;
627 if ((given & (1 << bitstart)) != 0)
628 func (stream, "%c", *c++);
629 else
630 func (stream, "%c", *++c);
631 break;
632 default:
633 abort ();
635 break;
637 default:
638 abort ();
642 else
643 func (stream, "%c", *c);
645 return 4;
648 abort ();
651 /* Print one instruction from PC on INFO->STREAM.
652 Return the size of the instruction. */
653 static int
654 print_insn_thumb (pc, info, given)
655 bfd_vma pc;
656 struct disassemble_info * info;
657 long given;
659 struct thumb_opcode * insn;
660 void * stream = info->stream;
661 fprintf_ftype func = info->fprintf_func;
663 for (insn = thumb_opcodes; insn->assembler; insn++)
665 if ((given & insn->mask) == insn->value)
667 char * c = insn->assembler;
669 /* Special processing for Thumb 2 instruction BL sequence: */
670 if (!*c) /* Check for empty (not NULL) assembler string. */
672 long offset;
674 info->bytes_per_chunk = 4;
675 info->bytes_per_line = 4;
677 offset = BDISP23 (given);
679 if ((given & 0x10000000) == 0)
681 func (stream, "blx\t");
683 /* The spec says that bit 1 of the branch's destination
684 address comes from bit 1 of the instruction's
685 address and not from the offset in the instruction. */
686 if (offset & 0x1)
688 /* func (stream, "*malformed!* "); */
689 offset &= ~ 0x1;
692 offset |= ((pc & 0x2) >> 1);
694 else
695 func (stream, "bl\t");
697 info->print_address_func (offset * 2 + pc + 4, info);
698 return 4;
700 else
702 info->bytes_per_chunk = 2;
703 info->bytes_per_line = 4;
705 given &= 0xffff;
707 for (; *c; c++)
709 if (*c == '%')
711 int domaskpc = 0;
712 int domasklr = 0;
714 switch (*++c)
716 case '%':
717 func (stream, "%%");
718 break;
720 case 'S':
722 long reg;
724 reg = (given >> 3) & 0x7;
725 if (given & (1 << 6))
726 reg += 8;
728 func (stream, "%s", arm_regnames[reg]);
730 break;
732 case 'D':
734 long reg;
736 reg = given & 0x7;
737 if (given & (1 << 7))
738 reg += 8;
740 func (stream, "%s", arm_regnames[reg]);
742 break;
744 case 'T':
745 func (stream, "%s",
746 arm_conditional [(given >> 8) & 0xf]);
747 break;
749 case 'N':
750 if (given & (1 << 8))
751 domasklr = 1;
752 /* Fall through. */
753 case 'O':
754 if (*c == 'O' && (given & (1 << 8)))
755 domaskpc = 1;
756 /* Fall through. */
757 case 'M':
759 int started = 0;
760 int reg;
762 func (stream, "{");
764 /* It would be nice if we could spot
765 ranges, and generate the rS-rE format: */
766 for (reg = 0; (reg < 8); reg++)
767 if ((given & (1 << reg)) != 0)
769 if (started)
770 func (stream, ", ");
771 started = 1;
772 func (stream, "%s", arm_regnames[reg]);
775 if (domasklr)
777 if (started)
778 func (stream, ", ");
779 started = 1;
780 func (stream, arm_regnames[14] /* "lr" */);
783 if (domaskpc)
785 if (started)
786 func (stream, ", ");
787 func (stream, arm_regnames[15] /* "pc" */);
790 func (stream, "}");
792 break;
795 case '0': case '1': case '2': case '3': case '4':
796 case '5': case '6': case '7': case '8': case '9':
798 int bitstart = *c++ - '0';
799 int bitend = 0;
801 while (*c >= '0' && *c <= '9')
802 bitstart = (bitstart * 10) + *c++ - '0';
804 switch (*c)
806 case '-':
808 long reg;
810 c++;
811 while (*c >= '0' && *c <= '9')
812 bitend = (bitend * 10) + *c++ - '0';
813 if (!bitend)
814 abort ();
815 reg = given >> bitstart;
816 reg &= (2 << (bitend - bitstart)) - 1;
817 switch (*c)
819 case 'r':
820 func (stream, "%s", arm_regnames[reg]);
821 break;
823 case 'd':
824 func (stream, "%d", reg);
825 break;
827 case 'H':
828 func (stream, "%d", reg << 1);
829 break;
831 case 'W':
832 func (stream, "%d", reg << 2);
833 break;
835 case 'a':
836 /* PC-relative address -- the bottom two
837 bits of the address are dropped
838 before the calculation. */
839 info->print_address_func
840 (((pc + 4) & ~3) + (reg << 2), info);
841 break;
843 case 'x':
844 func (stream, "0x%04x", reg);
845 break;
847 case 'I':
848 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
849 func (stream, "%d", reg);
850 break;
852 case 'B':
853 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
854 (*info->print_address_func)
855 (reg * 2 + pc + 4, info);
856 break;
858 default:
859 abort ();
862 break;
864 case '\'':
865 c++;
866 if ((given & (1 << bitstart)) != 0)
867 func (stream, "%c", *c);
868 break;
870 case '?':
871 ++c;
872 if ((given & (1 << bitstart)) != 0)
873 func (stream, "%c", *c++);
874 else
875 func (stream, "%c", *++c);
876 break;
878 default:
879 abort ();
882 break;
884 default:
885 abort ();
888 else
889 func (stream, "%c", *c);
892 return 2;
896 /* No match. */
897 abort ();
900 /* Parse an individual disassembler option. */
901 void
902 parse_arm_disassembler_option (option)
903 char * option;
905 if (option == NULL)
906 return;
908 if (strneq (option, "reg-names-", 10))
910 int i;
912 option += 10;
914 for (i = NUM_ARM_REGNAMES; i--;)
915 if (streq (option, regnames[i].name))
917 regname_selected = i;
918 break;
921 if (i < 0)
922 fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
924 else if (streq (option, "force-thumb"))
925 force_thumb = 1;
926 else if (streq (option, "no-force-thumb"))
927 force_thumb = 0;
928 else
929 fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
931 return;
934 /* Parse the string of disassembler options, spliting it at whitespaces. */
935 static void
936 parse_disassembler_options (options)
937 char * options;
939 char * space;
941 if (options == NULL)
942 return;
946 space = strchr (options, ' ');
948 if (space)
950 * space = '\0';
951 parse_arm_disassembler_option (options);
952 * space = ' ';
953 options = space + 1;
955 else
956 parse_arm_disassembler_option (options);
958 while (space);
961 /* NOTE: There are no checks in these routines that
962 the relevant number of data bytes exist. */
963 static int
964 print_insn (pc, info, little)
965 bfd_vma pc;
966 struct disassemble_info * info;
967 boolean little;
969 unsigned char b[4];
970 long given;
971 int status;
972 int is_thumb;
974 if (info->disassembler_options)
976 parse_disassembler_options (info->disassembler_options);
978 /* To avoid repeated parsing of these options, we remove them here. */
979 info->disassembler_options = NULL;
982 is_thumb = force_thumb;
984 if (!is_thumb && info->symbols != NULL)
986 if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
988 coff_symbol_type * cs;
990 cs = coffsymbol (*info->symbols);
991 is_thumb = ( cs->native->u.syment.n_sclass == C_THUMBEXT
992 || cs->native->u.syment.n_sclass == C_THUMBSTAT
993 || cs->native->u.syment.n_sclass == C_THUMBLABEL
994 || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
995 || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
997 else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
999 elf_symbol_type * es;
1000 unsigned int type;
1002 es = *(elf_symbol_type **)(info->symbols);
1003 type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
1005 is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
1009 info->bytes_per_chunk = 4;
1010 info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
1012 if (little)
1014 status = info->read_memory_func (pc, (bfd_byte *) &b[0], 4, info);
1015 if (status != 0 && is_thumb)
1017 info->bytes_per_chunk = 2;
1019 status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
1020 b[3] = b[2] = 0;
1023 if (status != 0)
1025 info->memory_error_func (status, pc, info);
1026 return -1;
1029 given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
1031 else
1033 status = info->read_memory_func
1034 (pc & ~ 0x3, (bfd_byte *) &b[0], 4, info);
1035 if (status != 0)
1037 info->memory_error_func (status, pc, info);
1038 return -1;
1041 if (is_thumb)
1043 if (pc & 0x2)
1045 given = (b[2] << 8) | b[3];
1047 status = info->read_memory_func
1048 ((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
1049 if (status != 0)
1051 info->memory_error_func (status, pc + 4, info);
1052 return -1;
1055 given |= (b[0] << 24) | (b[1] << 16);
1057 else
1058 given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16);
1060 else
1061 given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
1064 if (info->flags & INSN_HAS_RELOC)
1065 /* If the instruction has a reloc associated with it, then
1066 the offset field in the instruction will actually be the
1067 addend for the reloc. (We are using REL type relocs).
1068 In such cases, we can ignore the pc when computing
1069 addresses, since the addend is not currently pc-relative. */
1070 pc = 0;
1072 if (is_thumb)
1073 status = print_insn_thumb (pc, info, given);
1074 else
1075 status = print_insn_arm (pc, info, given);
1077 return status;
1081 print_insn_big_arm (pc, info)
1082 bfd_vma pc;
1083 struct disassemble_info * info;
1085 return print_insn (pc, info, false);
1089 print_insn_little_arm (pc, info)
1090 bfd_vma pc;
1091 struct disassemble_info * info;
1093 return print_insn (pc, info, true);
1096 void
1097 print_arm_disassembler_options (FILE * stream)
1099 int i;
1101 fprintf (stream, _("\n\
1102 The following ARM specific disassembler options are supported for use with\n\
1103 the -M switch:\n"));
1105 for (i = NUM_ARM_REGNAMES; i--;)
1106 fprintf (stream, " reg-names-%s %*c%s\n",
1107 regnames[i].name,
1108 14 - strlen (regnames[i].name), ' ',
1109 regnames[i].description);
1111 fprintf (stream, " force-thumb Assume all insns are Thumb insns\n");
1112 fprintf (stream, " no-force-thumb Examine preceeding label to determine an insn's type\n\n");