Fix typo in gdb.python/py-objfile.exp
[deliverable/binutils-gdb.git] / gdb / nios2-tdep.c
index aa26af97066cad7f7c81747442c8075a72c86c44..1968a88a9f65f7b4ea502cf5ef19d6a244dd6b53 100644 (file)
@@ -1,5 +1,5 @@
 /* Target-machine dependent code for Nios II, for GDB.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Contributed by Peter Brookes (pbrookes@altera.com)
    and Andrew Draper (adraper@altera.com).
    Contributed by Mentor Graphics, Inc.
@@ -589,26 +589,42 @@ nios2_in_epilogue_p (struct gdbarch *gdbarch,
                     CORE_ADDR start_pc)
 {
   unsigned long mach = gdbarch_bfd_arch_info (gdbarch)->mach;
+  /* Maximum number of possibly-epilogue instructions to check.
+     Note that this number should not be too large, else we can
+     potentially end up iterating through unmapped memory.  */
+  int ninsns, max_insns = 5;
   unsigned int insn;
   const struct nios2_opcode *op = NULL;
   unsigned int uimm;
   int imm;
   int ra, rb, rc;
   enum branch_condition cond;
+  CORE_ADDR pc;
 
   /* There has to be a previous instruction in the function.  */
-  if (current_pc > start_pc)
-    {
-      int ok = 0;
+  if (current_pc <= start_pc)
+    return 0;
+
+  /* Find the previous instruction before current_pc.
+     For the moment we will assume that all instructions are the
+     same size here.  */
+  pc = current_pc - NIOS2_OPCODE_SIZE;
 
-      /* Check whether the previous instruction was a stack adjustment.
-        Possible instructions here include:
+  /* Beginning with the previous instruction we just located, check whether
+     we are in a sequence of at least one stack adjustment instruction.
+     Possible instructions here include:
         ADDI sp, sp, n
         ADD sp, sp, rn
         LDW sp, n(sp)  */
-      op = nios2_fetch_insn (gdbarch, current_pc - NIOS2_OPCODE_SIZE, &insn);
+  for (ninsns = 0; ninsns < max_insns; ninsns++)
+    {
+      int ok = 0;
+
+      /* Fetch the insn at pc.  */
+      op = nios2_fetch_insn (gdbarch, pc, &insn);
       if (op == NULL)
        return 0;
+      pc += op->size;
 
       /* Was it a stack adjustment?  */
       if (nios2_match_addi (insn, op, mach, &ra, &rb, &imm))
@@ -618,25 +634,34 @@ nios2_in_epilogue_p (struct gdbarch *gdbarch,
       else if (nios2_match_ldw (insn, op, mach, &ra, &rb, &imm))
        ok = (rb == NIOS2_SP_REGNUM);
       if (!ok)
-       return 0;
-
-      /* Then check if it's followed by a return or a tail call.  */
-      op = nios2_fetch_insn (gdbarch, current_pc, &insn);
-      if (op == NULL)
-       return 0;
-      if (nios2_match_jmpr (insn, op, mach, &ra)
-         || nios2_match_jmpi (insn, op, mach, &uimm)
-         || (nios2_match_branch (insn, op, mach, &ra, &rb, &imm, &cond)
-             && cond == branch_none))
-       return 1;
+       break;
     }
+
+  /* No stack adjustments found.  */
+  if (ninsns == 0)
+    return 0;
+
+  /* We found more stack adjustments than we expect GCC to be generating.
+     Since it looks like a stack unwind might be in progress tell GDB to
+     treat it as such.  */
+  if (ninsns == max_insns)
+    return 1;
+
+  /* The next instruction following the stack adjustments must be a
+     return, jump, or unconditional branch.  */
+  if (nios2_match_jmpr (insn, op, mach, &ra)
+      || nios2_match_jmpi (insn, op, mach, &uimm)
+      || (nios2_match_branch (insn, op, mach, &ra, &rb, &imm, &cond)
+         && cond == branch_none))
+    return 1;
+
   return 0;
 }
 
-/* Implement the in_function_epilogue_p gdbarch method.  */
+/* Implement the stack_frame_destroyed_p gdbarch method.  */
 
 static int
-nios2_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+nios2_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   CORE_ADDR func_addr;
 
@@ -817,6 +842,11 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
              cache->reg_saved[NIOS2_SP_REGNUM].addr = -4;
            }
 
+         else if (rc == NIOS2_SP_REGNUM && ra == NIOS2_FP_REGNUM)
+           /* This is setting SP from FP.  This only happens in the
+              function epilogue.  */
+           break;
+
          else if (rc != 0)
            {
              if (value[rb].reg == 0)
@@ -828,13 +858,21 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
              value[rc].offset = value[ra].offset + value[rb].offset;
            }
 
