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