/* 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.
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;
stw sp, constant(rx)
mov sp, rx
- 5) A frame pointer save, which can be either a MOV or ADDI.
+ 4) A frame pointer save, which can be either a MOV or ADDI.
- 6) A further stack pointer adjustment. This is normally included
- adjustment in step 4 unless the total adjustment is too large
+ 5) A further stack pointer adjustment. This is normally included
+ adjustment in step 3 unless the total adjustment is too large
to be done in one step.
7) A stack overflow check, which can take either of these forms:
bgeu sp, rx, +8
- break 3
+ trap 3
or
bltu sp, rx, .Lstack_overflow
...
.Lstack_overflow:
- break 3
- If present, this is inserted after the stack pointer adjustments
- for steps 3, 4, and 6.
+ trap 3
+
+ Older versions of GCC emitted "break 3" instead of "trap 3" here,
+ so we check for both cases.
+
+ Older GCC versions emitted stack overflow checks after the SP
+ adjustments in both steps 3 and 4. Starting with GCC 6, there is
+ at most one overflow check, which is placed before the first
+ stack adjustment for R2 CDX and after the first stack adjustment
+ otherwise.
The prologue instructions may be combined or interleaved with other
instructions.
if (orig > 0
&& (value[rb].offset == 0
|| (orig == NIOS2_EA_REGNUM && value[rb].offset == -4))
- && ((value[ra].reg == NIOS2_SP_REGNUM
- && cache->reg_saved[orig].basereg != NIOS2_SP_REGNUM)
- || cache->reg_saved[orig].basereg == -1))
+ && value[ra].reg == NIOS2_SP_REGNUM)
{
if (pc < current_pc)
{
else if (cond == branch_geu)
{
/* BGEU sp, rx, +8
- BREAK 3
+ TRAP 3 (or BREAK 3)
This instruction sequence is used in stack checking;
we can ignore it. */
unsigned int next_insn;
const struct nios2_opcode *next_op
= nios2_fetch_insn (gdbarch, pc, &next_insn);
if (next_op != NULL
- && nios2_match_break (next_insn, op, mach, &uimm))
+ && (nios2_match_trap (next_insn, op, mach, &uimm)
+ || nios2_match_break (next_insn, op, mach, &uimm)))
pc += next_op->size;
else
break;
else if (cond == branch_ltu)
{
/* BLTU sp, rx, .Lstackoverflow
- If the location branched to holds a BREAK 3 instruction
- then this is also stack overflow detection. */
+ If the location branched to holds a TRAP or BREAK
+ instruction then this is also stack overflow detection. */
unsigned int next_insn;
const struct nios2_opcode *next_op
= nios2_fetch_insn (gdbarch, pc + imm, &next_insn);
if (next_op != NULL
- && nios2_match_break (next_insn, op, mach, &uimm))
+ && (nios2_match_trap (next_insn, op, mach, &uimm)
+ || nios2_match_break (next_insn, op, mach, &uimm)))
;
else
break;
break;
}
- /* All other calls or jumps (including returns) terminate
+ /* All other calls, jumps, returns, TRAPs, or BREAKs terminate
the prologue. */
else if (nios2_match_callr (insn, op, mach, &ra)
|| nios2_match_jmpr (insn, op, mach, &ra)
- || nios2_match_jmpi (insn, op, mach, &uimm))
+ || nios2_match_jmpi (insn, op, mach, &uimm)
+ || nios2_match_trap (insn, op, mach, &uimm)
+ || nios2_match_break (insn, op, mach, &uimm))
break;
}
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,
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;
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);