* varobj.c (install_new_value): Only call value_get_print_value
[deliverable/binutils-gdb.git] / gdb / arm-tdep.c
index ba713f21419cd5e4f2611fb111e701e6a120acad..7b92cd7975ce1d16b977183b49e6d325c2c163b9 100644 (file)
@@ -1,7 +1,7 @@
 /* Common target dependent code for GDB on ARM systems.
 
-   Copyright 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1998, 1999, 2000,
+   2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -17,8 +17,8 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 #include <ctype.h>             /* XXX for isupper () */
 
@@ -39,6 +39,8 @@
 #include "trad-frame.h"
 #include "objfiles.h"
 #include "dwarf2-frame.h"
+#include "gdbtypes.h"
+#include "prologue-value.h"
 
 #include "arm-tdep.h"
 #include "gdb/sim-arm.h"
 
 static int arm_debug;
 
-/* Each OS has a different mechanism for accessing the various
-   registers stored in the sigcontext structure.
-
-   SIGCONTEXT_REGISTER_ADDRESS should be defined to the name (or
-   function pointer) which may be used to determine the addresses
-   of the various saved registers in the sigcontext structure.
-
-   For the ARM target, there are three parameters to this function. 
-   The first is the pc value of the frame under consideration, the
-   second the stack pointer of this frame, and the last is the
-   register number to fetch.  
-
-   If the tm.h file does not define this macro, then it's assumed that
-   no mechanism is needed and we define SIGCONTEXT_REGISTER_ADDRESS to
-   be 0. 
-   
-   When it comes time to multi-arching this code, see the identically
-   named machinery in ia64-tdep.c for an example of how it could be
-   done.  It should not be necessary to modify the code below where
-   this macro is used.  */
-
-#ifdef SIGCONTEXT_REGISTER_ADDRESS
-#ifndef SIGCONTEXT_REGISTER_ADDRESS_P
-#define SIGCONTEXT_REGISTER_ADDRESS_P() 1
-#endif
-#else
-#define SIGCONTEXT_REGISTER_ADDRESS(SP,PC,REG) 0
-#define SIGCONTEXT_REGISTER_ADDRESS_P() 0
-#endif
-
 /* Macros for setting and testing a bit in a minimal symbol that marks
    it as Thumb function.  The MSB of the minimal symbol's "info" field
    is used for this purpose.
@@ -240,95 +212,156 @@ arm_smash_text_address (CORE_ADDR val)
   return val & ~1;
 }
 
-/* Immediately after a function call, return the saved pc.  Can't
-   always go through the frames for this because on some machines the
-   new frame is not set up until the new function executes some
-   instructions.  */
-
-static CORE_ADDR
-arm_saved_pc_after_call (struct frame_info *frame)
-{
-  return ADDR_BITS_REMOVE (read_register (ARM_LR_REGNUM));
-}
-
-/* A typical Thumb prologue looks like this:
-   push    {r7, lr}
-   add     sp, sp, #-28
-   add     r7, sp, #12
-   Sometimes the latter instruction may be replaced by:
-   mov     r7, sp
-   
-   or like this:
-   push    {r7, lr}
-   mov     r7, sp
-   sub    sp, #12
-   
-   or, on tpcs, like this:
-   sub     sp,#16
-   push    {r7, lr}
-   (many instructions)
-   mov     r7, sp
-   sub    sp, #12
-
-   There is always one instruction of three classes:
-   1 - push
-   2 - setting of r7
-   3 - adjusting of sp
-   
-   When we have found at least one of each class we are done with the prolog.
-   Note that the "sub sp, #NN" before the push does not count.
-   */
+/* Analyze a Thumb prologue, looking for a recognizable stack frame
+   and frame pointer.  Scan until we encounter a store that could
+   clobber the stack frame unexpectedly, or an unknown instruction.  */
 
 static CORE_ADDR
