*** empty log message ***
[deliverable/binutils-gdb.git] / opcodes / arm-dis.c
index a3f44db738bbd9e8ae32bc4cf266a2a5bd763a7d..9d280a17b79581d9768d81d7e8f91d0da389f796 100644 (file)
@@ -1,5 +1,6 @@
 /* Instruction printing code for the ARM
-   Copyright (C) 1994, 95, 96, 97, 98, 99, 2000 Free Software Foundation, Inc. 
+   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+   Free Software Foundation, Inc.
    Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
    Modification by James G. Smith (jsmith@cygnus.co.uk)
 
@@ -60,17 +61,19 @@ 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"}},
+  { "gcc",  "Select register names used by GCC",
+    { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl",  "fp",  "ip",  "sp",  "lr",  "pc" }},
   { "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",
+  { "special-atpcs", "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.  */
+/* Default to GCC register name set.  */
 static unsigned int regname_selected = 1;
 
 #define NUM_ARM_REGNAMES  NUM_ELEM (regnames)
@@ -90,8 +93,38 @@ static int  print_insn_arm   PARAMS ((bfd_vma, struct disassemble_info *, long))
 static int  print_insn_thumb PARAMS ((bfd_vma, struct disassemble_info *, long));
 static void parse_disassembler_options PARAMS ((char *));
 static int  print_insn       PARAMS ((bfd_vma, struct disassemble_info *, boolean));
+int get_arm_regname_num_options (void);
+int set_arm_regname_option (int option);
+int get_arm_regnames (int option, const char **setname,
+                     const char **setdescription,
+                     const char ***register_names);
 \f
 /* Functions. */
+int
+get_arm_regname_num_options (void)
+{
+  return NUM_ARM_REGNAMES;
+}
+
+int
+set_arm_regname_option (int option)
+{
+  int old = regname_selected;
+  regname_selected = option;
+  return old;
+}
+
+int
+get_arm_regnames (int option, const char **setname,
+                 const char **setdescription,
+                  const char ***register_names)
+{
+  *setname = regnames[option].name;
+  *setdescription = regnames[option].description;
+  *register_names = regnames[option].reg_names;
+  return 16;
+}
+
 static void
 arm_decode_shift (given, func, stream)
      long given;
@@ -389,22 +422,39 @@ print_insn_arm (pc, info, given)
                        }
                      break;
 
+                   case 'B':
+                     /* Print ARM V5 BLX(1) address: pc+25 bits.  */
+                     {
+                       bfd_vma address;
+                       bfd_vma offset = 0;
+                       
+                       if (given & 0x00800000)
+                         /* Is signed, hi bits should be ones.  */
+                         offset = (-1) ^ 0x00ffffff;
+
+                       /* Offset is (SignExtend(offset field)<<2).  */
+                       offset += given & 0x00ffffff;
+                       offset <<= 2;
+                       address = offset + pc + 8;
+                       
+                       if (given & 0x01000000)
+                         /* H bit allows addressing to 2-byte boundaries.  */
+                         address += 2;
+
+                       info->print_address_func (address, info);
+                     }
+                     break;
+
                    case 'C':
-                     switch (given & 0x00090000)
-                       {
-                       default:
-                         func (stream, "_???");
-                         break;
-                       case 0x90000:
-                         func (stream, "_all");
-                         break;
-                       case 0x10000:
-                         func (stream, "_ctl");
-                         break;
-                       case 0x80000:
-                         func (stream, "_flg");
-                         break;
-                       }
+                     func (stream, "_");
+                     if (given & 0x80000)
+                       func (stream, "f");
+                     if (given & 0x40000)
+                       func (stream, "s");
+                     if (given & 0x20000)
+                       func (stream, "x");
+                     if (given & 0x10000)
+                       func (stream, "c");
                      break;
 
                    case 'F':
@@ -619,12 +669,32 @@ print_insn_thumb (pc, info, given)
           /* Special processing for Thumb 2 instruction BL sequence:  */
           if (!*c) /* Check for empty (not NULL) assembler string.  */
             {
+             long offset;
+             
              info->bytes_per_chunk = 4;
              info->bytes_per_line  = 4;
+
+             offset = BDISP23 (given);
              
-                func (stream, "bl\t");
-               
-              info->print_address_func (BDISP23 (given) * 2 + pc + 4, info);
+             if ((given & 0x10000000) == 0)
+               {
+                 func (stream, "blx\t");
+
+                 /* The spec says that bit 1 of the branch's destination
+                    address comes from bit 1 of the instruction's
+                    address and not from the offset in the instruction.  */
+                 if (offset & 0x1)
+                   {
+                     /* func (stream, "*malformed!* "); */
+                     offset &= ~ 0x1;
+                   }
+
+                 offset |= ((pc & 0x2) >> 1);
+               }
+             else
+               func (stream, "bl\t");
+
+             info->print_address_func (offset * 2 + pc + 4, info);
               return 4;
             }
           else
@@ -707,14 +777,14 @@ print_insn_thumb (pc, info, given)
                                 if (started)
                                   func (stream, ", ");
                                 started = 1;
-                                func (stream, "lr");
+                                func (stream, arm_regnames[14] /* "lr" */);
                               }
 
                             if (domaskpc)
                               {
                                 if (started)
                                   func (stream, ", ");
-                                func (stream, "pc");
+                                func (stream, arm_regnames[15] /* "pc" */);
                               }
 
                             func (stream, "}");
@@ -991,6 +1061,14 @@ print_insn (pc, info, little)
        given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
     }
   
+  if (info->flags & INSN_HAS_RELOC)
+    /* If the instruction has a reloc associated with it, then
+       the offset field in the instruction will actually be the
+       addend for the reloc.  (We are using REL type relocs).
+       In such cases, we can ignore the pc when computing
+       addresses, since the addend is not currently pc-relative.  */
+    pc = 0;
+  
   if (is_thumb)
     status = print_insn_thumb (pc, info, given);
   else
This page took 0.032755 seconds and 4 git commands to generate.