]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/arm-dis.c
Run the relax test.
[thirdparty/binutils-gdb.git] / opcodes / arm-dis.c
CommitLineData
252b5132 1/* Instruction printing code for the ARM
0dd132b6 2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
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;
09d92015
MM
642 case 'W':
643 {
644 long reg;
645
646 reg = given >> bitstart;
647 reg &= (2 << (bitend - bitstart)) - 1;
648
649 func (stream, "%d", reg + 1);
650 }
651 break;
252b5132
RH
652 case 'x':
653 {
654 long reg;
b34976b6 655
252b5132
RH
656 reg = given >> bitstart;
657 reg &= (2 << (bitend - bitstart)) - 1;
b34976b6 658
252b5132 659 func (stream, "0x%08x", reg);
b34976b6 660
58efb6c0
NC
661 /* Some SWI instructions have special
662 meanings. */
5876e06d
NC
663 if ((given & 0x0fffffff) == 0x0FF00000)
664 func (stream, "\t; IMB");
665 else if ((given & 0x0fffffff) == 0x0FF00001)
666 func (stream, "\t; IMBRange");
252b5132
RH
667 }
668 break;
cfbd315c
DL
669 case 'X':
670 {
671 long reg;
b34976b6 672
cfbd315c
DL
673 reg = given >> bitstart;
674 reg &= (2 << (bitend - bitstart)) - 1;
b34976b6 675
cfbd315c
DL
676 func (stream, "%01x", reg & 0xf);
677 }
678 break;
252b5132
RH
679 case 'f':
680 {
681 long reg;
b34976b6 682
252b5132
RH
683 reg = given >> bitstart;
684 reg &= (2 << (bitend - bitstart)) - 1;
b34976b6 685
252b5132
RH
686 if (reg > 7)
687 func (stream, "#%s",
688 arm_fp_const[reg & 7]);
689 else
690 func (stream, "f%d", reg);
691 }
692 break;
e16bb312
NC
693
694 case 'w':
695 {
696 long reg;
697
698 if (bitstart != bitend)
699 {
700 reg = given >> bitstart;
701 reg &= (2 << (bitend - bitstart)) - 1;
702 if (bitend - bitstart == 1)
703 func (stream, "%s", iwmmxt_wwnames[reg]);
704 else
705 func (stream, "%s", iwmmxt_wwssnames[reg]);
706 }
707 else
708 {
709 reg = (((given >> 8) & 0x1) |
710 ((given >> 22) & 0x1));
711 func (stream, "%s", iwmmxt_wwnames[reg]);
712 }
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);
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 case 'G':
734 {
735 long reg;
736 int current_regnames;
737
738 if (! iwmmxt_regnames)
739 iwmmxt_regnames = set_iwmmxt_regnames ();
740 current_regnames = set_arm_regname_option
741 (iwmmxt_regnames + 1);
742
743 reg = given >> bitstart;
744 reg &= (2 << (bitend - bitstart)) - 1;
745 func (stream, "%s", arm_regnames[reg]);
746 set_arm_regname_option (current_regnames);
747 }
748 break;
749
252b5132
RH
750 default:
751 abort ();
752 }
753 break;
a660f11e
RE
754
755 case 'y':
756 case 'z':
757 {
758 int single = *c == 'y';
759 int regno;
760
761 switch (bitstart)
762 {
763 case 4: /* Sm pair */
764 func (stream, "{");
765 /* Fall through. */
766 case 0: /* Sm, Dm */
767 regno = given & 0x0000000f;
768 if (single)
769 {
770 regno <<= 1;
771 regno += (given >> 5) & 1;
772 }
773 break;
774
775 case 1: /* Sd, Dd */
776 regno = (given >> 12) & 0x0000000f;
777 if (single)
778 {
779 regno <<= 1;
780 regno += (given >> 22) & 1;
781 }
782 break;
783
784 case 2: /* Sn, Dn */
785 regno = (given >> 16) & 0x0000000f;
786 if (single)
787 {
788 regno <<= 1;
789 regno += (given >> 7) & 1;
790 }
791 break;
792
793 case 3: /* List */
794 func (stream, "{");
795 regno = (given >> 12) & 0x0000000f;
796 if (single)
797 {
798 regno <<= 1;
799 regno += (given >> 22) & 1;
800 }
801 break;
802
b34976b6 803
a660f11e
RE
804 default:
805 abort ();
806 }
807
808 func (stream, "%c%d", single ? 's' : 'd', regno);
809
810 if (bitstart == 3)
811 {
812 int count = given & 0xff;
813
814 if (single == 0)
815 count >>= 1;
816
817 if (--count)
818 {
819 func (stream, "-%c%d",
820 single ? 's' : 'd',
821 regno + count);
822 }
823
824 func (stream, "}");
825 }
826 else if (bitstart == 4)
827 func (stream, ", %c%d}", single ? 's' : 'd',
828 regno + 1);
829
830 break;
831 }
832
252b5132
RH
833 case '`':
834 c++;
835 if ((given & (1 << bitstart)) == 0)
836 func (stream, "%c", *c);
837 break;
838 case '\'':
839 c++;
840 if ((given & (1 << bitstart)) != 0)
841 func (stream, "%c", *c);
842 break;
843 case '?':
844 ++c;
845 if ((given & (1 << bitstart)) != 0)
846 func (stream, "%c", *c++);
847 else
848 func (stream, "%c", *++c);
849 break;
850 default:
851 abort ();
852 }
853 break;
854
e16bb312
NC
855 case 'L':
856 switch (given & 0x00400100)
857 {
858 case 0x00000000: func (stream, "b"); break;
859 case 0x00400000: func (stream, "h"); break;
860 case 0x00000100: func (stream, "w"); break;
861 case 0x00400100: func (stream, "d"); break;
862 default:
863 break;
864 }
865 break;
866
867 case 'Z':
868 {
869 int value;
870 /* given (20, 23) | given (0, 3) */
871 value = ((given >> 16) & 0xf0) | (given & 0xf);
872 func (stream, "%d", value);
873 }
874 break;
875
876 case 'l':
877 /* This is like the 'A' operator, except that if
878 the width field "M" is zero, then the offset is
879 *not* multiplied by four. */
880 {
881 int offset = given & 0xff;
882 int multiplier = (given & 0x00000100) ? 4 : 1;
883
884 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
885
886 if (offset)
887 {
888 if ((given & 0x01000000) != 0)
8e6446ff 889 func (stream, ", #%s%d]%s",
e16bb312
NC
890 ((given & 0x00800000) == 0 ? "-" : ""),
891 offset * multiplier,
892 ((given & 0x00200000) != 0 ? "!" : ""));
893 else
8e6446ff 894 func (stream, "], #%s%d",
e16bb312
NC
895 ((given & 0x00800000) == 0 ? "-" : ""),
896 offset * multiplier);
897 }
898 else
899 func (stream, "]");
900 }
901 break;
902
0dd132b6
NC
903 case 'e':
904 {
905 int imm;
906
907 imm = (given & 0xf) | ((given & 0xfff00) >> 4);
908 func (stream, "%d", imm);
909 }
910 break;
911
252b5132
RH
912 default:
913 abort ();
914 }
915 }
916 }
917 else
918 func (stream, "%c", *c);
919 }
920 return 4;
921 }
922 }
923 abort ();
924}
925
926/* Print one instruction from PC on INFO->STREAM.
927 Return the size of the instruction. */
baf0cc5e 928
252b5132
RH
929static int
930print_insn_thumb (pc, info, given)
6a51a8a8
AM
931 bfd_vma pc;
932 struct disassemble_info *info;
933 long given;
252b5132 934{
6a51a8a8
AM
935 const struct thumb_opcode *insn;
936 void *stream = info->stream;
937 fprintf_ftype func = info->fprintf_func;
252b5132
RH
938
939 for (insn = thumb_opcodes; insn->assembler; insn++)
940 {
941 if ((given & insn->mask) == insn->value)
942 {
5876e06d 943 char * c = insn->assembler;
252b5132 944
58efb6c0
NC
945 /* Special processing for Thumb 2 instruction BL sequence: */
946 if (!*c) /* Check for empty (not NULL) assembler string. */
252b5132 947 {
4f3c3dbb 948 long offset;
b34976b6 949
252b5132
RH
950 info->bytes_per_chunk = 4;
951 info->bytes_per_line = 4;
4f3c3dbb
NC
952
953 offset = BDISP23 (given);
baf0cc5e
NC
954 offset = offset * 2 + pc + 4;
955
077b8428 956 if ((given & 0x10000000) == 0)
4f3c3dbb
NC
957 {
958 func (stream, "blx\t");
baf0cc5e 959 offset &= 0xfffffffc;
4f3c3dbb 960 }
077b8428 961 else
4f3c3dbb
NC
962 func (stream, "bl\t");
963
baf0cc5e 964 info->print_address_func (offset, info);
252b5132
RH
965 return 4;
966 }
967 else
968 {
969 info->bytes_per_chunk = 2;
970 info->bytes_per_line = 4;
b34976b6 971
252b5132 972 given &= 0xffff;
b34976b6 973
252b5132
RH
974 for (; *c; c++)
975 {
976 if (*c == '%')
977 {
978 int domaskpc = 0;
979 int domasklr = 0;
b34976b6 980
252b5132
RH
981 switch (*++c)
982 {
983 case '%':
984 func (stream, "%%");
985 break;
986
987 case 'S':
988 {
989 long reg;
b34976b6 990
252b5132
RH
991 reg = (given >> 3) & 0x7;
992 if (given & (1 << 6))
993 reg += 8;
b34976b6 994
252b5132
RH
995 func (stream, "%s", arm_regnames[reg]);
996 }
997 break;
998
999 case 'D':
1000 {
1001 long reg;
b34976b6 1002
252b5132
RH
1003 reg = given & 0x7;
1004 if (given & (1 << 7))
1005 reg += 8;
b34976b6 1006
252b5132
RH
1007 func (stream, "%s", arm_regnames[reg]);
1008 }
1009 break;
1010
1011 case 'T':
1012 func (stream, "%s",
1013 arm_conditional [(given >> 8) & 0xf]);
1014 break;
1015
1016 case 'N':
1017 if (given & (1 << 8))
1018 domasklr = 1;
58efb6c0 1019 /* Fall through. */
252b5132
RH
1020 case 'O':
1021 if (*c == 'O' && (given & (1 << 8)))
1022 domaskpc = 1;
58efb6c0 1023 /* Fall through. */
252b5132
RH
1024 case 'M':
1025 {
1026 int started = 0;
1027 int reg;
b34976b6 1028
252b5132 1029 func (stream, "{");
b34976b6 1030
252b5132
RH
1031 /* It would be nice if we could spot
1032 ranges, and generate the rS-rE format: */
1033 for (reg = 0; (reg < 8); reg++)
1034 if ((given & (1 << reg)) != 0)
1035 {
1036 if (started)
1037 func (stream, ", ");
1038 started = 1;
1039 func (stream, "%s", arm_regnames[reg]);
1040 }
1041
1042 if (domasklr)
1043 {
1044 if (started)
1045 func (stream, ", ");
1046 started = 1;
a7f8487e 1047 func (stream, arm_regnames[14] /* "lr" */);
252b5132
RH
1048 }
1049
1050 if (domaskpc)
1051 {
1052 if (started)
1053 func (stream, ", ");
a7f8487e 1054 func (stream, arm_regnames[15] /* "pc" */);
252b5132
RH
1055 }
1056
1057 func (stream, "}");
1058 }
1059 break;
1060
1061
b34976b6 1062 case '0': case '1': case '2': case '3': case '4':
252b5132
RH
1063 case '5': case '6': case '7': case '8': case '9':
1064 {
1065 int bitstart = *c++ - '0';
1066 int bitend = 0;
b34976b6 1067
252b5132
RH
1068 while (*c >= '0' && *c <= '9')
1069 bitstart = (bitstart * 10) + *c++ - '0';
1070
1071 switch (*c)
1072 {
1073 case '-':
1074 {
1075 long reg;
b34976b6 1076
252b5132
RH
1077 c++;
1078 while (*c >= '0' && *c <= '9')
1079 bitend = (bitend * 10) + *c++ - '0';
1080 if (!bitend)
1081 abort ();
1082 reg = given >> bitstart;
1083 reg &= (2 << (bitend - bitstart)) - 1;
1084 switch (*c)
1085 {
1086 case 'r':
1087 func (stream, "%s", arm_regnames[reg]);
1088 break;
1089
1090 case 'd':
1091 func (stream, "%d", reg);
1092 break;
1093
1094 case 'H':
1095 func (stream, "%d", reg << 1);
1096 break;
1097
1098 case 'W':
1099 func (stream, "%d", reg << 2);
1100 break;
1101
1102 case 'a':
1103 /* PC-relative address -- the bottom two
58efb6c0
NC
1104 bits of the address are dropped
1105 before the calculation. */
252b5132
RH
1106 info->print_address_func
1107 (((pc + 4) & ~3) + (reg << 2), info);
1108 break;
1109
1110 case 'x':
1111 func (stream, "0x%04x", reg);
1112 break;
1113
1114 case 'I':
1115 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
1116 func (stream, "%d", reg);
1117 break;
1118
1119 case 'B':
1120 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
1121 (*info->print_address_func)
1122 (reg * 2 + pc + 4, info);
1123 break;
1124
1125 default:
5876e06d 1126 abort ();
252b5132
RH
1127 }
1128 }
1129 break;
1130
1131 case '\'':
1132 c++;
1133 if ((given & (1 << bitstart)) != 0)
1134 func (stream, "%c", *c);
1135 break;
1136
1137 case '?':
1138 ++c;
1139 if ((given & (1 << bitstart)) != 0)
1140 func (stream, "%c", *c++);
1141 else
1142 func (stream, "%c", *++c);
1143 break;
1144
1145 default:
5876e06d 1146 abort ();
252b5132
RH
1147 }
1148 }
1149 break;
1150
1151 default:
1152 abort ();
1153 }
1154 }
1155 else
1156 func (stream, "%c", *c);
1157 }
1158 }
1159 return 2;
1160 }
1161 }
1162
58efb6c0 1163 /* No match. */
252b5132
RH
1164 abort ();
1165}
1166
22a398e1
NC
1167/* Disallow mapping symbols ($a, $b, $d, $t etc) from
1168 being displayed in symbol relative addresses. */
1169
1170bfd_boolean
1171arm_symbol_is_valid (asymbol * sym,
1172 struct disassemble_info * info ATTRIBUTE_UNUSED)
1173{
1174 const char * name;
1175
1176 if (sym == NULL)
1177 return FALSE;
1178
1179 name = bfd_asymbol_name (sym);
1180
1181 return (name && *name != '$');
1182}
1183
58efb6c0 1184/* Parse an individual disassembler option. */
baf0cc5e 1185
a3d9c82d
NC
1186void
1187parse_arm_disassembler_option (option)
01c7f630 1188 char * option;
dd92f639 1189{
01c7f630 1190 if (option == NULL)
dd92f639 1191 return;
b34976b6 1192
01c7f630 1193 if (strneq (option, "reg-names-", 10))
dd92f639 1194 {
58efb6c0 1195 int i;
b34976b6 1196
01c7f630 1197 option += 10;
58efb6c0
NC
1198
1199 for (i = NUM_ARM_REGNAMES; i--;)
31e0f3cd 1200 if (strneq (option, regnames[i].name, strlen (regnames[i].name)))
58efb6c0
NC
1201 {
1202 regname_selected = i;
1203 break;
1204 }
b34976b6 1205
58efb6c0 1206 if (i < 0)
31e0f3cd 1207 /* XXX - should break 'option' at following delimiter. */
58efb6c0 1208 fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
dd92f639 1209 }
31e0f3cd 1210 else if (strneq (option, "force-thumb", 11))
01c7f630 1211 force_thumb = 1;
31e0f3cd 1212 else if (strneq (option, "no-force-thumb", 14))
01c7f630 1213 force_thumb = 0;
dd92f639 1214 else
31e0f3cd 1215 /* XXX - should break 'option' at following delimiter. */
58efb6c0 1216 fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
b34976b6 1217
dd92f639
NC
1218 return;
1219}
1220
31e0f3cd
NC
1221/* Parse the string of disassembler options, spliting it at whitespaces
1222 or commas. (Whitespace separators supported for backwards compatibility). */
baf0cc5e 1223
01c7f630
NC
1224static void
1225parse_disassembler_options (options)
1226 char * options;
1227{
01c7f630
NC
1228 if (options == NULL)
1229 return;
1230
31e0f3cd 1231 while (*options)
01c7f630 1232 {
31e0f3cd
NC
1233 parse_arm_disassembler_option (options);
1234
1235 /* Skip forward to next seperator. */
1236 while ((*options) && (! ISSPACE (*options)) && (*options != ','))
1237 ++ options;
1238 /* Skip forward past seperators. */
1239 while (ISSPACE (*options) || (*options == ','))
1240 ++ options;
01c7f630 1241 }
01c7f630
NC
1242}
1243
58efb6c0
NC
1244/* NOTE: There are no checks in these routines that
1245 the relevant number of data bytes exist. */
baf0cc5e 1246
58efb6c0
NC
1247static int
1248print_insn (pc, info, little)
252b5132 1249 bfd_vma pc;
5876e06d 1250 struct disassemble_info * info;
b34976b6 1251 bfd_boolean little;
252b5132
RH
1252{
1253 unsigned char b[4];
1254 long given;
1255 int status;
252b5132 1256 int is_thumb;
58efb6c0 1257
dd92f639
NC
1258 if (info->disassembler_options)
1259 {
1260 parse_disassembler_options (info->disassembler_options);
b34976b6 1261
58efb6c0 1262 /* To avoid repeated parsing of these options, we remove them here. */
dd92f639
NC
1263 info->disassembler_options = NULL;
1264 }
b34976b6 1265
01c7f630 1266 is_thumb = force_thumb;
b34976b6 1267
01c7f630 1268 if (!is_thumb && info->symbols != NULL)
252b5132 1269 {
5876e06d
NC
1270 if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
1271 {
2f0ca46a 1272 coff_symbol_type * cs;
b34976b6 1273
5876e06d
NC
1274 cs = coffsymbol (*info->symbols);
1275 is_thumb = ( cs->native->u.syment.n_sclass == C_THUMBEXT
1276 || cs->native->u.syment.n_sclass == C_THUMBSTAT
1277 || cs->native->u.syment.n_sclass == C_THUMBLABEL
1278 || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
1279 || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
1280 }
1281 else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
1282 {
2f0ca46a 1283 elf_symbol_type * es;
58efb6c0 1284 unsigned int type;
b34976b6 1285
5876e06d 1286 es = *(elf_symbol_type **)(info->symbols);
58efb6c0 1287 type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
b34976b6 1288
58efb6c0 1289 is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
5876e06d
NC
1290 }
1291 }
b34976b6 1292
252b5132 1293 info->bytes_per_chunk = 4;
58efb6c0 1294 info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
252b5132 1295
58efb6c0 1296 if (little)
252b5132 1297 {
58efb6c0
NC
1298 status = info->read_memory_func (pc, (bfd_byte *) &b[0], 4, info);
1299 if (status != 0 && is_thumb)
1300 {
1301 info->bytes_per_chunk = 2;
b34976b6 1302
58efb6c0
NC
1303 status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
1304 b[3] = b[2] = 0;
1305 }
b34976b6 1306
58efb6c0
NC
1307 if (status != 0)
1308 {
1309 info->memory_error_func (status, pc, info);
1310 return -1;
1311 }
b34976b6 1312
58efb6c0 1313 given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
252b5132 1314 }
58efb6c0 1315 else
252b5132 1316 {
58efb6c0
NC
1317 status = info->read_memory_func
1318 (pc & ~ 0x3, (bfd_byte *) &b[0], 4, info);
1319 if (status != 0)
252b5132 1320 {
58efb6c0
NC
1321 info->memory_error_func (status, pc, info);
1322 return -1;
1323 }
b34976b6 1324
58efb6c0
NC
1325 if (is_thumb)
1326 {
1327 if (pc & 0x2)
252b5132 1328 {
58efb6c0 1329 given = (b[2] << 8) | b[3];
b34976b6 1330
58efb6c0
NC
1331 status = info->read_memory_func
1332 ((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
1333 if (status != 0)
1334 {
1335 info->memory_error_func (status, pc + 4, info);
1336 return -1;
1337 }
b34976b6 1338
58efb6c0 1339 given |= (b[0] << 24) | (b[1] << 16);
252b5132 1340 }
58efb6c0
NC
1341 else
1342 given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16);
252b5132
RH
1343 }
1344 else
58efb6c0 1345 given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
252b5132 1346 }
b34976b6 1347
6a56ec7e
NC
1348 if (info->flags & INSN_HAS_RELOC)
1349 /* If the instruction has a reloc associated with it, then
1350 the offset field in the instruction will actually be the
1351 addend for the reloc. (We are using REL type relocs).
1352 In such cases, we can ignore the pc when computing
1353 addresses, since the addend is not currently pc-relative. */
1354 pc = 0;
b34976b6 1355
252b5132 1356 if (is_thumb)
5876e06d 1357 status = print_insn_thumb (pc, info, given);
252b5132 1358 else
5876e06d 1359 status = print_insn_arm (pc, info, given);
252b5132
RH
1360
1361 return status;
1362}
1363
1364int
58efb6c0 1365print_insn_big_arm (pc, info)
252b5132
RH
1366 bfd_vma pc;
1367 struct disassemble_info * info;
1368{
b34976b6 1369 return print_insn (pc, info, FALSE);
58efb6c0 1370}
01c7f630 1371
58efb6c0
NC
1372int
1373print_insn_little_arm (pc, info)
1374 bfd_vma pc;
1375 struct disassemble_info * info;
1376{
b34976b6 1377 return print_insn (pc, info, TRUE);
58efb6c0 1378}
252b5132 1379
58efb6c0
NC
1380void
1381print_arm_disassembler_options (FILE * stream)
1382{
1383 int i;
252b5132 1384
58efb6c0
NC
1385 fprintf (stream, _("\n\
1386The following ARM specific disassembler options are supported for use with\n\
1387the -M switch:\n"));
b34976b6 1388
58efb6c0
NC
1389 for (i = NUM_ARM_REGNAMES; i--;)
1390 fprintf (stream, " reg-names-%s %*c%s\n",
1391 regnames[i].name,
d5b2f4d6 1392 (int)(14 - strlen (regnames[i].name)), ' ',
58efb6c0
NC
1393 regnames[i].description);
1394
1395 fprintf (stream, " force-thumb Assume all insns are Thumb insns\n");
1396 fprintf (stream, " no-force-thumb Examine preceeding label to determine an insn's type\n\n");
252b5132 1397}