/* Target-dependent code for GDB, the GNU debugger.
Copyright (C) 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GDB.
/* Return non-zero if the architecture described by GDBARCH has
VSX registers (vsr0 --- vsr63). */
-int
+static int
ppc_vsx_support_p (struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
/* Fix up the state of registers and memory after having single-stepped
a displaced instruction. */
-void
+static void
ppc_displaced_step_fixup (struct gdbarch *gdbarch,
- struct displaced_step_closure *closure,
- CORE_ADDR from, CORE_ADDR to,
- struct regcache *regs)
+ struct displaced_step_closure *closure,
+ CORE_ADDR from, CORE_ADDR to,
+ struct regcache *regs)
{
/* Since we use simple_displaced_step_copy_insn, our closure is a
copy of the instruction. */
#define BL_INSTRUCTION 0x48000001
#define BL_DISPLACEMENT_MASK 0x03fffffc
+static unsigned long
+rs6000_fetch_instruction (const CORE_ADDR pc)
+{
+ gdb_byte buf[4];
+ unsigned long op;
+
+ /* Fetch the instruction and convert it to an integer. */
+ if (target_read_memory (pc, buf, 4))
+ return 0;
+ op = extract_unsigned_integer (buf, 4);
+
+ return op;
+}
+
+/* GCC generates several well-known sequences of instructions at the begining
+ of each function prologue when compiling with -fstack-check. If one of
+ such sequences starts at START_PC, then return the address of the
+ instruction immediately past this sequence. Otherwise, return START_PC. */
+
+static CORE_ADDR
+rs6000_skip_stack_check (const CORE_ADDR start_pc)
+{
+ CORE_ADDR pc = start_pc;
+ unsigned long op = rs6000_fetch_instruction (pc);
+
+ /* First possible sequence: A small number of probes.
+ stw 0, -<some immediate>(1)
+ [repeat this instruction any (small) number of times]
+ */
+
+ if ((op & 0xffff0000) == 0x90010000)
+ {
+ while ((op & 0xffff0000) == 0x90010000)
+ {
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (pc);
+ }
+ return pc;
+ }
+
+ /* Second sequence: A probing loop.
+ addi 12,1,-<some immediate>
+ lis 0,-<some immediate>
+ [possibly ori 0,0,<some immediate>]
+ add 0,12,0
+ cmpw 0,12,0
+ beq 0,<disp>
+ addi 12,12,-<some immediate>
+ stw 0,0(12)
+ b <disp>
+ [possibly one last probe: stw 0,<some immediate>(12)]
+ */
+
+ while (1)
+ {
+ /* addi 12,1,-<some immediate> */
+ if ((op & 0xffff0000) != 0x39810000)
+ break;
+
+ /* lis 0,-<some immediate> */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (pc);
+ if ((op & 0xffff0000) != 0x3c000000)
+ break;
+
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (pc);
+ /* [possibly ori 0,0,<some immediate>] */
+ if ((op & 0xffff0000) == 0x60000000)
+ {
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (pc);
+ }
+ /* add 0,12,0 */
+ if (op != 0x7c0c0214)
+ break;
+
+ /* cmpw 0,12,0 */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (pc);
+ if (op != 0x7c0c0000)
+ break;
+
+ /* beq 0,<disp> */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (pc);
+ if ((op & 0xff9f0001) != 0x41820000)
+ break;
+
+ /* addi 12,12,-<some immediate> */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (pc);
+ if ((op & 0xffff0000) != 0x398c0000)
+ break;
+
+ /* stw 0,0(12) */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (pc);
+ if (op != 0x900c0000)
+ break;
+
+ /* b <disp> */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (pc);
+ if ((op & 0xfc000001) != 0x48000000)
+ break;
+
+ /* [possibly one last probe: stw 0,<some immediate>(12)] */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (pc);
+ if ((op & 0xffff0000) == 0x900c0000)
+ {
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (pc);
+ }
+
+ /* We found a valid stack-check sequence, return the new PC. */
+ return pc;
+ }
+
+ /* Third sequence: No probe; instead, a comparizon between the stack size
+ limit (saved in a run-time global variable) and the current stack
+ pointer:
+
+ addi 0,1,-<some immediate>
+ lis 12,__gnat_stack_limit@ha
+ lwz 12,__gnat_stack_limit@l(12)
+ twllt 0,12
+
+ or, with a small variant in the case of a bigger stack frame:
+ addis 0,1,<some immediate>
+ addic 0,0,-<some immediate>
+ lis 12,__gnat_stack_limit@ha
+ lwz 12,__gnat_stack_limit@l(12)
+ twllt 0,12
+ */
+ while (1)
+ {
+ /* addi 0,1,-<some immediate> */
+ if ((op & 0xffff0000) != 0x38010000)
+ {
+ /* small stack frame variant not recognized; try the
+ big stack frame variant: */
+
+ /* addis 0,1,<some immediate> */
+ if ((op & 0xffff0000) != 0x3c010000)
+ break;
+
+ /* addic 0,0,-<some immediate> */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (pc);
+ if ((op & 0xffff0000) != 0x30000000)
+ break;
+ }
+
+ /* lis 12,<some immediate> */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (pc);
+ if ((op & 0xffff0000) != 0x3d800000)
+ break;
+
+ /* lwz 12,<some immediate>(12) */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (pc);
+ if ((op & 0xffff0000) != 0x818c0000)
+ break;
+
+ /* twllt 0,12 */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (pc);
+ if ((op & 0xfffffffe) != 0x7c406008)
+ break;
+
+ /* We found a valid stack-check sequence, return the new PC. */
+ return pc;
+ }
+
+ /* No stack check code in our prologue, return the start_pc. */
+ return start_pc;
+}
+
/* return pc value after skipping a function prologue and also return
information about a function frame.
fdata->nosavedpc = 1;
fdata->lr_register = -1;
+ pc = rs6000_skip_stack_check (pc);
+ if (pc >= lim_pc)
+ pc = lim_pc;
+
for (;; pc += 4)
{
/* Sometimes it isn't clear if an instruction is a prologue
is greater. */
if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
{
- CORE_ADDR post_prologue_pc = skip_prologue_using_sal (func_addr);
+ CORE_ADDR post_prologue_pc
+ = skip_prologue_using_sal (gdbarch, func_addr);
if (post_prologue_pc != 0)
return max (pc, post_prologue_pc);
}
/* Find an upper limit on the function prologue using the debug
information. If the debug information could not be used to provide
that bound, then use an arbitrary large number as the upper bound. */
- limit_pc = skip_prologue_using_sal (pc);
+ limit_pc = skip_prologue_using_sal (gdbarch, pc);
if (limit_pc == 0)
limit_pc = pc + 100; /* Magic. */
address of the instruction following that call. Otherwise, it simply
returns PC. */
-CORE_ADDR
+static CORE_ADDR
rs6000_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
gdb_byte buf[4];
gdbarch_skip_trampoline_code hooks in handle_inferior_event() to skip past
@FIX code. */
-int
+static int
rs6000_in_solib_return_trampoline (CORE_ADDR pc, char *name)
{
return name && !strncmp (name, "@FIX", 4);
Result is desired PC to step until, or NULL if we are not in
code that should be skipped. */
-CORE_ADDR
+static CORE_ADDR
rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame));
t = init_composite_type ("__ppc_builtin_type_vec64", TYPE_CODE_UNION);
append_composite_type_field (t, "uint64", builtin_type_int64);
append_composite_type_field (t, "v2_float",
- init_vector_type (builtin_type_float, 2));
+ init_vector_type (builtin_type (gdbarch)
+ ->builtin_float, 2));
append_composite_type_field (t, "v2_int32",
init_vector_type (builtin_type_int32, 2));
append_composite_type_field (t, "v4_int16",
append_composite_type_field (t, "v8_int8",
init_vector_type (builtin_type_int8, 8));
- TYPE_FLAGS (t) |= TYPE_FLAG_VECTOR;
+ TYPE_VECTOR (t) = 1;
TYPE_NAME (t) = "ppc_builtin_type_vec64";
tdep->ppc_builtin_type_vec64 = t;
}
append_composite_type_field (t, "v16_int8",
init_vector_type (builtin_type_int8, 16));
- TYPE_FLAGS (t) |= TYPE_FLAG_VECTOR;
+ TYPE_VECTOR (t) = 1;
TYPE_NAME (t) = "ppc_builtin_type_vec128";
tdep->ppc_builtin_type_vec128 = t;
}
&& regnum >= tdep->ppc_fp0_regnum
&& regnum < tdep->ppc_fp0_regnum + ppc_num_fprs
&& TYPE_CODE (type) == TYPE_CODE_FLT
- && TYPE_LENGTH (type) != TYPE_LENGTH (builtin_type_double));
+ && TYPE_LENGTH (type)
+ != TYPE_LENGTH (builtin_type (gdbarch)->builtin_double));
}
static void
struct type *type,
gdb_byte *to)
{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
gdb_byte from[MAX_REGISTER_SIZE];
gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
get_frame_register (frame, regnum, from);
- convert_typed_floating (from, builtin_type_double, to, type);
+ convert_typed_floating (from, builtin_type (gdbarch)->builtin_double,
+ to, type);
}
static void
struct type *type,
const gdb_byte *from)
{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
gdb_byte to[MAX_REGISTER_SIZE];
gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
- convert_typed_floating (from, type, to, builtin_type_double);
+ convert_typed_floating (from, type,
+ to, builtin_type (gdbarch)->builtin_double);
put_frame_register (frame, regnum, to);
}
/* Frame handling. */
dwarf2_frame_set_init_reg (gdbarch, ppc_dwarf2_frame_init_reg);
+ /* Setup displaced stepping. */
+ set_gdbarch_displaced_step_copy_insn (gdbarch,
+ simple_displaced_step_copy_insn);
+ set_gdbarch_displaced_step_fixup (gdbarch, ppc_displaced_step_fixup);
+ set_gdbarch_displaced_step_free_closure (gdbarch,
+ simple_displaced_step_free_closure);
+ set_gdbarch_displaced_step_location (gdbarch,
+ displaced_step_at_entry_point);
+
+ set_gdbarch_max_insn_length (gdbarch, PPC_INSN_SIZE);
+
/* Hook in ABI-specific overrides, if they have been registered. */
info.target_desc = tdesc;
info.tdep_info = (void *) tdesc_data;
gdb_assert (gdbarch_num_regs (gdbarch)
+ gdbarch_num_pseudo_regs (gdbarch) == cur_reg);
- /* Setup displaced stepping. */
- set_gdbarch_displaced_step_copy_insn (gdbarch,
- simple_displaced_step_copy_insn);
- set_gdbarch_displaced_step_fixup (gdbarch, ppc_displaced_step_fixup);
- set_gdbarch_displaced_step_free_closure (gdbarch,
- simple_displaced_step_free_closure);
- set_gdbarch_displaced_step_location (gdbarch,
- displaced_step_at_entry_point);
-
- set_gdbarch_max_insn_length (gdbarch, PPC_INSN_SIZE);
-
return gdbarch;
}