-thumb_skip_prologue (CORE_ADDR pc, CORE_ADDR func_end)
+thumb_analyze_prologue (struct gdbarch *gdbarch,
+                       CORE_ADDR start, CORE_ADDR limit,
+                       struct arm_prologue_cache *cache)
 {
-  CORE_ADDR current_pc;
-  /* findmask:
-     bit 0 - push { rlist }
-     bit 1 - mov r7, sp  OR  add r7, sp, #imm  (setting of r7)
-     bit 2 - sub sp, #simm  OR  add sp, #simm  (adjusting of sp)
-  */
-  int findmask = 0;
+  int i;
+  pv_t regs[16];
+  struct pv_area *stack;
+  struct cleanup *back_to;
+  CORE_ADDR offset;
 
-  for (current_pc = pc;
-       current_pc + 2 < func_end && current_pc < pc + 40;
-       current_pc += 2)
+  for (i = 0; i < 16; i++)
+    regs[i] = pv_register (i, 0);
+  stack = make_pv_area (ARM_SP_REGNUM);
+  back_to = make_cleanup_free_pv_area (stack);
+
+  /* The call instruction saved PC in LR, and the current PC is not
+     interesting.  Due to this file's conventions, we want the value
+     of LR at this function's entry, not at the call site, so we do
+     not record the save of the PC - when the ARM prologue analyzer
+     has also been converted to the pv mechanism, we could record the
+     save here and remove the hack in prev_register.  */
+  regs[ARM_PC_REGNUM] = pv_unknown ();
+
+  while (start < limit)
     {
-      unsigned short insn = read_memory_unsigned_integer (current_pc, 2);
+      unsigned short insn;
+
+      insn = read_memory_unsigned_integer (start, 2);
 
       if ((insn & 0xfe00) == 0xb400)           /* push { rlist } */
        {
-         findmask |= 1;                        /* push found */
+         int regno;
+         int mask;
+         int stop = 0;
+
+         /* Bits 0-7 contain a mask for registers R0-R7.  Bit 8 says
+            whether to save LR (R14).  */
+         mask = (insn & 0xff) | ((insn & 0x100) << 6);
+
+         /* Calculate offsets of saved R0-R7 and LR.  */
+         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 */
        {
-         if ((findmask & 1) == 0)              /* before push ? */
-           continue;
+         offset = (insn & 0x7f) << 2;          /* get scaled offset */
+         if (insn & 0x80)                      /* Check for SUB.  */
+           regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM],
+                                                  -offset);
          else
-           findmask |= 4;                      /* add/sub sp found */
+           regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM],
+                                                  offset);
        }
       else if ((insn & 0xff00) == 0xaf00)      /* add r7, sp, #imm */
+       regs[THUMB_FP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM],
+                                                (insn & 0xff) << 2);
+      else if ((insn & 0xff00) == 0x4600)      /* mov hi, lo or mov lo, hi */
        {
-         findmask |= 2;                        /* setting of r7 found */
+         int dst_reg = (insn & 0x7) + ((insn & 0x80) >> 4);
+         int src_reg = (insn & 0x78) >> 3;
+         regs[dst_reg] = regs[src_reg];
        }
-      else if (insn == 0x466f)                 /* mov r7, sp */
+      else if ((insn & 0xf800) == 0x9000)      /* str rd, [sp, #off] */
        {
-         findmask |= 2;                        /* setting of r7 found */
+         /* Handle stores to the stack.  Normally pushes are used,
+            but with GCC -mtpcs-frame, there may be other stores
+            in the prologue to create the frame.  */
+         int regno = (insn >> 8) & 0x7;
+         pv_t addr;
+
+         offset = (insn & 0xff) << 2;
+         addr = pv_add_constant (regs[ARM_SP_REGNUM], offset);
+
+         if (pv_area_store_would_trash (stack, addr))
+           break;
+
+         pv_area_store (stack, addr, 4, regs[regno]);
        }
