2007-11-15 Markus Deuling <deuling@de.ibm.com>
[deliverable/binutils-gdb.git] / gdb / arm-tdep.c
index 325bd80df7ffd5a8f094dcf1e9b39137f3e0dff0..cc3f92eee8506e94701a03725df8a895475638eb 100644 (file)
@@ -187,13 +187,11 @@ struct arm_prologue_cache
      to identify this frame.  */
   CORE_ADDR prev_sp;
 
-  /* The frame base for this frame is just prev_sp + frame offset -
-     frame size.  FRAMESIZE is the size of this stack frame, and
-     FRAMEOFFSET if the initial offset from the stack pointer (this
-     frame's stack pointer, not PREV_SP) to the frame base.  */
+  /* The frame base for this frame is just prev_sp - frame size.
+     FRAMESIZE is the distance from the frame pointer to the
+     initial stack pointer.  */
 
   int framesize;
-  int frameoffset;
 
   /* The register used to hold the frame pointer for this frame.  */
   int framereg;
@@ -292,7 +290,9 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
        {
          int regno;
          int mask;
-         int stop = 0;
+
+         if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+           break;
 
          /* Bits 0-7 contain a mask for registers R0-R7.  Bit 8 says
             whether to save LR (R14).  */
@@ -302,19 +302,10 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
          for (regno = ARM_LR_REGNUM; regno >= 0; regno--)
            if (mask & (1 << regno))
              {
-               if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
-                 {
-                   stop = 1;
-                   break;
-                 }
-
                regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM],
                                                       -4);
                pv_area_store (stack, regs[ARM_SP_REGNUM], 4, regs[regno]);
              }
-
-         if (stop)
-           break;
        }
       else if ((insn & 0xff00) == 0xb000)      /* add sp, #simm  OR  
                                                   sub sp, #simm */
@@ -370,9 +361,6 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
       return start;
     }
 
