* config/tc-sh.c (md_assemble): For branches, check & update
[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)
289 func (stream, ", %s#%d",
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)
310 func (stream, "], %s#%d",
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)
353 func (stream, ", %s#%d",
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)
377 func (stream, "], %s#%d",
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]);
448 if ((given & 0x01000000) != 0)
449 {
450 int offset = given & 0xff;
451 if (offset)
452 func (stream, ", %s#%d]%s",
453 ((given & 0x00800000) == 0 ? "-" : ""),
454 offset * 4,
455 ((given & 0x00200000) != 0 ? "!" : ""));
456 else
457 func (stream, "]");
458 }
459 else
460 {
461 int offset = given & 0xff;
462 if (offset)
463 func (stream, "], %s#%d",
464 ((given & 0x00800000) == 0 ? "-" : ""),
465 offset * 4);
466 else
467 func (stream, "]");
468 }
469 break;
470
077b8428
NC
471 case 'B':
472 /* Print ARM V5 BLX(1) address: pc+25 bits. */
473 {
474 bfd_vma address;
475 bfd_vma offset = 0;
b34976b6 476
077b8428
NC
477 if (given & 0x00800000)
478 /* Is signed, hi bits should be ones. */
479 offset = (-1) ^ 0x00ffffff;
480
481 /* Offset is (SignExtend(offset field)<<2). */
482 offset += given & 0x00ffffff;
483 offset <<= 2;
484 address = offset + pc + 8;
b34976b6 485
077b8428
NC
486 if (given & 0x01000000)
487 /* H bit allows addressing to 2-byte boundaries. */
488 address += 2;
489
490 info->print_address_func (address, info);
491 }
492 break;
493
b1ee46c5
AH
494 case 'I':
495 /* Print a Cirrus/DSP shift immediate. */
496 /* Immediates are 7bit signed ints with bits 0..3 in
497 bits 0..3 of opcode and bits 4..6 in bits 5..7
498 of opcode. */
499 {
500 int imm;
501
502 imm = (given & 0xf) | ((given & 0xe0) >> 1);
503
504 /* Is ``imm'' a negative number? */
505 if (imm & 0x40)
506 imm |= (-1 << 7);
507
508 func (stream, "%d", imm);
509 }
510
511 break;
512
252b5132 513 case 'C':
6eeeb4b4
AO
514 func (stream, "_");
515 if (given & 0x80000)
516 func (stream, "f");
517 if (given & 0x40000)
518 func (stream, "s");
519 if (given & 0x20000)
520 func (stream, "x");
521 if (given & 0x10000)
522 func (stream, "c");
252b5132
RH
523 break;
524
525 case 'F':
526 switch (given & 0x00408000)
527 {
528 case 0:
529 func (stream, "4");
530 break;
531 case 0x8000:
532 func (stream, "1");
533 break;
534 case 0x00400000:
535 func (stream, "2");
536 break;
537 default:
538 func (stream, "3");
539 }
540 break;
b34976b6 541
252b5132
RH
542 case 'P':
543 switch (given & 0x00080080)
544 {
545 case 0:
546 func (stream, "s");
547 break;
548 case 0x80:
549 func (stream, "d");
550 break;
551 case 0x00080000:
552 func (stream, "e");
553 break;
554 default:
555 func (stream, _("<illegal precision>"));
556 break;
557 }
558 break;
559 case 'Q':
560 switch (given & 0x00408000)
561 {
562 case 0:
563 func (stream, "s");
564 break;
565 case 0x8000:
566 func (stream, "d");
567 break;
568 case 0x00400000:
569 func (stream, "e");
570 break;
571 default:
572 func (stream, "p");
573 break;
574 }
575 break;
576 case 'R':
577 switch (given & 0x60)
578 {
579 case 0:
580 break;
581 case 0x20:
582 func (stream, "p");
583 break;
584 case 0x40:
585 func (stream, "m");
586 break;
587 default:
588 func (stream, "z");
589 break;
590 }
591 break;
592
b34976b6 593 case '0': case '1': case '2': case '3': case '4':
252b5132
RH
594 case '5': case '6': case '7': case '8': case '9':
595 {
596 int bitstart = *c++ - '0';
597 int bitend = 0;
598 while (*c >= '0' && *c <= '9')
599 bitstart = (bitstart * 10) + *c++ - '0';
600
601 switch (*c)
602 {
603 case '-':
604 c++;
b34976b6 605
252b5132
RH
606 while (*c >= '0' && *c <= '9')
607 bitend = (bitend * 10) + *c++ - '0';
b34976b6 608
252b5132
RH
609 if (!bitend)
610 abort ();
b34976b6 611
252b5132
RH
612 switch (*c)
613 {
614 case 'r':
615 {
616 long reg;
b34976b6 617
252b5132
RH
618 reg = given >> bitstart;
619 reg &= (2 << (bitend - bitstart)) - 1;
b34976b6 620
252b5132
RH
621 func (stream, "%s", arm_regnames[reg]);
622 }
623 break;
624 case 'd':
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, "%d", reg);
632 }
633 break;
634 case 'x':
635 {
636 long reg;
b34976b6 637
252b5132
RH
638 reg = given >> bitstart;
639 reg &= (2 << (bitend - bitstart)) - 1;
b34976b6 640
252b5132 641 func (stream, "0x%08x", reg);
b34976b6 642
58efb6c0
NC
643 /* Some SWI instructions have special
644 meanings. */
5876e06d
NC
645 if ((given & 0x0fffffff) == 0x0FF00000)
646 func (stream, "\t; IMB");
647 else if ((given & 0x0fffffff) == 0x0FF00001)
648 func (stream, "\t; IMBRange");
252b5132
RH
649 }
650 break;
cfbd315c
DL
651 case 'X':
652 {
653 long reg;
b34976b6 654
cfbd315c
DL
655 reg = given >> bitstart;
656 reg &= (2 << (bitend - bitstart)) - 1;
b34976b6 657
cfbd315c
DL
658 func (stream, "%01x", reg & 0xf);
659 }
660 break;
252b5132
RH
661 case 'f':
662 {
663 long reg;
b34976b6 664
252b5132
RH
665 reg = given >> bitstart;
666 reg &= (2 << (bitend - bitstart)) - 1;
b34976b6 667
252b5132
RH
668 if (reg > 7)
669 func (stream, "#%s",
670 arm_fp_const[reg & 7]);
671 else
672 func (stream, "f%d", reg);
673 }
674 break;
e16bb312
NC
675
676 case 'w':
677 {
678 long reg;
679
680 if (bitstart != bitend)
681 {
682 reg = given >> bitstart;
683 reg &= (2 << (bitend - bitstart)) - 1;
684 if (bitend - bitstart == 1)
685 func (stream, "%s", iwmmxt_wwnames[reg]);
686 else
687 func (stream, "%s", iwmmxt_wwssnames[reg]);
688 }
689 else
690 {
691 reg = (((given >> 8) & 0x1) |
692 ((given >> 22) & 0x1));
693 func (stream, "%s", iwmmxt_wwnames[reg]);
694 }
695 }
696 break;
697
698 case 'g':
699 {
700 long reg;
701 int current_regnames;
702
703 if (! iwmmxt_regnames)
704 iwmmxt_regnames = set_iwmmxt_regnames ();
705 current_regnames = set_arm_regname_option
706 (iwmmxt_regnames);
707
708 reg = given >> bitstart;
709 reg &= (2 << (bitend - bitstart)) - 1;
710 func (stream, "%s", arm_regnames[reg]);
711 set_arm_regname_option (current_regnames);
712 }
713 break;
714
715 case 'G':
716 {
717 long reg;
718 int current_regnames;
719
720 if (! iwmmxt_regnames)
721 iwmmxt_regnames = set_iwmmxt_regnames ();
722 current_regnames = set_arm_regname_option
723 (iwmmxt_regnames + 1);
724
725 reg = given >> bitstart;
726 reg &= (2 << (bitend - bitstart)) - 1;
727 func (stream, "%s", arm_regnames[reg]);
728 set_arm_regname_option (current_regnames);
729 }
730 break;
731
252b5132
RH
732 default:
733 abort ();
734 }
735 break;
a660f11e
RE
736
737 case 'y':
738 case 'z':
739 {
740 int single = *c == 'y';
741 int regno;
742
743 switch (bitstart)
744 {
745 case 4: /* Sm pair */
746 func (stream, "{");
747 /* Fall through. */
748 case 0: /* Sm, Dm */
749 regno = given & 0x0000000f;
750 if (single)
751 {
752 regno <<= 1;
753 regno += (given >> 5) & 1;
754 }
755 break;
756
757 case 1: /* Sd, Dd */
758 regno = (given >> 12) & 0x0000000f;
759 if (single)
760 {
761 regno <<= 1;
762 regno += (given >> 22) & 1;
763 }
764 break;
765
766 case 2: /* Sn, Dn */
767 regno = (given >> 16) & 0x0000000f;
768 if (single)
769 {
770 regno <<= 1;
771 regno += (given >> 7) & 1;
772 }
773 break;
774
775 case 3: /* List */
776 func (stream, "{");
777 regno = (given >> 12) & 0x0000000f;
778 if (single)
779 {
780 regno <<= 1;
781 regno += (given >> 22) & 1;
782 }
783 break;
784
b34976b6 785
a660f11e
RE
786 default:
787 abort ();
788 }
789
790 func (stream, "%c%d", single ? 's' : 'd', regno);
791
792 if (bitstart == 3)
793 {
794 int count = given & 0xff;
795
796 if (single == 0)
797 count >>= 1;
798
799 if (--count)
800 {
801 func (stream, "-%c%d",
802 single ? 's' : 'd',
803 regno + count);
804 }
805
806 func (stream, "}");
807 }
808 else if (bitstart == 4)
809 func (stream, ", %c%d}", single ? 's' : 'd',
810 regno + 1);
811
812 break;
813 }
814
252b5132
RH
815 case '`':
816 c++;
817 if ((given & (1 << bitstart)) == 0)
818 func (stream, "%c", *c);
819 break;
820 case '\'':
821 c++;
822 if ((given & (1 << bitstart)) != 0)
823 func (stream, "%c", *c);
824 break;
825 case '?':
826 ++c;
827 if ((given & (1 << bitstart)) != 0)
828 func (stream, "%c", *c++);
829 else
830 func (stream, "%c", *++c);
831 break;
832 default:
833 abort ();
834 }
835 break;
836
e16bb312
NC
837 case 'L':
838 switch (given & 0x00400100)
839 {
840 case 0x00000000: func (stream, "b"); break;
841 case 0x00400000: func (stream, "h"); break;
842 case 0x00000100: func (stream, "w"); break;
843 case 0x00400100: func (stream, "d"); break;
844 default:
845 break;
846 }
847 break;
848
849 case 'Z':
850 {
851 int value;
852 /* given (20, 23) | given (0, 3) */
853 value = ((given >> 16) & 0xf0) | (given & 0xf);
854 func (stream, "%d", value);
855 }
856 break;
857
858 case 'l':
859 /* This is like the 'A' operator, except that if
860 the width field "M" is zero, then the offset is
861 *not* multiplied by four. */
862 {
863 int offset = given & 0xff;
864 int multiplier = (given & 0x00000100) ? 4 : 1;
865
866 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
867
868 if (offset)
869 {
870 if ((given & 0x01000000) != 0)
871 func (stream, ", %s#%d]%s",
872 ((given & 0x00800000) == 0 ? "-" : ""),
873 offset * multiplier,
874 ((given & 0x00200000) != 0 ? "!" : ""));
875 else
876 func (stream, "], %s#%d",
877 ((given & 0x00800000) == 0 ? "-" : ""),
878 offset * multiplier);
879 }
880 else
881 func (stream, "]");
882 }
883 break;
884
252b5132
RH
885 default:
886 abort ();
887 }
888 }
889 }
890 else
891 func (stream, "%c", *c);
892 }
893 return 4;
894 }
895 }
896 abort ();
897}
898
899/* Print one instruction from PC on INFO->STREAM.
900 Return the size of the instruction. */
baf0cc5e 901
252b5132
RH
902static int
903print_insn_thumb (pc, info, given)
6a51a8a8
AM
904 bfd_vma pc;
905 struct disassemble_info *info;
906 long given;
252b5132 907{
6a51a8a8
AM
908 const struct thumb_opcode *insn;
909 void *stream = info->stream;
910 fprintf_ftype func = info->fprintf_func;
252b5132
RH
911
912 for (insn = thumb_opcodes; insn->assembler; insn++)
913 {
914 if ((given & insn->mask) == insn->value)
915 {
5876e06d 916 char * c = insn->assembler;
252b5132 917
58efb6c0
NC
918 /* Special processing for Thumb 2 instruction BL sequence: */
919 if (!*c) /* Check for empty (not NULL) assembler string. */
252b5132 920 {
4f3c3dbb 921 long offset;
b34976b6 922
252b5132
RH
923 info->bytes_per_chunk = 4;
924 info->bytes_per_line = 4;
4f3c3dbb
NC
925
926 offset = BDISP23 (given);
baf0cc5e
NC
927 offset = offset * 2 + pc + 4;
928
077b8428 929 if ((given & 0x10000000) == 0)
4f3c3dbb
NC
930 {
931 func (stream, "blx\t");
baf0cc5e 932 offset &= 0xfffffffc;
4f3c3dbb 933 }
077b8428 934 else
4f3c3dbb
NC
935 func (stream, "bl\t");
936
baf0cc5e 937 info->print_address_func (offset, info);
252b5132
RH
938 return 4;
939 }
940 else
941 {
942 info->bytes_per_chunk = 2;
943 info->bytes_per_line = 4;
b34976b6 944
252b5132 945 given &= 0xffff;
b34976b6 946
252b5132
RH
947 for (; *c; c++)
948 {
949 if (*c == '%')
950 {
951 int domaskpc = 0;
952 int domasklr = 0;
b34976b6 953
252b5132
RH
954 switch (*++c)
955 {
956 case '%':
957 func (stream, "%%");
958 break;
959
960 case 'S':
961 {
962 long reg;
b34976b6 963
252b5132
RH
964 reg = (given >> 3) & 0x7;
965 if (given & (1 << 6))
966 reg += 8;
b34976b6 967
252b5132
RH
968 func (stream, "%s", arm_regnames[reg]);
969 }
970 break;
971
972 case 'D':
973 {
974 long reg;
b34976b6 975
252b5132
RH
976 reg = given & 0x7;
977 if (given & (1 << 7))
978 reg += 8;
b34976b6 979
252b5132
RH
980 func (stream, "%s", arm_regnames[reg]);
981 }
982 break;
983
984 case 'T':
985 func (stream, "%s",
986 arm_conditional [(given >> 8) & 0xf]);
987 break;
988
989 case 'N':
990 if (given & (1 << 8))
991 domasklr = 1;
58efb6c0 992 /* Fall through. */
252b5132
RH
993 case 'O':
994 if (*c == 'O' && (given & (1 << 8)))
995 domaskpc = 1;
58efb6c0 996 /* Fall through. */
252b5132
RH
997 case 'M':
998 {
999 int started = 0;
1000 int reg;
b34976b6 1001
252b5132 1002 func (stream, "{");
b34976b6 1003
252b5132
RH
1004 /* It would be nice if we could spot
1005 ranges, and generate the rS-rE format: */
1006 for (reg = 0; (reg < 8); reg++)
1007 if ((given & (1 << reg)) != 0)
1008 {
1009 if (started)
1010 func (stream, ", ");
1011 started = 1;
1012 func (stream, "%s", arm_regnames[reg]);
1013 }
1014
1015 if (domasklr)
1016 {
1017 if (started)
1018 func (stream, ", ");
1019 started = 1;
a7f8487e 1020 func (stream, arm_regnames[14] /* "lr" */);
252b5132
RH
1021 }
1022
1023 if (domaskpc)
1024 {
1025 if (started)
1026 func (stream, ", ");
a7f8487e 1027 func (stream, arm_regnames[15] /* "pc" */);
252b5132
RH
1028 }
1029
1030 func (stream, "}");
1031 }
1032 break;
1033
1034
b34976b6 1035 case '0': case '1': case '2': case '3': case '4':
252b5132
RH
1036 case '5': case '6': case '7': case '8': case '9':
1037 {
1038 int bitstart = *c++ - '0';
1039 int bitend = 0;
b34976b6 1040
252b5132
RH
1041 while (*c >= '0' && *c <= '9')
1042 bitstart = (bitstart * 10) + *c++ - '0';
1043
1044 switch (*c)
1045 {
1046 case '-':
1047 {
1048 long reg;
b34976b6 1049
252b5132
RH
1050 c++;
1051 while (*c >= '0' && *c <= '9')
1052 bitend = (bitend * 10) + *c++ - '0';
1053 if (!bitend)
1054 abort ();
1055 reg = given >> bitstart;
1056 reg &= (2 << (bitend - bitstart)) - 1;
1057 switch (*c)
1058 {
1059 case 'r':
1060 func (stream, "%s", arm_regnames[reg]);
1061 break;
1062
1063 case 'd':
1064 func (stream, "%d", reg);
1065 break;
1066
1067 case 'H':
1068 func (stream, "%d", reg << 1);
1069 break;
1070
1071 case 'W':
1072 func (stream, "%d", reg << 2);
1073 break;
1074
1075 case 'a':
1076 /* PC-relative address -- the bottom two
58efb6c0
NC
1077 bits of the address are dropped
1078 before the calculation. */
252b5132
RH
1079 info->print_address_func
1080 (((pc + 4) & ~3) + (reg << 2), info);
1081 break;
1082
1083 case 'x':
1084 func (stream, "0x%04x", reg);
1085 break;
1086
1087 case 'I':
1088 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
1089 func (stream, "%d", reg);
1090 break;
1091
1092 case 'B':
1093 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
1094 (*info->print_address_func)
1095 (reg * 2 + pc + 4, info);
1096 break;
1097
1098 default:
5876e06d 1099 abort ();
252b5132
RH
1100 }
1101 }
1102 break;
1103
1104 case '\'':
1105 c++;
1106 if ((given & (1 << bitstart)) != 0)
1107 func (stream, "%c", *c);
1108 break;
1109
1110 case '?':
1111 ++c;
1112 if ((given & (1 << bitstart)) != 0)
1113 func (stream, "%c", *c++);
1114 else
1115 func (stream, "%c", *++c);
1116 break;
1117
1118 default:
5876e06d 1119 abort ();
252b5132
RH
1120 }
1121 }
1122 break;
1123
1124 default:
1125 abort ();
1126 }
1127 }
1128 else
1129 func (stream, "%c", *c);
1130 }
1131 }
1132 return 2;
1133 }
1134 }
1135
58efb6c0 1136 /* No match. */
252b5132
RH
1137 abort ();
1138}
1139
58efb6c0 1140/* Parse an individual disassembler option. */
baf0cc5e 1141
a3d9c82d
NC
1142void
1143parse_arm_disassembler_option (option)
01c7f630 1144 char * option;
dd92f639 1145{
01c7f630 1146 if (option == NULL)
dd92f639 1147 return;
b34976b6 1148
01c7f630 1149 if (strneq (option, "reg-names-", 10))
dd92f639 1150 {
58efb6c0 1151 int i;
b34976b6 1152
01c7f630 1153 option += 10;
58efb6c0
NC
1154
1155 for (i = NUM_ARM_REGNAMES; i--;)
31e0f3cd 1156 if (strneq (option, regnames[i].name, strlen (regnames[i].name)))
58efb6c0
NC
1157 {
1158 regname_selected = i;
1159 break;
1160 }
b34976b6 1161
58efb6c0 1162 if (i < 0)
31e0f3cd 1163 /* XXX - should break 'option' at following delimiter. */
58efb6c0 1164 fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
dd92f639 1165 }
31e0f3cd 1166 else if (strneq (option, "force-thumb", 11))
01c7f630 1167 force_thumb = 1;
31e0f3cd 1168 else if (strneq (option, "no-force-thumb", 14))
01c7f630 1169 force_thumb = 0;
dd92f639 1170 else
31e0f3cd 1171 /* XXX - should break 'option' at following delimiter. */
58efb6c0 1172 fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
b34976b6 1173
dd92f639
NC
1174 return;
1175}
1176
31e0f3cd
NC
1177/* Parse the string of disassembler options, spliting it at whitespaces
1178 or commas. (Whitespace separators supported for backwards compatibility). */
baf0cc5e 1179
01c7f630
NC
1180static void
1181parse_disassembler_options (options)
1182 char * options;
1183{
01c7f630
NC
1184 if (options == NULL)
1185 return;
1186
31e0f3cd 1187 while (*options)
01c7f630 1188 {
31e0f3cd
NC
1189 parse_arm_disassembler_option (options);
1190
1191 /* Skip forward to next seperator. */
1192 while ((*options) && (! ISSPACE (*options)) && (*options != ','))
1193 ++ options;
1194 /* Skip forward past seperators. */
1195 while (ISSPACE (*options) || (*options == ','))
1196 ++ options;
01c7f630 1197 }
01c7f630
NC
1198}
1199
58efb6c0
NC
1200/* NOTE: There are no checks in these routines that
1201 the relevant number of data bytes exist. */
baf0cc5e 1202
58efb6c0
NC
1203static int
1204print_insn (pc, info, little)
252b5132 1205 bfd_vma pc;
5876e06d 1206 struct disassemble_info * info;
b34976b6 1207 bfd_boolean little;
252b5132
RH
1208{
1209 unsigned char b[4];
1210 long given;
1211 int status;
252b5132 1212 int is_thumb;
58efb6c0 1213
dd92f639
NC
1214 if (info->disassembler_options)
1215 {
1216 parse_disassembler_options (info->disassembler_options);
b34976b6 1217
58efb6c0 1218 /* To avoid repeated parsing of these options, we remove them here. */
dd92f639
NC
1219 info->disassembler_options = NULL;
1220 }
b34976b6 1221
01c7f630 1222 is_thumb = force_thumb;
b34976b6 1223
01c7f630 1224 if (!is_thumb && info->symbols != NULL)
252b5132 1225 {
5876e06d
NC
1226 if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
1227 {
2f0ca46a 1228 coff_symbol_type * cs;
b34976b6 1229
5876e06d
NC
1230 cs = coffsymbol (*info->symbols);
1231 is_thumb = ( cs->native->u.syment.n_sclass == C_THUMBEXT
1232 || cs->native->u.syment.n_sclass == C_THUMBSTAT
1233 || cs->native->u.syment.n_sclass == C_THUMBLABEL
1234 || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
1235 || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
1236 }
1237 else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
1238 {
2f0ca46a 1239 elf_symbol_type * es;
58efb6c0 1240 unsigned int type;
b34976b6 1241
5876e06d 1242 es = *(elf_symbol_type **)(info->symbols);
58efb6c0 1243 type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
b34976b6 1244
58efb6c0 1245 is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
5876e06d
NC
1246 }
1247 }
b34976b6 1248
252b5132 1249 info->bytes_per_chunk = 4;
58efb6c0 1250 info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
252b5132 1251
58efb6c0 1252 if (little)
252b5132 1253 {
58efb6c0
NC
1254 status = info->read_memory_func (pc, (bfd_byte *) &b[0], 4, info);
1255 if (status != 0 && is_thumb)
1256 {
1257 info->bytes_per_chunk = 2;
b34976b6 1258
58efb6c0
NC
1259 status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
1260 b[3] = b[2] = 0;
1261 }
b34976b6 1262
58efb6c0
NC
1263 if (status != 0)
1264 {
1265 info->memory_error_func (status, pc, info);
1266 return -1;
1267 }
b34976b6 1268
58efb6c0 1269 given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
252b5132 1270 }
58efb6c0 1271 else
252b5132 1272 {
58efb6c0
NC
1273 status = info->read_memory_func
1274 (pc & ~ 0x3, (bfd_byte *) &b[0], 4, info);
1275 if (status != 0)
252b5132 1276 {
58efb6c0
NC
1277 info->memory_error_func (status, pc, info);
1278 return -1;
1279 }
b34976b6 1280
58efb6c0
NC
1281 if (is_thumb)
1282 {
1283 if (pc & 0x2)
252b5132 1284 {
58efb6c0 1285 given = (b[2] << 8) | b[3];
b34976b6 1286
58efb6c0
NC
1287 status = info->read_memory_func
1288 ((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
1289 if (status != 0)
1290 {
1291 info->memory_error_func (status, pc + 4, info);
1292 return -1;
1293 }
b34976b6 1294
58efb6c0 1295 given |= (b[0] << 24) | (b[1] << 16);
252b5132 1296 }
58efb6c0
NC
1297 else
1298 given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16);
252b5132
RH
1299 }
1300 else
58efb6c0 1301 given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
252b5132 1302 }
b34976b6 1303
6a56ec7e
NC
1304 if (info->flags & INSN_HAS_RELOC)
1305 /* If the instruction has a reloc associated with it, then
1306 the offset field in the instruction will actually be the
1307 addend for the reloc. (We are using REL type relocs).
1308 In such cases, we can ignore the pc when computing
1309 addresses, since the addend is not currently pc-relative. */
1310 pc = 0;
b34976b6 1311
252b5132 1312 if (is_thumb)
5876e06d 1313 status = print_insn_thumb (pc, info, given);
252b5132 1314 else
5876e06d 1315 status = print_insn_arm (pc, info, given);
252b5132
RH
1316
1317 return status;
1318}
1319
1320int
58efb6c0 1321print_insn_big_arm (pc, info)
252b5132
RH
1322 bfd_vma pc;
1323 struct disassemble_info * info;
1324{
b34976b6 1325 return print_insn (pc, info, FALSE);
58efb6c0 1326}
01c7f630 1327
58efb6c0
NC
1328int
1329print_insn_little_arm (pc, info)
1330 bfd_vma pc;
1331 struct disassemble_info * info;
1332{
b34976b6 1333 return print_insn (pc, info, TRUE);
58efb6c0 1334}
252b5132 1335
58efb6c0
NC
1336void
1337print_arm_disassembler_options (FILE * stream)
1338{
1339 int i;
252b5132 1340
58efb6c0
NC
1341 fprintf (stream, _("\n\
1342The following ARM specific disassembler options are supported for use with\n\
1343the -M switch:\n"));
b34976b6 1344
58efb6c0
NC
1345 for (i = NUM_ARM_REGNAMES; i--;)
1346 fprintf (stream, " reg-names-%s %*c%s\n",
1347 regnames[i].name,
d5b2f4d6 1348 (int)(14 - strlen (regnames[i].name)), ' ',
58efb6c0
NC
1349 regnames[i].description);
1350
1351 fprintf (stream, " force-thumb Assume all insns are Thumb insns\n");
1352 fprintf (stream, " no-force-thumb Examine preceeding label to determine an insn's type\n\n");
252b5132 1353}
This page took 0.266874 seconds and 4 git commands to generate.