This is the mail archive of the binutils@sourceware.cygnus.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Arm disassembler tidy ups


Hi Guys,

  This is just to let you know that I have checked in the following
  patch.   It tidies up the ARM disassembler by:

   * Add a function to document the ARM specific disassembler
     options.

   * Removing the duplicate code in print_insn_little_arm and
     print_insn_big_arm.

   * Add support for the register names used in the new combined
     ARM/Thumb ABI (the ATPCS).

Cheers
	Nick

2000-01-27  Nick Clifton  <nickc@redhat.com>

	* dis-asm.h: Add prototype for disassembler_usage().
	Add prototype for arm_disassembler_options().
	Remvoe prototype for arm_toggle_regnames().

Index: include/dis-asm.h
===================================================================
RCS file: /cvs/binutils/binutils/include/dis-asm.h,v
retrieving revision 1.5
diff -p -r1.5 dis-asm.h
*** dis-asm.h	2000/01/27 21:44:26	1.5
--- dis-asm.h	2000/01/27 22:08:38
*************** extern int print_insn_vax		PARAMS ((bfd_
*** 189,195 ****
  extern int print_insn_tic80		PARAMS ((bfd_vma, disassemble_info*));
  extern int print_insn_pj		PARAMS ((bfd_vma, disassemble_info*));
  
! extern int arm_toggle_regnames          PARAMS ((void));
  
  /* Fetch the disassembler for a given BFD, if that support is available.  */
  extern disassembler_ftype disassembler	PARAMS ((bfd *));
--- 189,195 ----
  extern int print_insn_tic80		PARAMS ((bfd_vma, disassemble_info*));
  extern int print_insn_pj		PARAMS ((bfd_vma, disassemble_info*));
  
! extern void print_arm_disassembler_options PARAMS ((FILE *));
  
  /* Fetch the disassembler for a given BFD, if that support is available.  */
  extern disassembler_ftype disassembler	PARAMS ((bfd *));


2000-01-27  Nick Clifton  <nickc@redhat.com>

	* disassemble.c (disassembler_usage): New function: Print out any
	target specific disassembler options.
	Call arm_disassembler_options() if the ARM architecture is being
	supported.  

	* arm-dis.c (NUM_ELEM): Define this macro if not already
	defined.
	(arm_regname): New struct type for ARM register names.
	(arm_toggle_regnames): Delete.
	(parse_disassembler_option): Use register name structure.
	(print_insn): New function: Combines duplicate code found in
	print_insn_big_arm and print_insn_little_arm.
	(print_insn_big_arm): Call print_insn.
	(print_insn_little_arm): Call print_insn.
	(print_arm_disassembler_options): Display list of supported,
	ARM specific disassembler options.

	  
Index: opcodes/disassemble.c
===================================================================
RCS file: /cvs/binutils/binutils/opcodes/disassemble.c,v
retrieving revision 1.4
diff -p -r1.4 disassemble.c
*** disassemble.c	2000/01/27 21:44:26	1.4
--- disassemble.c	2000/01/27 22:08:38
*************** disassembler (abfd)
*** 255,259 ****
--- 255,263 ----
  void
  disassembler_usage (FILE * stream)
  {
+ #ifdef ARCH_arm
+   print_arm_disassembler_options (stream);
+ #endif
+   
    return;
  }

Index: opcodes/arm-dis.c
===================================================================
RCS file: /cvs/binutils/binutils/opcodes/arm-dis.c,v
retrieving revision 1.11
diff -p -r1.11 arm-dis.c
*** arm-dis.c	2000/01/27 20:05:28	1.11
--- arm-dis.c	2000/01/27 22:08:39
*************** Foundation, Inc., 59 Temple Place - Suit
*** 33,62 ****
  #include "elf/arm.h"
  
  #ifndef streq
! #define streq(a,b) (strcmp ((a), (b)) == 0)
  #endif
  #ifndef strneq
! #define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
  #endif
  
  static char * arm_conditional[] =
  {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
   "hi", "ls", "ge", "lt", "gt", "le", "", "nv"};
  
! static char * arm_regnames_raw[] =
! {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
!  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"};
! 
! static char * arm_regnames_standard[] =
! {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
!  "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc"};
! 
! static char * arm_regnames_apcs[] =
! {"a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4",
!  "v5", "v6", "sl", "fp", "ip", "sp", "lr", "pc"};
  
! /* Choose which register name set to use.  */
! static char ** arm_regnames = arm_regnames_standard;
  
  static boolean force_thumb = false;
  
--- 33,80 ----
  #include "elf/arm.h"
  
  #ifndef streq
! #define streq(a,b)	(strcmp ((a), (b)) == 0)
  #endif
+ 
  #ifndef strneq
! #define strneq(a,b,n)	(strncmp ((a), (b), (n)) == 0)
! #endif
! 
! #ifndef NUM_ELEM
! #define NUM_ELEM(a)     (sizeof (a) / sizeof (a)[0])
  #endif
  
  static char * arm_conditional[] =
  {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
   "hi", "ls", "ge", "lt", "gt", "le", "", "nv"};
+ 
+ typedef struct
+ {
+   const char * name;
+   const char * description;
+   const char * reg_names[16];
+ }
+ arm_regname;
+ 
+ static arm_regname regnames[] =
+ {
+   { "raw" , "Select raw register names",
+     { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}},
+   { "std",  "Select register names used in ARM's ISA documentation",
+     { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp",  "lr",  "pc" }},
+   { "apcs", "Select register names used in the APCS",
+     { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl",  "fp",  "ip",  "sp",  "lr",  "pc" }},
+   { "atpcs", "Select register names used in the ATPCS",
+     { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7",  "v8",  "IP",  "SP",  "LR",  "PC" }},
+   { "atpcs-special", "Select special register names used in the ATPCS",
+     { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL",  "FP",  "IP",  "SP",  "LR",  "PC" }}
+ };
  
! /* Default to standard register name set.  */
! static unsigned int regname_selected = 1;
  
! #define NUM_ARM_REGNAMES  NUM_ELEM (regnames)
! #define arm_regnames      regnames[regname_selected].reg_names
  
  static boolean force_thumb = false;
  
*************** static int  print_insn_arm   PARAMS ((bf
*** 72,77 ****
--- 90,96 ----
  static int  print_insn_thumb PARAMS ((bfd_vma, struct disassemble_info *, long));
  static void parse_disassembler_option PARAMS ((char *));
  static void parse_disassembler_options PARAMS ((char *));
+ static int  print_insn       PARAMS ((bfd_vma, struct disassemble_info *, boolean));
  
  /* Functions. */
  static void
*************** arm_decode_shift (given, func, stream)
*** 110,116 ****
  
  /* Print one instruction from PC on INFO->STREAM.
     Return the size of the instruction (always 4 on ARM). */
- 
  static int
  print_insn_arm (pc, info, given)
       bfd_vma                   pc;
--- 129,134 ----
*************** print_insn_arm (pc, info, given)
*** 155,172 ****
  
  			      offset += pc + 8;
  
! 			      /* Cope with the possibility of write-back being used.
! 				 Probably a very dangerous thing for the programmer
! 				 to do, but who are we to argue ?  */
  			      if (given & 0x00200000)
  				func (stream, "!");
  			    }
  			  else
  			    {
! 			      /* post indexed */
  			      func (stream, "], #%x", offset);
  
! 			      offset = pc + 8;  /* ie ignore the offset */
  			    }
  			  
  			  func (stream, "\t; ");
--- 173,191 ----
  
  			      offset += pc + 8;
  
! 			      /* Cope with the possibility of write-back
! 				 being used.  Probably a very dangerous thing
! 				 for the programmer to do, but who are we to
! 				 argue ?  */
  			      if (given & 0x00200000)
  				func (stream, "!");
  			    }
  			  else
  			    {
! 			      /* Post indexed.  */
  			      func (stream, "], #%x", offset);
  
! 			      offset = pc + 8;  /* ie ignore the offset.  */
  			    }
  			  
  			  func (stream, "\t; ");
*************** print_insn_arm (pc, info, given)
*** 223,229 ****
  		    case 's':
                        if ((given & 0x004f0000) == 0x004f0000)
  			{
!                           /* PC relative with immediate offset */
  			  int offset = ((given & 0xf00) >> 4) | (given & 0xf);
  			  
  			  if ((given & 0x00800000) == 0)
--- 242,248 ----
  		    case 's':
                        if ((given & 0x004f0000) == 0x004f0000)
  			{
!                           /* PC relative with immediate offset.  */
  			  int offset = ((given & 0xf00) >> 4) | (given & 0xf);
  			  
  			  if ((given & 0x00800000) == 0)
*************** print_insn_arm (pc, info, given)
*** 240,249 ****
  				arm_regnames[(given >> 16) & 0xf]);
  			  if ((given & 0x01000000) != 0)
  			    {
!                               /* pre-indexed */
  			      if ((given & 0x00400000) == 0x00400000)
  				{
!                                   /* immediate */
                                    int offset = ((given & 0xf00) >> 4) | (given & 0xf);
  				  if (offset)
  				    func (stream, ", %s#%d",
--- 259,268 ----
  				arm_regnames[(given >> 16) & 0xf]);
  			  if ((given & 0x01000000) != 0)
  			    {
!                               /* Pre-indexed.  */
  			      if ((given & 0x00400000) == 0x00400000)
  				{
!                                   /* Immediate.  */
                                    int offset = ((given & 0xf00) >> 4) | (given & 0xf);
  				  if (offset)
  				    func (stream, ", %s#%d",
*************** print_insn_arm (pc, info, given)
*** 252,258 ****
  				}
  			      else
  				{
!                                   /* register */
  				  func (stream, ", %s%s",
  					(((given & 0x00800000) == 0)
  					 ? "-" : ""),
--- 271,277 ----
  				}
  			      else
  				{
!                                   /* Register.  */
  				  func (stream, ", %s%s",
  					(((given & 0x00800000) == 0)
  					 ? "-" : ""),
*************** print_insn_arm (pc, info, given)
*** 264,273 ****
  			    }
  			  else
  			    {
!                               /* post-indexed */
  			      if ((given & 0x00400000) == 0x00400000)
  				{
!                                   /* immediate */
                                    int offset = ((given & 0xf00) >> 4) | (given & 0xf);
  				  if (offset)
  				    func (stream, "], %s#%d",
--- 283,292 ----
  			    }
  			  else
  			    {
!                               /* Post-indexed.  */
  			      if ((given & 0x00400000) == 0x00400000)
  				{
!                                   /* Immediate.  */
                                    int offset = ((given & 0xf00) >> 4) | (given & 0xf);
  				  if (offset)
  				    func (stream, "], %s#%d",
*************** print_insn_arm (pc, info, given)
*** 278,284 ****
  				}
  			      else
  				{
!                                   /* register */
  				  func (stream, "], %s%s",
  					(((given & 0x00800000) == 0)
  					 ? "-" : ""),
--- 297,303 ----
  				}
  			      else
  				{
!                                   /* Register.  */
  				  func (stream, "], %s%s",
  					(((given & 0x00800000) == 0)
  					 ? "-" : ""),
*************** print_insn_arm (pc, info, given)
*** 469,504 ****
  			  {
  			  case '-':
  			    c++;
  			    while (*c >= '0' && *c <= '9')
  			      bitend = (bitend * 10) + *c++ - '0';
  			    if (!bitend)
  			      abort ();
  			    switch (*c)
  			      {
  			      case 'r':
  				{
  				  long reg;
  				  reg = given >> bitstart;
  				  reg &= (2 << (bitend - bitstart)) - 1;
  				  func (stream, "%s", arm_regnames[reg]);
  				}
  				break;
  			      case 'd':
  				{
  				  long reg;
  				  reg = given >> bitstart;
  				  reg &= (2 << (bitend - bitstart)) - 1;
  				  func (stream, "%d", reg);
  				}
  				break;
  			      case 'x':
  				{
  				  long reg;
  				  reg = given >> bitstart;
  				  reg &= (2 << (bitend - bitstart)) - 1;
  				  func (stream, "0x%08x", reg);
  				  
! 				  /* Some SWI instructions have special meanings.  */
  				  if ((given & 0x0fffffff) == 0x0FF00000)
  				    func (stream, "\t; IMB");
  				  else if ((given & 0x0fffffff) == 0x0FF00001)
--- 488,533 ----
  			  {
  			  case '-':
  			    c++;
+ 			    
  			    while (*c >= '0' && *c <= '9')
  			      bitend = (bitend * 10) + *c++ - '0';
+ 			    
  			    if (!bitend)
  			      abort ();
+ 			    
  			    switch (*c)
  			      {
  			      case 'r':
  				{
  				  long reg;
+ 				  
  				  reg = given >> bitstart;
  				  reg &= (2 << (bitend - bitstart)) - 1;
+ 				  
  				  func (stream, "%s", arm_regnames[reg]);
  				}
  				break;
  			      case 'd':
  				{
  				  long reg;
+ 				  
  				  reg = given >> bitstart;
  				  reg &= (2 << (bitend - bitstart)) - 1;
+ 				  
  				  func (stream, "%d", reg);
  				}
  				break;
  			      case 'x':
  				{
  				  long reg;
+ 				  
  				  reg = given >> bitstart;
  				  reg &= (2 << (bitend - bitstart)) - 1;
+ 				  
  				  func (stream, "0x%08x", reg);
  				  
! 				  /* Some SWI instructions have special
! 				     meanings.  */
  				  if ((given & 0x0fffffff) == 0x0FF00000)
  				    func (stream, "\t; IMB");
  				  else if ((given & 0x0fffffff) == 0x0FF00001)
*************** print_insn_arm (pc, info, given)
*** 508,523 ****
--- 537,556 ----
  			      case 'X':
  				{
  				  long reg;
+ 				  
  				  reg = given >> bitstart;
  				  reg &= (2 << (bitend - bitstart)) - 1;
+ 				  
  				  func (stream, "%01x", reg & 0xf);
  				}
  				break;
  			      case 'f':
  				{
  				  long reg;
+ 				  
  				  reg = given >> bitstart;
  				  reg &= (2 << (bitend - bitstart)) - 1;
+ 				  
  				  if (reg > 7)
  				    func (stream, "#%s",
  					  arm_fp_const[reg & 7]);
*************** print_insn_arm (pc, info, given)
*** 529,534 ****
--- 562,568 ----
  				abort ();
  			      }
  			    break;
+ 			    
  			  case '`':
  			    c++;
  			    if ((given & (1 << bitstart)) == 0)
*************** print_insn_arm (pc, info, given)
*** 567,573 ****
  
  /* Print one instruction from PC on INFO->STREAM.
     Return the size of the instruction. */
- 
  static int
  print_insn_thumb (pc, info, given)
       bfd_vma                   pc;
--- 601,606 ----
*************** print_insn_thumb (pc, info, given)
*** 584,598 ****
          {
            char * c = insn->assembler;
  
!           /* Special processing for Thumb 2 instruction BL sequence: */
!           if (!*c) /* check for empty (not NULL) assembler string */
              {
  	      info->bytes_per_chunk = 4;
  	      info->bytes_per_line  = 4;
  	      
                func (stream, "bl\t");
!               (*info->print_address_func)
!                 (BDISP23 (given) * 2 + pc + 4, info);
                return 4;
              }
            else
--- 617,630 ----
          {
            char * c = insn->assembler;
  
!           /* Special processing for Thumb 2 instruction BL sequence:  */
!           if (!*c) /* Check for empty (not NULL) assembler string.  */
              {
  	      info->bytes_per_chunk = 4;
  	      info->bytes_per_line  = 4;
  	      
                func (stream, "bl\t");
!               info->print_address_func (BDISP23 (given) * 2 + pc + 4, info);
                return 4;
              }
            else
*************** print_insn_thumb (pc, info, given)
*** 601,607 ****
  	      info->bytes_per_line  = 4;
  	  	      
                given &= 0xffff;
! 
                for (; *c; c++)
                  {
                    if (*c == '%')
--- 633,639 ----
  	      info->bytes_per_line  = 4;
  	  	      
                given &= 0xffff;
! 	      
                for (; *c; c++)
                  {
                    if (*c == '%')
*************** print_insn_thumb (pc, info, given)
*** 618,626 ****
--- 650,660 ----
                          case 'S':
                            {
                              long reg;
+ 			    
                              reg = (given >> 3) & 0x7;
                              if (given & (1 << 6))
                                reg += 8;
+ 			    
                              func (stream, "%s", arm_regnames[reg]);
                            }
                            break;
*************** print_insn_thumb (pc, info, given)
*** 632,637 ****
--- 666,672 ----
                              reg = given & 0x7;
                              if (given & (1 << 7))
                               reg += 8;
+ 			    
                              func (stream, "%s", arm_regnames[reg]);
                            }
                            break;
*************** print_insn_thumb (pc, info, given)
*** 644,660 ****
                          case 'N':
                            if (given & (1 << 8))
                              domasklr = 1;
!                           /* fall through */
                          case 'O':
                            if (*c == 'O' && (given & (1 << 8)))
                              domaskpc = 1;
!                           /* fall through */
                          case 'M':
                            {
                              int started = 0;
                              int reg;
  			    
                              func (stream, "{");
                              /* It would be nice if we could spot
                                 ranges, and generate the rS-rE format: */
                              for (reg = 0; (reg < 8); reg++)
--- 679,696 ----
                          case 'N':
                            if (given & (1 << 8))
                              domasklr = 1;
!                           /* Fall through.  */
                          case 'O':
                            if (*c == 'O' && (given & (1 << 8)))
                              domaskpc = 1;
!                           /* Fall through.  */
                          case 'M':
                            {
                              int started = 0;
                              int reg;
  			    
                              func (stream, "{");
+ 			    
                              /* It would be nice if we could spot
                                 ranges, and generate the rS-rE format: */
                              for (reg = 0; (reg < 8); reg++)
*************** print_insn_thumb (pc, info, given)
*** 728,735 ****
  
                                      case 'a':
  				      /* PC-relative address -- the bottom two
! 					 bits of the address are dropped before
! 					 the calculation.  */
                                        info->print_address_func
  					(((pc + 4) & ~3) + (reg << 2), info);
                                        break;
--- 764,771 ----
  
                                      case 'a':
  				      /* PC-relative address -- the bottom two
! 					 bits of the address are dropped
! 					 before the calculation.  */
                                        info->print_address_func
  					(((pc + 4) & ~3) + (reg << 2), info);
                                        break;
*************** print_insn_thumb (pc, info, given)
*** 787,809 ****
         }
      }
  
!   /* no match */
    abort ();
  }
  
! /* Select a different register name set.
!    Returns true if the name set selected is the APCS name set.  */
! int
! arm_toggle_regnames ()
! {
!   if (arm_regnames == arm_regnames_standard)
!     arm_regnames = arm_regnames_apcs;
!   else
!     arm_regnames = arm_regnames_standard;
! 
!   return arm_regnames == arm_regnames_apcs;
! }
! 
  static void
  parse_disassembler_option (option)
       char * option;
--- 823,833 ----
         }
      }
  
!   /* No match.  */
    abort ();
  }
  
! /* Parse an individual disassembler option.  */
  static void
  parse_disassembler_option (option)
       char * option;
*************** parse_disassembler_option (option)
*** 813,839 ****
        
    if (strneq (option, "reg-names-", 10))
      {
        option += 10;
        
!       if (streq (option, "std"))
! 	arm_regnames = arm_regnames_standard;
!       else if (streq (option, "apcs"))
! 	arm_regnames = arm_regnames_apcs;
!       else if (streq (option, "raw"))
! 	arm_regnames = arm_regnames_raw;
!       else
! 	fprintf (stderr, "Unrecognised register name set: %s\n", option);
      }
    else if (streq (option, "force-thumb"))
      force_thumb = 1;
    else if (streq (option, "no-force-thumb"))
      force_thumb = 0;
    else
!     fprintf (stderr, "Unrecognised disassembler option: %s\n", option);
    
    return;
  }
  
  static void
  parse_disassembler_options (options)
       char * options;
--- 837,867 ----
        
    if (strneq (option, "reg-names-", 10))
      {
+       int i;
+ 	
        option += 10;
+ 
+       for (i = NUM_ARM_REGNAMES; i--;)
+ 	if (streq (option, regnames[i].name))
+ 	  {
+ 	    regname_selected = i;
+ 	    break;
+ 	  }
        
!       if (i < 0)
! 	fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
      }
    else if (streq (option, "force-thumb"))
      force_thumb = 1;
    else if (streq (option, "no-force-thumb"))
      force_thumb = 0;
    else
!     fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
    
    return;
  }
  
+ /* Parse the string of disassembler options, spliting it at whitespaces.  */
  static void
  parse_disassembler_options (options)
       char * options;
*************** parse_disassembler_options (options)
*** 860,883 ****
    while (space);
  }
  
! /* NOTE: There are no checks in these routines that the relevant number of
!    data bytes exist.  */
! 
! int
! print_insn_big_arm (pc, info)
       bfd_vma pc;
       struct disassemble_info * info;
  {
    unsigned char      b[4];
    long               given;
    int                status;
    int                is_thumb;
!   
    if (info->disassembler_options)
      {
        parse_disassembler_options (info->disassembler_options);
        
!       /* To avoid repeated parsing of the options, we remove it here.  */
        info->disassembler_options = NULL;
      }
    
--- 888,911 ----
    while (space);
  }
  
! /* NOTE: There are no checks in these routines that
!    the relevant number of data bytes exist.  */
! static int
! print_insn (pc, info, little)
       bfd_vma pc;
       struct disassemble_info * info;
+      boolean little;
  {
    unsigned char      b[4];
    long               given;
    int                status;
    int                is_thumb;
! 
    if (info->disassembler_options)
      {
        parse_disassembler_options (info->disassembler_options);
        
!       /* To avoid repeated parsing of these options, we remove them here.  */
        info->disassembler_options = NULL;
      }
    
*************** print_insn_big_arm (pc, info)
*** 899,944 ****
        else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
  	{
  	  elf_symbol_type *  es;
  	  
  	  es = *(elf_symbol_type **)(info->symbols);
! 	  is_thumb = (ELF_ST_TYPE (es->internal_elf_sym.st_info) == STT_ARM_TFUNC)
! 	          || (ELF_ST_TYPE (es->internal_elf_sym.st_info) == STT_ARM_16BIT);
  	}
      }
! 
    info->bytes_per_chunk = 4;
!   info->display_endian = BFD_ENDIAN_BIG;
  
!   /* Always fetch word aligned values.  */
!   
!   status = (*info->read_memory_func) (pc & ~ 0x3, (bfd_byte *) &b[0], 4, info);
!   if (status != 0)
      {
!       (*info->memory_error_func) (status, pc, info);
!       return -1;
      }
! 
!   if (is_thumb)
      {
!       if (pc & 0x2)
  	{
! 	  given = (b[2] << 8) | b[3];
! 
! 	  status = info->read_memory_func ((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
! 	  if (status != 0)
  	    {
! 	      info->memory_error_func (status, pc + 4, info);
! 	      return -1;
  	    }
! 	  
! 	  given |= (b[0] << 24) | (b[1] << 16);
  	}
        else
! 	given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16);
      }
!   else
!     given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
! 
    if (is_thumb)
      status = print_insn_thumb (pc, info, given);
    else
--- 927,996 ----
        else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
  	{
  	  elf_symbol_type *  es;
+ 	  unsigned int       type;
  	  
  	  es = *(elf_symbol_type **)(info->symbols);
! 	  type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
! 	  
! 	  is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
  	}
      }
!   
    info->bytes_per_chunk = 4;
!   info->display_endian  = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
  
!   if (little)
      {
!       status = info->read_memory_func (pc, (bfd_byte *) &b[0], 4, info);
!       if (status != 0 && is_thumb)
! 	{
! 	  info->bytes_per_chunk = 2;
! 	  
! 	  status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
! 	  b[3] = b[2] = 0;
! 	}
!       
!       if (status != 0)
! 	{
! 	  info->memory_error_func (status, pc, info);
! 	  return -1;
! 	}
!       
!       given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
      }
!   else
      {
!       status = info->read_memory_func
! 	(pc & ~ 0x3, (bfd_byte *) &b[0], 4, info);
!       if (status != 0)
  	{
! 	  info->memory_error_func (status, pc, info);
! 	  return -1;
! 	}
!       
!       if (is_thumb)
! 	{
! 	  if (pc & 0x2)
  	    {
! 	      given = (b[2] << 8) | b[3];
! 	      
! 	      status = info->read_memory_func
! 		((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
! 	      if (status != 0)
! 		{
! 		  info->memory_error_func (status, pc + 4, info);
! 		  return -1;
! 		}
! 	      
! 	      given |= (b[0] << 24) | (b[1] << 16);
  	    }
! 	  else
! 	    given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16);
  	}
        else
! 	given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
      }
!   
    if (is_thumb)
      status = print_insn_thumb (pc, info, given);
    else
*************** print_insn_big_arm (pc, info)
*** 948,1019 ****
  }
  
  int
! print_insn_little_arm (pc, info)
       bfd_vma pc;
       struct disassemble_info * info;
  {
!   unsigned char      b[4];
!   long               given;
!   int                status;
!   int                is_thumb;
! 
!   if (info->disassembler_options)
!     {
!       parse_disassembler_options (info->disassembler_options);
!       
!       /* To avoid repeated parsing of the options, we remove it here.  */
!       info->disassembler_options = NULL;
!     }
  
!   is_thumb = force_thumb;
!   
!   if (!is_thumb && info->symbols != NULL)
!     {
!       if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
! 	{
! 	  coff_symbol_type * cs;
! 	  
! 	  cs = coffsymbol (*info->symbols);
! 	  is_thumb = (   cs->native->u.syment.n_sclass == C_THUMBEXT
! 		      || cs->native->u.syment.n_sclass == C_THUMBSTAT
! 		      || cs->native->u.syment.n_sclass == C_THUMBLABEL
! 		      || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
! 		      || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
! 	}
!       else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
! 	{
! 	  elf_symbol_type *  es;
! 	  
! 	  es = *(elf_symbol_type **)(info->symbols);
! 	  is_thumb = (ELF_ST_TYPE (es->internal_elf_sym.st_info) == STT_ARM_TFUNC)
! 	          || (ELF_ST_TYPE (es->internal_elf_sym.st_info) == STT_ARM_16BIT);
! 	}
!     }
!   
!   info->bytes_per_chunk = 4;
!   info->display_endian = BFD_ENDIAN_LITTLE;
  
!   status = (*info->read_memory_func) (pc, (bfd_byte *) &b[0], 4, info);
!   if (status != 0 && is_thumb)
!     {
!       info->bytes_per_chunk = 2;
  
!       status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
!       b[3] = b[2] = 0;
!     }
    
!   if (status != 0)
!     {
!       info->memory_error_func (status, pc, info);
!       return -1;
!     }
  
!   given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
! 
!   if (is_thumb)
!     status = print_insn_thumb (pc, info, given);
!   else
!     status = print_insn_arm (pc, info, given);
! 
!   return status;
  }
--- 1000,1035 ----
  }
  
  int
! print_insn_big_arm (pc, info)
       bfd_vma pc;
       struct disassemble_info * info;
  {
!   return print_insn (pc, info, false);
! }
  
! int
! print_insn_little_arm (pc, info)
!      bfd_vma pc;
!      struct disassemble_info * info;
! {
!   return print_insn (pc, info, true);
! }
  
! void
! print_arm_disassembler_options (FILE * stream)
! {
!   int i;
  
!   fprintf (stream, _("\n\
! The following ARM specific disassembler options are supported for use with\n\
! the -M switch:\n"));
    
!   for (i = NUM_ARM_REGNAMES; i--;)
!     fprintf (stream, "  reg-names-%s %*c%s\n",
! 	     regnames[i].name,
! 	     14 - strlen (regnames[i].name), ' ',
! 	     regnames[i].description);
  
!   fprintf (stream, "  force-thumb              Assume all insns are Thumb insns\n");
!   fprintf (stream, "  no-force-thumb           Examine preceeding label to determine an insn's type\n\n");
  }


2000-01-27  Nick Clifton  <nickc@redhat.com>

	* binutils.texi (objdump): Document new ARM specific
	disassembler options.

	* objdump.c (usage): Call disassembler_usage().

Index: binutils/binutils.texi
===================================================================
RCS file: /cvs/binutils/binutils/binutils/binutils.texi,v
retrieving revision 1.16
diff -p -r1.16 binutils.texi
*** binutils.texi	2000/01/07 22:33:48	1.16
--- binutils.texi	2000/01/27 22:08:39
*************** some targets.
*** 1346,1358 ****
  
  If the target is an ARM architecture then this switch can be used to
  select which register name set is used during disassembler.  Specifying
! @samp{--disassembler-options=reg-name-std} (the default) will select the
! register names as used in ARM's instruction set documentation, but with
! register 13 called 'sp', register 14 called 'lr' and register 15 called
! 'pc'.  Specifying @samp{--disassembler-options=reg-names-apcs} will
! select the name set used by the ARM Procedure Call Standard, whilst
! specifying @samp{--disassembler-options=reg-names-raw} will just use
! @samp{r} followed by the register number.
  
  This option can also be used for ARM architectures to force the
  disassembler to interpret all instructions as THUMB instructions by
--- 1346,1362 ----
  
  If the target is an ARM architecture then this switch can be used to
  select which register name set is used during disassembler.  Specifying
! @samp{-M reg-name-std} (the default) will select the register names as
! used in ARM's instruction set documentation, but with register 13 called
! 'sp', register 14 called 'lr' and register 15 called 'pc'.  Specifying
! @samp{-M reg-names-apcs} will select the name set used by the ARM
! Procedure Call Standard, whilst specifying @samp{-M reg-names-raw} will
! just use @samp{r} followed by the register number.
! 
! There are also two variants on the APCS register naming scheme enabled
! by @samp{-M reg-names-atpcs} and @samp{-M reg-names-atpcs-special} which
! use the ARM/Thumb Procedure Call Standard naming conventions.  (Eiuther
! with the normal register name sor the special register names).
  
  This option can also be used for ARM architectures to force the
  disassembler to interpret all instructions as THUMB instructions by

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]