-  /* frameoffset is unused for this unwinder.  */
-  cache->frameoffset = 0;
-
   if (pv_is_register (regs[ARM_FP_REGNUM], ARM_SP_REGNUM))
     {
       /* Frame pointer is fp.  Frame size is constant.  */
@@ -648,16 +636,21 @@ thumb_scan_prologue (CORE_ADDR prev_pc, struct arm_prologue_cache *cache)
  */
 
 static void
-arm_scan_prologue (struct frame_info *next_frame, struct arm_prologue_cache *cache)
+arm_scan_prologue (struct frame_info *next_frame,
+                  struct arm_prologue_cache *cache)
 {
-  int regno, sp_offset, fp_offset, ip_offset;
+  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  int regno;
   CORE_ADDR prologue_start, prologue_end, current_pc;
   CORE_ADDR prev_pc = frame_pc_unwind (next_frame);
+  pv_t regs[ARM_FPS_REGNUM];
+  struct pv_area *stack;
+  struct cleanup *back_to;
+  CORE_ADDR offset;
 
   /* Assume there is no frame until proven otherwise.  */
   cache->framereg = ARM_SP_REGNUM;
   cache->framesize = 0;
-  cache->frameoffset = 0;
 
   /* Check for Thumb prologue.  */
   if (arm_pc_is_thumb (prev_pc))
@@ -723,7 +716,7 @@ arm_scan_prologue (struct frame_info *next_frame, struct arm_prologue_cache *cac
       else
         {
           prologue_start = gdbarch_addr_bits_remove 
-                            (current_gdbarch, return_value) - 8;
+                            (gdbarch, return_value) - 8;
           prologue_end = prologue_start + 64;  /* See above.  */
         }
     }
@@ -752,7 +745,12 @@ arm_scan_prologue (struct frame_info *next_frame, struct arm_prologue_cache *cac
      in which case it is often (but not always) replaced by
      "str lr, [sp, #-4]!".  - Michael Snyder, 2002-04-23]  */
 
-  sp_offset = fp_offset = ip_offset = 0;
+  for (regno = 0; regno < ARM_FPS_REGNUM; regno++)
+    regs[regno] = pv_register (regno, 0);
+  stack = make_pv_area (ARM_SP_REGNUM);
+  back_to = make_cleanup_free_pv_area (stack);
+
+  regs[ARM_PC_REGNUM] = pv_unknown ();
 
   for (current_pc = prologue_start;
        current_pc < prologue_end;
@@ -762,7 +760,7 @@ arm_scan_prologue (struct frame_info *next_frame, struct arm_prologue_cache *cac
 
       if (insn == 0xe1a0c00d)          /* mov ip, sp */
        {
-         ip_offset = 0;
+         regs[ARM_IP_REGNUM] = regs[ARM_SP_REGNUM];
          continue;
        }
       else if ((insn & 0xfffff000) == 0xe28dc000) /* add ip, sp #n */
@@ -770,7 +768,7 @@ arm_scan_prologue (struct frame_info *next_frame, struct arm_prologue_cache *cac
          unsigned imm = insn & 0xff;                   /* immediate value */
          unsigned rot = (insn & 0xf00) >> 7;           /* rotate amount */
          imm = (imm >> rot) | (imm << (32 - rot));
-         ip_offset = imm;
+         regs[ARM_IP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], imm);
          continue;
        }
       else if ((insn & 0xfffff000) == 0xe24dc000) /* sub ip, sp #n */
@@ -778,13 +776,15 @@ arm_scan_prologue (struct frame_info *next_frame, struct arm_prologue_cache *cac
          unsigned imm = insn & 0xff;                   /* immediate value */
          unsigned rot = (insn & 0xf00) >> 7;           /* rotate amount */
          imm = (imm >> rot) | (imm << (32 - rot));
-         ip_offset = -imm;
+         regs[ARM_IP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -imm);
          continue;
        }
       else if (insn == 0xe52de004)     /* str lr, [sp, #-4]! */
        {
-         sp_offset -= 4;
-         cache->saved_regs[ARM_LR_REGNUM].addr = sp_offset;
+         if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+           break;
+         regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -4);
+         pv_area_store (stack, regs[ARM_SP_REGNUM], 4, regs[ARM_LR_REGNUM]);
          continue;
        }
       else if ((insn & 0xffff0000) == 0xe92d0000)
@@ -794,12 +794,15 @@ arm_scan_prologue (struct frame_info *next_frame, struct arm_prologue_cache *cac
        {
          int mask = insn & 0xffff;
 
+         if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+           break;
+
          /* Calculate offsets of saved registers.  */
          for (regno = ARM_PC_REGNUM; regno >= 0; regno--)
            if (mask & (1 << regno))
              {
-               sp_offset -= 4;
-               cache->saved_regs[regno].addr = sp_offset;
+               regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -4);
+               pv_area_store (stack, regs[ARM_SP_REGNUM], 4, regs[regno]);
              }
        }
       else if ((insn & 0xffffc000) == 0xe54b0000 ||    /* strb rx,[r11,#-n] */
@@ -821,29 +824,34 @@ arm_scan_prologue (struct frame_info *next_frame, struct arm_prologue_cache *cac
          unsigned imm = insn & 0xff;                   /* immediate value */
          unsigned rot = (insn & 0xf00) >> 7;           /* rotate amount */
          imm = (imm >> rot) | (imm << (32 - rot));
-         fp_offset = -imm + ip_offset;
-         cache->framereg = ARM_FP_REGNUM;
+         regs[ARM_FP_REGNUM] = pv_add_constant (regs[ARM_IP_REGNUM], -imm);
        }
       else if ((insn & 0xfffff000) == 0xe24dd000)      /* sub sp, sp #n */
        {
          unsigned imm = insn & 0xff;                   /* immediate value */
          unsigned rot = (insn & 0xf00) >> 7;           /* rotate amount */
          imm = (imm >> rot) | (imm << (32 - rot));
-         sp_offset -= imm;
+         regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -imm);
        }
       else if ((insn & 0xffff7fff) == 0xed6d0103       /* stfe f?, [sp, -#c]! */
-              && gdbarch_tdep (current_gdbarch)->have_fpa_registers)
+              && gdbarch_tdep (gdbarch)->have_fpa_registers)
        {
-         sp_offset -= 12;
+         if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+           break;
+
+         regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -12);
          regno = ARM_F0_REGNUM + ((insn >> 12) & 0x07);
-         cache->saved_regs[regno].addr = sp_offset;
+         pv_area_store (stack, regs[ARM_SP_REGNUM], 12, regs[regno]);
        }
       else if ((insn & 0xffbf0fff) == 0xec2d0200       /* sfmfd f0, 4, [sp!] */
-              && gdbarch_tdep (current_gdbarch)->have_fpa_registers)
+              && gdbarch_tdep (gdbarch)->have_fpa_registers)
        {
          int n_saved_fp_regs;
          unsigned int fp_start_reg, fp_bound_reg;
 
+         if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+           break;
+
          if ((insn & 0x800) == 0x800)          /* N0 is set */
            {
              if ((insn & 0x40000) == 0x40000)  /* N1 is set */
@@ -863,8 +871,9 @@ arm_scan_prologue (struct frame_info *next_frame, struct arm_prologue_cache *cac
          fp_bound_reg = fp_start_reg + n_saved_fp_regs;
          for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
            {
-             sp_offset -= 12;
-             cache->saved_regs[fp_start_reg++].addr = sp_offset;
+             regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -12);
+             pv_area_store (stack, regs[ARM_SP_REGNUM], 12,
+                            regs[fp_start_reg++]);
            }
        }
       else if ((insn & 0xf0000000) != 0xe0000000)
@@ -877,14 +886,32 @@ arm_scan_prologue (struct frame_info *next_frame, struct arm_prologue_cache *cac
        continue;
     }
 
-  /* The frame size is just the negative of the offset (from the
-     original SP) of the last thing thing we pushed on the stack. 
-     The frame offset is [new FP] - [new SP].  */
-  cache->framesize = -sp_offset;
-  if (cache->framereg == ARM_FP_REGNUM)
-    cache->frameoffset = fp_offset - sp_offset;
+  /* The frame size is just the distance from the frame register
+     to the original stack pointer.  */
+  if (pv_is_register (regs[ARM_FP_REGNUM], ARM_SP_REGNUM))
+    {
+      /* Frame pointer is fp.  */
+      cache->framereg = ARM_FP_REGNUM;
+      cache->framesize = -regs[ARM_FP_REGNUM].k;
+    }
+  else if (pv_is_register (regs[ARM_SP_REGNUM], ARM_SP_REGNUM))
+    {
+      /* Try the stack pointer... this is a bit desperate.  */
+      cache->framereg = ARM_SP_REGNUM;
+      cache->framesize = -regs[ARM_SP_REGNUM].k;
+    }
   else
-    cache->frameoffset = 0;
+    {
+      /* We're just out of luck.  We don't know where the frame is.  */
+      cache->framereg = -1;
+      cache->framesize = 0;
+    }
+
+  for (regno = 0; regno < ARM_FPS_REGNUM; regno++)
+    if (pv_area_find_reg (stack, gdbarch, regno, &offset))
+      cache->saved_regs[regno].addr = offset;
+
+  do_cleanups (back_to);
 }
 
 static struct arm_prologue_cache *
