2007-06-09 Markus Deuling <deuling@de.ibm.com>
[deliverable/binutils-gdb.git] / gdb / arm-tdep.c
index ab7b2e99f3d2e3d74f35200e9d5835cca2767c21..7205471ba71ef73eecae68c2d8463c2c7c7486b0 100644 (file)
@@ -217,7 +217,7 @@ int arm_apcs_32 = 1;
 /* Determine if the program counter specified in MEMADDR is in a Thumb
    function.  */
 
-int
+static int
 arm_pc_is_thumb (CORE_ADDR memaddr)
 {
   struct minimal_symbol *sym;
@@ -832,13 +832,15 @@ arm_scan_prologue (struct frame_info *next_frame, struct arm_prologue_cache *cac
          imm = (imm >> rot) | (imm << (32 - rot));
          sp_offset -= imm;
        }
-      else if ((insn & 0xffff7fff) == 0xed6d0103)      /* stfe f?, [sp, -#c]! */
+      else if ((insn & 0xffff7fff) == 0xed6d0103       /* stfe f?, [sp, -#c]! */
+              && gdbarch_tdep (current_gdbarch)->have_fpa_registers)
        {
          sp_offset -= 12;
          regno = ARM_F0_REGNUM + ((insn >> 12) & 0x07);
          cache->saved_regs[regno].addr = sp_offset;
        }
-      else if ((insn & 0xffbf0fff) == 0xec2d0200)      /* sfmfd f0, 4, [sp!] */
+      else if ((insn & 0xffbf0fff) == 0xec2d0200       /* sfmfd f0, 4, [sp!] */
+              && gdbarch_tdep (current_gdbarch)->have_fpa_registers)
        {
          int n_saved_fp_regs;
          unsigned int fp_start_reg, fp_bound_reg;
@@ -906,7 +908,7 @@ arm_make_prologue_cache (struct frame_info *next_frame)
 
   /* Calculate actual addresses of saved registers using offsets
      determined by arm_scan_prologue.  */
-  for (reg = 0; reg < NUM_REGS; reg++)
+  for (reg = 0; reg < gdbarch_num_regs (current_gdbarch); reg++)
     if (trad_frame_addr_p (cache->saved_regs, reg))
       cache->saved_regs[reg].addr += cache->prev_sp;
 
@@ -929,7 +931,7 @@ arm_prologue_this_id (struct frame_info *next_frame,
     *this_cache = arm_make_prologue_cache (next_frame);
   cache = *this_cache;
 
-  func = frame_func_unwind (next_frame);
+  func = frame_func_unwind (next_frame, NORMAL_FRAME);
 
   /* This is meant to halt the backtrace at "_start".  Make sure we
      don't halt it at a generic dummy frame. */
@@ -1034,9 +1036,11 @@ struct frame_unwind arm_stub_unwind = {
 static const struct frame_unwind *
 arm_stub_unwind_sniffer (struct frame_info *next_frame)
 {
+  CORE_ADDR addr_in_block;
   char dummy[4];
 
-  if (in_plt_section (frame_unwind_address_in_block (next_frame), NULL)
+  addr_in_block = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
+  if (in_plt_section (addr_in_block, NULL)
       || target_read_memory (frame_pc_unwind (next_frame), dummy, 4) != 0)
     return &arm_stub_unwind;
 
@@ -1207,7 +1211,8 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
     {
       if (arm_debug)
        fprintf_unfiltered (gdb_stdlog, "struct return in %s = 0x%s\n",
-                           REGISTER_NAME (argreg), paddr (struct_addr));
+                           gdbarch_register_name (current_gdbarch, argreg),
+                           paddr (struct_addr));
       regcache_cooked_write_unsigned (regcache, argreg, struct_addr);
       argreg++;
     }
@@ -1285,7 +1290,9 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              CORE_ADDR regval = extract_unsigned_integer (val, partial_len);
              if (arm_debug)
                fprintf_unfiltered (gdb_stdlog, "arg %d in %s = 0x%s\n",
-                                   argnum, REGISTER_NAME (argreg),
+                                   argnum,
+                                   gdbarch_register_name
+                                     (current_gdbarch, argreg),
                                    phex (regval, DEPRECATED_REGISTER_SIZE));
              regcache_cooked_write_unsigned (regcache, argreg, regval);
              argreg++;
@@ -1383,16 +1390,63 @@ arm_register_type (struct gdbarch *gdbarch, int regnum)
     return builtin_type_void_data_ptr;
   else if (regnum == ARM_PC_REGNUM)
     return builtin_type_void_func_ptr;
+  else if (regnum >= ARRAY_SIZE (arm_register_names))
+    /* These registers are only supported on targets which supply
+       an XML description.  */
+    return builtin_type_int0;
   else
     return builtin_type_uint32;
 }
 
+/* Map a DWARF register REGNUM onto the appropriate GDB register
+   number.  */
+
+static int
+arm_dwarf_reg_to_regnum (int reg)
+{
+  /* Core integer regs.  */
+  if (reg >= 0 && reg <= 15)
+    return reg;
+
+  /* Legacy FPA encoding.  These were once used in a way which
+     overlapped with VFP register numbering, so their use is
+     discouraged, but GDB doesn't support the ARM toolchain
+     which used them for VFP.  */
+  if (reg >= 16 && reg <= 23)
+    return ARM_F0_REGNUM + reg - 16;
+
+  /* New assignments for the FPA registers.  */
+  if (reg >= 96 && reg <= 103)
+    return ARM_F0_REGNUM + reg - 96;
+
+  /* WMMX register assignments.  */
+  if (reg >= 104 && reg <= 111)
+    return ARM_WCGR0_REGNUM + reg - 104;
+
+  if (reg >= 112 && reg <= 127)
+    return ARM_WR0_REGNUM + reg - 112;
+
+  if (reg >= 192 && reg <= 199)
+    return ARM_WC0_REGNUM + reg - 192;
+
+  return -1;
+}
+
 /* Map GDB internal REGNUM onto the Arm simulator register numbers.  */
 static int
 arm_register_sim_regno (int regnum)
 {
   int reg = regnum;
-  gdb_assert (reg >= 0 && reg < NUM_REGS);
+  gdb_assert (reg >= 0 && reg < gdbarch_num_regs (current_gdbarch));
+
+  if (regnum >= ARM_WR0_REGNUM && regnum <= ARM_WR15_REGNUM)
+    return regnum - ARM_WR0_REGNUM + SIM_ARM_IWMMXT_COP0R0_REGNUM;
+
+  if (regnum >= ARM_WC0_REGNUM && regnum <= ARM_WC7_REGNUM)
+    return regnum - ARM_WC0_REGNUM + SIM_ARM_IWMMXT_COP1R0_REGNUM;
+
+  if (regnum >= ARM_WCGR0_REGNUM && regnum <= ARM_WCGR7_REGNUM)
+    return regnum - ARM_WCGR0_REGNUM + SIM_ARM_IWMMXT_COP1R8_REGNUM;
 
   if (reg < NUM_GREGS)
     return SIM_ARM_R0_REGNUM + reg;
@@ -1419,7 +1473,7 @@ convert_from_extended (const struct floatformat *fmt, const void *ptr,
                       void *dbl)
 {
   DOUBLEST d;
-  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+  if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
     floatformat_to_doublest (&floatformat_arm_ext_big, ptr, &d);
   else
     floatformat_to_doublest (&floatformat_arm_ext_littlebyte_bigword,
@@ -1432,7 +1486,7 @@ convert_to_extended (const struct floatformat *fmt, void *dbl, const void *ptr)
 {
   DOUBLEST d;
   floatformat_to_doublest (fmt, ptr, &d);
-  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+  if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
     floatformat_from_doublest (&floatformat_arm_ext_big, &d, dbl);
   else
     floatformat_from_doublest (&floatformat_arm_ext_littlebyte_bigword,
@@ -1552,7 +1606,7 @@ bitcount (unsigned long val)
   return nbits;
 }
 
-CORE_ADDR
+static CORE_ADDR
 thumb_get_next_pc (CORE_ADDR pc)
 {
   unsigned long pc_val = ((unsigned long) pc) + 4;     /* PC after prefetch */
@@ -1608,7 +1662,7 @@ thumb_get_next_pc (CORE_ADDR pc)
   return nextpc;
 }
 
-CORE_ADDR
+static CORE_ADDR
 arm_get_next_pc (CORE_ADDR pc)
 {
   unsigned long pc_val;
@@ -1851,26 +1905,19 @@ arm_get_next_pc (CORE_ADDR pc)
 /* single_step() is called just before we want to resume the inferior,
    if we want to single-step it but there is no hardware or kernel
    single-step support.  We find the target of the coming instruction
-   and breakpoint it.
-
-   single_step() is also called just after the inferior stops.  If we
-   had set up a simulated single-step, we undo our damage.  */
+   and breakpoint it.  */
 
-static void
-arm_software_single_step (enum target_signal sig, int insert_bpt)
+int
+arm_software_single_step (struct regcache *regcache)
 {
   /* NOTE: This may insert the wrong breakpoint instruction when
      single-stepping over a mode-changing instruction, if the
      CPSR heuristics are used.  */
 
-  if (insert_bpt)
-    {
-      CORE_ADDR next_pc = arm_get_next_pc (read_register (ARM_PC_REGNUM));
+  CORE_ADDR next_pc = arm_get_next_pc (read_register (ARM_PC_REGNUM));
+  insert_single_step_breakpoint (next_pc);
 
-      insert_single_step_breakpoint (next_pc);
-    }
-  else
-    remove_single_step_breakpoints ();
+  return 1;
 }
 
 #include "bfd-in2.h"
@@ -1910,7 +1957,7 @@ gdb_print_insn_arm (bfd_vma memaddr, disassemble_info *info)
   else
     info->symbols = NULL;
 
-  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+  if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
     return print_insn_big_arm (memaddr, info);
   else
     return print_insn_little_arm (memaddr, info);
@@ -1945,21 +1992,10 @@ gdb_print_insn_arm (bfd_vma memaddr, disassemble_info *info)
    instruction to force a trap.  This can be handled by by the
    abi-specific code during establishment of the gdbarch vector.  */
 
-
-/* NOTE rearnsha 2002-02-18: for now we allow a non-multi-arch gdb to
-   override these definitions.  */
-#ifndef ARM_LE_BREAKPOINT
 #define ARM_LE_BREAKPOINT {0xFE,0xDE,0xFF,0xE7}
-#endif
-#ifndef ARM_BE_BREAKPOINT
 #define ARM_BE_BREAKPOINT {0xE7,0xFF,0xDE,0xFE}
-#endif
-#ifndef THUMB_LE_BREAKPOINT
-#define THUMB_LE_BREAKPOINT {0xfe,0xdf}
-#endif
-#ifndef THUMB_BE_BREAKPOINT
-#define THUMB_BE_BREAKPOINT {0xdf,0xfe}
-#endif
+#define THUMB_LE_BREAKPOINT {0xbe,0xbe}
+#define THUMB_BE_BREAKPOINT {0xbe,0xbe}
 
 static const char arm_default_arm_le_breakpoint[] = ARM_LE_BREAKPOINT;
 static const char arm_default_arm_be_breakpoint[] = ARM_BE_BREAKPOINT;
@@ -2482,6 +2518,11 @@ set_disassembly_style_sfunc (char *args, int from_tty,
 static const char *
 arm_register_name (int i)
 {
+  if (i >= ARRAY_SIZE (arm_register_names))
+    /* These registers are only supported on targets which supply
+       an XML description.  */
+    return "";
+
   return arm_register_names[i];
 }
 
@@ -2597,6 +2638,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   enum arm_float_model fp_model = arm_fp_model;
   struct tdesc_arch_data *tdesc_data = NULL;
   int i;
+  int have_fpa_registers = 1;
 
   /* Check any target description for validity.  */
   if (tdesc_has_registers (info.target_desc))
@@ -2653,6 +2695,43 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
              return NULL;
            }
        }
+      else
+       have_fpa_registers = 0;
+
+      feature = tdesc_find_feature (info.target_desc,
+                                   "org.gnu.gdb.xscale.iwmmxt");
+      if (feature != NULL)
+       {
+         static const char *const iwmmxt_names[] = {
+           "wR0", "wR1", "wR2", "wR3", "wR4", "wR5", "wR6", "wR7",
+           "wR8", "wR9", "wR10", "wR11", "wR12", "wR13", "wR14", "wR15",
+           "wCID", "wCon", "wCSSF", "wCASF", "", "", "", "",
+           "wCGR0", "wCGR1", "wCGR2", "wCGR3", "", "", "", "",
+         };
+
+         valid_p = 1;
+         for (i = ARM_WR0_REGNUM; i <= ARM_WR15_REGNUM; i++)
+           valid_p
+             &= tdesc_numbered_register (feature, tdesc_data, i,
+                                         iwmmxt_names[i - ARM_WR0_REGNUM]);
+
+         /* Check for the control registers, but do not fail if they
+            are missing.  */
+         for (i = ARM_WC0_REGNUM; i <= ARM_WCASF_REGNUM; i++)
+           tdesc_numbered_register (feature, tdesc_data, i,
+                                    iwmmxt_names[i - ARM_WR0_REGNUM]);
+
+         for (i = ARM_WCGR0_REGNUM; i <= ARM_WCGR3_REGNUM; i++)
+           valid_p
+             &= tdesc_numbered_register (feature, tdesc_data, i,
+                                         iwmmxt_names[i - ARM_WR0_REGNUM]);
+
+         if (!valid_p)
+           {
+             tdesc_data_cleanup (tdesc_data);
+             return NULL;
+           }
+       }
     }
 
   /* If we have an object to base this architecture on, try to determine
@@ -2796,6 +2875,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      These are gdbarch discriminators, like the OSABI.  */
   tdep->arm_abi = arm_abi;
   tdep->fp_model = fp_model;
+  tdep->have_fpa_registers = have_fpa_registers;
 
   /* Breakpoints.  */
   switch (info.byte_order)
@@ -2851,6 +2931,9 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Advance PC across function entry code.  */
   set_gdbarch_skip_prologue (gdbarch, arm_skip_prologue);
 
+  /* Skip trampolines.  */
+  set_gdbarch_skip_trampoline_code (gdbarch, arm_skip_stub);
+
   /* The stack grows downward.  */
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
 
@@ -2858,14 +2941,20 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_breakpoint_from_pc (gdbarch, arm_breakpoint_from_pc);
 
   /* Information about registers, etc.  */
-  set_gdbarch_print_float_info (gdbarch, arm_print_float_info);
   set_gdbarch_deprecated_fp_regnum (gdbarch, ARM_FP_REGNUM);   /* ??? */
   set_gdbarch_sp_regnum (gdbarch, ARM_SP_REGNUM);
   set_gdbarch_pc_regnum (gdbarch, ARM_PC_REGNUM);
-  set_gdbarch_num_regs (gdbarch, NUM_GREGS + NUM_FREGS + NUM_SREGS);
+  set_gdbarch_num_regs (gdbarch, ARM_NUM_REGS);
   set_gdbarch_register_type (gdbarch, arm_register_type);
 
+  /* This "info float" is FPA-specific.  Use the generic version if we
+     do not have FPA.  */
+  if (gdbarch_tdep (gdbarch)->have_fpa_registers)
+    set_gdbarch_print_float_info (gdbarch, arm_print_float_info);
+
   /* Internal <-> external register number maps.  */
+  set_gdbarch_dwarf_reg_to_regnum (gdbarch, arm_dwarf_reg_to_regnum);
+  set_gdbarch_dwarf2_reg_to_regnum (gdbarch, arm_dwarf_reg_to_regnum);
   set_gdbarch_register_sim_regno (gdbarch, arm_register_sim_regno);
 
   /* Integer registers are 4 bytes.  */
@@ -2875,10 +2964,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Returning results.  */
   set_gdbarch_return_value (gdbarch, arm_return_value);
 
-  /* Single stepping.  */
-  /* XXX For an RDI target we should ask the target if it can single-step.  */
-  set_gdbarch_software_single_step (gdbarch, arm_software_single_step);
-
   /* Disassembly.  */
   set_gdbarch_print_insn (gdbarch, gdb_print_insn_arm);
 
This page took 0.03176 seconds and 4 git commands to generate.