Revision 5fafdf24 arm-dis.c

b/arm-dis.c
4 4
   Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 5
   Modification by James G. Smith (jsmith@cygnus.co.uk)
6 6

  
7
This file is part of libopcodes. 
7
This file is part of libopcodes.
8 8

  
9 9
This program is free software; you can redistribute it and/or modify it under
10 10
the terms of the GNU General Public License as published by the Free
11 11
Software Foundation; either version 2 of the License, or (at your option)
12
any later version. 
12
any later version.
13 13

  
14 14
This program is distributed in the hope that it will be useful, but WITHOUT
15 15
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 16
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
17
more details. 
17
more details.
18 18

  
19 19
You should have received a copy of the GNU General Public License
20 20
along with this program; if not, write to the Free Software
......
34 34
};
35 35

  
36 36
/* format of the assembler string :
37
   
37
  
38 38
   %%			%
39 39
   %<bitfield>d		print the bitfield in decimal
40 40
   %<bitfield>x		print the bitfield in hex
......
104 104
    {0x0c400000, 0x0ff00fff, "mar%c\tacc0, %12-15r, %16-19r"},
105 105
    {0x0c500000, 0x0ff00fff, "mra%c\t%12-15r, %16-19r, acc0"},
106 106
    {0xf450f000, 0xfc70f000, "pld\t%a"},
107
    
107
   
108 108
    /* V5 Instructions.  */
109 109
    {0xe1200070, 0xfff000f0, "bkpt\t0x%16-19X%12-15X%8-11X%0-3X"},
110 110
    {0xfa000000, 0xfe000000, "blx\t%B"},