@@ -903,11 +930,11 @@ arm_make_prologue_cache (struct frame_info *next_frame)
   if (unwound_fp == 0)
     return cache;
 
-  cache->prev_sp = unwound_fp + cache->framesize - cache->frameoffset;
+  cache->prev_sp = unwound_fp + cache->framesize;
 
   /* Calculate actual addresses of saved registers using offsets
      determined by arm_scan_prologue.  */
-  for (reg = 0; reg < gdbarch_num_regs (current_gdbarch); reg++)
+  for (reg = 0; reg < gdbarch_num_regs (get_frame_arch (next_frame)); reg++)
     if (trad_frame_addr_p (cache->saved_regs, reg))
       cache->saved_regs[reg].addr += cache->prev_sp;
 
@@ -934,7 +961,7 @@ arm_prologue_this_id (struct frame_info *next_frame,
 
   /* This is meant to halt the backtrace at "_start".  Make sure we
      don't halt it at a generic dummy frame. */
-  if (func <= LOWEST_PC)
+  if (func <= gdbarch_tdep (get_frame_arch (next_frame))->lowest_pc)
     return;
 
   /* If we've hit a wall, stop.  */
@@ -1055,7 +1082,7 @@ arm_normal_frame_base (struct frame_info *next_frame, void **this_cache)
     *this_cache = arm_make_prologue_cache (next_frame);
   cache = *this_cache;
 
-  return cache->prev_sp + cache->frameoffset - cache->framesize;
+  return cache->prev_sp - cache->framesize;
 }
 
 struct frame_base arm_normal_base = {
@@ -1210,7 +1237,7 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
     {
       if (arm_debug)
        fprintf_unfiltered (gdb_stdlog, "struct return in %s = 0x%s\n",
-                           gdbarch_register_name (current_gdbarch, argreg),
+                           gdbarch_register_name (gdbarch, argreg),
                            paddr (struct_addr));
       regcache_cooked_write_unsigned (regcache, argreg, struct_addr);
       argreg++;
@@ -1287,13 +1314,13 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              /* The argument is being passed in a general purpose
                 register.  */
              CORE_ADDR regval = extract_unsigned_integer (val, partial_len);
-             if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
+             if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
                regval <<= (INT_REGISTER_SIZE - partial_len) * 8;
              if (arm_debug)
                fprintf_unfiltered (gdb_stdlog, "arg %d in %s = 0x%s\n",
                                    argnum,
                                    gdbarch_register_name
-                                     (current_gdbarch, argreg),
+                                     (gdbarch, argreg),
                                    phex (regval, INT_REGISTER_SIZE));
              regcache_cooked_write_unsigned (regcache, argreg, regval);
              argreg++;
@@ -1611,6 +1638,7 @@ bitcount (unsigned long val)
 static CORE_ADDR
 thumb_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
 {
+  struct gdbarch *gdbarch = get_frame_arch (frame);
   unsigned long pc_val = ((unsigned long) pc) + 4;     /* PC after prefetch */
   unsigned short inst1 = read_memory_unsigned_integer (pc, 2);
   CORE_ADDR nextpc = pc + 2;           /* default is next instruction */
@@ -1625,7 +1653,7 @@ thumb_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
       offset = bitcount (bits (inst1, 0, 7)) * INT_REGISTER_SIZE;
       sp = get_frame_register_unsigned (frame, ARM_SP_REGNUM);
       nextpc = (CORE_ADDR) read_memory_unsigned_integer (sp + offset, 4);
-      nextpc = gdbarch_addr_bits_remove (current_gdbarch, nextpc);
+      nextpc = gdbarch_addr_bits_remove (gdbarch, nextpc);
       if (nextpc == pc)
        error (_("Infinite loop detected"));
     }
@@ -1656,7 +1684,7 @@ thumb_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
       else
        nextpc = get_frame_register_unsigned (frame, bits (inst1, 3, 6));
 
-      nextpc = gdbarch_addr_bits_remove (current_gdbarch, nextpc);
+      nextpc = gdbarch_addr_bits_remove (gdbarch, nextpc);
       if (nextpc == pc)
        error (_("Infinite loop detected"));
     }
@@ -1667,6 +1695,7 @@ thumb_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
 CORE_ADDR
 arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
 {
+  struct gdbarch *gdbarch = get_frame_arch (frame);
   unsigned long pc_val;
   unsigned long this_instr;
   unsigned long status;
@@ -1690,7 +1719,7 @@ arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
          nextpc = BranchDest (pc, this_instr);
          nextpc |= bit (this_instr, 24) << 1;
 
-         nextpc = gdbarch_addr_bits_remove (current_gdbarch, nextpc);
+         nextpc = gdbarch_addr_bits_remove (gdbarch, nextpc);
          if (nextpc == pc)
            error (_("Infinite loop detected"));
          break;
@@ -1731,7 +1760,7 @@ arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
                result = (rn == 15) ? pc_val + 8
                                    : get_frame_register_unsigned (frame, rn);
                nextpc = (CORE_ADDR) gdbarch_addr_bits_remove
-                                      (current_gdbarch, result);
+                                      (gdbarch, result);
 
                if (nextpc == pc)
                  error (_("Infinite loop detected"));
@@ -1814,7 +1843,7 @@ arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
                break;
              }
            nextpc = (CORE_ADDR) gdbarch_addr_bits_remove
-                                  (current_gdbarch, result);
+                                  (gdbarch, result);
 
            if (nextpc == pc)
              error (_("Infinite loop detected"));
@@ -1858,7 +1887,7 @@ arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
                  nextpc = (CORE_ADDR) read_memory_integer ((CORE_ADDR) base,
                                                            4);
 
-                 nextpc = gdbarch_addr_bits_remove (current_gdbarch, nextpc);
+                 nextpc = gdbarch_addr_bits_remove (gdbarch, nextpc);
 
                  if (nextpc == pc)
                    error (_("Infinite loop detected"));
@@ -1897,7 +1926,7 @@ arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
                                                       4);
                  }
                  nextpc = gdbarch_addr_bits_remove