-      else if (findmask == (4+2+1))
+      else
        {
-         /* We have found one of each type of prologue instruction */
+         /* We don't know what this instruction is.  We're finished
+            scanning.  NOTE: Recognizing more safe-to-ignore
+            instructions here will improve support for optimized
+            code.  */
          break;
        }
-      else
-       /* Something in the prolog that we don't care about or some
-          instruction from outside the prolog scheduled here for
-          optimization.  */
-       continue;
+
+      start += 2;
+    }
+
+  if (cache == NULL)
+    {
+      do_cleanups (back_to);
+      return start;
     }
 
-  return current_pc;
+  /* 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.  */
+      cache->framereg = ARM_FP_REGNUM;
+      cache->framesize = -regs[ARM_FP_REGNUM].k;
+    }
+  else if (pv_is_register (regs[THUMB_FP_REGNUM], ARM_SP_REGNUM))
+    {
+      /* Frame pointer is r7.  Frame size is constant.  */
+      cache->framereg = THUMB_FP_REGNUM;
+      cache->framesize = -regs[THUMB_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
+    {
+      /* We're just out of luck.  We don't know where the frame is.  */
+      cache->framereg = -1;
+      cache->framesize = 0;
+    }
+
+  for (i = 0; i < 16; i++)
+    if (pv_area_find_reg (stack, gdbarch, i, &offset))
+      cache->saved_regs[i].addr = offset;
+
+  do_cleanups (back_to);
+  return start;
 }
 
 /* Advance the PC across any function entry prologue instructions to
@@ -376,10 +409,6 @@ arm_skip_prologue (CORE_ADDR pc)
         }
     }
 
-  /* Check if this is Thumb code.  */
-  if (arm_pc_is_thumb (pc))
-    return thumb_skip_prologue (pc, func_end);
-
   /* Can't find the prologue end in the symbol table, try it the hard way
      by disassembling the instructions.  */
 
@@ -387,9 +416,13 @@ arm_skip_prologue (CORE_ADDR pc)
   if (func_end == 0 || func_end > pc + 64)
     func_end = pc + 64;
 
+  /* Check if this is Thumb code.  */
+  if (arm_pc_is_thumb (pc))
+    return thumb_analyze_prologue (current_gdbarch, pc, func_end, NULL);
+
   for (skip_pc = pc; skip_pc < func_end; skip_pc += 4)
     {
-      inst = read_memory_integer (skip_pc, 4);
+      inst = read_memory_unsigned_integer (skip_pc, 4);
 
       /* "mov ip, sp" is no longer a required part of the prologue.  */
       if (inst == 0xe1a0c00d)                  /* mov ip, sp */
@@ -495,92 +528,14 @@ thumb_scan_prologue (CORE_ADDR prev_pc, struct arm_prologue_cache *cache)
        prologue_end = sal.end;         /* (probably means no prologue)  */
     }
   else
-    /* We're in the boondocks: allow for 
-       16 pushes, an add, and "mv fp,sp".  */
-    prologue_end = prologue_start + 40;
+    /* We're in the boondocks: we have no idea where the start of the
+       function is.  */
+    return;
 
   prologue_end = min (prologue_end, prev_pc);
 
-  /* Initialize the saved register map.  When register H is copied to
-     register L, we will put H in saved_reg[L].  */
-  for (i = 0; i < 16; i++)
-    saved_reg[i] = i;
-
-  /* Search the prologue looking for instructions that set up the
-     frame pointer, adjust the stack pointer, and save registers.
-     Do this until all basic prolog instructions are found.  */
-
-  cache->framesize = 0;
-  for (current_pc = prologue_start;
-       (current_pc < prologue_end) && ((findmask & 7) != 7);
-       current_pc += 2)
-    {
-      unsigned short insn;
-      int regno;
-      int offset;
-
-      insn = read_memory_unsigned_integer (current_pc, 2);
-
-      if ((insn & 0xfe00) == 0xb400)   /* push { rlist } */
-       {
-         int mask;
-         findmask |= 1;                /* push found */
-         /* Bits 0-7 contain a mask for registers R0-R7.  Bit 8 says
-            whether to save LR (R14).  */
-         mask = (insn & 0xff) | ((insn & 0x100) << 6);
-
-         /* Calculate offsets of saved R0-R7 and LR.  */
-         for (regno = ARM_LR_REGNUM; regno >= 0; regno--)
-           if (mask & (1 << regno))
-             {
-               cache->framesize += 4;
-               cache->saved_regs[saved_reg[regno]].addr = -cache->framesize;
-               /* Reset saved register map.  */
-               saved_reg[regno] = regno;
-             }
-       }
-      else if ((insn & 0xff00) == 0xb000)      /* add sp, #simm  OR  
-                                                  sub sp, #simm */
-       {
-         if ((findmask & 1) == 0)              /* before push?  */
-           continue;
-         else
-           findmask |= 4;                      /* add/sub sp found */
-         
-         offset = (insn & 0x7f) << 2;          /* get scaled offset */
-         if (insn & 0x80)              /* is it signed? (==subtracting) */
-           {
-             cache->frameoffset += offset;
-             offset = -offset;
-           }
-         cache->framesize -= offset;
-       }
-      else if ((insn & 0xff00) == 0xaf00)      /* add r7, sp, #imm */
-       {
-         findmask |= 2;                        /* setting of r7 found */
-         cache->framereg = THUMB_FP_REGNUM;
-         /* get scaled offset */
-         cache->frameoffset = (insn & 0xff) << 2;
-       }
-      else if (insn == 0x466f)                 /* mov r7, sp */
-       {
-         findmask |= 2;                        /* setting of r7 found */
-         cache->framereg = THUMB_FP_REGNUM;
-         cache->frameoffset = 0;
-         saved_reg[THUMB_FP_REGNUM] = ARM_SP_REGNUM;
-       }
-      else if ((insn & 0xffc0) == 0x4640)      /* mov r0-r7, r8-r15 */
-       {
-         int lo_reg = insn & 7;                /* dest.  register (r0-r7) */
-         int hi_reg = ((insn >> 3) & 7) + 8;   /* source register (r8-15) */
-         saved_reg[lo_reg] = hi_reg;           /* remember hi reg was saved */
-       }
-      else
-       /* Something in the prolog that we don't care about or some
-          instruction from outside the prolog scheduled here for
-          optimization.  */ 
-       continue;
-    }
+  thumb_analyze_prologue (current_gdbarch, prologue_start, prologue_end,
+                         cache);
 }
 
 /* This function decodes an ARM function prologue to determine:
@@ -894,7 +849,7 @@ arm_make_prologue_cache (struct frame_info *next_frame)
   struct arm_prologue_cache *cache;
   CORE_ADDR unwound_fp;
 
-  cache = frame_obstack_zalloc (sizeof (struct arm_prologue_cache));
+  cache = FRAME_OBSTACK_ZALLOC (struct arm_prologue_cache);
   cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
 
   arm_scan_prologue (next_frame, cache);
@@ -1001,7 +956,7 @@ arm_make_stub_cache (struct frame_info *next_frame)
   struct arm_prologue_cache *cache;
   CORE_ADDR unwound_fp;
 
-  cache = frame_obstack_zalloc (sizeof (struct arm_prologue_cache));
+  cache = FRAME_OBSTACK_ZALLOC (struct arm_prologue_cache);
   cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
 
   cache->prev_sp = frame_unwind_register_unsigned (next_frame, ARM_SP_REGNUM);
@@ -1063,84 +1018,6 @@ struct frame_base arm_normal_base = {
   arm_normal_frame_base
 };
 
-static struct arm_prologue_cache *
-arm_make_sigtramp_cache (struct frame_info *next_frame)
-{
-  struct arm_prologue_cache *cache;
-  int reg;
-
-  cache = frame_obstack_zalloc (sizeof (struct arm_prologue_cache));
-
-  cache->prev_sp = frame_unwind_register_unsigned (next_frame, ARM_SP_REGNUM);
-
-  cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
-
-  for (reg = 0; reg < NUM_REGS; reg++)
-    cache->saved_regs[reg].addr
-      = SIGCONTEXT_REGISTER_ADDRESS (cache->prev_sp,
-                                    frame_pc_unwind (next_frame), reg);
-
-  /* FIXME: What about thumb mode?  */
-  cache->framereg = ARM_SP_REGNUM;
-  cache->prev_sp
-    = read_memory_integer (cache->saved_regs[cache->framereg].addr,
-                          register_size (current_gdbarch, cache->framereg));
-
-  return cache;
-}
-
-static void
-arm_sigtramp_this_id (struct frame_info *next_frame,
-                     void **this_cache,
-                     struct frame_id *this_id)
-{
-  struct arm_prologue_cache *cache;
-
-  if (*this_cache == NULL)
-    *this_cache = arm_make_sigtramp_cache (next_frame);
-  cache = *this_cache;
-
-  /* FIXME drow/2003-07-07: This isn't right if we single-step within
-     the sigtramp frame; the PC should be the beginning of the trampoline.  */
-  *this_id = frame_id_build (cache->prev_sp, frame_pc_unwind (next_frame));
-}
-
-static void
-arm_sigtramp_prev_register (struct frame_info *next_frame,
-                           void **this_cache,
-                           int prev_regnum,
-                           int *optimized,
-                           enum lval_type *lvalp,
-                           CORE_ADDR *addrp,
-                           int *realnump,
-                           gdb_byte *valuep)
-{
-  struct arm_prologue_cache *cache;
-
-  if (*this_cache == NULL)
-    *this_cache = arm_make_sigtramp_cache (next_frame);
-  cache = *this_cache;
-
-  trad_frame_get_prev_register (next_frame, cache->saved_regs, prev_regnum,
-                               optimized, lvalp, addrp, realnump, valuep);
-}
-
-struct frame_unwind arm_sigtramp_unwind = {
-  SIGTRAMP_FRAME,
-  arm_sigtramp_this_id,
-  arm_sigtramp_prev_register
-};
-
-static const struct frame_unwind *
-arm_sigtramp_unwind_sniffer (struct frame_info *next_frame)
-{
-  if (SIGCONTEXT_REGISTER_ADDRESS_P ()
-      && legacy_pc_in_sigtramp (frame_pc_unwind (next_frame), (char *) 0))
-    return &arm_sigtramp_unwind;
-
-  return NULL;
-}
-
 /* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that
    dummy frame.  The frame ID's base needs to match the TOS value
    saved by save_dummy_frame_tos() and returned from
@@ -1163,7 +1040,7 @@ arm_unwind_pc (struct gdbarch *gdbarch, struct frame_info *this_frame)
 {
   CORE_ADDR pc;
   pc = frame_unwind_register_unsigned (this_frame, ARM_PC_REGNUM);
-  return IS_THUMB_ADDR (pc) ? UNMAKE_THUMB_ADDR (pc) : pc;
+  return arm_addr_bits_remove (pc);
 }
 
 static CORE_ADDR
@@ -1280,11 +1157,6 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   argreg = ARM_A1_REGNUM;
   nstack = 0;
 
-  /* Some platforms require a double-word aligned stack.  Make sure sp
-     is correctly aligned before we start.  We always do this even if
-     it isn't really needed -- it can never hurt things.  */
-  sp &= ~(CORE_ADDR)(2 * DEPRECATED_REGISTER_SIZE - 1);
-
   /* The struct_return pointer occupies the first parameter
      passing register.  */
   if (struct_return)