......
116 116
    {0xfe000010, 0xff100010, "mcr2\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
117 117
    {0xfe100010, 0xff100010, "mrc2\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
118 118

  
119
    /* V5E "El Segundo" Instructions.  */    
119
    /* V5E "El Segundo" Instructions.  */   
120 120
    {0x000000d0, 0x0e1000f0, "ldr%cd\t%12-15r, %s"},
121 121
    {0x000000f0, 0x0e1000f0, "str%cd\t%12-15r, %s"},
122 122
    {0x01000080, 0x0ff000f0, "smlabb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
......
303 303
    {0x0d100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"},
304 304
    {0x0c100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"},
305 305
    {0x0d500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"},
306
    {0x0c500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"}, 
306
    {0x0c500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"},
307 307
    {0x0d100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"},
308 308
    {0x0c100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"},
309 309
    {0x0d500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"},
......
571 571
static char * arm_fp_const[] =
572 572
{"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
573 573

  
574
static char * arm_shift[] = 
574
static char * arm_shift[] =
575 575
{"lsl", "lsr", "asr", "ror"};
576 576

577 577
/* Forward declarations.  */
......
621 621
     void * stream;
622 622
{
623 623
  func (stream, "%s", arm_regnames[given & 0xf]);
624
  
624
 
625 625
  if ((given & 0xff0) != 0)
626 626
    {
627 627
      if ((given & 0x10) == 0)
628 628
	{
629 629
	  int amount = (given & 0xf80) >> 7;
630 630
	  int shift = (given & 0x60) >> 5;
631
	  
631
	 
632 632
	  if (amount == 0)
633 633
	    {
634 634
	      if (shift == 3)
......
636 636
		  func (stream, ", rrx");
637 637
		  return;
638 638
		}
639
	      
639
	     
640 640
	      amount = 32;
641 641
	    }
642
	  
642
	 
643 643
	  func (stream, ", %s #%d", arm_shift[shift], amount);
644 644
	}
645 645
      else
......
666 666
      if ((given & insn->mask) == insn->value)
667 667
	{
668 668
	  char * c;
669
	  
669
	 
670 670
	  for (c = insn->assembler; *c; c++)
671 671
	    {
672 672
	      if (*c == '%')
......
682 682
			  && ((given & 0x02000000) == 0))
683 683
			{
684 684
			  int offset = given & 0xfff;
685
			  
685
			 
686 686
			  func (stream, "[pc");
687
 
687

  
688 688
			  if (given & 0x01000000)
689 689
			    {
690 690
			      if ((given & 0x00800000) == 0)
691 691
				offset = - offset;
692
			  
692
			 
693 693
			      /* Pre-indexed.  */
694 694
			      func (stream, ", #%d]", offset);
695 695

  
......
710 710
			      /* ie ignore the offset.  */
711 711
			      offset = pc + 8;
712 712
			    }
713
			  
713
			 
714 714
			  func (stream, "\t; ");
715 715
			  info->print_address_func (offset, info);
716 716
			}
717 717
		      else
718 718
			{
719
			  func (stream, "[%s", 
719
			  func (stream, "[%s",
720 720
				arm_regnames[(given >> 16) & 0xf]);
721 721
			  if ((given & 0x01000000) != 0)
722 722
			    {
......
736 736
				  arm_decode_shift (given, func, stream);
737 737
				}
738 738

  
739
			      func (stream, "]%s", 
739
			      func (stream, "]%s",
740 740
				    ((given & 0x00200000) != 0) ? "!" : "");
741 741
			    }
742 742
			  else
......
748 748
				    func (stream, "], %s#%d",
749 749
					  (((given & 0x00800000) == 0)
750 750
					   ? "-" : ""), offset);
751
				  else 
751
				  else
752 752
				    func (stream, "]");
753 753
				}
754 754
			      else
755 755
				{
756 756
				  func (stream, "], %s",
757
					(((given & 0x00800000) == 0) 
757
					(((given & 0x00800000) == 0)
758 758
					 ? "-" : ""));
759 759
				  arm_decode_shift (given, func, stream);
760 760
				}
......
767 767
			{
768 768
                          /* PC relative with immediate offset.  */
769 769
			  int offset = ((given & 0xf00) >> 4) | (given & 0xf);
770
			  
770
			 
771 771
			  if ((given & 0x00800000) == 0)
772 772
			    offset = -offset;
773
			  
773
			 
774 774
			  func (stream, "[pc, #%d]\t; ", offset);
775
			  
775
			 
776 776
			  (*info->print_address_func)
777 777
			    (offset + pc + 8, info);
778 778
			}
779 779
		      else
780 780
			{
781
			  func (stream, "[%s", 
781
			  func (stream, "[%s",
782 782
				arm_regnames[(given >> 16) & 0xf]);
783 783
			  if ((given & 0x01000000) != 0)
784 784
			    {
......
801 801
                                        arm_regnames[given & 0xf]);
802 802
				}
803 803

  
804
			      func (stream, "]%s", 
804
			      func (stream, "]%s",
805 805
				    ((given & 0x00200000) != 0) ? "!" : "");
806 806
			    }
807 807
			  else
......
815 815
				    func (stream, "], %s#%d",
816 816
					  (((given & 0x00800000) == 0)
817 817
					   ? "-" : ""), offset);
818
				  else 
818
				  else
819 819
				    func (stream, "]");
820 820
				}
821 821
			      else
......
829 829
			    }
830 830
			}
831 831
		      break;
832
			  
832
			 
833 833
		    case 'b':
834 834
		      (*info->print_address_func)
835 835
			(BDISP (given) * 4 + pc + 8, info);
......
911 911
		      {
912 912
			bfd_vma address;
913 913
			bfd_vma offset = 0;
914
			
914
		
915 915
			if (given & 0x00800000)
916 916
			  /* Is signed, hi bits should be ones.  */
917 917
			  offset = (-1) ^ 0x00ffffff;
......
920 920
			offset += given & 0x00ffffff;
921 921
			offset <<= 2;
922 922
			address = offset + pc + 8;
923
			
923
		
924 924
			if (given & 0x01000000)
925 925
			  /* H bit allows addressing to 2-byte boundaries.  */
926 926
			  address += 2;
......
976 976
			  func (stream, "3");
977 977
			}
978 978
		      break;
979
			
979
		
980 980
		    case 'P':
981 981
		      switch (given & 0x00080080)
982 982
			{
......
1028 1028
			}
1029 1029
		      break;
1030 1030

  
1031
		    case '0': case '1': case '2': case '3': case '4': 
1031
		    case '0': case '1': case '2': case '3': case '4':
1032 1032
		    case '5': case '6': case '7': case '8': case '9':
1033 1033
		      {
1034 1034
			int bitstart = *c++ - '0';
......
1040 1040
			  {
1041 1041
			  case '-':
1042 1042
			    c++;
1043
			    
1043
			   
1044 1044
			    while (*c >= '0' && *c <= '9')
1045 1045
			      bitend = (bitend * 10) + *c++ - '0';
1046
			    
1046
			   
1047 1047
			    if (!bitend)
1048 1048
			      abort ();
1049
			    
1049
			   
1050 1050
			    switch (*c)
1051 1051
			      {
1052 1052
			      case 'r':
1053 1053
				{
1054 1054
				  long reg;
1055
				  
1055
				 
1056 1056
				  reg = given >> bitstart;
1057 1057
				  reg &= (2 << (bitend - bitstart)) - 1;
1058
				  
1058
				 
1059 1059
				  func (stream, "%s", arm_regnames[reg]);
1060 1060
				}
1061 1061
				break;
1062 1062
			      case 'd':
1063 1063
				{
1064 1064
				  long reg;
1065
				  
1065
				 
1066 1066
				  reg = given >> bitstart;
1067 1067
				  reg &= (2 << (bitend - bitstart)) - 1;
1068
				  
1068
				 
1069 1069
				  func (stream, "%d", reg);
1070 1070
				}
1071 1071
				break;
1072 1072
			      case 'x':
1073 1073
				{
1074 1074
				  long reg;
1075
				  
1075
				 
1076 1076
				  reg = given >> bitstart;
1077 1077
				  reg &= (2 << (bitend - bitstart)) - 1;
1078
				  
1078
				 
1079 1079
				  func (stream, "0x%08x", reg);
1080
				  
1080
				 
1081 1081
				  /* Some SWI instructions have special
1082 1082
				     meanings.  */
1083 1083
				  if ((given & 0x0fffffff) == 0x0FF00000)
......
1089 1089
			      case 'X':
1090 1090
				{
1091 1091
				  long reg;
1092
				  
1092
				 
1093 1093
				  reg = given >> bitstart;
1094 1094
				  reg &= (2 << (bitend - bitstart)) - 1;
1095
				  
1095
				 
1096 1096
				  func (stream, "%01x", reg & 0xf);
1097 1097
				}
1098 1098
				break;
1099 1099
			      case 'f':
1100 1100
				{
1101 1101
				  long reg;
1102
				  
1102
				 
1103 1103
				  reg = given >> bitstart;
1104 1104
				  reg &= (2 << (bitend - bitstart)) - 1;
1105
				  
1105
				 
1106 1106
				  if (reg > 7)
1107 1107
				    func (stream, "#%s",
1108 1108
					  arm_fp_const[reg & 7]);
......
1163 1163
				    }
1164 1164
				  break;
1165 1165

  
1166
				  
1166
				 
1167 1167
				default:
1168 1168
				  abort ();
1169 1169
				}
......
1252 1252
          if (!*c) /* Check for empty (not NULL) assembler string.  */
1253 1253
            {
1254 1254
	      long offset;
1255
	      
1255
	     
1256 1256
	      info->bytes_per_chunk = 4;
1257 1257
	      info->bytes_per_line  = 4;
1258 1258

  
......
1274 1274
            {
1275 1275
	      info->bytes_per_chunk = 2;
1276 1276
	      info->bytes_per_line  = 4;
1277
	  	      
1277
	  	     
1278 1278
              given &= 0xffff;
1279
	      
1279
	     
1280 1280
              for (; *c; c++)
1281 1281
                {
1282 1282
                  if (*c == '%')
1283 1283
                    {
1284 1284
                      int domaskpc = 0;
1285 1285
                      int domasklr = 0;
1286
		      
1286
		     
1287 1287
                      switch (*++c)
1288 1288
                        {
1289 1289
                        case '%':
......
1293 1293
                        case 'S':
1294 1294
                          {
1295 1295
                            long reg;
1296
			    
1296
			   
1297 1297
                            reg = (given >> 3) & 0x7;
1298 1298
                            if (given & (1 << 6))
1299 1299
                              reg += 8;
1300
			    
1300
			   
1301 1301
                            func (stream, "%s", arm_regnames[reg]);
1302 1302
                          }
1303 1303
                          break;
......
1305 1305
                        case 'D':
1306 1306
                          {
1307 1307
                            long reg;
1308
			    
1308
			   
1309 1309
                            reg = given & 0x7;
1310 1310
                            if (given & (1 << 7))
1311 1311
                             reg += 8;
1312
			    
1312
			   
1313 1313
                            func (stream, "%s", arm_regnames[reg]);
1314 1314
                          }
1315 1315
                          break;
......
1331 1331
                          {
1332 1332
                            int started = 0;
1333 1333
                            int reg;
1334
			    
1334
			   
1335 1335
                            func (stream, "{");
1336
			    
1336
			   
1337 1337
                            /* It would be nice if we could spot
1338 1338
                               ranges, and generate the rS-rE format: */
1339 1339
                            for (reg = 0; (reg < 8); reg++)
......
1365 1365
                          break;
1366 1366

  
1367 1367

  
1368
                        case '0': case '1': case '2': case '3': case '4': 
1368
                        case '0': case '1': case '2': case '3': case '4':
1369 1369
                        case '5': case '6': case '7': case '8': case '9':
1370 1370
                          {
1371 1371
                            int bitstart = *c++ - '0';
1372 1372
                            int bitend = 0;
1373
			    
1373
			   
1374 1374
                            while (*c >= '0' && *c <= '9')
1375 1375
                              bitstart = (bitstart * 10) + *c++ - '0';
1376 1376

  
......
1379 1379
                              case '-':
1380 1380
                                {
1381 1381
                                  long reg;
1382
				  
1382
				 
1383 1383
                                  c++;
1384 1384
                                  while (*c >= '0' && *c <= '9')
1385 1385
                                    bitend = (bitend * 10) + *c++ - '0';
......
1478 1478
{
1479 1479
  if (option == NULL)
1480 1480
    return;
1481
      
1481
     
1482 1482
  if (strneq (option, "reg-names-", 10))
1483 1483
    {
1484 1484
      int i;
1485
	
1485

  
1486 1486
      option += 10;
1487 1487

  
1488 1488
      for (i = NUM_ARM_REGNAMES; i--;)
......
1491 1491
	    regname_selected = i;
1492 1492
	    break;
1493 1493
	  }
1494
      
1494
     
1495 1495
      if (i < 0)
1496 1496
	fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
1497 1497
    }
......
1501 1501
    force_thumb = 0;
1502 1502
  else
1503 1503
    fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
1504
  
1504
 
1505 1505
  return;
1506 1506
}
1507 1507

  
......
1512 1512
     char * options;
1513 1513
{
1514 1514
  char * space;
1515
  
1515
 
1516 1516
  if (options == NULL)
1517 1517
    return;
1518 1518

  
......
1550 1550
  if (info->disassembler_options)
1551 1551
    {
1552 1552
      parse_disassembler_options (info->disassembler_options);
1553
      
1553
     
1554 1554
      /* To avoid repeated parsing of these options, we remove them here.  */
1555 1555
      info->disassembler_options = NULL;
1556 1556
    }
1557
  
1557
 
1558 1558
  is_thumb = force_thumb;
1559 1559
  if (pc & 1)
1560 1560
    {
1561 1561
      is_thumb = 1;
1562 1562
      pc &= ~(bfd_vma) 1;
1563 1563
    }
1564
  
1564
 
1565 1565
#if 0
1566 1566
  if (!is_thumb && info->symbols != NULL)
1567 1567
    {
1568 1568
      if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
1569 1569
	{
1570 1570
	  coff_symbol_type * cs;
1571
	  
1571
	 
1572 1572
	  cs = coffsymbol (*info->symbols);
1573 1573
	  is_thumb = (   cs->native->u.syment.n_sclass == C_THUMBEXT
1574 1574
		      || cs->native->u.syment.n_sclass == C_THUMBSTAT
......
1580 1580
	{
1581 1581
	  elf_symbol_type *  es;
1582 1582
	  unsigned int       type;
1583
	  
1583
	 
1584 1584
	  es = *(elf_symbol_type **)(info->symbols);
1585 1585
	  type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
1586
	  
1586
	 
1587 1587
	  is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
1588 1588
	}
1589 1589
    }
1590 1590
#endif
1591
  
1591
 
1592 1592
  little = (info->endian == BFD_ENDIAN_LITTLE);
1593 1593
  info->bytes_per_chunk = 4;
1594 1594
  info->display_endian  = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
......
1599 1599
      if (status != 0 && is_thumb)
1600 1600
	{
1601 1601
	  info->bytes_per_chunk = 2;
1602
	  
1602
	 
1603 1603
	  status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
1604 1604
	  b[3] = b[2] = 0;
1605 1605
	}
1606
      
1606
     
1607 1607
      if (status != 0)
1608 1608
	{
1609 1609
	  info->memory_error_func (status, pc, info);
1610 1610
	  return -1;
1611 1611
	}
1612
      
1612
     
1613 1613
      given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
1614 1614
    }
1615 1615
  else
......
1621 1621
	  info->memory_error_func (status, pc, info);
1622 1622
	  return -1;
1623 1623
	}
1624
      
1624
     
1625 1625
      if (is_thumb)
1626 1626
	{
1627 1627
	  if (pc & 0x2)
1628 1628
	    {
1629 1629
	      given = (b[2] << 8) | b[3];
1630
	      
1630
	     
1631 1631
	      status = info->read_memory_func
1632 1632
		((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
1633 1633
	      if (status != 0)
......
1635 1635
		  info->memory_error_func (status, pc + 4, info);
1636 1636
		  return -1;
1637 1637
		}
1638
	      
1638
	     
1639 1639
	      given |= (b[0] << 24) | (b[1] << 16);
1640 1640
	    }
1641 1641
	  else
......
1644 1644
      else
1645 1645
	given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
1646 1646
    }
1647
  
1647
 
1648 1648
  if (info->flags & INSN_HAS_RELOC)
1649 1649
    /* If the instruction has a reloc associated with it, then
1650 1650
       the offset field in the instruction will actually be the
......
1668 1668
  fprintf (stream, _("\n\
1669 1669
The following ARM specific disassembler options are supported for use with\n\
1670 1670
the -M switch:\n"));
1671
  
1671
 
1672 1672
  for (i = NUM_ARM_REGNAMES; i--;)
1673 1673
    fprintf (stream, "  reg-names-%s %*c%s\n",
1674 1674
	     regnames[i].name,

Also available in: Unified diff