source: branches/libc-0.6/src/binutils/opcodes/arm-dis.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 33.6 KB
Line 
1/* Instruction printing code for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
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
7 This file is part of libopcodes.
8
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.
13
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.
18
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. */
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 { "iwmmxt_regnames", "Select register names used on the Intel Wireless MMX technology coprocessor",
75 { "wr0", "wr1", "wr2", "wr3", "wr4", "wr5", "wr6", "wr7", "wr8", "wr9", "wr10", "wr11", "wr12", "wr13", "wr14", "wr15"}},
76 { "iwmmxt_Cregnames", "Select control register names used on the Intel Wireless MMX technology coprocessor",
77 {"wcid", "wcon", "wcssf", "wcasf", "reserved", "reserved", "reserved", "reserved", "wcgr0", "wcgr1", "wcgr2", "wcgr3", "reserved", "reserved", "reserved", "reserved"}}
78};
79
80static char * iwmmxt_wwnames[] =
81{"b", "h", "w", "d"};
82
83static char * iwmmxt_wwssnames[] =
84{"b", "bus", "b", "bss",
85 "h", "hus", "h", "hss",
86 "w", "wus", "w", "wss",
87 "d", "dus", "d", "dss"
88};
89
90/* Default to GCC register name set. */
91static unsigned int regname_selected = 1;
92
93#define NUM_ARM_REGNAMES NUM_ELEM (regnames)
94#define arm_regnames regnames[regname_selected].reg_names
95
96static bfd_boolean force_thumb = FALSE;
97
98static char * arm_fp_const[] =
99{"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
100
101static char * arm_shift[] =
102{"lsl", "lsr", "asr", "ror"};
103
104
105/* Forward declarations. */
106static void arm_decode_shift
107 PARAMS ((long, fprintf_ftype, void *));
108static int print_insn_arm
109 PARAMS ((bfd_vma, struct disassemble_info *, long));
110static int print_insn_thumb
111 PARAMS ((bfd_vma, struct disassemble_info *, long));
112static void parse_disassembler_options
113 PARAMS ((char *));
114static int print_insn
115 PARAMS ((bfd_vma, struct disassemble_info *, bfd_boolean));
116static int set_iwmmxt_regnames
117 PARAMS ((void));
118
119int get_arm_regname_num_options
120 PARAMS ((void));
121int set_arm_regname_option
122 PARAMS ((int));
123int get_arm_regnames
124 PARAMS ((int, const char **, const char **, const char ***));
125
126
127/* Functions. */
128int
129get_arm_regname_num_options ()
130{
131 return NUM_ARM_REGNAMES;
132}
133
134int
135set_arm_regname_option (option)
136 int option;
137{
138 int old = regname_selected;
139 regname_selected = option;
140 return old;
141}
142
143int
144get_arm_regnames (option, setname, setdescription, register_names)
145 int option;
146 const char **setname;
147 const char **setdescription;
148 const char ***register_names;
149{
150 *setname = regnames[option].name;
151 *setdescription = regnames[option].description;
152 *register_names = regnames[option].reg_names;
153 return 16;
154}
155
156static void
157arm_decode_shift (given, func, stream)
158 long given;
159 fprintf_ftype func;
160 void * stream;
161{
162 func (stream, "%s", arm_regnames[given & 0xf]);
163
164 if ((given & 0xff0) != 0)
165 {
166 if ((given & 0x10) == 0)
167 {
168 int amount = (given & 0xf80) >> 7;
169 int shift = (given & 0x60) >> 5;
170
171 if (amount == 0)
172 {
173 if (shift == 3)
174 {
175 func (stream, ", rrx");
176 return;
177 }
178
179 amount = 32;
180 }
181
182 func (stream, ", %s #%d", arm_shift[shift], amount);
183 }
184 else
185 func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5],
186 arm_regnames[(given & 0xf00) >> 8]);
187 }
188}
189
190static int
191set_iwmmxt_regnames ()
192{
193 const char * setname;
194 const char * setdesc;
195 const char ** regnames;
196 int iwmmxt_regnames = 0;
197 int num_regnames = get_arm_regname_num_options ();
198
199 get_arm_regnames (iwmmxt_regnames, &setname,
200 &setdesc, &regnames);
201 while ((strcmp ("iwmmxt_regnames", setname))
202 && (iwmmxt_regnames < num_regnames))
203 get_arm_regnames (++iwmmxt_regnames, &setname, &setdesc, &regnames);
204
205 return iwmmxt_regnames;
206}
207
208/* Print one instruction from PC on INFO->STREAM.
209 Return the size of the instruction (always 4 on ARM). */
210
211static int
212print_insn_arm (pc, info, given)
213 bfd_vma pc;
214 struct disassemble_info *info;
215 long given;
216{
217 const struct arm_opcode *insn;
218 void *stream = info->stream;
219 fprintf_ftype func = info->fprintf_func;
220 static int iwmmxt_regnames = 0;
221
222 for (insn = arm_opcodes; insn->assembler; insn++)
223 {
224 if (insn->value == FIRST_IWMMXT_INSN
225 && info->mach != bfd_mach_arm_XScale
226 && info->mach != bfd_mach_arm_iWMMXt)
227 insn = insn + IWMMXT_INSN_COUNT;
228
229 if ((given & insn->mask) == insn->value)
230 {
231 char * c;
232
233 for (c = insn->assembler; *c; c++)
234 {
235 if (*c == '%')
236 {
237 switch (*++c)
238 {
239 case '%':
240 func (stream, "%%");
241 break;
242
243 case 'a':
244 if (((given & 0x000f0000) == 0x000f0000)
245 && ((given & 0x02000000) == 0))
246 {
247 int offset = given & 0xfff;
248
249 func (stream, "[pc");
250
251 if (given & 0x01000000)
252 {
253 if ((given & 0x00800000) == 0)
254 offset = - offset;
255
256 /* Pre-indexed. */
257 func (stream, ", #%d]", offset);
258
259 offset += pc + 8;
260
261 /* Cope with the possibility of write-back
262 being used. Probably a very dangerous thing
263 for the programmer to do, but who are we to
264 argue ? */
265 if (given & 0x00200000)
266 func (stream, "!");
267 }
268 else
269 {
270 /* Post indexed. */
271 func (stream, "], #%d", offset);
272
273 /* ie ignore the offset. */
274 offset = pc + 8;
275 }
276
277 func (stream, "\t; ");
278 info->print_address_func (offset, info);
279 }
280 else
281 {
282 func (stream, "[%s",
283 arm_regnames[(given >> 16) & 0xf]);
284 if ((given & 0x01000000) != 0)
285 {
286 if ((given & 0x02000000) == 0)
287 {
288 int offset = given & 0xfff;
289 if (offset)
290 func (stream, ", %s#%d",
291 (((given & 0x00800000) == 0)
292 ? "-" : ""), offset);
293 }
294 else
295 {
296 func (stream, ", %s",
297 (((given & 0x00800000) == 0)
298 ? "-" : ""));
299 arm_decode_shift (given, func, stream);
300 }
301
302 func (stream, "]%s",
303 ((given & 0x00200000) != 0) ? "!" : "");
304 }
305 else
306 {
307 if ((given & 0x02000000) == 0)
308 {
309 int offset = given & 0xfff;
310 if (offset)
311 func (stream, "], %s#%d",
312 (((given & 0x00800000) == 0)
313 ? "-" : ""), offset);
314 else
315 func (stream, "]");
316 }
317 else
318 {
319 func (stream, "], %s",
320 (((given & 0x00800000) == 0)
321 ? "-" : ""));
322 arm_decode_shift (given, func, stream);
323 }
324 }
325 }
326 break;
327
328 case 's':
329 if ((given & 0x004f0000) == 0x004f0000)
330 {
331 /* PC relative with immediate offset. */
332 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
333
334 if ((given & 0x00800000) == 0)
335 offset = -offset;
336
337 func (stream, "[pc, #%d]\t; ", offset);
338
339 (*info->print_address_func)
340 (offset + pc + 8, info);
341 }
342 else
343 {
344 func (stream, "[%s",
345 arm_regnames[(given >> 16) & 0xf]);
346 if ((given & 0x01000000) != 0)
347 {
348 /* Pre-indexed. */
349 if ((given & 0x00400000) == 0x00400000)
350 {
351 /* Immediate. */
352 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
353 if (offset)
354 func (stream, ", %s#%d",
355 (((given & 0x00800000) == 0)
356 ? "-" : ""), offset);
357 }
358 else
359 {
360 /* Register. */
361 func (stream, ", %s%s",
362 (((given & 0x00800000) == 0)
363 ? "-" : ""),
364 arm_regnames[given & 0xf]);
365 }
366
367 func (stream, "]%s",
368 ((given & 0x00200000) != 0) ? "!" : "");
369 }
370 else
371 {
372 /* Post-indexed. */
373 if ((given & 0x00400000) == 0x00400000)
374 {
375 /* Immediate. */
376 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
377 if (offset)
378 func (stream, "], %s#%d",
379 (((given & 0x00800000) == 0)
380 ? "-" : ""), offset);
381 else
382 func (stream, "]");
383 }
384 else
385 {
386 /* Register. */
387 func (stream, "], %s%s",
388 (((given & 0x00800000) == 0)
389 ? "-" : ""),
390 arm_regnames[given & 0xf]);
391 }
392 }
393 }
394 break;
395
396 case 'b':
397 (*info->print_address_func)
398 (BDISP (given) * 4 + pc + 8, info);
399 break;
400
401 case 'c':
402 func (stream, "%s",
403 arm_conditional [(given >> 28) & 0xf]);
404 break;
405
406 case 'm':
407 {
408 int started = 0;
409 int reg;
410
411 func (stream, "{");
412 for (reg = 0; reg < 16; reg++)
413 if ((given & (1 << reg)) != 0)
414 {
415 if (started)
416 func (stream, ", ");
417 started = 1;
418 func (stream, "%s", arm_regnames[reg]);
419 }
420 func (stream, "}");
421 }
422 break;
423
424 case 'o':
425 if ((given & 0x02000000) != 0)
426 {
427 int rotate = (given & 0xf00) >> 7;
428 int immed = (given & 0xff);
429 immed = (((immed << (32 - rotate))
430 | (immed >> rotate)) & 0xffffffff);
431 func (stream, "#%d\t; 0x%x", immed, immed);
432 }
433 else
434 arm_decode_shift (given, func, stream);
435 break;
436
437 case 'p':
438 if ((given & 0x0000f000) == 0x0000f000)
439 func (stream, "p");
440 break;
441
442 case 't':
443 if ((given & 0x01200000) == 0x00200000)
444 func (stream, "t");
445 break;
446
447 case 'A':
448 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
449 if ((given & 0x01000000) != 0)
450 {
451 int offset = given & 0xff;
452 if (offset)
453 func (stream, ", %s#%d]%s",
454 ((given & 0x00800000) == 0 ? "-" : ""),
455 offset * 4,
456 ((given & 0x00200000) != 0 ? "!" : ""));
457 else
458 func (stream, "]");
459 }
460 else
461 {
462 int offset = given & 0xff;
463 if (offset)
464 func (stream, "], %s#%d",
465 ((given & 0x00800000) == 0 ? "-" : ""),
466 offset * 4);
467 else
468 func (stream, "]");
469 }
470 break;
471
472 case 'B':
473 /* Print ARM V5 BLX(1) address: pc+25 bits. */
474 {
475 bfd_vma address;
476 bfd_vma offset = 0;
477
478 if (given & 0x00800000)
479 /* Is signed, hi bits should be ones. */
480 offset = (-1) ^ 0x00ffffff;
481
482 /* Offset is (SignExtend(offset field)<<2). */
483 offset += given & 0x00ffffff;
484 offset <<= 2;
485 address = offset + pc + 8;
486
487 if (given & 0x01000000)
488 /* H bit allows addressing to 2-byte boundaries. */
489 address += 2;
490
491 info->print_address_func (address, info);
492 }
493 break;
494
495 case 'I':
496 /* Print a Cirrus/DSP shift immediate. */
497 /* Immediates are 7bit signed ints with bits 0..3 in
498 bits 0..3 of opcode and bits 4..6 in bits 5..7
499 of opcode. */
500 {
501 int imm;
502
503 imm = (given & 0xf) | ((given & 0xe0) >> 1);
504
505 /* Is ``imm'' a negative number? */
506 if (imm & 0x40)
507 imm |= (-1 << 7);
508
509 func (stream, "%d", imm);
510 }
511
512 break;
513
514 case 'C':
515 func (stream, "_");
516 if (given & 0x80000)
517 func (stream, "f");
518 if (given & 0x40000)
519 func (stream, "s");
520 if (given & 0x20000)
521 func (stream, "x");
522 if (given & 0x10000)
523 func (stream, "c");
524 break;
525
526 case 'F':
527 switch (given & 0x00408000)
528 {
529 case 0:
530 func (stream, "4");
531 break;
532 case 0x8000:
533 func (stream, "1");
534 break;
535 case 0x00400000:
536 func (stream, "2");
537 break;
538 default:
539 func (stream, "3");
540 }
541 break;
542
543 case 'P':
544 switch (given & 0x00080080)
545 {
546 case 0:
547 func (stream, "s");
548 break;
549 case 0x80:
550 func (stream, "d");
551 break;
552 case 0x00080000:
553 func (stream, "e");
554 break;
555 default:
556 func (stream, _("<illegal precision>"));
557 break;
558 }
559 break;
560 case 'Q':
561 switch (given & 0x00408000)
562 {
563 case 0:
564 func (stream, "s");
565 break;
566 case 0x8000:
567 func (stream, "d");
568 break;
569 case 0x00400000:
570 func (stream, "e");
571 break;
572 default:
573 func (stream, "p");
574 break;
575 }
576 break;
577 case 'R':
578 switch (given & 0x60)
579 {
580 case 0:
581 break;
582 case 0x20:
583 func (stream, "p");
584 break;
585 case 0x40:
586 func (stream, "m");
587 break;
588 default:
589 func (stream, "z");
590 break;
591 }
592 break;
593
594 case '0': case '1': case '2': case '3': case '4':
595 case '5': case '6': case '7': case '8': case '9':
596 {
597 int bitstart = *c++ - '0';
598 int bitend = 0;
599 while (*c >= '0' && *c <= '9')
600 bitstart = (bitstart * 10) + *c++ - '0';
601
602 switch (*c)
603 {
604 case '-':
605 c++;
606
607 while (*c >= '0' && *c <= '9')
608 bitend = (bitend * 10) + *c++ - '0';
609
610 if (!bitend)
611 abort ();
612
613 switch (*c)
614 {
615 case 'r':
616 {
617 long reg;
618
619 reg = given >> bitstart;
620 reg &= (2 << (bitend - bitstart)) - 1;
621
622 func (stream, "%s", arm_regnames[reg]);
623 }
624 break;
625 case 'd':
626 {
627 long reg;
628
629 reg = given >> bitstart;
630 reg &= (2 << (bitend - bitstart)) - 1;
631
632 func (stream, "%d", reg);
633 }
634 break;
635 case 'x':
636 {
637 long reg;
638
639 reg = given >> bitstart;
640 reg &= (2 << (bitend - bitstart)) - 1;
641
642 func (stream, "0x%08x", reg);
643
644 /* Some SWI instructions have special
645 meanings. */
646 if ((given & 0x0fffffff) == 0x0FF00000)
647 func (stream, "\t; IMB");
648 else if ((given & 0x0fffffff) == 0x0FF00001)
649 func (stream, "\t; IMBRange");
650 }
651 break;
652 case 'X':
653 {
654 long reg;
655
656 reg = given >> bitstart;
657 reg &= (2 << (bitend - bitstart)) - 1;
658
659 func (stream, "%01x", reg & 0xf);
660 }
661 break;
662 case 'f':
663 {
664 long reg;
665
666 reg = given >> bitstart;
667 reg &= (2 << (bitend - bitstart)) - 1;
668
669 if (reg > 7)
670 func (stream, "#%s",
671 arm_fp_const[reg & 7]);
672 else
673 func (stream, "f%d", reg);
674 }
675 break;
676
677 case 'w':
678 {
679 long reg;
680
681 if (bitstart != bitend)
682 {
683 reg = given >> bitstart;
684 reg &= (2 << (bitend - bitstart)) - 1;
685 if (bitend - bitstart == 1)
686 func (stream, "%s", iwmmxt_wwnames[reg]);
687 else
688 func (stream, "%s", iwmmxt_wwssnames[reg]);
689 }
690 else
691 {
692 reg = (((given >> 8) & 0x1) |
693 ((given >> 22) & 0x1));
694 func (stream, "%s", iwmmxt_wwnames[reg]);
695 }
696 }
697 break;
698
699 case 'g':
700 {
701 long reg;
702 int current_regnames;
703
704 if (! iwmmxt_regnames)
705 iwmmxt_regnames = set_iwmmxt_regnames ();
706 current_regnames = set_arm_regname_option
707 (iwmmxt_regnames);
708
709 reg = given >> bitstart;
710 reg &= (2 << (bitend - bitstart)) - 1;
711 func (stream, "%s", arm_regnames[reg]);
712 set_arm_regname_option (current_regnames);
713 }
714 break;
715
716 case 'G':
717 {
718 long reg;
719 int current_regnames;
720
721 if (! iwmmxt_regnames)
722 iwmmxt_regnames = set_iwmmxt_regnames ();
723 current_regnames = set_arm_regname_option
724 (iwmmxt_regnames + 1);
725
726 reg = given >> bitstart;
727 reg &= (2 << (bitend - bitstart)) - 1;
728 func (stream, "%s", arm_regnames[reg]);
729 set_arm_regname_option (current_regnames);
730 }
731 break;
732
733 default:
734 abort ();
735 }
736 break;
737
738 case 'y':
739 case 'z':
740 {
741 int single = *c == 'y';
742 int regno;
743
744 switch (bitstart)
745 {
746 case 4: /* Sm pair */
747 func (stream, "{");
748 /* Fall through. */
749 case 0: /* Sm, Dm */
750 regno = given & 0x0000000f;
751 if (single)
752 {
753 regno <<= 1;
754 regno += (given >> 5) & 1;
755 }
756 break;
757
758 case 1: /* Sd, Dd */
759 regno = (given >> 12) & 0x0000000f;
760 if (single)
761 {
762 regno <<= 1;
763 regno += (given >> 22) & 1;
764 }
765 break;
766
767 case 2: /* Sn, Dn */
768 regno = (given >> 16) & 0x0000000f;
769 if (single)
770 {
771 regno <<= 1;
772 regno += (given >> 7) & 1;
773 }
774 break;
775
776 case 3: /* List */
777 func (stream, "{");
778 regno = (given >> 12) & 0x0000000f;
779 if (single)
780 {
781 regno <<= 1;
782 regno += (given >> 22) & 1;
783 }
784 break;
785
786
787 default:
788 abort ();
789 }
790
791 func (stream, "%c%d", single ? 's' : 'd', regno);
792
793 if (bitstart == 3)
794 {
795 int count = given & 0xff;
796
797 if (single == 0)
798 count >>= 1;
799
800 if (--count)
801 {
802 func (stream, "-%c%d",
803 single ? 's' : 'd',
804 regno + count);
805 }
806
807 func (stream, "}");
808 }
809 else if (bitstart == 4)
810 func (stream, ", %c%d}", single ? 's' : 'd',
811 regno + 1);
812
813 break;
814 }
815
816 case '`':
817 c++;
818 if ((given & (1 << bitstart)) == 0)
819 func (stream, "%c", *c);
820 break;
821 case '\'':
822 c++;
823 if ((given & (1 << bitstart)) != 0)
824 func (stream, "%c", *c);
825 break;
826 case '?':
827 ++c;
828 if ((given & (1 << bitstart)) != 0)
829 func (stream, "%c", *c++);
830 else
831 func (stream, "%c", *++c);
832 break;
833 default:
834 abort ();
835 }
836 break;
837
838 case 'L':
839 switch (given & 0x00400100)
840 {
841 case 0x00000000: func (stream, "b"); break;
842 case 0x00400000: func (stream, "h"); break;
843 case 0x00000100: func (stream, "w"); break;
844 case 0x00400100: func (stream, "d"); break;
845 default:
846 break;
847 }
848 break;
849
850 case 'Z':
851 {
852 int value;
853 /* given (20, 23) | given (0, 3) */
854 value = ((given >> 16) & 0xf0) | (given & 0xf);
855 func (stream, "%d", value);
856 }
857 break;
858
859 case 'l':
860 /* This is like the 'A' operator, except that if
861 the width field "M" is zero, then the offset is
862 *not* multiplied by four. */
863 {
864 int offset = given & 0xff;
865 int multiplier = (given & 0x00000100) ? 4 : 1;
866
867 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
868
869 if (offset)
870 {
871 if ((given & 0x01000000) != 0)
872 func (stream, ", %s#%d]%s",
873 ((given & 0x00800000) == 0 ? "-" : ""),
874 offset * multiplier,
875 ((given & 0x00200000) != 0 ? "!" : ""));
876 else
877 func (stream, "], %s#%d",
878 ((given & 0x00800000) == 0 ? "-" : ""),
879 offset * multiplier);
880 }
881 else
882 func (stream, "]");
883 }
884 break;
885
886 default:
887 abort ();
888 }
889 }
890 }
891 else
892 func (stream, "%c", *c);
893 }
894 return 4;
895 }
896 }
897 abort ();
898}
899
900/* Print one instruction from PC on INFO->STREAM.
901 Return the size of the instruction. */
902
903static int
904print_insn_thumb (pc, info, given)
905 bfd_vma pc;
906 struct disassemble_info *info;
907 long given;
908{
909 const struct thumb_opcode *insn;
910 void *stream = info->stream;
911 fprintf_ftype func = info->fprintf_func;
912
913 for (insn = thumb_opcodes; insn->assembler; insn++)
914 {
915 if ((given & insn->mask) == insn->value)
916 {
917 char * c = insn->assembler;
918
919 /* Special processing for Thumb 2 instruction BL sequence: */
920 if (!*c) /* Check for empty (not NULL) assembler string. */
921 {
922 long offset;
923
924 info->bytes_per_chunk = 4;
925 info->bytes_per_line = 4;
926
927 offset = BDISP23 (given);
928 offset = offset * 2 + pc + 4;
929
930 if ((given & 0x10000000) == 0)
931 {
932 func (stream, "blx\t");
933 offset &= 0xfffffffc;
934 }
935 else
936 func (stream, "bl\t");
937
938 info->print_address_func (offset, info);
939 return 4;
940 }
941 else
942 {
943 info->bytes_per_chunk = 2;
944 info->bytes_per_line = 4;
945
946 given &= 0xffff;
947
948 for (; *c; c++)
949 {
950 if (*c == '%')
951 {
952 int domaskpc = 0;
953 int domasklr = 0;
954
955 switch (*++c)
956 {
957 case '%':
958 func (stream, "%%");
959 break;
960
961 case 'S':
962 {
963 long reg;
964
965 reg = (given >> 3) & 0x7;
966 if (given & (1 << 6))
967 reg += 8;
968
969 func (stream, "%s", arm_regnames[reg]);
970 }
971 break;
972
973 case 'D':
974 {
975 long reg;
976
977 reg = given & 0x7;
978 if (given & (1 << 7))
979 reg += 8;
980
981 func (stream, "%s", arm_regnames[reg]);
982 }
983 break;
984
985 case 'T':
986 func (stream, "%s",
987 arm_conditional [(given >> 8) & 0xf]);
988 break;
989
990 case 'N':
991 if (given & (1 << 8))
992 domasklr = 1;
993 /* Fall through. */
994 case 'O':
995 if (*c == 'O' && (given & (1 << 8)))
996 domaskpc = 1;
997 /* Fall through. */
998 case 'M':
999 {
1000 int started = 0;
1001 int reg;
1002
1003 func (stream, "{");
1004
1005 /* It would be nice if we could spot
1006 ranges, and generate the rS-rE format: */
1007 for (reg = 0; (reg < 8); reg++)
1008 if ((given & (1 << reg)) != 0)
1009 {
1010 if (started)
1011 func (stream, ", ");
1012 started = 1;
1013 func (stream, "%s", arm_regnames[reg]);
1014 }
1015
1016 if (domasklr)
1017 {
1018 if (started)
1019 func (stream, ", ");
1020 started = 1;
1021 func (stream, arm_regnames[14] /* "lr" */);
1022 }
1023
1024 if (domaskpc)
1025 {
1026 if (started)
1027 func (stream, ", ");
1028 func (stream, arm_regnames[15] /* "pc" */);
1029 }
1030
1031 func (stream, "}");
1032 }
1033 break;
1034
1035
1036 case '0': case '1': case '2': case '3': case '4':
1037 case '5': case '6': case '7': case '8': case '9':
1038 {
1039 int bitstart = *c++ - '0';
1040 int bitend = 0;
1041
1042 while (*c >= '0' && *c <= '9')
1043 bitstart = (bitstart * 10) + *c++ - '0';
1044
1045 switch (*c)
1046 {
1047 case '-':
1048 {
1049 long reg;
1050
1051 c++;
1052 while (*c >= '0' && *c <= '9')
1053 bitend = (bitend * 10) + *c++ - '0';
1054 if (!bitend)
1055 abort ();
1056 reg = given >> bitstart;
1057 reg &= (2 << (bitend - bitstart)) - 1;
1058 switch (*c)
1059 {
1060 case 'r':
1061 func (stream, "%s", arm_regnames[reg]);
1062 break;
1063
1064 case 'd':
1065 func (stream, "%d", reg);
1066 break;
1067
1068 case 'H':
1069 func (stream, "%d", reg << 1);
1070 break;
1071
1072 case 'W':
1073 func (stream, "%d", reg << 2);
1074 break;
1075
1076 case 'a':
1077 /* PC-relative address -- the bottom two
1078 bits of the address are dropped
1079 before the calculation. */
1080 info->print_address_func
1081 (((pc + 4) & ~3) + (reg << 2), info);
1082 break;
1083
1084 case 'x':
1085 func (stream, "0x%04x", reg);
1086 break;
1087
1088 case 'I':
1089 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
1090 func (stream, "%d", reg);
1091 break;
1092
1093 case 'B':
1094 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
1095 (*info->print_address_func)
1096 (reg * 2 + pc + 4, info);
1097 break;
1098
1099 default:
1100 abort ();
1101 }
1102 }
1103 break;
1104
1105 case '\'':
1106 c++;
1107 if ((given & (1 << bitstart)) != 0)
1108 func (stream, "%c", *c);
1109 break;
1110
1111 case '?':
1112 ++c;
1113 if ((given & (1 << bitstart)) != 0)
1114 func (stream, "%c", *c++);
1115 else
1116 func (stream, "%c", *++c);
1117 break;
1118
1119 default:
1120 abort ();
1121 }
1122 }
1123 break;
1124
1125 default:
1126 abort ();
1127 }
1128 }
1129 else
1130 func (stream, "%c", *c);
1131 }
1132 }
1133 return 2;
1134 }
1135 }
1136
1137 /* No match. */
1138 abort ();
1139}
1140
1141/* Parse an individual disassembler option. */
1142
1143void
1144parse_arm_disassembler_option (option)
1145 char * option;
1146{
1147 if (option == NULL)
1148 return;
1149
1150 if (strneq (option, "reg-names-", 10))
1151 {
1152 int i;
1153
1154 option += 10;
1155
1156 for (i = NUM_ARM_REGNAMES; i--;)
1157 if (streq (option, regnames[i].name))
1158 {
1159 regname_selected = i;
1160 break;
1161 }
1162
1163 if (i < 0)
1164 fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
1165 }
1166 else if (streq (option, "force-thumb"))
1167 force_thumb = 1;
1168 else if (streq (option, "no-force-thumb"))
1169 force_thumb = 0;
1170 else
1171 fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
1172
1173 return;
1174}
1175
1176/* Parse the string of disassembler options, spliting it at whitespaces. */
1177
1178static void
1179parse_disassembler_options (options)
1180 char * options;
1181{
1182 char * space;
1183
1184 if (options == NULL)
1185 return;
1186
1187 do
1188 {
1189 space = strchr (options, ' ');
1190
1191 if (space)
1192 {
1193 * space = '\0';
1194 parse_arm_disassembler_option (options);
1195 * space = ' ';
1196 options = space + 1;
1197 }
1198 else
1199 parse_arm_disassembler_option (options);
1200 }
1201 while (space);
1202}
1203
1204/* NOTE: There are no checks in these routines that
1205 the relevant number of data bytes exist. */
1206
1207static int
1208print_insn (pc, info, little)
1209 bfd_vma pc;
1210 struct disassemble_info * info;
1211 bfd_boolean little;
1212{
1213 unsigned char b[4];
1214 long given;
1215 int status;
1216 int is_thumb;
1217
1218 if (info->disassembler_options)
1219 {
1220 parse_disassembler_options (info->disassembler_options);
1221
1222 /* To avoid repeated parsing of these options, we remove them here. */
1223 info->disassembler_options = NULL;
1224 }
1225
1226 is_thumb = force_thumb;
1227
1228 if (!is_thumb && info->symbols != NULL)
1229 {
1230 if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
1231 {
1232 coff_symbol_type * cs;
1233
1234 cs = coffsymbol (*info->symbols);
1235 is_thumb = ( cs->native->u.syment.n_sclass == C_THUMBEXT
1236 || cs->native->u.syment.n_sclass == C_THUMBSTAT
1237 || cs->native->u.syment.n_sclass == C_THUMBLABEL
1238 || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
1239 || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
1240 }
1241 else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
1242 {
1243 elf_symbol_type * es;
1244 unsigned int type;
1245
1246 es = *(elf_symbol_type **)(info->symbols);
1247 type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
1248
1249 is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
1250 }
1251 }
1252
1253 info->bytes_per_chunk = 4;
1254 info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
1255
1256 if (little)
1257 {
1258 status = info->read_memory_func (pc, (bfd_byte *) &b[0], 4, info);
1259 if (status != 0 && is_thumb)
1260 {
1261 info->bytes_per_chunk = 2;
1262
1263 status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
1264 b[3] = b[2] = 0;
1265 }
1266
1267 if (status != 0)
1268 {
1269 info->memory_error_func (status, pc, info);
1270 return -1;
1271 }
1272
1273 given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
1274 }
1275 else
1276 {
1277 status = info->read_memory_func
1278 (pc & ~ 0x3, (bfd_byte *) &b[0], 4, info);
1279 if (status != 0)
1280 {
1281 info->memory_error_func (status, pc, info);
1282 return -1;
1283 }
1284
1285 if (is_thumb)
1286 {
1287 if (pc & 0x2)
1288 {
1289 given = (b[2] << 8) | b[3];
1290
1291 status = info->read_memory_func
1292 ((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
1293 if (status != 0)
1294 {
1295 info->memory_error_func (status, pc + 4, info);
1296 return -1;
1297 }
1298
1299 given |= (b[0] << 24) | (b[1] << 16);
1300 }
1301 else
1302 given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16);
1303 }
1304 else
1305 given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
1306 }
1307
1308 if (info->flags & INSN_HAS_RELOC)
1309 /* If the instruction has a reloc associated with it, then
1310 the offset field in the instruction will actually be the
1311 addend for the reloc. (We are using REL type relocs).
1312 In such cases, we can ignore the pc when computing
1313 addresses, since the addend is not currently pc-relative. */
1314 pc = 0;
1315
1316 if (is_thumb)
1317 status = print_insn_thumb (pc, info, given);
1318 else
1319 status = print_insn_arm (pc, info, given);
1320
1321 return status;
1322}
1323
1324int
1325print_insn_big_arm (pc, info)
1326 bfd_vma pc;
1327 struct disassemble_info * info;
1328{
1329 return print_insn (pc, info, FALSE);
1330}
1331
1332int
1333print_insn_little_arm (pc, info)
1334 bfd_vma pc;
1335 struct disassemble_info * info;
1336{
1337 return print_insn (pc, info, TRUE);
1338}
1339
1340void
1341print_arm_disassembler_options (FILE * stream)
1342{
1343 int i;
1344
1345 fprintf (stream, _("\n\
1346The following ARM specific disassembler options are supported for use with\n\
1347the -M switch:\n"));
1348
1349 for (i = NUM_ARM_REGNAMES; i--;)
1350 fprintf (stream, " reg-names-%s %*c%s\n",
1351 regnames[i].name,
1352 (int)(14 - strlen (regnames[i].name)), ' ',
1353 regnames[i].description);
1354
1355 fprintf (stream, " force-thumb Assume all insns are Thumb insns\n");
1356 fprintf (stream, " no-force-thumb Examine preceeding label to determine an insn's type\n\n");
1357}
Note: See TracBrowser for help on using the repository browser.