source: trunk/src/binutils/opcodes/arm-dis.c@ 524

Last change on this file since 524 was 10, checked in by bird, 22 years ago

Initial revision

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