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