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