-                            (current_gdbarch, nextpc);
+                            (gdbarch, nextpc);
                  if (nextpc == pc)
                    error (_("Infinite loop detected"));
                }
@@ -1909,7 +1938,7 @@ arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
          {
            nextpc = BranchDest (pc, this_instr);
 
-           nextpc = gdbarch_addr_bits_remove (current_gdbarch, nextpc);
+           nextpc = gdbarch_addr_bits_remove (gdbarch, nextpc);
            if (nextpc == pc)
              error (_("Infinite loop detected"));
            break;
@@ -2039,9 +2068,9 @@ static const char arm_default_thumb_be_breakpoint[] = THUMB_BE_BREAKPOINT;
    breakpoint should be inserted.  */
 
 static const unsigned char *
-arm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
+arm_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   if (arm_pc_is_thumb (*pcptr))
     {
@@ -2066,7 +2095,7 @@ arm_extract_return_value (struct type *type, struct regcache *regs,
 {
   if (TYPE_CODE_FLT == TYPE_CODE (type))
     {
-      switch (gdbarch_tdep (current_gdbarch)->fp_model)
+      switch (gdbarch_tdep (get_regcache_arch (regs))->fp_model)
        {
        case ARM_FLOAT_FPA:
          {
@@ -2255,7 +2284,7 @@ arm_store_return_value (struct type *type, struct regcache *regs,
     {
       char buf[MAX_REGISTER_SIZE];
 
-      switch (gdbarch_tdep (current_gdbarch)->fp_model)
+      switch (gdbarch_tdep (get_regcache_arch (regs))->fp_model)
        {
        case ARM_FLOAT_FPA:
 
@@ -2567,7 +2596,7 @@ set_disassembly_style_sfunc (char *args, int from_tty,
 \f
 /* Return the ARM register name corresponding to register I.  */
 static const char *
-arm_register_name (int i)
+arm_register_name (struct gdbarch *gdbarch, int i)
 {
   if (i >= ARRAY_SIZE (arm_register_names))
     /* These registers are only supported on targets which supply
@@ -3045,7 +3074,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     }
 
   if (tdesc_data)
-    tdesc_use_registers (gdbarch, tdesc_data);
+    tdesc_use_registers (gdbarch, info.target_desc, tdesc_data);
 
   /* Add standard register aliases.  We add aliases even for those
      nanes which are used by the current architecture - it's simpler,
@@ -3058,9 +3087,9 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 }
 
 static void
-arm_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
+arm_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   if (tdep == NULL)
     return;
This page took 0.029567 seconds and 4 git commands to generate.