xref: /openbsd/gnu/usr.bin/binutils/opcodes/arm-dis.c (revision 09467b48)
1 /* Instruction printing code for the ARM
2    Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3    Free Software Foundation, Inc.
4    Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5    Modification by James G. Smith (jsmith@cygnus.co.uk)
6 
7    This file is part of libopcodes.
8 
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.
13 
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.
18 
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.  */
22 
23 #include "sysdep.h"
24 #include "dis-asm.h"
25 #define DEFINE_TABLE
26 #include "arm-opc.h"
27 #include "coff/internal.h"
28 #include "libcoff.h"
29 #include "opintl.h"
30 #include "safe-ctype.h"
31 
32 /* FIXME: This shouldn't be done here.  */
33 #include "elf-bfd.h"
34 #include "elf/internal.h"
35 #include "elf/arm.h"
36 
37 #ifndef streq
38 #define streq(a,b)	(strcmp ((a), (b)) == 0)
39 #endif
40 
41 #ifndef strneq
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])
47 #endif
48 
49 static char * arm_conditional[] =
50 {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
51  "hi", "ls", "ge", "lt", "gt", "le", "", "nv"};
52 
53 typedef struct
54 {
55   const char * name;
56   const char * description;
57   const char * reg_names[16];
58 }
59 arm_regname;
60 
61 static 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"}},
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" }},
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" }},
73   { "special-atpcs", "Select special register names used in the ATPCS",
74     { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL",  "FP",  "IP",  "SP",  "LR",  "PC" }},
75   { "iwmmxt_regnames", "Select register names used on the Intel Wireless MMX technology coprocessor",
76     { "wr0", "wr1", "wr2", "wr3", "wr4", "wr5", "wr6", "wr7", "wr8", "wr9", "wr10", "wr11", "wr12", "wr13", "wr14", "wr15"}},
77   { "iwmmxt_Cregnames", "Select control register names used on the Intel Wireless MMX technology coprocessor",
78     {"wcid", "wcon", "wcssf", "wcasf", "reserved", "reserved", "reserved", "reserved", "wcgr0", "wcgr1", "wcgr2", "wcgr3", "reserved", "reserved", "reserved", "reserved"}}
79 };
80 
81 static char * iwmmxt_wwnames[] =
82 {"b", "h", "w", "d"};
83 
84 static char * iwmmxt_wwssnames[] =
85 {"b", "bus", "b", "bss",
86  "h", "hus", "h", "hss",
87  "w", "wus", "w", "wss",
88  "d", "dus", "d", "dss"
89 };
90 
91 /* Default to GCC register name set.  */
92 static unsigned int regname_selected = 1;
93 
94 #define NUM_ARM_REGNAMES  NUM_ELEM (regnames)
95 #define arm_regnames      regnames[regname_selected].reg_names
96 
97 static bfd_boolean force_thumb = FALSE;
98 
99 static char * arm_fp_const[] =
100 {"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
101 
102 static char * arm_shift[] =
103 {"lsl", "lsr", "asr", "ror"};
104 
105 /* Forward declarations.  */
106 static void arm_decode_shift
107   PARAMS ((long, fprintf_ftype, void *));
108 static int  print_insn_arm
109   PARAMS ((bfd_vma, struct disassemble_info *, long));
110 static int  print_insn_thumb
111   PARAMS ((bfd_vma, struct disassemble_info *, long));
112 static void parse_disassembler_options
113   PARAMS ((char *));
114 static int  print_insn
115   PARAMS ((bfd_vma, struct disassemble_info *, bfd_boolean));
116 static int set_iwmmxt_regnames
117   PARAMS ((void));
118 
119 int get_arm_regname_num_options
120   PARAMS ((void));
121 int set_arm_regname_option
122   PARAMS ((int));
123 int get_arm_regnames
124   PARAMS ((int, const char **, const char **, const char ***));
125 
126 /* Functions.  */
127 int
128 get_arm_regname_num_options ()
129 {
130   return NUM_ARM_REGNAMES;
131 }
132 
133 int
134 set_arm_regname_option (option)
135      int option;
136 {
137   int old = regname_selected;
138   regname_selected = option;
139   return old;
140 }
141 
142 int
143 get_arm_regnames (option, setname, setdescription, register_names)
144      int option;
145      const char **setname;
146      const char **setdescription;
147      const char ***register_names;
148 {
149   *setname = regnames[option].name;
150   *setdescription = regnames[option].description;
151   *register_names = regnames[option].reg_names;
152   return 16;
153 }
154 
155 static void
156 arm_decode_shift (given, func, stream)
157      long given;
158      fprintf_ftype func;
159      void * stream;
160 {
161   func (stream, "%s", arm_regnames[given & 0xf]);
162 
163   if ((given & 0xff0) != 0)
164     {
165       if ((given & 0x10) == 0)
166 	{
167 	  int amount = (given & 0xf80) >> 7;
168 	  int shift = (given & 0x60) >> 5;
169 
170 	  if (amount == 0)
171 	    {
172 	      if (shift == 3)
173 		{
174 		  func (stream, ", rrx");
175 		  return;
176 		}
177 
178 	      amount = 32;
179 	    }
180 
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 
189 static int
190 set_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 
207 /* Print one instruction from PC on INFO->STREAM.
208    Return the size of the instruction (always 4 on ARM). */
209 
210 static int
211 print_insn_arm (pc, info, given)
212      bfd_vma pc;
213      struct disassemble_info *info;
214      long given;
215 {
216   const struct arm_opcode *insn;
217   void *stream = info->stream;
218   fprintf_ftype func   = info->fprintf_func;
219   static int iwmmxt_regnames = 0;
220 
221   for (insn = arm_opcodes; insn->assembler; insn++)
222     {
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 
228       if ((given & insn->mask) == insn->value)
229 	{
230 	  char * c;
231 
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;
247 
248 			  func (stream, "[pc");
249 
250 			  if (given & 0x01000000)
251 			    {
252 			      if ((given & 0x00800000) == 0)
253 				offset = - offset;
254 
255 			      /* Pre-indexed.  */
256 			      func (stream, ", #%d]", offset);
257 
258 			      offset += pc + 8;
259 
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 ?  */
264 			      if (given & 0x00200000)
265 				func (stream, "!");
266 			    }
267 			  else
268 			    {
269 			      /* Post indexed.  */
270 			      func (stream, "], #%d", offset);
271 
272 			      /* ie ignore the offset.  */
273 			      offset = pc + 8;
274 			    }
275 
276 			  func (stream, "\t; ");
277 			  info->print_address_func (offset, info);
278 			}
279 		      else
280 			{
281 			  func (stream, "[%s",
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 
301 			      func (stream, "]%s",
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);
313 				  else
314 				    func (stream, "]");
315 				}
316 			      else
317 				{
318 				  func (stream, "], %s",
319 					(((given & 0x00800000) == 0)
320 					 ? "-" : ""));
321 				  arm_decode_shift (given, func, stream);
322 				}
323 			    }
324 			}
325 		      break;
326 
327 		    case 's':
328                       if ((given & 0x004f0000) == 0x004f0000)
329 			{
330                           /* PC relative with immediate offset.  */
331 			  int offset = ((given & 0xf00) >> 4) | (given & 0xf);
332 
333 			  if ((given & 0x00800000) == 0)
334 			    offset = -offset;
335 
336 			  func (stream, "[pc, #%d]\t; ", offset);
337 
338 			  (*info->print_address_func)
339 			    (offset + pc + 8, info);
340 			}
341 		      else
342 			{
343 			  func (stream, "[%s",
344 				arm_regnames[(given >> 16) & 0xf]);
345 			  if ((given & 0x01000000) != 0)
346 			    {
347                               /* Pre-indexed.  */
348 			      if ((given & 0x00400000) == 0x00400000)
349 				{
350                                   /* Immediate.  */
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 				{
359                                   /* Register.  */
360 				  func (stream, ", %s%s",
361 					(((given & 0x00800000) == 0)
362 					 ? "-" : ""),
363                                         arm_regnames[given & 0xf]);
364 				}
365 
366 			      func (stream, "]%s",
367 				    ((given & 0x00200000) != 0) ? "!" : "");
368 			    }
369 			  else
370 			    {
371                               /* Post-indexed.  */
372 			      if ((given & 0x00400000) == 0x00400000)
373 				{
374                                   /* Immediate.  */
375                                   int offset = ((given & 0xf00) >> 4) | (given & 0xf);
376 				  if (offset)
377 				    func (stream, "], #%s%d",
378 					  (((given & 0x00800000) == 0)
379 					   ? "-" : ""), offset);
380 				  else
381 				    func (stream, "]");
382 				}
383 			      else
384 				{
385                                   /* Register.  */
386 				  func (stream, "], %s%s",
387 					(((given & 0x00800000) == 0)
388 					 ? "-" : ""),
389                                         arm_regnames[given & 0xf]);
390 				}
391 			    }
392 			}
393 		      break;
394 
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);
428 			  immed = (((immed << (32 - rotate))
429 				    | (immed >> rotate)) & 0xffffffff);
430 			  func (stream, "#%d\t; 0x%x", immed, immed);
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 
446 		    case 'A':
447 		      func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
448 
449 		      if ((given & (1 << 24)) != 0)
450 			{
451 			  int offset = given & 0xff;
452 
453 			  if (offset)
454 			    func (stream, ", #%s%d]%s",
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;
464 
465 			  func (stream, "]");
466 
467 			  if (given & (1 << 21))
468 			    {
469 			      if (offset)
470 				func (stream, ", #%s%d",
471 				      ((given & 0x00800000) == 0 ? "-" : ""),
472 				      offset * 4);
473 			    }
474 			  else
475 			    func (stream, ", {%d}", offset);
476 			}
477 		      break;
478 
479 		    case 'B':
480 		      /* Print ARM V5 BLX(1) address: pc+25 bits.  */
481 		      {
482 			bfd_vma address;
483 			bfd_vma offset = 0;
484 
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;
493 
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 
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 
521 		    case 'C':
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");
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;
549 
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 
601 		    case '0': case '1': case '2': case '3': case '4':
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++;
613 
614 			    while (*c >= '0' && *c <= '9')
615 			      bitend = (bitend * 10) + *c++ - '0';
616 
617 			    if (!bitend)
618 			      abort ();
619 
620 			    switch (*c)
621 			      {
622 			      case 'r':
623 				{
624 				  long reg;
625 
626 				  reg = given >> bitstart;
627 				  reg &= (2 << (bitend - bitstart)) - 1;
628 
629 				  func (stream, "%s", arm_regnames[reg]);
630 				}
631 				break;
632 			      case 'd':
633 				{
634 				  long reg;
635 
636 				  reg = given >> bitstart;
637 				  reg &= (2 << (bitend - bitstart)) - 1;
638 
639 				  func (stream, "%d", reg);
640 				}
641 				break;
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;
652 			      case 'x':
653 				{
654 				  long reg;
655 
656 				  reg = given >> bitstart;
657 				  reg &= (2 << (bitend - bitstart)) - 1;
658 
659 				  func (stream, "0x%08x", reg);
660 
661 				  /* Some SWI instructions have special
662 				     meanings.  */
663 				  if ((given & 0x0fffffff) == 0x0FF00000)
664 				    func (stream, "\t; IMB");
665 				  else if ((given & 0x0fffffff) == 0x0FF00001)
666 				    func (stream, "\t; IMBRange");
667 				}
668 				break;
669 			      case 'X':
670 				{
671 				  long reg;
672 
673 				  reg = given >> bitstart;
674 				  reg &= (2 << (bitend - bitstart)) - 1;
675 
676 				  func (stream, "%01x", reg & 0xf);
677 				}
678 				break;
679 			      case 'f':
680 				{
681 				  long reg;
682 
683 				  reg = given >> bitstart;
684 				  reg &= (2 << (bitend - bitstart)) - 1;
685 
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;
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 
750 			      default:
751 				abort ();
752 			      }
753 			    break;
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 
803 
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 
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 
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)
889 				func (stream, ", #%s%d]%s",
890 				      ((given & 0x00800000) == 0 ? "-" : ""),
891 				      offset * multiplier,
892 				      ((given & 0x00200000) != 0 ? "!" : ""));
893 			      else
894 				func (stream, "], #%s%d",
895 				      ((given & 0x00800000) == 0 ? "-" : ""),
896 				      offset * multiplier);
897 			    }
898 			  else
899 			    func (stream, "]");
900 			}
901 			break;
902 
903 		      default:
904 			abort ();
905 		      }
906 		    }
907 		}
908 	      else
909 		func (stream, "%c", *c);
910 	    }
911 	  return 4;
912 	}
913     }
914   abort ();
915 }
916 
917 /* Print one instruction from PC on INFO->STREAM.
918    Return the size of the instruction. */
919 
920 static int
921 print_insn_thumb (pc, info, given)
922      bfd_vma pc;
923      struct disassemble_info *info;
924      long given;
925 {
926   const struct thumb_opcode *insn;
927   void *stream = info->stream;
928   fprintf_ftype func = info->fprintf_func;
929 
930   for (insn = thumb_opcodes; insn->assembler; insn++)
931     {
932       if ((given & insn->mask) == insn->value)
933         {
934           char * c = insn->assembler;
935 
936           /* Special processing for Thumb 2 instruction BL sequence:  */
937           if (!*c) /* Check for empty (not NULL) assembler string.  */
938             {
939 	      long offset;
940 
941 	      info->bytes_per_chunk = 4;
942 	      info->bytes_per_line  = 4;
943 
944 	      offset = BDISP23 (given);
945 	      offset = offset * 2 + pc + 4;
946 
947 	      if ((given & 0x10000000) == 0)
948 		{
949 		  func (stream, "blx\t");
950 		  offset &= 0xfffffffc;
951 		}
952 	      else
953 		func (stream, "bl\t");
954 
955 	      info->print_address_func (offset, info);
956               return 4;
957             }
958           else
959             {
960 	      info->bytes_per_chunk = 2;
961 	      info->bytes_per_line  = 4;
962 
963               given &= 0xffff;
964 
965               for (; *c; c++)
966                 {
967                   if (*c == '%')
968                     {
969                       int domaskpc = 0;
970                       int domasklr = 0;
971 
972                       switch (*++c)
973                         {
974                         case '%':
975                           func (stream, "%%");
976                           break;
977 
978                         case 'S':
979                           {
980                             long reg;
981 
982                             reg = (given >> 3) & 0x7;
983                             if (given & (1 << 6))
984                               reg += 8;
985 
986                             func (stream, "%s", arm_regnames[reg]);
987                           }
988                           break;
989 
990                         case 'D':
991                           {
992                             long reg;
993 
994                             reg = given & 0x7;
995                             if (given & (1 << 7))
996                              reg += 8;
997 
998                             func (stream, "%s", arm_regnames[reg]);
999                           }
1000                           break;
1001 
1002                         case 'T':
1003                           func (stream, "%s",
1004                                 arm_conditional [(given >> 8) & 0xf]);
1005                           break;
1006 
1007                         case 'N':
1008                           if (given & (1 << 8))
1009                             domasklr = 1;
1010                           /* Fall through.  */
1011                         case 'O':
1012                           if (*c == 'O' && (given & (1 << 8)))
1013                             domaskpc = 1;
1014                           /* Fall through.  */
1015                         case 'M':
1016                           {
1017                             int started = 0;
1018                             int reg;
1019 
1020                             func (stream, "{");
1021 
1022                             /* It would be nice if we could spot
1023                                ranges, and generate the rS-rE format: */
1024                             for (reg = 0; (reg < 8); reg++)
1025                               if ((given & (1 << reg)) != 0)
1026                                 {
1027                                   if (started)
1028                                     func (stream, ", ");
1029                                   started = 1;
1030                                   func (stream, "%s", arm_regnames[reg]);
1031                                 }
1032 
1033                             if (domasklr)
1034                               {
1035                                 if (started)
1036                                   func (stream, ", ");
1037                                 started = 1;
1038                                 func (stream, arm_regnames[14] /* "lr" */);
1039                               }
1040 
1041                             if (domaskpc)
1042                               {
1043                                 if (started)
1044                                   func (stream, ", ");
1045                                 func (stream, arm_regnames[15] /* "pc" */);
1046                               }
1047 
1048                             func (stream, "}");
1049                           }
1050                           break;
1051 
1052 
1053                         case '0': case '1': case '2': case '3': case '4':
1054                         case '5': case '6': case '7': case '8': case '9':
1055                           {
1056                             int bitstart = *c++ - '0';
1057                             int bitend = 0;
1058 
1059                             while (*c >= '0' && *c <= '9')
1060                               bitstart = (bitstart * 10) + *c++ - '0';
1061 
1062                             switch (*c)
1063                               {
1064                               case '-':
1065                                 {
1066                                   long reg;
1067 
1068                                   c++;
1069                                   while (*c >= '0' && *c <= '9')
1070                                     bitend = (bitend * 10) + *c++ - '0';
1071                                   if (!bitend)
1072                                     abort ();
1073                                   reg = given >> bitstart;
1074                                   reg &= (2 << (bitend - bitstart)) - 1;
1075                                   switch (*c)
1076                                     {
1077                                     case 'r':
1078                                       func (stream, "%s", arm_regnames[reg]);
1079                                       break;
1080 
1081                                     case 'd':
1082                                       func (stream, "%d", reg);
1083                                       break;
1084 
1085                                     case 'H':
1086                                       func (stream, "%d", reg << 1);
1087                                       break;
1088 
1089                                     case 'W':
1090                                       func (stream, "%d", reg << 2);
1091                                       break;
1092 
1093                                     case 'a':
1094 				      /* PC-relative address -- the bottom two
1095 					 bits of the address are dropped
1096 					 before the calculation.  */
1097                                       info->print_address_func
1098 					(((pc + 4) & ~3) + (reg << 2), info);
1099                                       break;
1100 
1101                                     case 'x':
1102                                       func (stream, "0x%04x", reg);
1103                                       break;
1104 
1105                                     case 'I':
1106                                       reg = ((reg ^ (1 << bitend)) - (1 << bitend));
1107                                       func (stream, "%d", reg);
1108                                       break;
1109 
1110                                     case 'B':
1111                                       reg = ((reg ^ (1 << bitend)) - (1 << bitend));
1112                                       (*info->print_address_func)
1113                                         (reg * 2 + pc + 4, info);
1114                                       break;
1115 
1116                                     default:
1117                                       abort ();
1118                                     }
1119                                 }
1120                                 break;
1121 
1122                               case '\'':
1123                                 c++;
1124                                 if ((given & (1 << bitstart)) != 0)
1125                                   func (stream, "%c", *c);
1126                                 break;
1127 
1128                               case '?':
1129                                 ++c;
1130                                 if ((given & (1 << bitstart)) != 0)
1131                                   func (stream, "%c", *c++);
1132                                 else
1133                                   func (stream, "%c", *++c);
1134                                 break;
1135 
1136                               default:
1137                                  abort ();
1138                               }
1139                           }
1140                           break;
1141 
1142                         default:
1143                           abort ();
1144                         }
1145                     }
1146                   else
1147                     func (stream, "%c", *c);
1148                 }
1149              }
1150           return 2;
1151        }
1152     }
1153 
1154   /* No match.  */
1155   abort ();
1156 }
1157 
1158 /* Disallow mapping symbols ($a, $b, $d, $t etc) from
1159    being displayed in symbol relative addresses.  */
1160 
1161 bfd_boolean
1162 arm_symbol_is_valid (asymbol * sym,
1163 		     struct disassemble_info * info ATTRIBUTE_UNUSED)
1164 {
1165   const char * name;
1166 
1167   if (sym == NULL)
1168     return FALSE;
1169 
1170   name = bfd_asymbol_name (sym);
1171 
1172   return (name && *name != '$');
1173 }
1174 
1175 /* Parse an individual disassembler option.  */
1176 
1177 void
1178 parse_arm_disassembler_option (option)
1179      char * option;
1180 {
1181   if (option == NULL)
1182     return;
1183 
1184   if (strneq (option, "reg-names-", 10))
1185     {
1186       int i;
1187 
1188       option += 10;
1189 
1190       for (i = NUM_ARM_REGNAMES; i--;)
1191 	if (strneq (option, regnames[i].name, strlen (regnames[i].name)))
1192 	  {
1193 	    regname_selected = i;
1194 	    break;
1195 	  }
1196 
1197       if (i < 0)
1198 	/* XXX - should break 'option' at following delimiter.  */
1199 	fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
1200     }
1201   else if (strneq (option, "force-thumb", 11))
1202     force_thumb = 1;
1203   else if (strneq (option, "no-force-thumb", 14))
1204     force_thumb = 0;
1205   else
1206     /* XXX - should break 'option' at following delimiter.  */
1207     fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
1208 
1209   return;
1210 }
1211 
1212 /* Parse the string of disassembler options, spliting it at whitespaces
1213    or commas.  (Whitespace separators supported for backwards compatibility).  */
1214 
1215 static void
1216 parse_disassembler_options (options)
1217      char * options;
1218 {
1219   if (options == NULL)
1220     return;
1221 
1222   while (*options)
1223     {
1224       parse_arm_disassembler_option (options);
1225 
1226       /* Skip forward to next seperator.  */
1227       while ((*options) && (! ISSPACE (*options)) && (*options != ','))
1228 	++ options;
1229       /* Skip forward past seperators.  */
1230       while (ISSPACE (*options) || (*options == ','))
1231 	++ options;
1232     }
1233 }
1234 
1235 /* NOTE: There are no checks in these routines that
1236    the relevant number of data bytes exist.  */
1237 
1238 static int
1239 print_insn (pc, info, little)
1240      bfd_vma pc;
1241      struct disassemble_info * info;
1242      bfd_boolean little;
1243 {
1244   unsigned char      b[4];
1245   long               given;
1246   int                status;
1247   int                is_thumb;
1248 
1249   if (info->disassembler_options)
1250     {
1251       parse_disassembler_options (info->disassembler_options);
1252 
1253       /* To avoid repeated parsing of these options, we remove them here.  */
1254       info->disassembler_options = NULL;
1255     }
1256 
1257   is_thumb = force_thumb;
1258 
1259   if (!is_thumb && info->symbols != NULL)
1260     {
1261       if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
1262 	{
1263 	  coff_symbol_type * cs;
1264 
1265 	  cs = coffsymbol (*info->symbols);
1266 	  is_thumb = (   cs->native->u.syment.n_sclass == C_THUMBEXT
1267 		      || cs->native->u.syment.n_sclass == C_THUMBSTAT
1268 		      || cs->native->u.syment.n_sclass == C_THUMBLABEL
1269 		      || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
1270 		      || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
1271 	}
1272       else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
1273 	{
1274 	  elf_symbol_type *  es;
1275 	  unsigned int       type;
1276 
1277 	  es = *(elf_symbol_type **)(info->symbols);
1278 	  type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
1279 
1280 	  is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
1281 	}
1282     }
1283 
1284   info->bytes_per_chunk = 4;
1285   info->display_endian  = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
1286 
1287   if (little)
1288     {
1289       status = info->read_memory_func (pc, (bfd_byte *) &b[0], 4, info);
1290       if (status != 0 && is_thumb)
1291 	{
1292 	  info->bytes_per_chunk = 2;
1293 
1294 	  status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
1295 	  b[3] = b[2] = 0;
1296 	}
1297 
1298       if (status != 0)
1299 	{
1300 	  info->memory_error_func (status, pc, info);
1301 	  return -1;
1302 	}
1303 
1304       given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
1305     }
1306   else
1307     {
1308       status = info->read_memory_func
1309 	(pc & ~ 0x3, (bfd_byte *) &b[0], 4, info);
1310       if (status != 0)
1311 	{
1312 	  info->memory_error_func (status, pc, info);
1313 	  return -1;
1314 	}
1315 
1316       if (is_thumb)
1317 	{
1318 	  if (pc & 0x2)
1319 	    {
1320 	      given = (b[2] << 8) | b[3];
1321 
1322 	      status = info->read_memory_func
1323 		((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
1324 	      if (status != 0)
1325 		{
1326 		  info->memory_error_func (status, pc + 4, info);
1327 		  return -1;
1328 		}
1329 
1330 	      given |= (b[0] << 24) | (b[1] << 16);
1331 	    }
1332 	  else
1333 	    given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16);
1334 	}
1335       else
1336 	given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
1337     }
1338 
1339   if (info->flags & INSN_HAS_RELOC)
1340     /* If the instruction has a reloc associated with it, then
1341        the offset field in the instruction will actually be the
1342        addend for the reloc.  (We are using REL type relocs).
1343        In such cases, we can ignore the pc when computing
1344        addresses, since the addend is not currently pc-relative.  */
1345     pc = 0;
1346 
1347   if (is_thumb)
1348     status = print_insn_thumb (pc, info, given);
1349   else
1350     status = print_insn_arm (pc, info, given);
1351 
1352   return status;
1353 }
1354 
1355 int
1356 print_insn_big_arm (pc, info)
1357      bfd_vma pc;
1358      struct disassemble_info * info;
1359 {
1360   return print_insn (pc, info, FALSE);
1361 }
1362 
1363 int
1364 print_insn_little_arm (pc, info)
1365      bfd_vma pc;
1366      struct disassemble_info * info;
1367 {
1368   return print_insn (pc, info, TRUE);
1369 }
1370 
1371 void
1372 print_arm_disassembler_options (FILE * stream)
1373 {
1374   int i;
1375 
1376   fprintf (stream, _("\n\
1377 The following ARM specific disassembler options are supported for use with\n\
1378 the -M switch:\n"));
1379 
1380   for (i = NUM_ARM_REGNAMES; i--;)
1381     fprintf (stream, "  reg-names-%s %*c%s\n",
1382 	     regnames[i].name,
1383 	     (int)(14 - strlen (regnames[i].name)), ' ',
1384 	     regnames[i].description);
1385 
1386   fprintf (stream, "  force-thumb              Assume all insns are Thumb insns\n");
1387   fprintf (stream, "  no-force-thumb           Examine preceeding label to determine an insn's type\n\n");
1388 }
1389