return 0;
}
-/* Implementation of gdbarch_in_function_epilogue_p. */
+/* Implement the stack_frame_destroyed_p gdbarch method. */
static int
-rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+rs6000_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
{
return rs6000_in_function_epilogue_frame_p (get_current_frame (),
gdbarch, pc);
#define BXL_INSN 0x4c000000
#define BP_INSN 0x7C000008
+/* Instruction masks used during single-stepping of atomic
+ sequences. */
+#define LWARX_MASK 0xfc0007fe
+#define LWARX_INSTRUCTION 0x7c000028
+#define LDARX_INSTRUCTION 0x7c0000A8
+#define STWCX_MASK 0xfc0007ff
+#define STWCX_INSTRUCTION 0x7c00012d
+#define STDCX_INSTRUCTION 0x7c0001ad
+
+/* We can't displaced step atomic sequences. Otherwise this is just
+ like simple_displaced_step_copy_insn. */
+
+static struct displaced_step_closure *
+ppc_displaced_step_copy_insn (struct gdbarch *gdbarch,
+ CORE_ADDR from, CORE_ADDR to,
+ struct regcache *regs)
+{
+ size_t len = gdbarch_max_insn_length (gdbarch);
+ gdb_byte *buf = xmalloc (len);
+ struct cleanup *old_chain = make_cleanup (xfree, buf);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ int insn;
+
+ read_memory (from, buf, len);
+
+ insn = extract_signed_integer (buf, PPC_INSN_SIZE, byte_order);
+
+ /* Assume all atomic sequences start with a lwarx/ldarx instruction. */
+ if ((insn & LWARX_MASK) == LWARX_INSTRUCTION
+ || (insn & LWARX_MASK) == LDARX_INSTRUCTION)
+ {
+ if (debug_displaced)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "displaced: can't displaced step "
+ "atomic sequence at %s\n",
+ paddress (gdbarch, from));
+ }
+ do_cleanups (old_chain);
+ return NULL;
+ }
+
+ write_memory (to, buf, len);
+
+ if (debug_displaced)
+ {
+ fprintf_unfiltered (gdb_stdlog, "displaced: copy %s->%s: ",
+ paddress (gdbarch, from), paddress (gdbarch, to));
+ displaced_step_dump_bytes (gdb_stdlog, buf, len);
+ }
+
+ discard_cleanups (old_chain);
+ return (struct displaced_step_closure *) buf;
+}
+
/* Fix up the state of registers and memory after having single-stepped
a displaced instruction. */
static void
struct regcache *regs)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- /* Since we use simple_displaced_step_copy_insn, our closure is a
- copy of the instruction. */
+ /* Our closure is a copy of the instruction. */
ULONGEST insn = extract_unsigned_integer ((gdb_byte *) closure,
PPC_INSN_SIZE, byte_order);
ULONGEST opcode = 0;
return 1;
}
-/* Instruction masks used during single-stepping of atomic sequences. */
-#define LWARX_MASK 0xfc0007fe
-#define LWARX_INSTRUCTION 0x7c000028
-#define LDARX_INSTRUCTION 0x7c0000A8
-#define STWCX_MASK 0xfc0007ff
-#define STWCX_INSTRUCTION 0x7c00012d
-#define STDCX_INSTRUCTION 0x7c0001ad
-
/* Checks for an atomic sequence of instructions beginning with a LWARX/LDARX
instruction and ending with a STWCX/STDCX instruction. If such a sequence
is found, attempt to step through it. A breakpoint is placed at the end of
rs6000_in_solib_return_trampoline (struct gdbarch *gdbarch,
CORE_ADDR pc, const char *name)
{
- return name && !strncmp (name, "@FIX", 4);
+ return name && startswith (name, "@FIX");
}
/* Skip code that the user doesn't want to see when stepping:
default_frame_sniffer
};
+/* Allocate and initialize a frame cache for an epilogue frame.
+ SP is restored and prev-PC is stored in LR. */
+
static struct rs6000_frame_cache *
rs6000_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache)
{
- volatile struct gdb_exception ex;
struct rs6000_frame_cache *cache;
struct gdbarch *gdbarch = get_frame_arch (this_frame);
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- CORE_ADDR sp;
if (*this_cache)
return *this_cache;
(*this_cache) = cache;
cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
- TRY_CATCH (ex, RETURN_MASK_ERROR)
+ TRY
{
/* At this point the stack looks as if we just entered the
function, and the return address is stored in LR. */
trad_frame_set_value (cache->saved_regs,
gdbarch_pc_regnum (gdbarch), lr);
}
- if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
- throw_exception (ex);
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ if (ex.error != NOT_AVAILABLE_ERROR)
+ throw_exception (ex);
+ }
+ END_CATCH
return cache;
}
+/* Implementation of frame_unwind.this_id, as defined in frame_unwind.h.
+ Return the frame ID of an epilogue frame. */
+
static void
rs6000_epilogue_frame_this_id (struct frame_info *this_frame,
void **this_cache, struct frame_id *this_id)
(*this_id) = frame_id_build (info->base, pc);
}
+/* Implementation of frame_unwind.prev_register, as defined in frame_unwind.h.
+ Return the register value of REGNUM in previous frame. */
+
static struct value *
rs6000_epilogue_frame_prev_register (struct frame_info *this_frame,
void **this_cache, int regnum)
return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
}
+/* Implementation of frame_unwind.sniffer, as defined in frame_unwind.h.
+ Check whether this an epilogue frame. */
+
static int
rs6000_epilogue_frame_sniffer (const struct frame_unwind *self,
struct frame_info *this_frame,
return 0;
}
+/* Frame unwinder for epilogue frame. This is required for reverse step-over
+ a function without debug information. */
+
static const struct frame_unwind rs6000_epilogue_frame_unwind =
{
NORMAL_FRAME,
#define PPC_XT(insn) ((PPC_TX (insn) << 5) | PPC_T (insn))
#define PPC_XER_NB(xer) (xer & 0x7f)
-/* Record Vector-Scalar Registers. */
+/* Record Vector-Scalar Registers.
+ For VSR less than 32, it's represented by an FPR and an VSR-upper register.
+ Otherwise, it's just a VR register. Record them accordingly. */
static int
ppc_record_vsr (struct regcache *regcache, struct gdbarch_tdep *tdep, int vsr)
return 0;
}
-/* Parse instructions of primary opcode-4. */
+/* Parse and record instructions primary opcode-4 at ADDR.
+ Return 0 if successful. */
static int
ppc_process_record_op4 (struct gdbarch *gdbarch, struct regcache *regcache,
- CORE_ADDR addr, uint32_t insn)
+ CORE_ADDR addr, uint32_t insn)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
int ext = PPC_FIELD (insn, 21, 11);
return 0;
}
- fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record "
- "%08x at %08lx, 4-%d.\n", insn, addr, ext);
+ fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
+ "at %s, 4-%d.\n", insn, paddress (gdbarch, addr), ext);
return -1;
}
-/* Parse instructions of primary opcode-19. */
+/* Parse and record instructions of primary opcode-19 at ADDR.
+ Return 0 if successful. */
static int
ppc_process_record_op19 (struct gdbarch *gdbarch, struct regcache *regcache,
return 0;
}
- fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record "
- "%08x at %08lx, 19-%d.\n", insn, addr, ext);
+ fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
+ "at %s, 19-%d.\n", insn, paddress (gdbarch, addr), ext);
return -1;
}
-/* Parse instructions of primary opcode-31. */
+/* Parse and record instructions of primary opcode-31 at ADDR.
+ Return 0 if successful. */
static int
ppc_process_record_op31 (struct gdbarch *gdbarch, struct regcache *regcache,
case 878: /* Transaction Abort Doubleword Conditional Immediate */
case 910: /* Transaction Abort */
fprintf_unfiltered (gdb_stdlog, "Cannot record Transaction instructions. "
- "%08x at %08lx, 31-%d.\n", insn, addr, ext);
+ "%08x at %s, 31-%d.\n",
+ insn, paddress (gdbarch, addr), ext);
return -1;
case 1014: /* Data Cache Block set to Zero */
}
UNKNOWN_OP:
- fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record "
- "%08x at %08lx, 31-%d.\n", insn, addr, ext);
+ fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
+ "at %s, 31-%d.\n", insn, paddress (gdbarch, addr), ext);
return -1;
}
-/* Parse instructions of primary opcode-59. */
+/* Parse and record instructions of primary opcode-59 at ADDR.
+ Return 0 if successful. */
static int
ppc_process_record_op59 (struct gdbarch *gdbarch, struct regcache *regcache,
return 0;
}
- fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record "
- "%08x at %08lx, 59-%d.\n", insn, addr, ext);
+ fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
+ "at %s, 59-%d.\n", insn, paddress (gdbarch, addr), ext);
return -1;
}
-/* Parse instructions of primary opcode-60. */
+/* Parse and record instructions of primary opcode-60 at ADDR.
+ Return 0 if successful. */
static int
ppc_process_record_op60 (struct gdbarch *gdbarch, struct regcache *regcache,
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
int ext = PPC_EXTOP (insn);
- int tmp;
switch (ext >> 2)
{
return 0;
}
- fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record "
- "%08x at %08lx, 60-%d.\n", insn, addr, ext);
+ fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
+ "at %s, 60-%d.\n", insn, paddress (gdbarch, addr), ext);
return -1;
}
-/* Parse instructions of primary opcode-63. */
+/* Parse and record instructions of primary opcode-63 at ADDR.
+ Return 0 if successful. */
static int
ppc_process_record_op63 (struct gdbarch *gdbarch, struct regcache *regcache,
}
- fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record "
- "%08x at %08lx, 59-%d.\n", insn, addr, ext);
+ fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
+ "at %s, 59-%d.\n", insn, paddress (gdbarch, addr), ext);
return -1;
}
default:
UNKNOWN_OP:
- fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record "
- "%08x at %08lx, %d.\n", insn, addr, op6);
+ fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
+ "at %s, %d.\n", insn, paddress (gdbarch, addr), op6);
return -1;
}
set_gdbarch_push_dummy_call (gdbarch, ppc64_sysv_abi_push_dummy_call);
set_gdbarch_skip_prologue (gdbarch, rs6000_skip_prologue);
- set_gdbarch_in_function_epilogue_p (gdbarch, rs6000_in_function_epilogue_p);
+ set_gdbarch_stack_frame_destroyed_p (gdbarch, rs6000_stack_frame_destroyed_p);
set_gdbarch_skip_main_prologue (gdbarch, rs6000_skip_main_prologue);
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
/* Setup displaced stepping. */
set_gdbarch_displaced_step_copy_insn (gdbarch,
- simple_displaced_step_copy_insn);
+ ppc_displaced_step_copy_insn);
set_gdbarch_displaced_step_hw_singlestep (gdbarch,
ppc_displaced_step_hw_singlestep);
set_gdbarch_displaced_step_fixup (gdbarch, ppc_displaced_step_fixup);
struct cmd_list_element *c)
{
struct gdbarch_info info;
- enum powerpc_vector_abi vector_abi;
+ int vector_abi;
for (vector_abi = POWERPC_VEC_AUTO;
vector_abi != POWERPC_VEC_LAST;
if (strcmp (powerpc_vector_abi_string,
powerpc_vector_strings[vector_abi]) == 0)
{
- powerpc_vector_abi_global = vector_abi;
+ powerpc_vector_abi_global = (enum powerpc_vector_abi) vector_abi;
break;
}