@@ -1406,6 +1278,17 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   return sp;
 }
 
+
+/* Always align the frame to an 8-byte boundary.  This is required on
+   some platforms and harmless on the rest.  */
+
+static CORE_ADDR
+arm_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
+{
+  /* Align the stack to eight bytes.  */
+  return sp & ~ (CORE_ADDR) 7;
+}
+
 static void
 print_fpu_flags (int flags)
 {
@@ -1451,14 +1334,13 @@ static struct type *
 arm_register_type (struct gdbarch *gdbarch, int regnum)
 {
   if (regnum >= ARM_F0_REGNUM && regnum < ARM_F0_REGNUM + NUM_FREGS)
-    {
-      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
-       return builtin_type_arm_ext_big;
-      else
-       return builtin_type_arm_ext_littlebyte_bigword;
-    }
+    return builtin_type_arm_ext;
+  else if (regnum == ARM_SP_REGNUM)
+    return builtin_type_void_data_ptr;
+  else if (regnum == ARM_PC_REGNUM)
+    return builtin_type_void_func_ptr;
   else
-    return builtin_type_int32;
+    return builtin_type_uint32;
 }
 
 /* Index within `registers' of the first byte of the space for
@@ -1647,7 +1529,7 @@ CORE_ADDR
 thumb_get_next_pc (CORE_ADDR pc)
 {
   unsigned long pc_val = ((unsigned long) pc) + 4;     /* PC after prefetch */
-  unsigned short inst1 = read_memory_integer (pc, 2);
+  unsigned short inst1 = read_memory_unsigned_integer (pc, 2);
   CORE_ADDR nextpc = pc + 2;           /* default is next instruction */
   unsigned long offset;
 
@@ -1659,7 +1541,7 @@ thumb_get_next_pc (CORE_ADDR pc)
          all of the other registers.  */
       offset = bitcount (bits (inst1, 0, 7)) * DEPRECATED_REGISTER_SIZE;
       sp = read_register (ARM_SP_REGNUM);
-      nextpc = (CORE_ADDR) read_memory_integer (sp + offset, 4);
+      nextpc = (CORE_ADDR) read_memory_unsigned_integer (sp + offset, 4);
       nextpc = ADDR_BITS_REMOVE (nextpc);
       if (nextpc == pc)
        error (_("Infinite loop detected"));
@@ -1677,7 +1559,7 @@ thumb_get_next_pc (CORE_ADDR pc)
     }
   else if ((inst1 & 0xf800) == 0xf000) /* long branch with link, and blx */
     {
-      unsigned short inst2 = read_memory_integer (pc + 2, 2);
+      unsigned short inst2 = read_memory_unsigned_integer (pc + 2, 2);
       offset = (sbits (inst1, 0, 10) << 12) + (bits (inst2, 0, 10) << 1);
       nextpc = pc_val + offset;
       /* For BLX make sure to clear the low bits.  */
@@ -1711,7 +1593,7 @@ arm_get_next_pc (CORE_ADDR pc)
     return thumb_get_next_pc (pc);
 
   pc_val = (unsigned long) pc;
-  this_instr = read_memory_integer (pc, 4);
+  this_instr = read_memory_unsigned_integer (pc, 4);
   status = read_register (ARM_PS_REGNUM);
   nextpc = (CORE_ADDR) (pc_val + 4);   /* Default case */
 
@@ -1736,8 +1618,8 @@ arm_get_next_pc (CORE_ADDR pc)
              error (_("Invalid update to pc in instruction"));
 
            /* BX <reg>, BLX <reg> */
-           if (bits (this_instr, 4, 28) == 0x12fff1
-               || bits (this_instr, 4, 28) == 0x12fff3)
+           if (bits (this_instr, 4, 27) == 0x12fff1
+               || bits (this_instr, 4, 27) == 0x12fff3)
              {
                rn = bits (this_instr, 0, 3);
                result = (rn == 15) ? pc_val + 8 : read_register (rn);
@@ -1950,16 +1832,18 @@ arm_get_next_pc (CORE_ADDR pc)
 static void
 arm_software_single_step (enum target_signal sig, int insert_bpt)
 {
-  static int next_pc;           /* State between setting and unsetting.  */
-  static char break_mem[BREAKPOINT_MAX]; /* Temporary storage for mem@bpt */
+  /* 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)
     {
-      next_pc = arm_get_next_pc (read_register (ARM_PC_REGNUM));
-      target_insert_breakpoint (next_pc, break_mem);
+      CORE_ADDR next_pc = arm_get_next_pc (read_register (ARM_PC_REGNUM));
+
+      insert_single_step_breakpoint (next_pc);
     }
   else
-    target_remove_breakpoint (next_pc, break_mem);
+    remove_single_step_breakpoints ();
 }
 
 #include "bfd-in2.h"
@@ -2063,11 +1947,6 @@ static const char arm_default_thumb_be_breakpoint[] = THUMB_BE_BREAKPOINT;
    necessary) to point to the actual memory location where the
    breakpoint should be inserted.  */
 
-/* XXX ??? from old tm-arm.h: if we're using RDP, then we're inserting
-   breakpoints and storing their handles instread of what was in
-   memory.  It is nice that this is the same size as a handle -
-   otherwise remote-rdp will have to change.  */
-
 static const unsigned char *
 arm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
 {
@@ -2366,14 +2245,17 @@ arm_store_return_value (struct type *type, struct regcache *regs,
 
 static enum return_value_convention
 arm_return_value (struct gdbarch *gdbarch, struct type *valtype,
-                 struct regcache *regcache, void *readbuf,
-                 const void *writebuf)
+                 struct regcache *regcache, gdb_byte *readbuf,
+                 const gdb_byte *writebuf)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
   if (TYPE_CODE (valtype) == TYPE_CODE_STRUCT
       || TYPE_CODE (valtype) == TYPE_CODE_UNION
       || TYPE_CODE (valtype) == TYPE_CODE_ARRAY)
     {
-      if (arm_return_in_memory (gdbarch, valtype))
+      if (tdep->struct_return == pcc_struct_return
+         || arm_return_in_memory (gdbarch, valtype))
        return RETURN_VALUE_STRUCT_CONVENTION;
     }
 
@@ -2704,7 +2586,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   if (arm_abi == ARM_ABI_AUTO && info.abfd != NULL)
     {
-      int ei_osabi;
+      int ei_osabi, e_flags;
 
       switch (bfd_get_flavour (info.abfd))
        {
@@ -2721,19 +2603,18 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
        case bfd_target_elf_flavour:
          ei_osabi = elf_elfheader (info.abfd)->e_ident[EI_OSABI];
+         e_flags = elf_elfheader (info.abfd)->e_flags;
+
          if (ei_osabi == ELFOSABI_ARM)
            {
              /* GNU tools used to use this value, but do not for EABI
-                objects.  There's nowhere to tag an EABI version anyway,
-                so assume APCS.  */
+                objects.  There's nowhere to tag an EABI version
+                anyway, so assume APCS.  */
              arm_abi = ARM_ABI_APCS;
            }
          else if (ei_osabi == ELFOSABI_NONE)
            {
-             int e_flags, eabi_ver;
-
-             e_flags = elf_elfheader (info.abfd)->e_flags;
-             eabi_ver = EF_ARM_EABI_VERSION (e_flags);
+             int eabi_ver = EF_ARM_EABI_VERSION (e_flags);
 
              switch (eabi_ver)
                {
@@ -2743,6 +2624,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                  break;
 
                case EF_ARM_EABI_VER4:
+               case EF_ARM_EABI_VER5:
                  arm_abi = ARM_ABI_AAPCS;
                  /* EABI binaries default to VFP float ordering.  */
                  if (fp_model == ARM_FLOAT_AUTO)
@@ -2750,8 +2632,32 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                  break;
 
                default:
+                 /* Leave it as "auto".  */
                  warning (_("unknown ARM EABI version 0x%x"), eabi_ver);
-                 arm_abi = ARM_ABI_APCS;
+                 break;
+               }
+           }
+
+         if (fp_model == ARM_FLOAT_AUTO)
+           {
+             int e_flags = elf_elfheader (info.abfd)->e_flags;
+
+             switch (e_flags & (EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT))
+               {
+               case 0:
+                 /* Leave it as "auto".  Strictly speaking this case
+                    means FPA, but almost nobody uses that now, and
+                    many toolchains fail to set the appropriate bits
+                    for the floating-point model they use.  */
+                 break;
+               case EF_ARM_SOFT_FLOAT:
+                 fp_model = ARM_FLOAT_SOFT_FPA;
+                 break;
+               case EF_ARM_VFP_FLOAT:
+                 fp_model = ARM_FLOAT_VFP;
+                 break;
+               case EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT:
+                 fp_model = ARM_FLOAT_SOFT_VFP;
                  break;
                }
            }
@@ -2844,7 +2750,12 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->lowest_pc = 0x20;
   tdep->jb_pc = -1;    /* Longjump support not enabled by default.  */
 
+  /* The default, for both APCS and AAPCS, is to return small
+     structures in registers.  */
+  tdep->struct_return = reg_struct_return;
+
   set_gdbarch_push_dummy_call (gdbarch, arm_push_dummy_call);
+  set_gdbarch_frame_align (gdbarch, arm_frame_align);
 
   set_gdbarch_write_pc (gdbarch, arm_write_pc);
 
@@ -2862,9 +2773,6 @@ 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);
 
-  /* Get the PC when a frame might not be available.  */
-  set_gdbarch_deprecated_saved_pc_after_call (gdbarch, arm_saved_pc_after_call);
-
   /* The stack grows downward.  */
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
 
@@ -2902,12 +2810,14 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_coff_make_msymbol_special (gdbarch,
                                         arm_coff_make_msymbol_special);
 
+  /* Virtual tables.  */
+  set_gdbarch_vbit_in_delta (gdbarch, 1);
+
   /* Hook in the ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
 
   /* Add some default predicates.  */
   frame_unwind_append_sniffer (gdbarch, arm_stub_unwind_sniffer);
-  frame_unwind_append_sniffer (gdbarch, arm_sigtramp_unwind_sniffer);
   frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
   frame_unwind_append_sniffer (gdbarch, arm_prologue_unwind_sniffer);
 
@@ -2918,34 +2828,18 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     set_gdbarch_get_longjmp_target (gdbarch, arm_get_longjmp_target);
 
   /* Floating point sizes and format.  */
-  switch (info.byte_order)
+  set_gdbarch_float_format (gdbarch, floatformats_ieee_single);
+  if (fp_model == ARM_FLOAT_SOFT_FPA || fp_model == ARM_FLOAT_FPA)
     {
-    case BFD_ENDIAN_BIG:
-      set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_big);
-      set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_big);
-      set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
-      break;
-
-    case BFD_ENDIAN_LITTLE:
-      set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_little);
-      if (fp_model == ARM_FLOAT_SOFT_FPA || fp_model == ARM_FLOAT_FPA)
-       {
-         set_gdbarch_double_format
-           (gdbarch, &floatformat_ieee_double_littlebyte_bigword);
-         set_gdbarch_long_double_format
-           (gdbarch, &floatformat_ieee_double_littlebyte_bigword);
-       }
-      else
-       {
-         set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_little);
-         set_gdbarch_long_double_format (gdbarch,
-                                         &floatformat_ieee_double_little);
-       }
-      break;
-
-    default:
-      internal_error (__FILE__, __LINE__,
-                     _("arm_gdbarch_init: bad byte order for float format"));
+      set_gdbarch_double_format
+       (gdbarch, floatformats_ieee_double_littlebyte_bigword);
+      set_gdbarch_long_double_format
+       (gdbarch, floatformats_ieee_double_littlebyte_bigword);
+    }
+  else
+    {
+      set_gdbarch_double_format (gdbarch, floatformats_ieee_double);
+      set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
     }
 
   return gdbarch;
This page took 0.033478 seconds and 4 git commands to generate.