-         prologue_end = pc;
+         /* The add/move is only considered a prologue instruction
+            if the destination is SP or FP.  */
+         if (rc == NIOS2_SP_REGNUM || rc == NIOS2_FP_REGNUM)
+           prologue_end = pc;
        }
       
       else if (nios2_match_sub (insn, op, mach, &ra, &rb, &rc))
        {
          /* SUB   rc, ra, rb */
-         if (rc != 0)
+         if (rc == NIOS2_SP_REGNUM && rb == NIOS2_SP_REGNUM
+             && value[rc].reg != 0)
+           /* If we are decrementing the SP by a non-constant amount,
+              this is alloca, not part of the prologue.  */
+           break;
+         else if (rc != 0)
            {
              if (value[rb].reg == 0)
                value[rc].reg = value[ra].reg;
@@ -848,12 +886,13 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
        {
          /* ADDI    rb, ra, imm */
 
-         /* The first stack adjustment is part of the prologue.
-            Any subsequent stack adjustments are either down to
-            alloca or the epilogue so stop analysing when we hit
-            them.  */
+         /* A positive stack adjustment has to be part of the epilogue.  */
          if (rb == NIOS2_SP_REGNUM
-             && (value[rb].offset != 0 || value[ra].reg != NIOS2_SP_REGNUM))
+             && (imm > 0 || value[ra].reg != NIOS2_SP_REGNUM))
+           break;
+
+         /* Likewise restoring SP from FP.  */
+         else if (rb == NIOS2_SP_REGNUM && ra == NIOS2_FP_REGNUM)
            break;
 
          if (rb != 0)
@@ -862,7 +901,10 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
              value[rb].offset = value[ra].offset + imm;
            }
 
-         prologue_end = pc;
+         /* The add is only considered a prologue instruction
+            if the destination is SP or FP.  */
+         if (rb == NIOS2_SP_REGNUM || rb == NIOS2_FP_REGNUM)
+           prologue_end = pc;
        }
 
       else if (nios2_match_orhi (insn, op, mach, &ra, &rb, &uimm))
@@ -1147,7 +1189,15 @@ nios2_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
   return nios2_analyze_prologue (gdbarch, start_pc, start_pc, &cache, NULL);
 }
 
-/* Implement the breakpoint_from_pc gdbarch hook.  */
+/* Implement the breakpoint_from_pc gdbarch hook.
+
+   The Nios II ABI for Linux says: "Userspace programs should not use
+   the break instruction and userspace debuggers should not insert
+   one." and "Userspace breakpoints are accomplished using the trap
+   instruction with immediate operand 31 (all ones)."
+
+   So, we use "trap 31" consistently as the breakpoint on bare-metal
+   as well as Linux targets.  */
 
 static const gdb_byte*
 nios2_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
@@ -1156,11 +1206,11 @@ nios2_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
   unsigned long mach = gdbarch_bfd_arch_info (gdbarch)->mach;
 
-  /* R1 break encoding:
-     ((0x1e << 17) | (0x34 << 11) | (0x1f << 6) | (0x3a << 0))
-     0x003da7fa */
-  static const gdb_byte r1_breakpoint_le[] = {0xfa, 0xa7, 0x3d, 0x0};
-  static const gdb_byte r1_breakpoint_be[] = {0x0, 0x3d, 0xa7, 0xfa};
+  /* R1 trap encoding:
+     ((0x1d << 17) | (0x2d << 11) | (0x1f << 6) | (0x3a << 0))
+     0x003b6ffa */
+  static const gdb_byte r1_breakpoint_le[] = {0xfa, 0x6f, 0x3b, 0x0};
+  static const gdb_byte r1_breakpoint_be[] = {0x0, 0x3b, 0x6f, 0xfa};
   *bp_size = NIOS2_OPCODE_SIZE;
   if (byte_order_for_code == BFD_ENDIAN_BIG)
     return r1_breakpoint_be;
@@ -1725,7 +1775,7 @@ nios2_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_return_value (gdbarch, nios2_return_value);
 
   set_gdbarch_skip_prologue (gdbarch, nios2_skip_prologue);
-  set_gdbarch_in_function_epilogue_p (gdbarch, nios2_in_function_epilogue_p);
+  set_gdbarch_stack_frame_destroyed_p (gdbarch, nios2_stack_frame_destroyed_p);
   set_gdbarch_breakpoint_from_pc (gdbarch, nios2_breakpoint_from_pc);
 
   set_gdbarch_dummy_id (gdbarch, nios2_dummy_id);
This page took 0.025665 seconds and 4 git commands to generate.