/* 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
- Free Software Foundation, Inc.
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+ 2010 Free Software Foundation, Inc.
This file is part of GDB.
#include "gdb/sim-ppc.h"
#include "reggroups.h"
#include "dwarf2-frame.h"
+#include "target-descriptions.h"
+#include "user-regs.h"
#include "libbfd.h" /* for bfd_default_set_arch_mach */
#include "coff/internal.h" /* for libcoff.h */
#include "libxcoff.h"
#include "elf-bfd.h"
+#include "elf/ppc.h"
#include "solib-svr4.h"
#include "ppc-tdep.h"
#include "frame-unwind.h"
#include "frame-base.h"
-#include "rs6000-tdep.h"
+#include "features/rs6000/powerpc-32.c"
+#include "features/rs6000/powerpc-altivec32.c"
+#include "features/rs6000/powerpc-vsx32.c"
+#include "features/rs6000/powerpc-403.c"
+#include "features/rs6000/powerpc-403gc.c"
+#include "features/rs6000/powerpc-405.c"
+#include "features/rs6000/powerpc-505.c"
+#include "features/rs6000/powerpc-601.c"
+#include "features/rs6000/powerpc-602.c"
+#include "features/rs6000/powerpc-603.c"
+#include "features/rs6000/powerpc-604.c"
+#include "features/rs6000/powerpc-64.c"
+#include "features/rs6000/powerpc-altivec64.c"
+#include "features/rs6000/powerpc-vsx64.c"
+#include "features/rs6000/powerpc-7400.c"
+#include "features/rs6000/powerpc-750.c"
+#include "features/rs6000/powerpc-860.c"
+#include "features/rs6000/powerpc-e500.c"
+#include "features/rs6000/rs6000.c"
+
+/* Determine if regnum is an SPE pseudo-register. */
+#define IS_SPE_PSEUDOREG(tdep, regnum) ((tdep)->ppc_ev0_regnum >= 0 \
+ && (regnum) >= (tdep)->ppc_ev0_regnum \
+ && (regnum) < (tdep)->ppc_ev0_regnum + 32)
+
+/* Determine if regnum is a decimal float pseudo-register. */
+#define IS_DFP_PSEUDOREG(tdep, regnum) ((tdep)->ppc_dl0_regnum >= 0 \
+ && (regnum) >= (tdep)->ppc_dl0_regnum \
+ && (regnum) < (tdep)->ppc_dl0_regnum + 16)
+
+/* Determine if regnum is a POWER7 VSX register. */
+#define IS_VSX_PSEUDOREG(tdep, regnum) ((tdep)->ppc_vsr0_regnum >= 0 \
+ && (regnum) >= (tdep)->ppc_vsr0_regnum \
+ && (regnum) < (tdep)->ppc_vsr0_regnum + ppc_num_vsrs)
+
+/* Determine if regnum is a POWER7 Extended FP register. */
+#define IS_EFP_PSEUDOREG(tdep, regnum) ((tdep)->ppc_efpr0_regnum >= 0 \
+ && (regnum) >= (tdep)->ppc_efpr0_regnum \
+ && (regnum) < (tdep)->ppc_efpr0_regnum + ppc_num_fprs)
+
+/* The list of available "set powerpc ..." and "show powerpc ..."
+ commands. */
+static struct cmd_list_element *setpowerpccmdlist = NULL;
+static struct cmd_list_element *showpowerpccmdlist = NULL;
+
+static enum auto_boolean powerpc_soft_float_global = AUTO_BOOLEAN_AUTO;
+
+/* The vector ABI to use. Keep this in sync with powerpc_vector_abi. */
+static const char *powerpc_vector_strings[] =
+{
+ "auto",
+ "generic",
+ "altivec",
+ "spe",
+ NULL
+};
-/* If the kernel has to deliver a signal, it pushes a sigcontext
- structure on the stack and then calls the signal handler, passing
- the address of the sigcontext in an argument register. Usually
- the signal handler doesn't save this register, so we have to
- access the sigcontext structure via an offset from the signal handler
- frame.
- The following constants were determined by experimentation on AIX 3.2. */
-#define SIG_FRAME_PC_OFFSET 96
-#define SIG_FRAME_LR_OFFSET 108
-#define SIG_FRAME_FP_OFFSET 284
+/* A variable that can be configured by the user. */
+static enum powerpc_vector_abi powerpc_vector_abi_global = POWERPC_VEC_AUTO;
+static const char *powerpc_vector_abi_string = "auto";
/* To be used by skip_prologue. */
by which we decrement sp to allocate
the frame */
int saved_gpr; /* smallest # of saved gpr */
+ unsigned int gpr_mask; /* Each bit is an individual saved GPR. */
int saved_fpr; /* smallest # of saved fpr */
int saved_vr; /* smallest # of saved vr */
int saved_ev; /* smallest # of saved ev */
int alloca_reg; /* alloca register number (frame ptr) */
char frameless; /* true if frameless functions. */
char nosavedpc; /* true if pc not saved. */
+ char used_bl; /* true if link register clobbered */
int gpr_offset; /* offset of saved gprs from prev sp */
int fpr_offset; /* offset of saved fprs from prev sp */
int vr_offset; /* offset of saved vrs from prev sp */
int ev_offset; /* offset of saved evs from prev sp */
int lr_offset; /* offset of saved lr */
+ int lr_register; /* register of saved lr, if trustworthy */
int cr_offset; /* offset of saved cr */
int vrsave_offset; /* offset of saved vrsave register */
};
-/* Description of a single register. */
-
-struct reg
- {
- char *name; /* name of register */
- unsigned char sz32; /* size on 32-bit arch, 0 if nonexistent */
- unsigned char sz64; /* size on 64-bit arch, 0 if nonexistent */
- unsigned char fpr; /* whether register is floating-point */
- unsigned char pseudo; /* whether register is pseudo */
- int spr_num; /* PowerPC SPR number, or -1 if not an SPR.
- This is an ISA SPR number, not a GDB
- register number. */
- };
-
-/* Hook for determining the TOC address when calling functions in the
- inferior under AIX. The initialization code in rs6000-nat.c sets
- this hook to point to find_toc_address. */
-
-CORE_ADDR (*rs6000_find_toc_address_hook) (CORE_ADDR) = NULL;
-
-/* Static function prototypes */
-static CORE_ADDR branch_dest (struct frame_info *frame, int opcode,
- int instr, CORE_ADDR pc, CORE_ADDR safety);
-static CORE_ADDR skip_prologue (CORE_ADDR, CORE_ADDR,
- struct rs6000_framedata *);
+/* Is REGNO a VSX register? Return 1 if so, 0 otherwise. */
+int
+vsx_register_p (struct gdbarch *gdbarch, int regno)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ if (tdep->ppc_vsr0_regnum < 0)
+ return 0;
+ else
+ return (regno >= tdep->ppc_vsr0_upper_regnum && regno
+ <= tdep->ppc_vsr0_upper_regnum + 31);
+}
/* Is REGNO an AltiVec register? Return 1 if so, 0 otherwise. */
int
-altivec_register_p (int regno)
+altivec_register_p (struct gdbarch *gdbarch, int regno)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
if (tdep->ppc_vr0_regnum < 0 || tdep->ppc_vrsave_regnum < 0)
return 0;
else
/* Return true if REGNO is an SPE register, false otherwise. */
int
-spe_register_p (int regno)
+spe_register_p (struct gdbarch *gdbarch, int regno)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
/* Is it a reference to EV0 -- EV31, and do we have those? */
- if (tdep->ppc_ev0_regnum >= 0
- && tdep->ppc_ev31_regnum >= 0
- && tdep->ppc_ev0_regnum <= regno && regno <= tdep->ppc_ev31_regnum)
+ if (IS_SPE_PSEUDOREG (tdep, regno))
return 1;
/* Is it a reference to one of the raw upper GPR halves? */
&& tdep->ppc_fpscr_regnum >= 0);
}
+/* Return non-zero if the architecture described by GDBARCH has
+ VSX registers (vsr0 --- vsr63). */
+static int
+ppc_vsx_support_p (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ return tdep->ppc_vsr0_regnum >= 0;
+}
+
+/* Return non-zero if the architecture described by GDBARCH has
+ Altivec registers (vr0 --- vr31, vrsave and vscr). */
+int
+ppc_altivec_support_p (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ return (tdep->ppc_vr0_regnum >= 0
+ && tdep->ppc_vrsave_regnum >= 0);
+}
/* Check that TABLE[GDB_REGNO] is not already initialized, and then
set it to SIM_REGNO.
init_sim_regno_table (struct gdbarch *arch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
- int total_regs = gdbarch_num_regs (arch) + gdbarch_num_pseudo_regs (arch);
- const struct reg *regs = tdep->regs;
+ int total_regs = gdbarch_num_regs (arch);
int *sim_regno = GDBARCH_OBSTACK_CALLOC (arch, total_regs, int);
int i;
+ static const char *const segment_regs[] = {
+ "sr0", "sr1", "sr2", "sr3", "sr4", "sr5", "sr6", "sr7",
+ "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15"
+ };
/* Presume that all registers not explicitly mentioned below are
unavailable from the sim. */
set_sim_regno (sim_regno, tdep->ppc_cr_regnum, sim_ppc_cr_regnum);
/* Segment registers. */
- if (tdep->ppc_sr0_regnum >= 0)
- for (i = 0; i < ppc_num_srs; i++)
- set_sim_regno (sim_regno,
- tdep->ppc_sr0_regnum + i,
- sim_ppc_sr0_regnum + i);
+ for (i = 0; i < ppc_num_srs; i++)
+ {
+ int gdb_regno;
+
+ gdb_regno = user_reg_map_name_to_regnum (arch, segment_regs[i], -1);
+ if (gdb_regno >= 0)
+ set_sim_regno (sim_regno, gdb_regno, sim_ppc_sr0_regnum + i);
+ }
/* Altivec registers. */
if (tdep->ppc_vr0_regnum >= 0)
/* vsave is a special-purpose register, so the code below handles it. */
/* SPE APU (E500) registers. */
- if (tdep->ppc_ev0_regnum >= 0)
- for (i = 0; i < ppc_num_gprs; i++)
- set_sim_regno (sim_regno,
- tdep->ppc_ev0_regnum + i,
- sim_ppc_ev0_regnum + i);
if (tdep->ppc_ev0_upper_regnum >= 0)
for (i = 0; i < ppc_num_gprs; i++)
set_sim_regno (sim_regno,
set_sim_regno (sim_regno, tdep->ppc_acc_regnum, sim_ppc_acc_regnum);
/* spefscr is a special-purpose register, so the code below handles it. */
+#ifdef WITH_SIM
/* Now handle all special-purpose registers. Verify that they
haven't mistakenly been assigned numbers by any of the above
- code). */
- for (i = 0; i < total_regs; i++)
- if (regs[i].spr_num >= 0)
- set_sim_regno (sim_regno, i, regs[i].spr_num + sim_ppc_spr0_regnum);
+ code. */
+ for (i = 0; i < sim_ppc_num_sprs; i++)
+ {
+ const char *spr_name = sim_spr_register_name (i);
+ int gdb_regno = -1;
+
+ if (spr_name != NULL)
+ gdb_regno = user_reg_map_name_to_regnum (arch, spr_name, -1);
+
+ if (gdb_regno != -1)
+ set_sim_regno (sim_regno, gdb_regno, sim_ppc_spr0_regnum + i);
+ }
+#endif
/* Drop the initialized array into place. */
tdep->sim_regno = sim_regno;
/* Given a GDB register number REG, return the corresponding SIM
register number. */
static int
-rs6000_register_sim_regno (int reg)
+rs6000_register_sim_regno (struct gdbarch *gdbarch, int reg)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
int sim_regno;
+ if (tdep->sim_regno == NULL)
+ init_sim_regno_table (gdbarch);
+
gdb_assert (0 <= reg
- && reg <= gdbarch_num_regs (current_gdbarch)
- + gdbarch_num_pseudo_regs (current_gdbarch));
+ && reg <= gdbarch_num_regs (gdbarch)
+ + gdbarch_num_pseudo_regs (gdbarch));
sim_regno = tdep->sim_regno[reg];
if (sim_regno >= 0)
/* REGS + OFFSET contains register REGNUM in a field REGSIZE wide.
Write the register to REGCACHE. */
-static void
+void
ppc_supply_reg (struct regcache *regcache, int regnum,
const gdb_byte *regs, size_t offset, int regsize)
{
/* Read register REGNUM from REGCACHE and store to REGS + OFFSET
in a field REGSIZE wide. Zero pad as necessary. */
-static void
+void
ppc_collect_reg (const struct regcache *regcache, int regnum,
gdb_byte *regs, size_t offset, int regsize)
{
return -1;
}
+static int
+ppc_vrreg_offset (struct gdbarch_tdep *tdep,
+ const struct ppc_reg_offsets *offsets,
+ int regnum)
+{
+ if (regnum >= tdep->ppc_vr0_regnum
+ && regnum < tdep->ppc_vr0_regnum + ppc_num_vrs)
+ return offsets->vr0_offset + (regnum - tdep->ppc_vr0_regnum) * 16;
+
+ if (regnum == tdep->ppc_vrsave_regnum - 1)
+ return offsets->vscr_offset;
+
+ if (regnum == tdep->ppc_vrsave_regnum)
+ return offsets->vrsave_offset;
+
+ return -1;
+}
+
/* Supply register REGNUM in the general-purpose register set REGSET
from the buffer specified by GREGS and LEN to register cache
REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8);
}
+/* Supply register REGNUM in the VSX register set REGSET
+ from the buffer specified by VSXREGS and LEN to register cache
+ REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
+
+void
+ppc_supply_vsxregset (const struct regset *regset, struct regcache *regcache,
+ int regnum, const void *vsxregs, size_t len)
+{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep;
+
+ if (!ppc_vsx_support_p (gdbarch))
+ return;
+
+ tdep = gdbarch_tdep (gdbarch);
+
+ if (regnum == -1)
+ {
+ int i;
+
+ for (i = tdep->ppc_vsr0_upper_regnum;
+ i < tdep->ppc_vsr0_upper_regnum + 32;
+ i++)
+ ppc_supply_reg (regcache, i, vsxregs, 0, 8);
+
+ return;
+ }
+ else
+ ppc_supply_reg (regcache, regnum, vsxregs, 0, 8);
+}
+
+/* Supply register REGNUM in the Altivec register set REGSET
+ from the buffer specified by VRREGS and LEN to register cache
+ REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
+
+void
+ppc_supply_vrregset (const struct regset *regset, struct regcache *regcache,
+ int regnum, const void *vrregs, size_t len)
+{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep;
+ const struct ppc_reg_offsets *offsets;
+ size_t offset;
+
+ if (!ppc_altivec_support_p (gdbarch))
+ return;
+
+ tdep = gdbarch_tdep (gdbarch);
+ offsets = regset->descr;
+ if (regnum == -1)
+ {
+ int i;
+
+ for (i = tdep->ppc_vr0_regnum, offset = offsets->vr0_offset;
+ i < tdep->ppc_vr0_regnum + ppc_num_vrs;
+ i++, offset += 16)
+ ppc_supply_reg (regcache, i, vrregs, offset, 16);
+
+ ppc_supply_reg (regcache, (tdep->ppc_vrsave_regnum - 1),
+ vrregs, offsets->vscr_offset, 4);
+
+ ppc_supply_reg (regcache, tdep->ppc_vrsave_regnum,
+ vrregs, offsets->vrsave_offset, 4);
+ return;
+ }
+
+ offset = ppc_vrreg_offset (tdep, offsets, regnum);
+ if (regnum != tdep->ppc_vrsave_regnum
+ && regnum != tdep->ppc_vrsave_regnum - 1)
+ ppc_supply_reg (regcache, regnum, vrregs, offset, 16);
+ else
+ ppc_supply_reg (regcache, regnum,
+ vrregs, offset, 4);
+}
+
/* Collect register REGNUM in the general-purpose register set
REGSET from register cache REGCACHE into the buffer specified by
GREGS and LEN. If REGNUM is -1, do this for all registers in
ppc_collect_reg (regcache, regnum, fpregs, offset,
regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8);
}
-\f
-/* Read a LEN-byte address from debugged memory address MEMADDR. */
+/* Collect register REGNUM in the VSX register set
+ REGSET from register cache REGCACHE into the buffer specified by
+ VSXREGS and LEN. If REGNUM is -1, do this for all registers in
+ REGSET. */
-static CORE_ADDR
-read_memory_addr (CORE_ADDR memaddr, int len)
+void
+ppc_collect_vsxregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *vsxregs, size_t len)
{
- return read_memory_unsigned_integer (memaddr, len);
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep;
+
+ if (!ppc_vsx_support_p (gdbarch))
+ return;
+
+ tdep = gdbarch_tdep (gdbarch);
+
+ if (regnum == -1)
+ {
+ int i;
+
+ for (i = tdep->ppc_vsr0_upper_regnum;
+ i < tdep->ppc_vsr0_upper_regnum + 32;
+ i++)
+ ppc_collect_reg (regcache, i, vsxregs, 0, 8);
+
+ return;
+ }
+ else
+ ppc_collect_reg (regcache, regnum, vsxregs, 0, 8);
}
-static CORE_ADDR
-rs6000_skip_prologue (CORE_ADDR pc)
+
+/* Collect register REGNUM in the Altivec register set
+ REGSET from register cache REGCACHE into the buffer specified by
+ VRREGS and LEN. If REGNUM is -1, do this for all registers in
+ REGSET. */
+
+void
+ppc_collect_vrregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *vrregs, size_t len)
{
- struct rs6000_framedata frame;
- CORE_ADDR limit_pc, func_addr;
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep;
+ const struct ppc_reg_offsets *offsets;
+ size_t offset;
- /* See if we can determine the end of the prologue via the symbol table.
- If so, then return either PC, or the PC after the prologue, whichever
- is greater. */
- if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
+ if (!ppc_altivec_support_p (gdbarch))
+ return;
+
+ tdep = gdbarch_tdep (gdbarch);
+ offsets = regset->descr;
+ if (regnum == -1)
{
- CORE_ADDR post_prologue_pc = skip_prologue_using_sal (func_addr);
- if (post_prologue_pc != 0)
- return max (pc, post_prologue_pc);
- }
+ int i;
- /* Can't determine prologue from the symbol table, need to examine
- instructions. */
+ for (i = tdep->ppc_vr0_regnum, offset = offsets->vr0_offset;
+ i < tdep->ppc_vr0_regnum + ppc_num_vrs;
+ i++, offset += 16)
+ ppc_collect_reg (regcache, i, vrregs, offset, 16);
- /* 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);
- if (limit_pc == 0)
- limit_pc = pc + 100; /* Magic. */
+ ppc_collect_reg (regcache, (tdep->ppc_vrsave_regnum - 1),
+ vrregs, offsets->vscr_offset, 4);
- pc = skip_prologue (pc, limit_pc, &frame);
- return pc;
+ ppc_collect_reg (regcache, tdep->ppc_vrsave_regnum,
+ vrregs, offsets->vrsave_offset, 4);
+ return;
+ }
+
+ offset = ppc_vrreg_offset (tdep, offsets, regnum);
+ if (regnum != tdep->ppc_vrsave_regnum
+ && regnum != tdep->ppc_vrsave_regnum - 1)
+ ppc_collect_reg (regcache, regnum, vrregs, offset, 16);
+ else
+ ppc_collect_reg (regcache, regnum,
+ vrregs, offset, 4);
}
+\f
static int
insn_changes_sp_or_jumps (unsigned long insn)
static int
rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
bfd_byte insn_buf[PPC_INSN_SIZE];
CORE_ADDR scan_pc, func_start, func_end, epilogue_start, epilogue_end;
unsigned long insn;
{
if (!safe_frame_unwind_memory (curfrm, scan_pc, insn_buf, PPC_INSN_SIZE))
return 0;
- insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE);
+ insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE, byte_order);
if (insn == 0x4e800020)
break;
+ /* Assume a bctr is a tail call unless it points strictly within
+ this function. */
+ if (insn == 0x4e800420)
+ {
+ CORE_ADDR ctr = get_frame_register_unsigned (curfrm,
+ tdep->ppc_ctr_regnum);
+ if (ctr > func_start && ctr < func_end)
+ return 0;
+ else
+ break;
+ }
if (insn_changes_sp_or_jumps (insn))
return 0;
}
{
if (!safe_frame_unwind_memory (curfrm, scan_pc, insn_buf, PPC_INSN_SIZE))
return 0;
- insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE);
+ insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE, byte_order);
if (insn_changes_sp_or_jumps (insn))
return 1;
}
return get_frame_register_unsigned (frame, 3 + argi);
}
-/* Calculate the destination of a branch/jump. Return -1 if not a branch. */
+/* Sequence of bytes for breakpoint instruction. */
-static CORE_ADDR
-branch_dest (struct frame_info *frame, int opcode, int instr,
- CORE_ADDR pc, CORE_ADDR safety)
+const static unsigned char *
+rs6000_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
+ int *bp_size)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame));
- CORE_ADDR dest;
- int immediate;
- int absolute;
- int ext_op;
+ static unsigned char big_breakpoint[] = { 0x7d, 0x82, 0x10, 0x08 };
+ static unsigned char little_breakpoint[] = { 0x08, 0x10, 0x82, 0x7d };
+ *bp_size = 4;
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ return big_breakpoint;
+ else
+ return little_breakpoint;
+}
- absolute = (int) ((instr >> 1) & 1);
+/* Instruction masks for displaced stepping. */
+#define BRANCH_MASK 0xfc000000
+#define BP_MASK 0xFC0007FE
+#define B_INSN 0x48000000
+#define BC_INSN 0x40000000
+#define BXL_INSN 0x4c000000
+#define BP_INSN 0x7C000008
- switch (opcode)
- {
- case 18:
- immediate = ((instr & ~3) << 6) >> 6; /* br unconditional */
- if (absolute)
- dest = immediate;
- else
- dest = pc + immediate;
- break;
+/* Fix up the state of registers and memory after having single-stepped
+ a displaced instruction. */
+static void
+ppc_displaced_step_fixup (struct gdbarch *gdbarch,
+ struct displaced_step_closure *closure,
+ CORE_ADDR from, CORE_ADDR to,
+ 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. */
+ ULONGEST insn = extract_unsigned_integer ((gdb_byte *) closure,
+ PPC_INSN_SIZE, byte_order);
+ ULONGEST opcode = 0;
+ /* Offset for non PC-relative instructions. */
+ LONGEST offset = PPC_INSN_SIZE;
- case 16:
- immediate = ((instr & ~3) << 16) >> 16; /* br conditional */
- if (absolute)
- dest = immediate;
- else
- dest = pc + immediate;
- break;
+ opcode = insn & BRANCH_MASK;
+
+ if (debug_displaced)
+ fprintf_unfiltered (gdb_stdlog,
+ "displaced: (ppc) fixup (%s, %s)\n",
+ paddress (gdbarch, from), paddress (gdbarch, to));
+
+
+ /* Handle PC-relative branch instructions. */
+ if (opcode == B_INSN || opcode == BC_INSN || opcode == BXL_INSN)
+ {
+ ULONGEST current_pc;
- case 19:
- ext_op = (instr >> 1) & 0x3ff;
+ /* Read the current PC value after the instruction has been executed
+ in a displaced location. Calculate the offset to be applied to the
+ original PC value before the displaced stepping. */
+ regcache_cooked_read_unsigned (regs, gdbarch_pc_regnum (gdbarch),
+ ¤t_pc);
+ offset = current_pc - to;
- if (ext_op == 16) /* br conditional register */
+ if (opcode != BXL_INSN)
+ {
+ /* Check for AA bit indicating whether this is an absolute
+ addressing or PC-relative (1: absolute, 0: relative). */
+ if (!(insn & 0x2))
+ {
+ /* PC-relative addressing is being used in the branch. */
+ if (debug_displaced)
+ fprintf_unfiltered
+ (gdb_stdlog,
+ "displaced: (ppc) branch instruction: %s\n"
+ "displaced: (ppc) adjusted PC from %s to %s\n",
+ paddress (gdbarch, insn), paddress (gdbarch, current_pc),
+ paddress (gdbarch, from + offset));
+
+ regcache_cooked_write_unsigned (regs, gdbarch_pc_regnum (gdbarch),
+ from + offset);
+ }
+ }
+ else
{
- dest = get_frame_register_unsigned (frame, tdep->ppc_lr_regnum) & ~3;
-
- /* If we are about to return from a signal handler, dest is
- something like 0x3c90. The current frame is a signal handler
- caller frame, upon completion of the sigreturn system call
- execution will return to the saved PC in the frame. */
- if (dest < tdep->text_segment_base)
- dest = read_memory_addr (get_frame_base (frame) + SIG_FRAME_PC_OFFSET,
- tdep->wordsize);
+ /* If we're here, it means we have a branch to LR or CTR. If the
+ branch was taken, the offset is probably greater than 4 (the next
+ instruction), so it's safe to assume that an offset of 4 means we
+ did not take the branch. */
+ if (offset == PPC_INSN_SIZE)
+ regcache_cooked_write_unsigned (regs, gdbarch_pc_regnum (gdbarch),
+ from + PPC_INSN_SIZE);
}
- else if (ext_op == 528) /* br cond to count reg */
+ /* Check for LK bit indicating whether we should set the link
+ register to point to the next instruction
+ (1: Set, 0: Don't set). */
+ if (insn & 0x1)
{
- dest = get_frame_register_unsigned (frame, tdep->ppc_ctr_regnum) & ~3;
+ /* Link register needs to be set to the next instruction's PC. */
+ regcache_cooked_write_unsigned (regs,
+ gdbarch_tdep (gdbarch)->ppc_lr_regnum,
+ from + PPC_INSN_SIZE);
+ if (debug_displaced)
+ fprintf_unfiltered (gdb_stdlog,
+ "displaced: (ppc) adjusted LR to %s\n",
+ paddress (gdbarch, from + PPC_INSN_SIZE));
- /* If we are about to execute a system call, dest is something
- like 0x22fc or 0x3b00. Upon completion the system call
- will return to the address in the link register. */
- if (dest < tdep->text_segment_base)
- dest = get_frame_register_unsigned (frame, tdep->ppc_lr_regnum) & ~3;
}
- else
- return -1;
- break;
-
- default:
- return -1;
}
- return (dest < tdep->text_segment_base) ? safety : dest;
+ /* Check for breakpoints in the inferior. If we've found one, place the PC
+ right at the breakpoint instruction. */
+ else if ((insn & BP_MASK) == BP_INSN)
+ regcache_cooked_write_unsigned (regs, gdbarch_pc_regnum (gdbarch), from);
+ else
+ /* Handle any other instructions that do not fit in the categories above. */
+ regcache_cooked_write_unsigned (regs, gdbarch_pc_regnum (gdbarch),
+ from + offset);
}
-
-/* Sequence of bytes for breakpoint instruction. */
-
-const static unsigned char *
-rs6000_breakpoint_from_pc (CORE_ADDR *bp_addr, int *bp_size)
+/* Always use hardware single-stepping to execute the
+ displaced instruction. */
+static int
+ppc_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
+ struct displaced_step_closure *closure)
{
- static unsigned char big_breakpoint[] = { 0x7d, 0x82, 0x10, 0x08 };
- static unsigned char little_breakpoint[] = { 0x08, 0x10, 0x82, 0x7d };
- *bp_size = 4;
- if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
- return big_breakpoint;
- else
- return little_breakpoint;
+ return 1;
}
-
/* Instruction masks used during single-stepping of atomic sequences. */
#define LWARX_MASK 0xfc0007fe
#define LWARX_INSTRUCTION 0x7c000028
#define STWCX_MASK 0xfc0007ff
#define STWCX_INSTRUCTION 0x7c00012d
#define STDCX_INSTRUCTION 0x7c0001ad
-#define BC_MASK 0xfc000000
-#define BC_INSTRUCTION 0x40000000
/* 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
the sequence. */
-static int
-deal_with_atomic_sequence (struct frame_info *frame)
+int
+ppc_deal_with_atomic_sequence (struct frame_info *frame)
{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ struct address_space *aspace = get_frame_address_space (frame);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR pc = get_frame_pc (frame);
CORE_ADDR breaks[2] = {-1, -1};
CORE_ADDR loc = pc;
- CORE_ADDR branch_bp; /* Breakpoint at branch instruction's destination. */
CORE_ADDR closing_insn; /* Instruction that closes the atomic sequence. */
- int insn = read_memory_integer (loc, PPC_INSN_SIZE);
+ int insn = read_memory_integer (loc, PPC_INSN_SIZE, byte_order);
int insn_count;
int index;
int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed). */
for (insn_count = 0; insn_count < atomic_sequence_length; ++insn_count)
{
loc += PPC_INSN_SIZE;
- insn = read_memory_integer (loc, PPC_INSN_SIZE);
+ insn = read_memory_integer (loc, PPC_INSN_SIZE, byte_order);
/* Assume that there is at most one conditional branch in the atomic
sequence. If a conditional branch is found, put a breakpoint in
its destination address. */
- if ((insn & BC_MASK) == BC_INSTRUCTION)
+ if ((insn & BRANCH_MASK) == BC_INSN)
{
+ int immediate = ((insn & ~3) << 16) >> 16;
+ int absolute = ((insn >> 1) & 1);
+
if (bc_insn_count >= 1)
return 0; /* More than one conditional branch found, fallback
to the standard single-step code. */
-
- opcode = insn >> 26;
- branch_bp = branch_dest (frame, opcode, insn, pc, breaks[0]);
-
- if (branch_bp != -1)
- {
- breaks[1] = branch_bp;
- bc_insn_count++;
- last_breakpoint++;
- }
+
+ if (absolute)
+ breaks[1] = immediate;
+ else
+ breaks[1] = pc + immediate;
+
+ bc_insn_count++;
+ last_breakpoint++;
}
if ((insn & STWCX_MASK) == STWCX_INSTRUCTION
closing_insn = loc;
loc += PPC_INSN_SIZE;
- insn = read_memory_integer (loc, PPC_INSN_SIZE);
+ insn = read_memory_integer (loc, PPC_INSN_SIZE, byte_order);
/* Insert a breakpoint right after the end of the atomic sequence. */
breaks[0] = loc;
/* Effectively inserts the breakpoints. */
for (index = 0; index <= last_breakpoint; index++)
- insert_single_step_breakpoint (breaks[index]);
+ insert_single_step_breakpoint (gdbarch, aspace, breaks[index]);
return 1;
}
-/* AIX does not support PT_STEP. Simulate it. */
-
-int
-rs6000_software_single_step (struct frame_info *frame)
-{
- CORE_ADDR dummy;
- int breakp_sz;
- const gdb_byte *breakp = rs6000_breakpoint_from_pc (&dummy, &breakp_sz);
- int ii, insn;
- CORE_ADDR loc;
- CORE_ADDR breaks[2];
- int opcode;
- loc = get_frame_pc (frame);
+#define SIGNED_SHORT(x) \
+ ((sizeof (short) == 2) \
+ ? ((int)(short)(x)) \
+ : ((int)((((x) & 0xffff) ^ 0x8000) - 0x8000)))
- insn = read_memory_integer (loc, 4);
+#define GET_SRC_REG(x) (((x) >> 21) & 0x1f)
- if (deal_with_atomic_sequence (frame))
- return 1;
-
- breaks[0] = loc + breakp_sz;
- opcode = insn >> 26;
- breaks[1] = branch_dest (frame, opcode, insn, loc, breaks[0]);
+/* Limit the number of skipped non-prologue instructions, as the examining
+ of the prologue is expensive. */
+static int max_skip_non_prologue_insns = 10;
- /* Don't put two breakpoints on the same address. */
- if (breaks[1] == breaks[0])
- breaks[1] = -1;
+/* Return nonzero if the given instruction OP can be part of the prologue
+ of a function and saves a parameter on the stack. FRAMEP should be
+ set if one of the previous instructions in the function has set the
+ Frame Pointer. */
- for (ii = 0; ii < 2; ++ii)
+static int
+store_param_on_stack_p (unsigned long op, int framep, int *r0_contains_arg)
+{
+ /* Move parameters from argument registers to temporary register. */
+ if ((op & 0xfc0007fe) == 0x7c000378) /* mr(.) Rx,Ry */
{
- /* ignore invalid breakpoint. */
- if (breaks[ii] == -1)
- continue;
- insert_single_step_breakpoint (breaks[ii]);
- }
-
- errno = 0; /* FIXME, don't ignore errors! */
- /* What errors? {read,write}_memory call error(). */
- return 1;
-}
-
-
-/* return pc value after skipping a function prologue and also return
- information about a function frame.
-
- in struct rs6000_framedata fdata:
- - frameless is TRUE, if function does not have a frame.
- - nosavedpc is TRUE, if function does not save %pc value in its frame.
- - offset is the initial size of this stack frame --- the amount by
- which we decrement the sp to allocate the frame.
- - saved_gpr is the number of the first saved gpr.
- - saved_fpr is the number of the first saved fpr.
- - saved_vr is the number of the first saved vr.
- - saved_ev is the number of the first saved ev.
- - alloca_reg is the number of the register used for alloca() handling.
- Otherwise -1.
- - gpr_offset is the offset of the first saved gpr from the previous frame.
- - fpr_offset is the offset of the first saved fpr from the previous frame.
- - vr_offset is the offset of the first saved vr from the previous frame.
- - ev_offset is the offset of the first saved ev from the previous frame.
- - lr_offset is the offset of the saved lr
- - cr_offset is the offset of the saved cr
- - vrsave_offset is the offset of the saved vrsave register
- */
-
-#define SIGNED_SHORT(x) \
- ((sizeof (short) == 2) \
- ? ((int)(short)(x)) \
- : ((int)((((x) & 0xffff) ^ 0x8000) - 0x8000)))
-
-#define GET_SRC_REG(x) (((x) >> 21) & 0x1f)
-
-/* Limit the number of skipped non-prologue instructions, as the examining
- of the prologue is expensive. */
-static int max_skip_non_prologue_insns = 10;
-
-/* Return nonzero if the given instruction OP can be part of the prologue
- of a function and saves a parameter on the stack. FRAMEP should be
- set if one of the previous instructions in the function has set the
- Frame Pointer. */
-
-static int
-store_param_on_stack_p (unsigned long op, int framep, int *r0_contains_arg)
-{
- /* Move parameters from argument registers to temporary register. */
- if ((op & 0xfc0007fe) == 0x7c000378) /* mr(.) Rx,Ry */
- {
- /* Rx must be scratch register r0. */
- const int rx_regno = (op >> 16) & 31;
- /* Ry: Only r3 - r10 are used for parameter passing. */
- const int ry_regno = GET_SRC_REG (op);
+ /* Rx must be scratch register r0. */
+ const int rx_regno = (op >> 16) & 31;
+ /* Ry: Only r3 - r10 are used for parameter passing. */
+ const int ry_regno = GET_SRC_REG (op);
if (rx_regno == 0 && ry_regno >= 3 && ry_regno <= 10)
{
they can use to access PIC data using PC-relative offsets. */
static int
-bl_to_blrl_insn_p (CORE_ADDR pc, int insn)
+bl_to_blrl_insn_p (CORE_ADDR pc, int insn, enum bfd_endian byte_order)
{
CORE_ADDR dest;
int immediate;
else
dest = pc + immediate;
- dest_insn = read_memory_integer (dest, 4);
+ dest_insn = read_memory_integer (dest, 4, byte_order);
if ((dest_insn & 0xfc00ffff) == 0x4c000021) /* blrl */
return 1;
return 0;
}
+/* Masks for decoding a branch-and-link (bl) instruction.
+
+ BL_MASK and BL_INSTRUCTION are used in combination with each other.
+ The former is anded with the opcode in question; if the result of
+ this masking operation is equal to BL_INSTRUCTION, then the opcode in
+ question is a ``bl'' instruction.
+
+ BL_DISPLACMENT_MASK is anded with the opcode in order to extract
+ the branch displacement. */
+
+#define BL_MASK 0xfc000001
+#define BL_INSTRUCTION 0x48000001
+#define BL_DISPLACEMENT_MASK 0x03fffffc
+
+static unsigned long
+rs6000_fetch_instruction (struct gdbarch *gdbarch, const CORE_ADDR pc)
+{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ 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, byte_order);
+
+ 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 (struct gdbarch *gdbarch, const CORE_ADDR start_pc)
+{
+ CORE_ADDR pc = start_pc;
+ unsigned long op = rs6000_fetch_instruction (gdbarch, 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 (gdbarch, 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 (gdbarch, pc);
+ if ((op & 0xffff0000) != 0x3c000000)
+ break;
+
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (gdbarch, pc);
+ /* [possibly ori 0,0,<some immediate>] */
+ if ((op & 0xffff0000) == 0x60000000)
+ {
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (gdbarch, pc);
+ }
+ /* add 0,12,0 */
+ if (op != 0x7c0c0214)
+ break;
+
+ /* cmpw 0,12,0 */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (gdbarch, pc);
+ if (op != 0x7c0c0000)
+ break;
+
+ /* beq 0,<disp> */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (gdbarch, pc);
+ if ((op & 0xff9f0001) != 0x41820000)
+ break;
+
+ /* addi 12,12,-<some immediate> */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (gdbarch, pc);
+ if ((op & 0xffff0000) != 0x398c0000)
+ break;
+
+ /* stw 0,0(12) */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (gdbarch, pc);
+ if (op != 0x900c0000)
+ break;
+
+ /* b <disp> */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (gdbarch, pc);
+ if ((op & 0xfc000001) != 0x48000000)
+ break;
+
+ /* [possibly one last probe: stw 0,<some immediate>(12)] */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (gdbarch, pc);
+ if ((op & 0xffff0000) == 0x900c0000)
+ {
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (gdbarch, 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 (gdbarch, pc);
+ if ((op & 0xffff0000) != 0x30000000)
+ break;
+ }
+
+ /* lis 12,<some immediate> */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (gdbarch, pc);
+ if ((op & 0xffff0000) != 0x3d800000)
+ break;
+
+ /* lwz 12,<some immediate>(12) */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (gdbarch, pc);
+ if ((op & 0xffff0000) != 0x818c0000)
+ break;
+
+ /* twllt 0,12 */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (gdbarch, 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.
+
+ in struct rs6000_framedata fdata:
+ - frameless is TRUE, if function does not have a frame.
+ - nosavedpc is TRUE, if function does not save %pc value in its frame.
+ - offset is the initial size of this stack frame --- the amount by
+ which we decrement the sp to allocate the frame.
+ - saved_gpr is the number of the first saved gpr.
+ - saved_fpr is the number of the first saved fpr.
+ - saved_vr is the number of the first saved vr.
+ - saved_ev is the number of the first saved ev.
+ - alloca_reg is the number of the register used for alloca() handling.
+ Otherwise -1.
+ - gpr_offset is the offset of the first saved gpr from the previous frame.
+ - fpr_offset is the offset of the first saved fpr from the previous frame.
+ - vr_offset is the offset of the first saved vr from the previous frame.
+ - ev_offset is the offset of the first saved ev from the previous frame.
+ - lr_offset is the offset of the saved lr
+ - cr_offset is the offset of the saved cr
+ - vrsave_offset is the offset of the saved vrsave register
+ */
+
static CORE_ADDR
-skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
+skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
+ struct rs6000_framedata *fdata)
{
CORE_ADDR orig_pc = pc;
CORE_ADDR last_prologue_pc = pc;
int prev_insn_was_prologue_insn = 1;
int num_skip_non_prologue_insns = 0;
int r0_contains_arg = 0;
- const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (current_gdbarch);
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
memset (fdata, 0, sizeof (struct rs6000_framedata));
fdata->saved_gpr = -1;
fdata->alloca_reg = -1;
fdata->frameless = 1;
fdata->nosavedpc = 1;
+ fdata->lr_register = -1;
+
+ pc = rs6000_skip_stack_check (gdbarch, pc);
+ if (pc >= lim_pc)
+ pc = lim_pc;
for (;; pc += 4)
{
/* Fetch the instruction and convert it to an integer. */
if (target_read_memory (pc, buf, 4))
break;
- op = extract_unsigned_integer (buf, 4);
+ op = extract_unsigned_integer (buf, 4, byte_order);
if ((op & 0xfc1fffff) == 0x7c0802a6)
{ /* mflr Rx */
remember just the first one, but skip over additional
ones. */
if (lr_reg == -1)
- lr_reg = (op & 0x03e00000);
+ lr_reg = (op & 0x03e00000) >> 21;
if (lr_reg == 0)
r0_contains_arg = 0;
continue;
{
reg = GET_SRC_REG (op);
+ if ((op & 0xfc1f0000) == 0xbc010000)
+ fdata->gpr_mask |= ~((1U << reg) - 1);
+ else
+ fdata->gpr_mask |= 1U << reg;
if (fdata->saved_gpr == -1 || fdata->saved_gpr > reg)
{
fdata->saved_gpr = reg;
else if (op == 0x48000005)
{ /* bl .+4 used in
-mrelocatable */
+ fdata->used_bl = 1;
continue;
}
/* If the return address has already been saved, we can skip
calls to blrl (for PIC). */
- if (lr_reg != -1 && bl_to_blrl_insn_p (pc, op))
- continue;
+ if (lr_reg != -1 && bl_to_blrl_insn_p (pc, op, byte_order))
+ {
+ fdata->used_bl = 1;
+ continue;
+ }
/* Don't skip over the subroutine call if it is not within
the first three instructions of the prologue and either
break;
}
- op = read_memory_integer (pc + 4, 4);
+ op = read_memory_integer (pc + 4, 4, byte_order);
/* At this point, make sure this is not a trampoline
function (a function that simply calls another functions,
if (op == 0x4def7b82 || op == 0) /* crorc 15, 15, 15 */
break; /* don't skip over
this branch */
- continue;
+ fdata->used_bl = 1;
+ continue;
}
/* update stack pointer */
else if ((op & 0xfc1f0000) == 0x94010000)
else
{
+ unsigned int all_mask = ~((1U << fdata->saved_gpr) - 1);
+
/* Not a recognized prologue instruction.
Handle optimizer code motions into the prologue by continuing
the search if we have no valid frame yet or if the return
- address is not yet saved in the frame. */
- if (fdata->frameless == 0 && fdata->nosavedpc == 0)
+ address is not yet saved in the frame. Also skip instructions
+ if some of the GPRs expected to be saved are not yet saved. */
+ if (fdata->frameless == 0 && fdata->nosavedpc == 0
+ && (fdata->gpr_mask & all_mask) == all_mask)
break;
if (op == 0x4e800020 /* blr */
if ((op & 0xfc000001) == 0x48000001)
{ /* bl foo, an initializer function? */
- op = read_memory_integer (pc + 4, 4);
+ op = read_memory_integer (pc + 4, 4, byte_order);
if (op == 0x4def7b82)
{ /* cror 0xf, 0xf, 0xf (nop) */
}
#endif /* 0 */
+ if (pc == lim_pc && lr_reg >= 0)
+ fdata->lr_register = lr_reg;
+
fdata->offset = -fdata->offset;
return last_prologue_pc;
}
+static CORE_ADDR
+rs6000_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+ struct rs6000_framedata frame;
+ CORE_ADDR limit_pc, func_addr;
-/*************************************************************************
- Support for creating pushing a dummy frame into the stack, and popping
- frames, etc.
-*************************************************************************/
+ /* See if we can determine the end of the prologue via the symbol table.
+ If so, then return either PC, or the PC after the prologue, whichever
+ is greater. */
+ if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
+ {
+ CORE_ADDR post_prologue_pc
+ = skip_prologue_using_sal (gdbarch, func_addr);
+ if (post_prologue_pc != 0)
+ return max (pc, post_prologue_pc);
+ }
+ /* Can't determine prologue from the symbol table, need to examine
+ instructions. */
-/* All the ABI's require 16 byte alignment. */
-static CORE_ADDR
-rs6000_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
-{
- return (addr & -16);
-}
+ /* 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 (gdbarch, pc);
+ if (limit_pc == 0)
+ limit_pc = pc + 100; /* Magic. */
-/* Pass the arguments in either registers, or in the stack. In RS/6000,
- the first eight words of the argument list (that might be less than
- eight parameters if some parameters occupy more than one word) are
- passed in r3..r10 registers. float and double parameters are
- passed in fpr's, in addition to that. Rest of the parameters if any
- are passed in user stack. There might be cases in which half of the
- parameter is copied into registers, the other half is pushed into
- stack.
+ pc = skip_prologue (gdbarch, pc, limit_pc, &frame);
+ return pc;
+}
- Stack must be aligned on 64-bit boundaries when synthesizing
- function calls.
+/* When compiling for EABI, some versions of GCC emit a call to __eabi
+ in the prologue of main().
- If the function is returning a structure, then the return address is passed
- in r3, then the first 7 words of the parameters can be passed in registers,
- starting from r4. */
+ The function below examines the code pointed at by PC and checks to
+ see if it corresponds to a call to __eabi. If so, it returns the
+ address of the instruction following that call. Otherwise, it simply
+ returns PC. */
static CORE_ADDR
-rs6000_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
- struct regcache *regcache, CORE_ADDR bp_addr,
- int nargs, struct value **args, CORE_ADDR sp,
- int struct_return, CORE_ADDR struct_addr)
-{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
- int ii;
- int len = 0;
- int argno; /* current argument number */
- int argbytes; /* current argument byte */
- gdb_byte tmp_buffer[50];
- int f_argno = 0; /* current floating point argno */
- int wordsize = gdbarch_tdep (current_gdbarch)->wordsize;
- CORE_ADDR func_addr = find_function_addr (function, NULL);
-
- struct value *arg = 0;
- struct type *type;
-
- ULONGEST saved_sp;
-
- /* The calling convention this function implements assumes the
- processor has floating-point registers. We shouldn't be using it
- on PPC variants that lack them. */
- gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
-
- /* The first eight words of ther arguments are passed in registers.
- Copy them appropriately. */
- ii = 0;
-
- /* If the function is returning a `struct', then the first word
- (which will be passed in r3) is used for struct return address.
- In that case we should advance one word and start from r4
- register to copy parameters. */
- if (struct_return)
- {
- regcache_raw_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
- struct_addr);
- ii++;
- }
-
-/*
- effectively indirect call... gcc does...
-
- return_val example( float, int);
-
- eabi:
- float in fp0, int in r3
- offset of stack on overflow 8/16
- for varargs, must go by type.
- power open:
- float in r3&r4, int in r5
- offset of stack on overflow different
- both:
- return in r3 or f0. If no float, must study how gcc emulates floats;
- pay attention to arg promotion.
- User may have to cast\args to handle promotion correctly
- since gdb won't know if prototype supplied or not.
- */
+rs6000_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ gdb_byte buf[4];
+ unsigned long op;
+
+ if (target_read_memory (pc, buf, 4))
+ return pc;
+ op = extract_unsigned_integer (buf, 4, byte_order);
- for (argno = 0, argbytes = 0; argno < nargs && ii < 8; ++ii)
+ if ((op & BL_MASK) == BL_INSTRUCTION)
{
- int reg_size = register_size (current_gdbarch, ii + 3);
+ CORE_ADDR displ = op & BL_DISPLACEMENT_MASK;
+ CORE_ADDR call_dest = pc + 4 + displ;
+ struct minimal_symbol *s = lookup_minimal_symbol_by_pc (call_dest);
+
+ /* We check for ___eabi (three leading underscores) in addition
+ to __eabi in case the GCC option "-fleading-underscore" was
+ used to compile the program. */
+ if (s != NULL
+ && SYMBOL_LINKAGE_NAME (s) != NULL
+ && (strcmp (SYMBOL_LINKAGE_NAME (s), "__eabi") == 0
+ || strcmp (SYMBOL_LINKAGE_NAME (s), "___eabi") == 0))
+ pc += 4;
+ }
+ return pc;
+}
- arg = args[argno];
- type = check_typedef (value_type (arg));
- len = TYPE_LENGTH (type);
+/* All the ABI's require 16 byte alignment. */
+static CORE_ADDR
+rs6000_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ return (addr & -16);
+}
- if (TYPE_CODE (type) == TYPE_CODE_FLT)
- {
+/* Return whether handle_inferior_event() should proceed through code
+ starting at PC in function NAME when stepping.
- /* Floating point arguments are passed in fpr's, as well as gpr's.
- There are 13 fpr's reserved for passing parameters. At this point
- there is no way we would run out of them. */
+ The AIX -bbigtoc linker option generates functions @FIX0, @FIX1, etc. to
+ handle memory references that are too distant to fit in instructions
+ generated by the compiler. For example, if 'foo' in the following
+ instruction:
- gdb_assert (len <= 8);
+ lwz r9,foo(r2)
- regcache_cooked_write (regcache,
- tdep->ppc_fp0_regnum + 1 + f_argno,
- value_contents (arg));
- ++f_argno;
- }
+ is greater than 32767, the linker might replace the lwz with a branch to
+ somewhere in @FIX1 that does the load in 2 instructions and then branches
+ back to where execution should continue.
- if (len > reg_size)
- {
+ GDB should silently step over @FIX code, just like AIX dbx does.
+ Unfortunately, the linker uses the "b" instruction for the
+ branches, meaning that the link register doesn't get set.
+ Therefore, GDB's usual step_over_function () mechanism won't work.
- /* Argument takes more than one register. */
- while (argbytes < len)
- {
- gdb_byte word[MAX_REGISTER_SIZE];
- memset (word, 0, reg_size);
- memcpy (word,
- ((char *) value_contents (arg)) + argbytes,
- (len - argbytes) > reg_size
- ? reg_size : len - argbytes);
- regcache_cooked_write (regcache,
- tdep->ppc_gp0_regnum + 3 + ii,
- word);
- ++ii, argbytes += reg_size;
-
- if (ii >= 8)
- goto ran_out_of_registers_for_arguments;
- }
- argbytes = 0;
- --ii;
- }
- else
- {
- /* Argument can fit in one register. No problem. */
- int adj = gdbarch_byte_order (current_gdbarch)
- == BFD_ENDIAN_BIG ? reg_size - len : 0;
- gdb_byte word[MAX_REGISTER_SIZE];
-
- memset (word, 0, reg_size);
- memcpy (word, value_contents (arg), len);
- regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3 +ii, word);
- }
- ++argno;
- }
+ Instead, use the gdbarch_skip_trampoline_code and
+ gdbarch_skip_trampoline_code hooks in handle_inferior_event() to skip past
+ @FIX code. */
-ran_out_of_registers_for_arguments:
+static int
+rs6000_in_solib_return_trampoline (struct gdbarch *gdbarch,
+ CORE_ADDR pc, char *name)
+{
+ return name && !strncmp (name, "@FIX", 4);
+}
- regcache_cooked_read_unsigned (regcache,
- gdbarch_sp_regnum (current_gdbarch),
- &saved_sp);
+/* Skip code that the user doesn't want to see when stepping:
- /* Location for 8 parameters are always reserved. */
- sp -= wordsize * 8;
+ 1. Indirect function calls use a piece of trampoline code to do context
+ switching, i.e. to set the new TOC table. Skip such code if we are on
+ its first instruction (as when we have single-stepped to here).
- /* Another six words for back chain, TOC register, link register, etc. */
- sp -= wordsize * 6;
+ 2. Skip shared library trampoline code (which is different from
+ indirect function call trampolines).
- /* Stack pointer must be quadword aligned. */
- sp &= -16;
+ 3. Skip bigtoc fixup code.
- /* If there are more arguments, allocate space for them in
- the stack, then push them starting from the ninth one. */
+ Result is desired PC to step until, or NULL if we are not in
+ code that should be skipped. */
- if ((argno < nargs) || argbytes)
- {
- int space = 0, jj;
+static CORE_ADDR
+rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
+{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ unsigned int ii, op;
+ int rel;
+ CORE_ADDR solib_target_pc;
+ struct minimal_symbol *msymbol;
- if (argbytes)
- {
- space += ((len - argbytes + 3) & -4);
- jj = argno + 1;
- }
- else
- jj = argno;
+ static unsigned trampoline_code[] =
+ {
+ 0x800b0000, /* l r0,0x0(r11) */
+ 0x90410014, /* st r2,0x14(r1) */
+ 0x7c0903a6, /* mtctr r0 */
+ 0x804b0004, /* l r2,0x4(r11) */
+ 0x816b0008, /* l r11,0x8(r11) */
+ 0x4e800420, /* bctr */
+ 0x4e800020, /* br */
+ 0
+ };
- for (; jj < nargs; ++jj)
+ /* Check for bigtoc fixup code. */
+ msymbol = lookup_minimal_symbol_by_pc (pc);
+ if (msymbol
+ && rs6000_in_solib_return_trampoline (gdbarch, pc,
+ SYMBOL_LINKAGE_NAME (msymbol)))
+ {
+ /* Double-check that the third instruction from PC is relative "b". */
+ op = read_memory_integer (pc + 8, 4, byte_order);
+ if ((op & 0xfc000003) == 0x48000000)
{
- struct value *val = args[jj];
- space += ((TYPE_LENGTH (value_type (val))) + 3) & -4;
+ /* Extract bits 6-29 as a signed 24-bit relative word address and
+ add it to the containing PC. */
+ rel = ((int)(op << 6) >> 6);
+ return pc + 8 + rel;
}
-
- /* Add location required for the rest of the parameters. */
- space = (space + 15) & -16;
- sp -= space;
-
- /* This is another instance we need to be concerned about
- securing our stack space. If we write anything underneath %sp
- (r1), we might conflict with the kernel who thinks he is free
- to use this area. So, update %sp first before doing anything
- else. */
-
- regcache_raw_write_signed (regcache,
- gdbarch_sp_regnum (current_gdbarch), sp);
-
- /* If the last argument copied into the registers didn't fit there
- completely, push the rest of it into stack. */
-
- if (argbytes)
- {
- write_memory (sp + 24 + (ii * 4),
- value_contents (arg) + argbytes,
- len - argbytes);
- ++argno;
- ii += ((len - argbytes + 3) & -4) / 4;
- }
-
- /* Push the rest of the arguments into stack. */
- for (; argno < nargs; ++argno)
- {
-
- arg = args[argno];
- type = check_typedef (value_type (arg));
- len = TYPE_LENGTH (type);
-
-
- /* Float types should be passed in fpr's, as well as in the
- stack. */
- if (TYPE_CODE (type) == TYPE_CODE_FLT && f_argno < 13)
- {
-
- gdb_assert (len <= 8);
-
- regcache_cooked_write (regcache,
- tdep->ppc_fp0_regnum + 1 + f_argno,
- value_contents (arg));
- ++f_argno;
- }
-
- write_memory (sp + 24 + (ii * 4), value_contents (arg), len);
- ii += ((len + 3) & -4) / 4;
- }
- }
-
- /* Set the stack pointer. According to the ABI, the SP is meant to
- be set _before_ the corresponding stack space is used. On AIX,
- this even applies when the target has been completely stopped!
- Not doing this can lead to conflicts with the kernel which thinks
- that it still has control over this not-yet-allocated stack
- region. */
- regcache_raw_write_signed (regcache, gdbarch_sp_regnum (current_gdbarch), sp);
-
- /* Set back chain properly. */
- store_unsigned_integer (tmp_buffer, wordsize, saved_sp);
- write_memory (sp, tmp_buffer, wordsize);
-
- /* Point the inferior function call's return address at the dummy's
- breakpoint. */
- regcache_raw_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr);
-
- /* Set the TOC register, get the value from the objfile reader
- which, in turn, gets it from the VMAP table. */
- if (rs6000_find_toc_address_hook != NULL)
- {
- CORE_ADDR tocvalue = (*rs6000_find_toc_address_hook) (func_addr);
- regcache_raw_write_signed (regcache, tdep->ppc_toc_regnum, tocvalue);
- }
-
- target_store_registers (regcache, -1);
- return sp;
-}
-
-static enum return_value_convention
-rs6000_return_value (struct gdbarch *gdbarch, struct type *valtype,
- struct regcache *regcache, gdb_byte *readbuf,
- const gdb_byte *writebuf)
-{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
- gdb_byte buf[8];
-
- /* The calling convention this function implements assumes the
- processor has floating-point registers. We shouldn't be using it
- on PowerPC variants that lack them. */
- gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
-
- /* AltiVec extension: Functions that declare a vector data type as a
- return value place that return value in VR2. */
- if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype)
- && TYPE_LENGTH (valtype) == 16)
- {
- if (readbuf)
- regcache_cooked_read (regcache, tdep->ppc_vr0_regnum + 2, readbuf);
- if (writebuf)
- regcache_cooked_write (regcache, tdep->ppc_vr0_regnum + 2, writebuf);
-
- return RETURN_VALUE_REGISTER_CONVENTION;
- }
-
- /* If the called subprogram returns an aggregate, there exists an
- implicit first argument, whose value is the address of a caller-
- allocated buffer into which the callee is assumed to store its
- return value. All explicit parameters are appropriately
- relabeled. */
- if (TYPE_CODE (valtype) == TYPE_CODE_STRUCT
- || TYPE_CODE (valtype) == TYPE_CODE_UNION
- || TYPE_CODE (valtype) == TYPE_CODE_ARRAY)
- return RETURN_VALUE_STRUCT_CONVENTION;
-
- /* Scalar floating-point values are returned in FPR1 for float or
- double, and in FPR1:FPR2 for quadword precision. Fortran
- complex*8 and complex*16 are returned in FPR1:FPR2, and
- complex*32 is returned in FPR1:FPR4. */
- if (TYPE_CODE (valtype) == TYPE_CODE_FLT
- && (TYPE_LENGTH (valtype) == 4 || TYPE_LENGTH (valtype) == 8))
- {
- struct type *regtype = register_type (gdbarch, tdep->ppc_fp0_regnum);
- gdb_byte regval[8];
-
- /* FIXME: kettenis/2007-01-01: Add support for quadword
- precision and complex. */
-
- if (readbuf)
- {
- regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, regval);
- convert_typed_floating (regval, regtype, readbuf, valtype);
- }
- if (writebuf)
- {
- convert_typed_floating (writebuf, valtype, regval, regtype);
- regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, regval);
- }
-
- return RETURN_VALUE_REGISTER_CONVENTION;
- }
-
- /* Values of the types int, long, short, pointer, and char (length
- is less than or equal to four bytes), as well as bit values of
- lengths less than or equal to 32 bits, must be returned right
- justified in GPR3 with signed values sign extended and unsigned
- values zero extended, as necessary. */
- if (TYPE_LENGTH (valtype) <= tdep->wordsize)
- {
- if (readbuf)
- {
- ULONGEST regval;
-
- /* For reading we don't have to worry about sign extension. */
- regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
- ®val);
- store_unsigned_integer (readbuf, TYPE_LENGTH (valtype), regval);
- }
- if (writebuf)
- {
- /* For writing, use unpack_long since that should handle any
- required sign extension. */
- regcache_cooked_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
- unpack_long (valtype, writebuf));
- }
-
- return RETURN_VALUE_REGISTER_CONVENTION;
- }
-
- /* Eight-byte non-floating-point scalar values must be returned in
- GPR3:GPR4. */
-
- if (TYPE_LENGTH (valtype) == 8)
- {
- gdb_assert (TYPE_CODE (valtype) != TYPE_CODE_FLT);
- gdb_assert (tdep->wordsize == 4);
-
- if (readbuf)
- {
- gdb_byte regval[8];
-
- regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, regval);
- regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
- regval + 4);
- memcpy (readbuf, regval, 8);
- }
- if (writebuf)
- {
- regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3, writebuf);
- regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
- writebuf + 4);
- }
-
- return RETURN_VALUE_REGISTER_CONVENTION;
- }
-
- return RETURN_VALUE_STRUCT_CONVENTION;
-}
-
-/* Return whether handle_inferior_event() should proceed through code
- starting at PC in function NAME when stepping.
-
- The AIX -bbigtoc linker option generates functions @FIX0, @FIX1, etc. to
- handle memory references that are too distant to fit in instructions
- generated by the compiler. For example, if 'foo' in the following
- instruction:
-
- lwz r9,foo(r2)
-
- is greater than 32767, the linker might replace the lwz with a branch to
- somewhere in @FIX1 that does the load in 2 instructions and then branches
- back to where execution should continue.
-
- GDB should silently step over @FIX code, just like AIX dbx does.
- Unfortunately, the linker uses the "b" instruction for the
- branches, meaning that the link register doesn't get set.
- Therefore, GDB's usual step_over_function () mechanism won't work.
-
- Instead, use the gdbarch_skip_trampoline_code and
- gdbarch_skip_trampoline_code hooks in handle_inferior_event() to skip past
- @FIX code. */
-
-int
-rs6000_in_solib_return_trampoline (CORE_ADDR pc, char *name)
-{
- return name && !strncmp (name, "@FIX", 4);
-}
-
-/* Skip code that the user doesn't want to see when stepping:
-
- 1. Indirect function calls use a piece of trampoline code to do context
- switching, i.e. to set the new TOC table. Skip such code if we are on
- its first instruction (as when we have single-stepped to here).
-
- 2. Skip shared library trampoline code (which is different from
- indirect function call trampolines).
-
- 3. Skip bigtoc fixup code.
-
- Result is desired PC to step until, or NULL if we are not in
- code that should be skipped. */
-
-CORE_ADDR
-rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
-{
- unsigned int ii, op;
- int rel;
- CORE_ADDR solib_target_pc;
- struct minimal_symbol *msymbol;
-
- static unsigned trampoline_code[] =
- {
- 0x800b0000, /* l r0,0x0(r11) */
- 0x90410014, /* st r2,0x14(r1) */
- 0x7c0903a6, /* mtctr r0 */
- 0x804b0004, /* l r2,0x4(r11) */
- 0x816b0008, /* l r11,0x8(r11) */
- 0x4e800420, /* bctr */
- 0x4e800020, /* br */
- 0
- };
-
- /* Check for bigtoc fixup code. */
- msymbol = lookup_minimal_symbol_by_pc (pc);
- if (msymbol
- && rs6000_in_solib_return_trampoline (pc,
- DEPRECATED_SYMBOL_NAME (msymbol)))
- {
- /* Double-check that the third instruction from PC is relative "b". */
- op = read_memory_integer (pc + 8, 4);
- if ((op & 0xfc000003) == 0x48000000)
- {
- /* Extract bits 6-29 as a signed 24-bit relative word address and
- add it to the containing PC. */
- rel = ((int)(op << 6) >> 6);
- return pc + 8 + rel;
- }
- }
+ }
/* If pc is in a shared library trampoline, return its target. */
solib_target_pc = find_solib_trampoline_target (frame, pc);
for (ii = 0; trampoline_code[ii]; ++ii)
{
- op = read_memory_integer (pc + (ii * 4), 4);
+ op = read_memory_integer (pc + (ii * 4), 4, byte_order);
if (op != trampoline_code[ii])
return 0;
}
ii = get_frame_register_unsigned (frame, 11); /* r11 holds destination addr */
- pc = read_memory_addr (ii, gdbarch_tdep (current_gdbarch)->wordsize); /* (r11) value */
+ pc = read_memory_unsigned_integer (ii, tdep->wordsize, byte_order);
return pc;
}
if (!tdep->ppc_builtin_type_vec64)
{
+ const struct builtin_type *bt = builtin_type (gdbarch);
+
/* The type we're building is this: */
#if 0
union __gdb_builtin_type_vec64
struct type *t;
- t = init_composite_type ("__ppc_builtin_type_vec64", TYPE_CODE_UNION);
- append_composite_type_field (t, "uint64", builtin_type_int64);
+ t = arch_composite_type (gdbarch,
+ "__ppc_builtin_type_vec64", TYPE_CODE_UNION);
+ append_composite_type_field (t, "uint64", bt->builtin_int64);
append_composite_type_field (t, "v2_float",
- init_vector_type (builtin_type_float, 2));
+ init_vector_type (bt->builtin_float, 2));
append_composite_type_field (t, "v2_int32",
- init_vector_type (builtin_type_int32, 2));
+ init_vector_type (bt->builtin_int32, 2));
append_composite_type_field (t, "v4_int16",
- init_vector_type (builtin_type_int16, 4));
+ init_vector_type (bt->builtin_int16, 4));
append_composite_type_field (t, "v8_int8",
- init_vector_type (builtin_type_int8, 8));
+ init_vector_type (bt->builtin_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;
}
return tdep->ppc_builtin_type_vec64;
}
+/* Vector 128 type. */
+
static struct type *
rs6000_builtin_type_vec128 (struct gdbarch *gdbarch)
{
if (!tdep->ppc_builtin_type_vec128)
{
- /* The type we're building is this: */
-#if 0
- union __gdb_builtin_type_vec128
- {
- int128_t uint128;
- float v4_float[4];
- int32_t v4_int32[4];
- int16_t v8_int16[8];
- int8_t v16_int8[16];
- };
-#endif
+ const struct builtin_type *bt = builtin_type (gdbarch);
+
+ /* The type we're building is this
+
+ type = union __ppc_builtin_type_vec128 {
+ uint128_t uint128;
+ double v2_double[2];
+ float v4_float[4];
+ int32_t v4_int32[4];
+ int16_t v8_int16[8];
+ int8_t v16_int8[16];
+ }
+ */
struct type *t;
- t = init_composite_type ("__ppc_builtin_type_vec128", TYPE_CODE_UNION);
- append_composite_type_field (t, "uint128", builtin_type_int128);
+ t = arch_composite_type (gdbarch,
+ "__ppc_builtin_type_vec128", TYPE_CODE_UNION);
+ append_composite_type_field (t, "uint128", bt->builtin_uint128);
+ append_composite_type_field (t, "v2_double",
+ init_vector_type (bt->builtin_double, 2));
append_composite_type_field (t, "v4_float",
- init_vector_type (builtin_type_float, 4));
+ init_vector_type (bt->builtin_float, 4));
append_composite_type_field (t, "v4_int32",
- init_vector_type (builtin_type_int32, 4));
+ init_vector_type (bt->builtin_int32, 4));
append_composite_type_field (t, "v8_int16",
- init_vector_type (builtin_type_int16, 8));
+ init_vector_type (bt->builtin_int16, 8));
append_composite_type_field (t, "v16_int8",
- init_vector_type (builtin_type_int8, 16));
+ init_vector_type (bt->builtin_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;
}
return tdep->ppc_builtin_type_vec128;
}
-/* Return the size of register REG when words are WORDSIZE bytes long. If REG
- isn't available with that word size, return 0. */
+/* Return the name of register number REGNO, or the empty string if it
+ is an anonymous register. */
-static int
-regsize (const struct reg *reg, int wordsize)
+static const char *
+rs6000_register_name (struct gdbarch *gdbarch, int regno)
{
- return wordsize == 8 ? reg->sz64 : reg->sz32;
-}
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ /* The upper half "registers" have names in the XML description,
+ but we present only the low GPRs and the full 64-bit registers
+ to the user. */
+ if (tdep->ppc_ev0_upper_regnum >= 0
+ && tdep->ppc_ev0_upper_regnum <= regno
+ && regno < tdep->ppc_ev0_upper_regnum + ppc_num_gprs)
+ return "";
-/* Return the name of register number N, or null if no such register exists
- in the current architecture. */
+ /* Hide the upper halves of the vs0~vs31 registers. */
+ if (tdep->ppc_vsr0_regnum >= 0
+ && tdep->ppc_vsr0_upper_regnum <= regno
+ && regno < tdep->ppc_vsr0_upper_regnum + ppc_num_gprs)
+ return "";
-static const char *
-rs6000_register_name (int n)
-{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
- const struct reg *reg = tdep->regs + n;
+ /* Check if the SPE pseudo registers are available. */
+ if (IS_SPE_PSEUDOREG (tdep, regno))
+ {
+ static const char *const spe_regnames[] = {
+ "ev0", "ev1", "ev2", "ev3", "ev4", "ev5", "ev6", "ev7",
+ "ev8", "ev9", "ev10", "ev11", "ev12", "ev13", "ev14", "ev15",
+ "ev16", "ev17", "ev18", "ev19", "ev20", "ev21", "ev22", "ev23",
+ "ev24", "ev25", "ev26", "ev27", "ev28", "ev29", "ev30", "ev31",
+ };
+ return spe_regnames[regno - tdep->ppc_ev0_regnum];
+ }
+
+ /* Check if the decimal128 pseudo-registers are available. */
+ if (IS_DFP_PSEUDOREG (tdep, regno))
+ {
+ static const char *const dfp128_regnames[] = {
+ "dl0", "dl1", "dl2", "dl3",
+ "dl4", "dl5", "dl6", "dl7",
+ "dl8", "dl9", "dl10", "dl11",
+ "dl12", "dl13", "dl14", "dl15"
+ };
+ return dfp128_regnames[regno - tdep->ppc_dl0_regnum];
+ }
+
+ /* Check if this is a VSX pseudo-register. */
+ if (IS_VSX_PSEUDOREG (tdep, regno))
+ {
+ static const char *const vsx_regnames[] = {
+ "vs0", "vs1", "vs2", "vs3", "vs4", "vs5", "vs6", "vs7",
+ "vs8", "vs9", "vs10", "vs11", "vs12", "vs13", "vs14",
+ "vs15", "vs16", "vs17", "vs18", "vs19", "vs20", "vs21",
+ "vs22", "vs23", "vs24", "vs25", "vs26", "vs27", "vs28",
+ "vs29", "vs30", "vs31", "vs32", "vs33", "vs34", "vs35",
+ "vs36", "vs37", "vs38", "vs39", "vs40", "vs41", "vs42",
+ "vs43", "vs44", "vs45", "vs46", "vs47", "vs48", "vs49",
+ "vs50", "vs51", "vs52", "vs53", "vs54", "vs55", "vs56",
+ "vs57", "vs58", "vs59", "vs60", "vs61", "vs62", "vs63"
+ };
+ return vsx_regnames[regno - tdep->ppc_vsr0_regnum];
+ }
+
+ /* Check if the this is a Extended FP pseudo-register. */
+ if (IS_EFP_PSEUDOREG (tdep, regno))
+ {
+ static const char *const efpr_regnames[] = {
+ "f32", "f33", "f34", "f35", "f36", "f37", "f38",
+ "f39", "f40", "f41", "f42", "f43", "f44", "f45",
+ "f46", "f47", "f48", "f49", "f50", "f51",
+ "f52", "f53", "f54", "f55", "f56", "f57",
+ "f58", "f59", "f60", "f61", "f62", "f63"
+ };
+ return efpr_regnames[regno - tdep->ppc_efpr0_regnum];
+ }
- if (!regsize (reg, tdep->wordsize))
- return NULL;
- return reg->name;
+ return tdesc_register_name (gdbarch, regno);
}
-/* Return the GDB type object for the "standard" data type
- of data in register N. */
+/* Return the GDB type object for the "standard" data type of data in
+ register N. */
static struct type *
-rs6000_register_type (struct gdbarch *gdbarch, int n)
+rs6000_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- const struct reg *reg = tdep->regs + n;
- if (reg->fpr)
- return builtin_type_double;
+ /* These are the only pseudo-registers we support. */
+ gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum)
+ || IS_DFP_PSEUDOREG (tdep, regnum)
+ || IS_VSX_PSEUDOREG (tdep, regnum)
+ || IS_EFP_PSEUDOREG (tdep, regnum));
+
+ /* These are the e500 pseudo-registers. */
+ if (IS_SPE_PSEUDOREG (tdep, regnum))
+ return rs6000_builtin_type_vec64 (gdbarch);
+ else if (IS_DFP_PSEUDOREG (tdep, regnum))
+ /* PPC decimal128 pseudo-registers. */
+ return builtin_type (gdbarch)->builtin_declong;
+ else if (IS_VSX_PSEUDOREG (tdep, regnum))
+ /* POWER7 VSX pseudo-registers. */
+ return rs6000_builtin_type_vec128 (gdbarch);
else
- {
- int size = regsize (reg, tdep->wordsize);
- switch (size)
- {
- case 0:
- return builtin_type_int0;
- case 4:
- return builtin_type_uint32;
- case 8:
- if (tdep->ppc_ev0_regnum <= n && n <= tdep->ppc_ev31_regnum)
- return rs6000_builtin_type_vec64 (gdbarch);
- else
- return builtin_type_uint64;
- break;
- case 16:
- return rs6000_builtin_type_vec128 (gdbarch);
- break;
- default:
- internal_error (__FILE__, __LINE__, _("Register %d size %d unknown"),
- n, size);
- }
- }
+ /* POWER7 Extended FP pseudo-registers. */
+ return builtin_type (gdbarch)->builtin_double;
}
/* Is REGNUM a member of REGGROUP? */
static int
-rs6000_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
- struct reggroup *group)
+rs6000_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
+ struct reggroup *group)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- int float_p;
- int vector_p;
- int general_p;
- if (gdbarch_register_name (current_gdbarch, regnum) == NULL
- || *gdbarch_register_name (current_gdbarch, regnum) == '\0')
- return 0;
- if (group == all_reggroup)
- return 1;
+ /* These are the only pseudo-registers we support. */
+ gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum)
+ || IS_DFP_PSEUDOREG (tdep, regnum)
+ || IS_VSX_PSEUDOREG (tdep, regnum)
+ || IS_EFP_PSEUDOREG (tdep, regnum));
- float_p = (regnum == tdep->ppc_fpscr_regnum
- || (regnum >= tdep->ppc_fp0_regnum
- && regnum < tdep->ppc_fp0_regnum + 32));
- if (group == float_reggroup)
- return float_p;
-
- vector_p = ((tdep->ppc_vr0_regnum >= 0
- && regnum >= tdep->ppc_vr0_regnum
- && regnum < tdep->ppc_vr0_regnum + 32)
- || (tdep->ppc_ev0_regnum >= 0
- && regnum >= tdep->ppc_ev0_regnum
- && regnum < tdep->ppc_ev0_regnum + 32)
- || regnum == tdep->ppc_vrsave_regnum - 1 /* vscr */
- || regnum == tdep->ppc_vrsave_regnum
- || regnum == tdep->ppc_acc_regnum
- || regnum == tdep->ppc_spefscr_regnum);
- if (group == vector_reggroup)
- return vector_p;
-
- /* Note that PS aka MSR isn't included - it's a system register (and
- besides, due to GCC's CFI foobar you do not want to restore
- it). */
- general_p = ((regnum >= tdep->ppc_gp0_regnum
- && regnum < tdep->ppc_gp0_regnum + 32)
- || regnum == tdep->ppc_toc_regnum
- || regnum == tdep->ppc_cr_regnum
- || regnum == tdep->ppc_lr_regnum
- || regnum == tdep->ppc_ctr_regnum
- || regnum == tdep->ppc_xer_regnum
- || regnum == gdbarch_pc_regnum (current_gdbarch));
- if (group == general_reggroup)
- return general_p;
-
- if (group == save_reggroup || group == restore_reggroup)
- return general_p || vector_p || float_p;
-
- return 0;
+ /* These are the e500 pseudo-registers or the POWER7 VSX registers. */
+ if (IS_SPE_PSEUDOREG (tdep, regnum) || IS_VSX_PSEUDOREG (tdep, regnum))
+ return group == all_reggroup || group == vector_reggroup;
+ else
+ /* PPC decimal128 or Extended FP pseudo-registers. */
+ return group == all_reggroup || group == float_reggroup;
}
/* The register format for RS/6000 floating point registers is always
double, we need a conversion if the memory format is float. */
static int
-rs6000_convert_register_p (int regnum, struct type *type)
+rs6000_convert_register_p (struct gdbarch *gdbarch, int regnum,
+ struct type *type)
{
- const struct reg *reg = gdbarch_tdep (current_gdbarch)->regs + regnum;
-
- return (reg->fpr
- && TYPE_CODE (type) == TYPE_CODE_FLT
- && TYPE_LENGTH (type) != TYPE_LENGTH (builtin_type_double));
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ return (tdep->ppc_fp0_regnum >= 0
+ && 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 (gdbarch)->builtin_double));
}
static void
struct type *type,
gdb_byte *to)
{
- const struct reg *reg = gdbarch_tdep (current_gdbarch)->regs + regnum;
+ struct gdbarch *gdbarch = get_frame_arch (frame);
gdb_byte from[MAX_REGISTER_SIZE];
- gdb_assert (reg->fpr);
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)
{
- const struct reg *reg = gdbarch_tdep (current_gdbarch)->regs + regnum;
+ struct gdbarch *gdbarch = get_frame_arch (frame);
gdb_byte to[MAX_REGISTER_SIZE];
- gdb_assert (reg->fpr);
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);
}
int reg_index;
gdb_byte *byte_buffer = buffer;
- gdb_assert (tdep->ppc_ev0_regnum <= ev_reg
- && ev_reg < tdep->ppc_ev0_regnum + ppc_num_gprs);
+ gdb_assert (IS_SPE_PSEUDOREG (tdep, ev_reg));
reg_index = ev_reg - tdep->ppc_ev0_regnum;
- if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
+ if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG)
{
move (regcache, tdep->ppc_ev0_upper_regnum + reg_index, byte_buffer);
move (regcache, tdep->ppc_gp0_regnum + reg_index, byte_buffer + 4);
e500_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
int reg_nr, gdb_byte *buffer)
{
- struct gdbarch *regcache_arch = get_regcache_arch (regcache);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ e500_move_ev_register (regcache_raw_read, regcache, reg_nr, buffer);
+}
- gdb_assert (regcache_arch == gdbarch);
-
- if (tdep->ppc_ev0_regnum <= reg_nr
- && reg_nr < tdep->ppc_ev0_regnum + ppc_num_gprs)
- e500_move_ev_register (regcache_raw_read, regcache, reg_nr, buffer);
+static void
+e500_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+ int reg_nr, const gdb_byte *buffer)
+{
+ e500_move_ev_register ((void (*) (struct regcache *, int, gdb_byte *))
+ regcache_raw_write,
+ regcache, reg_nr, (gdb_byte *) buffer);
+}
+
+/* Read method for DFP pseudo-registers. */
+static void
+dfp_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+ int reg_nr, gdb_byte *buffer)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int reg_index = reg_nr - tdep->ppc_dl0_regnum;
+
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ {
+ /* Read two FP registers to form a whole dl register. */
+ regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+ 2 * reg_index, buffer);
+ regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+ 2 * reg_index + 1, buffer + 8);
+ }
else
- internal_error (__FILE__, __LINE__,
- _("e500_pseudo_register_read: "
- "called on unexpected register '%s' (%d)"),
- gdbarch_register_name (gdbarch, reg_nr), reg_nr);
+ {
+ regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+ 2 * reg_index + 1, buffer + 8);
+ regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+ 2 * reg_index, buffer);
+ }
}
+/* Write method for DFP pseudo-registers. */
static void
-e500_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+dfp_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+ int reg_nr, const gdb_byte *buffer)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int reg_index = reg_nr - tdep->ppc_dl0_regnum;
+
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ {
+ /* Write each half of the dl register into a separate
+ FP register. */
+ regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
+ 2 * reg_index, buffer);
+ regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
+ 2 * reg_index + 1, buffer + 8);
+ }
+ else
+ {
+ regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
+ 2 * reg_index + 1, buffer + 8);
+ regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
+ 2 * reg_index, buffer);
+ }
+}
+
+/* Read method for POWER7 VSX pseudo-registers. */
+static void
+vsx_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+ int reg_nr, gdb_byte *buffer)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int reg_index = reg_nr - tdep->ppc_vsr0_regnum;
+
+ /* Read the portion that overlaps the VMX registers. */
+ if (reg_index > 31)
+ regcache_raw_read (regcache, tdep->ppc_vr0_regnum +
+ reg_index - 32, buffer);
+ else
+ /* Read the portion that overlaps the FPR registers. */
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ {
+ regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+ reg_index, buffer);
+ regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
+ reg_index, buffer + 8);
+ }
+ else
+ {
+ regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+ reg_index, buffer + 8);
+ regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
+ reg_index, buffer);
+ }
+}
+
+/* Write method for POWER7 VSX pseudo-registers. */
+static void
+vsx_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+ int reg_nr, const gdb_byte *buffer)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int reg_index = reg_nr - tdep->ppc_vsr0_regnum;
+
+ /* Write the portion that overlaps the VMX registers. */
+ if (reg_index > 31)
+ regcache_raw_write (regcache, tdep->ppc_vr0_regnum +
+ reg_index - 32, buffer);
+ else
+ /* Write the portion that overlaps the FPR registers. */
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ {
+ regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
+ reg_index, buffer);
+ regcache_raw_write (regcache, tdep->ppc_vsr0_upper_regnum +
+ reg_index, buffer + 8);
+ }
+ else
+ {
+ regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
+ reg_index, buffer + 8);
+ regcache_raw_write (regcache, tdep->ppc_vsr0_upper_regnum +
+ reg_index, buffer);
+ }
+}
+
+/* Read method for POWER7 Extended FP pseudo-registers. */
+static void
+efpr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+ int reg_nr, gdb_byte *buffer)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+
+ /* Read the portion that overlaps the VMX registers. */
+ regcache_raw_read (regcache, tdep->ppc_vr0_regnum +
+ reg_index, buffer);
+}
+
+/* Write method for POWER7 Extended FP pseudo-registers. */
+static void
+efpr_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
int reg_nr, const gdb_byte *buffer)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+
+ /* Write the portion that overlaps the VMX registers. */
+ regcache_raw_write (regcache, tdep->ppc_vr0_regnum +
+ reg_index, buffer);
+}
+
+static void
+rs6000_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+ int reg_nr, gdb_byte *buffer)
{
struct gdbarch *regcache_arch = get_regcache_arch (regcache);
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
gdb_assert (regcache_arch == gdbarch);
-
- if (tdep->ppc_ev0_regnum <= reg_nr
- && reg_nr < tdep->ppc_ev0_regnum + ppc_num_gprs)
- e500_move_ev_register ((void (*) (struct regcache *, int, gdb_byte *))
- regcache_raw_write,
- regcache, reg_nr, (gdb_byte *) buffer);
+
+ if (IS_SPE_PSEUDOREG (tdep, reg_nr))
+ e500_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+ else if (IS_DFP_PSEUDOREG (tdep, reg_nr))
+ dfp_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+ else if (IS_VSX_PSEUDOREG (tdep, reg_nr))
+ vsx_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+ else if (IS_EFP_PSEUDOREG (tdep, reg_nr))
+ efpr_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
else
internal_error (__FILE__, __LINE__,
- _("e500_pseudo_register_read: "
- "called on unexpected register '%s' (%d)"),
- gdbarch_register_name (gdbarch, reg_nr), reg_nr);
+ _("rs6000_pseudo_register_read: "
+ "called on unexpected register '%s' (%d)"),
+ gdbarch_register_name (gdbarch, reg_nr), reg_nr);
}
-/* The E500 needs a custom reggroup function: it has anonymous raw
- registers, and default_register_reggroup_p assumes that anonymous
- registers are not members of any reggroup. */
-static int
-e500_register_reggroup_p (struct gdbarch *gdbarch,
- int regnum,
- struct reggroup *group)
+static void
+rs6000_pseudo_register_write (struct gdbarch *gdbarch,
+ struct regcache *regcache,
+ int reg_nr, const gdb_byte *buffer)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ struct gdbarch *regcache_arch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- /* The save and restore register groups need to include the
- upper-half registers, even though they're anonymous. */
- if ((group == save_reggroup
- || group == restore_reggroup)
- && (tdep->ppc_ev0_upper_regnum <= regnum
- && regnum < tdep->ppc_ev0_upper_regnum + ppc_num_gprs))
- return 1;
+ gdb_assert (regcache_arch == gdbarch);
- /* In all other regards, the default reggroup definition is fine. */
- return default_register_reggroup_p (gdbarch, regnum, group);
+ if (IS_SPE_PSEUDOREG (tdep, reg_nr))
+ e500_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+ else if (IS_DFP_PSEUDOREG (tdep, reg_nr))
+ dfp_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+ else if (IS_VSX_PSEUDOREG (tdep, reg_nr))
+ vsx_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+ else if (IS_EFP_PSEUDOREG (tdep, reg_nr))
+ efpr_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+ else
+ internal_error (__FILE__, __LINE__,
+ _("rs6000_pseudo_register_write: "
+ "called on unexpected register '%s' (%d)"),
+ gdbarch_register_name (gdbarch, reg_nr), reg_nr);
}
/* Convert a DBX STABS register number to a GDB register number. */
static int
-rs6000_stab_reg_to_regnum (int num)
+rs6000_stab_reg_to_regnum (struct gdbarch *gdbarch, int num)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
if (0 <= num && num <= 31)
return tdep->ppc_gp0_regnum + num;
/* Convert a Dwarf 2 register number to a GDB register number. */
static int
-rs6000_dwarf2_reg_to_regnum (int num)
+rs6000_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int num)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
if (0 <= num && num <= 31)
return tdep->ppc_gp0_regnum + num;
return num;
}
}
-\f
-/* Support for CONVERT_FROM_FUNC_PTR_ADDR (ARCH, ADDR, TARG).
-
- Usually a function pointer's representation is simply the address
- of the function. On the RS/6000 however, a function pointer is
- represented by a pointer to an OPD entry. This OPD entry contains
- three words, the first word is the address of the function, the
- second word is the TOC pointer (r2), and the third word is the
- static chain value. Throughout GDB it is currently assumed that a
- function pointer contains the address of the function, which is not
- easy to fix. In addition, the conversion of a function address to
- a function pointer would require allocation of an OPD entry in the
- inferior's memory space, with all its drawbacks. To be able to
- call C++ virtual methods in the inferior (which are called via
- function pointers), find_function_addr uses this function to get the
- function address from a function pointer. */
-
-/* Return real function address if ADDR (a function pointer) is in the data
- space and is therefore a special function pointer. */
-
-static CORE_ADDR
-rs6000_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
- CORE_ADDR addr,
- struct target_ops *targ)
-{
- struct obj_section *s;
-
- s = find_pc_section (addr);
- if (s && s->the_bfd_section->flags & SEC_CODE)
- return addr;
-
- /* ADDR is in the data space, so it's a special function pointer. */
- return read_memory_addr (addr, gdbarch_tdep (gdbarch)->wordsize);
-}
-\f
-
-/* Handling the various POWER/PowerPC variants. */
-
-
-/* The arrays here called registers_MUMBLE hold information about available
- registers.
-
- For each family of PPC variants, I've tried to isolate out the
- common registers and put them up front, so that as long as you get
- the general family right, GDB will correctly identify the registers
- common to that family. The common register sets are:
-
- For the 60x family: hid0 hid1 iabr dabr pir
-
- For the 505 and 860 family: eie eid nri
-
- For the 403 and 403GC: icdbdr esr dear evpr cdbcr tsr tcr pit tbhi
- tblo srr2 srr3 dbsr dbcr iac1 iac2 dac1 dac2 dccr iccr pbl1
- pbu1 pbl2 pbu2
-
- Most of these register groups aren't anything formal. I arrived at
- them by looking at the registers that occurred in more than one
- processor.
-
- Note: kevinb/2002-04-30: Support for the fpscr register was added
- during April, 2002. Slot 70 is being used for PowerPC and slot 71
- for Power. For PowerPC, slot 70 was unused and was already in the
- PPC_UISA_SPRS which is ideally where fpscr should go. For Power,
- slot 70 was being used for "mq", so the next available slot (71)
- was chosen. It would have been nice to be able to make the
- register numbers the same across processor cores, but this wasn't
- possible without either 1) renumbering some registers for some
- processors or 2) assigning fpscr to a really high slot that's
- larger than any current register number. Doing (1) is bad because
- existing stubs would break. Doing (2) is undesirable because it
- would introduce a really large gap between fpscr and the rest of
- the registers for most processors. */
-
-/* Convenience macros for populating register arrays. */
-
-/* Within another macro, convert S to a string. */
-
-#define STR(s) #s
-
-/* Return a struct reg defining register NAME that's 32 bits on 32-bit systems
- and 64 bits on 64-bit systems. */
-#define R(name) { STR(name), 4, 8, 0, 0, -1 }
-
-/* Return a struct reg defining register NAME that's 32 bits on all
- systems. */
-#define R4(name) { STR(name), 4, 4, 0, 0, -1 }
-
-/* Return a struct reg defining register NAME that's 64 bits on all
- systems. */
-#define R8(name) { STR(name), 8, 8, 0, 0, -1 }
-
-/* Return a struct reg defining register NAME that's 128 bits on all
- systems. */
-#define R16(name) { STR(name), 16, 16, 0, 0, -1 }
-
-/* Return a struct reg defining floating-point register NAME. */
-#define F(name) { STR(name), 8, 8, 1, 0, -1 }
-
-/* Return a struct reg defining a pseudo register NAME that is 64 bits
- long on all systems. */
-#define P8(name) { STR(name), 8, 8, 0, 1, -1 }
-
-/* Return a struct reg defining register NAME that's 32 bits on 32-bit
- systems and that doesn't exist on 64-bit systems. */
-#define R32(name) { STR(name), 4, 0, 0, 0, -1 }
-
-/* Return a struct reg defining register NAME that's 64 bits on 64-bit
- systems and that doesn't exist on 32-bit systems. */
-#define R64(name) { STR(name), 0, 8, 0, 0, -1 }
-
-/* Return a struct reg placeholder for a register that doesn't exist. */
-#define R0 { 0, 0, 0, 0, 0, -1 }
-
-/* Return a struct reg defining an anonymous raw register that's 32
- bits on all systems. */
-#define A4 { 0, 4, 4, 0, 0, -1 }
-
-/* Return a struct reg defining an SPR named NAME that is 32 bits on
- 32-bit systems and 64 bits on 64-bit systems. */
-#define S(name) { STR(name), 4, 8, 0, 0, ppc_spr_ ## name }
-
-/* Return a struct reg defining an SPR named NAME that is 32 bits on
- all systems. */
-#define S4(name) { STR(name), 4, 4, 0, 0, ppc_spr_ ## name }
-
-/* Return a struct reg defining an SPR named NAME that is 32 bits on
- all systems, and whose SPR number is NUMBER. */
-#define SN4(name, number) { STR(name), 4, 4, 0, 0, (number) }
-
-/* Return a struct reg defining an SPR named NAME that's 64 bits on
- 64-bit systems and that doesn't exist on 32-bit systems. */
-#define S64(name) { STR(name), 0, 8, 0, 0, ppc_spr_ ## name }
-
-/* UISA registers common across all architectures, including POWER. */
-
-#define COMMON_UISA_REGS \
- /* 0 */ R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7), \
- /* 8 */ R(r8), R(r9), R(r10),R(r11),R(r12),R(r13),R(r14),R(r15), \
- /* 16 */ R(r16),R(r17),R(r18),R(r19),R(r20),R(r21),R(r22),R(r23), \
- /* 24 */ R(r24),R(r25),R(r26),R(r27),R(r28),R(r29),R(r30),R(r31), \
- /* 32 */ F(f0), F(f1), F(f2), F(f3), F(f4), F(f5), F(f6), F(f7), \
- /* 40 */ F(f8), F(f9), F(f10),F(f11),F(f12),F(f13),F(f14),F(f15), \
- /* 48 */ F(f16),F(f17),F(f18),F(f19),F(f20),F(f21),F(f22),F(f23), \
- /* 56 */ F(f24),F(f25),F(f26),F(f27),F(f28),F(f29),F(f30),F(f31), \
- /* 64 */ R(pc), R(ps)
-
-/* UISA-level SPRs for PowerPC. */
-#define PPC_UISA_SPRS \
- /* 66 */ R4(cr), S(lr), S(ctr), S4(xer), R4(fpscr)
-
-/* UISA-level SPRs for PowerPC without floating point support. */
-#define PPC_UISA_NOFP_SPRS \
- /* 66 */ R4(cr), S(lr), S(ctr), S4(xer), R0
-
-/* Segment registers, for PowerPC. */
-#define PPC_SEGMENT_REGS \
- /* 71 */ R32(sr0), R32(sr1), R32(sr2), R32(sr3), \
- /* 75 */ R32(sr4), R32(sr5), R32(sr6), R32(sr7), \
- /* 79 */ R32(sr8), R32(sr9), R32(sr10), R32(sr11), \
- /* 83 */ R32(sr12), R32(sr13), R32(sr14), R32(sr15)
-
-/* OEA SPRs for PowerPC. */
-#define PPC_OEA_SPRS \
- /* 87 */ S4(pvr), \
- /* 88 */ S(ibat0u), S(ibat0l), S(ibat1u), S(ibat1l), \
- /* 92 */ S(ibat2u), S(ibat2l), S(ibat3u), S(ibat3l), \
- /* 96 */ S(dbat0u), S(dbat0l), S(dbat1u), S(dbat1l), \
- /* 100 */ S(dbat2u), S(dbat2l), S(dbat3u), S(dbat3l), \
- /* 104 */ S(sdr1), S64(asr), S(dar), S4(dsisr), \
- /* 108 */ S(sprg0), S(sprg1), S(sprg2), S(sprg3), \
- /* 112 */ S(srr0), S(srr1), S(tbl), S(tbu), \
- /* 116 */ S4(dec), S(dabr), S4(ear)
-
-/* AltiVec registers. */
-#define PPC_ALTIVEC_REGS \
- /*119*/R16(vr0), R16(vr1), R16(vr2), R16(vr3), R16(vr4), R16(vr5), R16(vr6), R16(vr7), \
- /*127*/R16(vr8), R16(vr9), R16(vr10),R16(vr11),R16(vr12),R16(vr13),R16(vr14),R16(vr15), \
- /*135*/R16(vr16),R16(vr17),R16(vr18),R16(vr19),R16(vr20),R16(vr21),R16(vr22),R16(vr23), \
- /*143*/R16(vr24),R16(vr25),R16(vr26),R16(vr27),R16(vr28),R16(vr29),R16(vr30),R16(vr31), \
- /*151*/R4(vscr), R4(vrsave)
-
-
-/* On machines supporting the SPE APU, the general-purpose registers
- are 64 bits long. There are SIMD vector instructions to treat them
- as pairs of floats, but the rest of the instruction set treats them
- as 32-bit registers, and only operates on their lower halves.
-
- In the GDB regcache, we treat their high and low halves as separate
- registers. The low halves we present as the general-purpose
- registers, and then we have pseudo-registers that stitch together
- the upper and lower halves and present them as pseudo-registers. */
-
-/* SPE GPR lower halves --- raw registers. */
-#define PPC_SPE_GP_REGS \
- /* 0 */ R4(r0), R4(r1), R4(r2), R4(r3), R4(r4), R4(r5), R4(r6), R4(r7), \
- /* 8 */ R4(r8), R4(r9), R4(r10),R4(r11),R4(r12),R4(r13),R4(r14),R4(r15), \
- /* 16 */ R4(r16),R4(r17),R4(r18),R4(r19),R4(r20),R4(r21),R4(r22),R4(r23), \
- /* 24 */ R4(r24),R4(r25),R4(r26),R4(r27),R4(r28),R4(r29),R4(r30),R4(r31)
-
-/* SPE GPR upper halves --- anonymous raw registers. */
-#define PPC_SPE_UPPER_GP_REGS \
- /* 0 */ A4, A4, A4, A4, A4, A4, A4, A4, \
- /* 8 */ A4, A4, A4, A4, A4, A4, A4, A4, \
- /* 16 */ A4, A4, A4, A4, A4, A4, A4, A4, \
- /* 24 */ A4, A4, A4, A4, A4, A4, A4, A4
-
-/* SPE GPR vector registers --- pseudo registers based on underlying
- gprs and the anonymous upper half raw registers. */
-#define PPC_EV_PSEUDO_REGS \
-/* 0*/P8(ev0), P8(ev1), P8(ev2), P8(ev3), P8(ev4), P8(ev5), P8(ev6), P8(ev7), \
-/* 8*/P8(ev8), P8(ev9), P8(ev10),P8(ev11),P8(ev12),P8(ev13),P8(ev14),P8(ev15),\
-/*16*/P8(ev16),P8(ev17),P8(ev18),P8(ev19),P8(ev20),P8(ev21),P8(ev22),P8(ev23),\
-/*24*/P8(ev24),P8(ev25),P8(ev26),P8(ev27),P8(ev28),P8(ev29),P8(ev30),P8(ev31)
-
-/* IBM POWER (pre-PowerPC) architecture, user-level view. We only cover
- user-level SPR's. */
-static const struct reg registers_power[] =
-{
- COMMON_UISA_REGS,
- /* 66 */ R4(cnd), S(lr), S(cnt), S4(xer), S4(mq),
- /* 71 */ R4(fpscr)
-};
-
-/* PowerPC UISA - a PPC processor as viewed by user-level code. A UISA-only
- view of the PowerPC. */
-static const struct reg registers_powerpc[] =
-{
- COMMON_UISA_REGS,
- PPC_UISA_SPRS,
- PPC_ALTIVEC_REGS
-};
-
-/* IBM PowerPC 403.
-
- Some notes about the "tcr" special-purpose register:
- - On the 403 and 403GC, SPR 986 is named "tcr", and it controls the
- 403's programmable interval timer, fixed interval timer, and
- watchdog timer.
- - On the 602, SPR 984 is named "tcr", and it controls the 602's
- watchdog timer, and nothing else.
-
- Some of the fields are similar between the two, but they're not
- compatible with each other. Since the two variants have different
- registers, with different numbers, but the same name, we can't
- splice the register name to get the SPR number. */
-static const struct reg registers_403[] =
-{
- COMMON_UISA_REGS,
- PPC_UISA_SPRS,
- PPC_SEGMENT_REGS,
- PPC_OEA_SPRS,
- /* 119 */ S(icdbdr), S(esr), S(dear), S(evpr),
- /* 123 */ S(cdbcr), S(tsr), SN4(tcr, ppc_spr_403_tcr), S(pit),
- /* 127 */ S(tbhi), S(tblo), S(srr2), S(srr3),
- /* 131 */ S(dbsr), S(dbcr), S(iac1), S(iac2),
- /* 135 */ S(dac1), S(dac2), S(dccr), S(iccr),
- /* 139 */ S(pbl1), S(pbu1), S(pbl2), S(pbu2)
-};
-
-/* IBM PowerPC 403GC.
- See the comments about 'tcr' for the 403, above. */
-static const struct reg registers_403GC[] =
-{
- COMMON_UISA_REGS,
- PPC_UISA_SPRS,
- PPC_SEGMENT_REGS,
- PPC_OEA_SPRS,
- /* 119 */ S(icdbdr), S(esr), S(dear), S(evpr),
- /* 123 */ S(cdbcr), S(tsr), SN4(tcr, ppc_spr_403_tcr), S(pit),
- /* 127 */ S(tbhi), S(tblo), S(srr2), S(srr3),
- /* 131 */ S(dbsr), S(dbcr), S(iac1), S(iac2),
- /* 135 */ S(dac1), S(dac2), S(dccr), S(iccr),
- /* 139 */ S(pbl1), S(pbu1), S(pbl2), S(pbu2),
- /* 143 */ S(zpr), S(pid), S(sgr), S(dcwr),
- /* 147 */ S(tbhu), S(tblu)
-};
-
-/* Motorola PowerPC 505. */
-static const struct reg registers_505[] =
-{
- COMMON_UISA_REGS,
- PPC_UISA_SPRS,
- PPC_SEGMENT_REGS,
- PPC_OEA_SPRS,
- /* 119 */ S(eie), S(eid), S(nri)
-};
-
-/* Motorola PowerPC 860 or 850. */
-static const struct reg registers_860[] =
-{
- COMMON_UISA_REGS,
- PPC_UISA_SPRS,
- PPC_SEGMENT_REGS,
- PPC_OEA_SPRS,
- /* 119 */ S(eie), S(eid), S(nri), S(cmpa),
- /* 123 */ S(cmpb), S(cmpc), S(cmpd), S(icr),
- /* 127 */ S(der), S(counta), S(countb), S(cmpe),
- /* 131 */ S(cmpf), S(cmpg), S(cmph), S(lctrl1),
- /* 135 */ S(lctrl2), S(ictrl), S(bar), S(ic_cst),
- /* 139 */ S(ic_adr), S(ic_dat), S(dc_cst), S(dc_adr),
- /* 143 */ S(dc_dat), S(dpdr), S(dpir), S(immr),
- /* 147 */ S(mi_ctr), S(mi_ap), S(mi_epn), S(mi_twc),
- /* 151 */ S(mi_rpn), S(md_ctr), S(m_casid), S(md_ap),
- /* 155 */ S(md_epn), S(m_twb), S(md_twc), S(md_rpn),
- /* 159 */ S(m_tw), S(mi_dbcam), S(mi_dbram0), S(mi_dbram1),
- /* 163 */ S(md_dbcam), S(md_dbram0), S(md_dbram1)
-};
-
-/* Motorola PowerPC 601. Note that the 601 has different register numbers
- for reading and writing RTCU and RTCL. However, how one reads and writes a
- register is the stub's problem. */
-static const struct reg registers_601[] =
-{
- COMMON_UISA_REGS,
- PPC_UISA_SPRS,
- PPC_SEGMENT_REGS,
- PPC_OEA_SPRS,
- /* 119 */ S(hid0), S(hid1), S(iabr), S(dabr),
- /* 123 */ S(pir), S(mq), S(rtcu), S(rtcl)
-};
-
-/* Motorola PowerPC 602.
- See the notes under the 403 about 'tcr'. */
-static const struct reg registers_602[] =
-{
- COMMON_UISA_REGS,
- PPC_UISA_SPRS,
- PPC_SEGMENT_REGS,
- PPC_OEA_SPRS,
- /* 119 */ S(hid0), S(hid1), S(iabr), R0,
- /* 123 */ R0, SN4(tcr, ppc_spr_602_tcr), S(ibr), S(esasrr),
- /* 127 */ S(sebr), S(ser), S(sp), S(lt)
-};
-
-/* Motorola/IBM PowerPC 603 or 603e. */
-static const struct reg registers_603[] =
-{
- COMMON_UISA_REGS,
- PPC_UISA_SPRS,
- PPC_SEGMENT_REGS,
- PPC_OEA_SPRS,
- /* 119 */ S(hid0), S(hid1), S(iabr), R0,
- /* 123 */ R0, S(dmiss), S(dcmp), S(hash1),
- /* 127 */ S(hash2), S(imiss), S(icmp), S(rpa)
-};
-
-/* Motorola PowerPC 604 or 604e. */
-static const struct reg registers_604[] =
-{
- COMMON_UISA_REGS,
- PPC_UISA_SPRS,
- PPC_SEGMENT_REGS,
- PPC_OEA_SPRS,
- /* 119 */ S(hid0), S(hid1), S(iabr), S(dabr),
- /* 123 */ S(pir), S(mmcr0), S(pmc1), S(pmc2),
- /* 127 */ S(sia), S(sda)
-};
-
-/* Motorola/IBM PowerPC 750 or 740. */
-static const struct reg registers_750[] =
-{
- COMMON_UISA_REGS,
- PPC_UISA_SPRS,
- PPC_SEGMENT_REGS,
- PPC_OEA_SPRS,
- /* 119 */ S(hid0), S(hid1), S(iabr), S(dabr),
- /* 123 */ R0, S(ummcr0), S(upmc1), S(upmc2),
- /* 127 */ S(usia), S(ummcr1), S(upmc3), S(upmc4),
- /* 131 */ S(mmcr0), S(pmc1), S(pmc2), S(sia),
- /* 135 */ S(mmcr1), S(pmc3), S(pmc4), S(l2cr),
- /* 139 */ S(ictc), S(thrm1), S(thrm2), S(thrm3)
-};
-
-
-/* Motorola PowerPC 7400. */
-static const struct reg registers_7400[] =
-{
- /* gpr0-gpr31, fpr0-fpr31 */
- COMMON_UISA_REGS,
- /* cr, lr, ctr, xer, fpscr */
- PPC_UISA_SPRS,
- /* sr0-sr15 */
- PPC_SEGMENT_REGS,
- PPC_OEA_SPRS,
- /* vr0-vr31, vrsave, vscr */
- PPC_ALTIVEC_REGS
- /* FIXME? Add more registers? */
-};
-
-/* Motorola e500. */
-static const struct reg registers_e500[] =
-{
- /* 0 .. 31 */ PPC_SPE_GP_REGS,
- /* 32 .. 63 */ PPC_SPE_UPPER_GP_REGS,
- /* 64 .. 65 */ R(pc), R(ps),
- /* 66 .. 70 */ PPC_UISA_NOFP_SPRS,
- /* 71 .. 72 */ R8(acc), S4(spefscr),
- /* NOTE: Add new registers here the end of the raw register
- list and just before the first pseudo register. */
- /* 73 .. 104 */ PPC_EV_PSEUDO_REGS
-};
-
-/* Information about a particular processor variant. */
-
-struct variant
- {
- /* Name of this variant. */
- char *name;
-
- /* English description of the variant. */
- char *description;
-
- /* bfd_arch_info.arch corresponding to variant. */
- enum bfd_architecture arch;
-
- /* bfd_arch_info.mach corresponding to variant. */
- unsigned long mach;
-
- /* Number of real registers. */
- int nregs;
-
- /* Number of pseudo registers. */
- int npregs;
-
- /* Number of total registers (the sum of nregs and npregs). */
- int num_tot_regs;
-
- /* Table of register names; registers[R] is the name of the register
- number R. */
- const struct reg *regs;
- };
-
-#define tot_num_registers(list) (sizeof (list) / sizeof((list)[0]))
-
-static int
-num_registers (const struct reg *reg_list, int num_tot_regs)
-{
- int i;
- int nregs = 0;
-
- for (i = 0; i < num_tot_regs; i++)
- if (!reg_list[i].pseudo)
- nregs++;
-
- return nregs;
-}
+\f
-static int
-num_pseudo_registers (const struct reg *reg_list, int num_tot_regs)
-{
- int i;
- int npregs = 0;
+/* Handling the various POWER/PowerPC variants. */
- for (i = 0; i < num_tot_regs; i++)
- if (reg_list[i].pseudo)
- npregs ++;
+/* Information about a particular processor variant. */
- return npregs;
-}
+struct variant
+ {
+ /* Name of this variant. */
+ char *name;
+
+ /* English description of the variant. */
+ char *description;
-/* Information in this table comes from the following web sites:
- IBM: http://www.chips.ibm.com:80/products/embedded/
- Motorola: http://www.mot.com/SPS/PowerPC/
+ /* bfd_arch_info.arch corresponding to variant. */
+ enum bfd_architecture arch;
- I'm sure I've got some of the variant descriptions not quite right.
- Please report any inaccuracies you find to GDB's maintainer.
+ /* bfd_arch_info.mach corresponding to variant. */
+ unsigned long mach;
- If you add entries to this table, please be sure to allow the new
- value as an argument to the --with-cpu flag, in configure.in. */
+ /* Target description for this variant. */
+ struct target_desc **tdesc;
+ };
static struct variant variants[] =
{
-
{"powerpc", "PowerPC user-level", bfd_arch_powerpc,
- bfd_mach_ppc, -1, -1, tot_num_registers (registers_powerpc),
- registers_powerpc},
+ bfd_mach_ppc, &tdesc_powerpc_altivec32},
{"power", "POWER user-level", bfd_arch_rs6000,
- bfd_mach_rs6k, -1, -1, tot_num_registers (registers_power),
- registers_power},
+ bfd_mach_rs6k, &tdesc_rs6000},
{"403", "IBM PowerPC 403", bfd_arch_powerpc,
- bfd_mach_ppc_403, -1, -1, tot_num_registers (registers_403),
- registers_403},
+ bfd_mach_ppc_403, &tdesc_powerpc_403},
+ {"405", "IBM PowerPC 405", bfd_arch_powerpc,
+ bfd_mach_ppc_405, &tdesc_powerpc_405},
{"601", "Motorola PowerPC 601", bfd_arch_powerpc,
- bfd_mach_ppc_601, -1, -1, tot_num_registers (registers_601),
- registers_601},
+ bfd_mach_ppc_601, &tdesc_powerpc_601},
{"602", "Motorola PowerPC 602", bfd_arch_powerpc,
- bfd_mach_ppc_602, -1, -1, tot_num_registers (registers_602),
- registers_602},
+ bfd_mach_ppc_602, &tdesc_powerpc_602},
{"603", "Motorola/IBM PowerPC 603 or 603e", bfd_arch_powerpc,
- bfd_mach_ppc_603, -1, -1, tot_num_registers (registers_603),
- registers_603},
+ bfd_mach_ppc_603, &tdesc_powerpc_603},
{"604", "Motorola PowerPC 604 or 604e", bfd_arch_powerpc,
- 604, -1, -1, tot_num_registers (registers_604),
- registers_604},
+ 604, &tdesc_powerpc_604},
{"403GC", "IBM PowerPC 403GC", bfd_arch_powerpc,
- bfd_mach_ppc_403gc, -1, -1, tot_num_registers (registers_403GC),
- registers_403GC},
+ bfd_mach_ppc_403gc, &tdesc_powerpc_403gc},
{"505", "Motorola PowerPC 505", bfd_arch_powerpc,
- bfd_mach_ppc_505, -1, -1, tot_num_registers (registers_505),
- registers_505},
+ bfd_mach_ppc_505, &tdesc_powerpc_505},
{"860", "Motorola PowerPC 860 or 850", bfd_arch_powerpc,
- bfd_mach_ppc_860, -1, -1, tot_num_registers (registers_860),
- registers_860},
+ bfd_mach_ppc_860, &tdesc_powerpc_860},
{"750", "Motorola/IBM PowerPC 750 or 740", bfd_arch_powerpc,
- bfd_mach_ppc_750, -1, -1, tot_num_registers (registers_750),
- registers_750},
+ bfd_mach_ppc_750, &tdesc_powerpc_750},
{"7400", "Motorola/IBM PowerPC 7400 (G4)", bfd_arch_powerpc,
- bfd_mach_ppc_7400, -1, -1, tot_num_registers (registers_7400),
- registers_7400},
+ bfd_mach_ppc_7400, &tdesc_powerpc_7400},
{"e500", "Motorola PowerPC e500", bfd_arch_powerpc,
- bfd_mach_ppc_e500, -1, -1, tot_num_registers (registers_e500),
- registers_e500},
+ bfd_mach_ppc_e500, &tdesc_powerpc_e500},
/* 64-bit */
{"powerpc64", "PowerPC 64-bit user-level", bfd_arch_powerpc,
- bfd_mach_ppc64, -1, -1, tot_num_registers (registers_powerpc),
- registers_powerpc},
+ bfd_mach_ppc64, &tdesc_powerpc_altivec64},
{"620", "Motorola PowerPC 620", bfd_arch_powerpc,
- bfd_mach_ppc_620, -1, -1, tot_num_registers (registers_powerpc),
- registers_powerpc},
+ bfd_mach_ppc_620, &tdesc_powerpc_64},
{"630", "Motorola PowerPC 630", bfd_arch_powerpc,
- bfd_mach_ppc_630, -1, -1, tot_num_registers (registers_powerpc),
- registers_powerpc},
+ bfd_mach_ppc_630, &tdesc_powerpc_64},
{"a35", "PowerPC A35", bfd_arch_powerpc,
- bfd_mach_ppc_a35, -1, -1, tot_num_registers (registers_powerpc),
- registers_powerpc},
+ bfd_mach_ppc_a35, &tdesc_powerpc_64},
{"rs64ii", "PowerPC rs64ii", bfd_arch_powerpc,
- bfd_mach_ppc_rs64ii, -1, -1, tot_num_registers (registers_powerpc),
- registers_powerpc},
+ bfd_mach_ppc_rs64ii, &tdesc_powerpc_64},
{"rs64iii", "PowerPC rs64iii", bfd_arch_powerpc,
- bfd_mach_ppc_rs64iii, -1, -1, tot_num_registers (registers_powerpc),
- registers_powerpc},
+ bfd_mach_ppc_rs64iii, &tdesc_powerpc_64},
/* FIXME: I haven't checked the register sets of the following. */
{"rs1", "IBM POWER RS1", bfd_arch_rs6000,
- bfd_mach_rs6k_rs1, -1, -1, tot_num_registers (registers_power),
- registers_power},
+ bfd_mach_rs6k_rs1, &tdesc_rs6000},
{"rsc", "IBM POWER RSC", bfd_arch_rs6000,
- bfd_mach_rs6k_rsc, -1, -1, tot_num_registers (registers_power),
- registers_power},
+ bfd_mach_rs6k_rsc, &tdesc_rs6000},
{"rs2", "IBM POWER RS2", bfd_arch_rs6000,
- bfd_mach_rs6k_rs2, -1, -1, tot_num_registers (registers_power),
- registers_power},
+ bfd_mach_rs6k_rs2, &tdesc_rs6000},
- {0, 0, 0, 0, 0, 0, 0, 0}
+ {0, 0, 0, 0, 0}
};
-/* Initialize the number of registers and pseudo registers in each variant. */
-
-static void
-init_variants (void)
-{
- struct variant *v;
-
- for (v = variants; v->name; v++)
- {
- if (v->nregs == -1)
- v->nregs = num_registers (v->regs, v->num_tot_regs);
- if (v->npregs == -1)
- v->npregs = num_pseudo_registers (v->regs, v->num_tot_regs);
- }
-}
-
/* Return the variant corresponding to architecture ARCH and machine number
MACH. If no such variant exists, return null. */
if (!info->disassembler_options)
info->disassembler_options = "any";
- if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
+ if (info->endian == BFD_ENDIAN_BIG)
return print_insn_big_powerpc (memaddr, info);
else
return print_insn_little_powerpc (memaddr, info);
rs6000_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
return frame_unwind_register_unsigned (next_frame,
- gdbarch_pc_regnum (current_gdbarch));
+ gdbarch_pc_regnum (gdbarch));
}
static struct frame_id
-rs6000_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+rs6000_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
{
- return frame_id_build (frame_unwind_register_unsigned
- (next_frame, gdbarch_sp_regnum (current_gdbarch)),
- frame_pc_unwind (next_frame));
+ return frame_id_build (get_frame_register_unsigned
+ (this_frame, gdbarch_sp_regnum (gdbarch)),
+ get_frame_pc (this_frame));
}
struct rs6000_frame_cache
};
static struct rs6000_frame_cache *
-rs6000_frame_cache (struct frame_info *next_frame, void **this_cache)
+rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
{
struct rs6000_frame_cache *cache;
- struct gdbarch *gdbarch = get_frame_arch (next_frame);
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
struct rs6000_framedata fdata;
int wordsize = tdep->wordsize;
CORE_ADDR func, pc;
return (*this_cache);
cache = FRAME_OBSTACK_ZALLOC (struct rs6000_frame_cache);
(*this_cache) = cache;
- cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+ cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
- func = frame_func_unwind (next_frame, NORMAL_FRAME);
- pc = frame_pc_unwind (next_frame);
- skip_prologue (func, pc, &fdata);
+ func = get_frame_func (this_frame);
+ pc = get_frame_pc (this_frame);
+ skip_prologue (gdbarch, func, pc, &fdata);
/* Figure out the parent's stack pointer. */
->frame pointed to the outer-most address of the frame. In
the mean time, the address of the prev frame is used as the
base address of this frame. */
- cache->base = frame_unwind_register_unsigned
- (next_frame, gdbarch_sp_regnum (current_gdbarch));
+ cache->base = get_frame_register_unsigned
+ (this_frame, gdbarch_sp_regnum (gdbarch));
/* If the function appears to be frameless, check a couple of likely
indicators that we have simply failed to find the frame setup.
Two common cases of this are missing symbols (i.e.
- frame_func_unwind returns the wrong address or 0), and assembly
+ get_frame_func returns the wrong address or 0), and assembly
stubs which have a fast exit path but set up a frame on the slow
path.
CORE_ADDR saved_lr;
int make_frame = 0;
- saved_lr = frame_unwind_register_unsigned (next_frame,
- tdep->ppc_lr_regnum);
+ saved_lr = get_frame_register_unsigned (this_frame, tdep->ppc_lr_regnum);
if (func == 0 && saved_lr == pc)
make_frame = 1;
else if (func != 0)
if (!fdata.frameless)
/* Frameless really means stackless. */
- cache->base = read_memory_addr (cache->base, wordsize);
+ cache->base
+ = read_memory_unsigned_integer (cache->base, wordsize, byte_order);
trad_frame_set_value (cache->saved_regs,
- gdbarch_sp_regnum (current_gdbarch), cache->base);
+ gdbarch_sp_regnum (gdbarch), cache->base);
/* if != -1, fdata.saved_fpr is the smallest number of saved_fpr.
All fpr's from saved_fpr to fp31 are saved. */
}
/* if != -1, fdata.saved_gpr is the smallest number of saved_gpr.
- All gpr's from saved_gpr to gpr31 are saved. */
+ All gpr's from saved_gpr to gpr31 are saved (except during the
+ prologue). */
if (fdata.saved_gpr >= 0)
{
CORE_ADDR gpr_addr = cache->base + fdata.gpr_offset;
for (i = fdata.saved_gpr; i < ppc_num_gprs; i++)
{
- cache->saved_regs[tdep->ppc_gp0_regnum + i].addr = gpr_addr;
+ if (fdata.gpr_mask & (1U << i))
+ cache->saved_regs[tdep->ppc_gp0_regnum + i].addr = gpr_addr;
gpr_addr += wordsize;
}
}
/* if != -1, fdata.saved_ev is the smallest number of saved_ev.
All vr's from saved_ev to ev31 are saved. ????? */
- if (tdep->ppc_ev0_regnum != -1 && tdep->ppc_ev31_regnum != -1)
+ if (tdep->ppc_ev0_regnum != -1)
{
if (fdata.saved_ev >= 0)
{
holds the LR. */
if (fdata.lr_offset != 0)
cache->saved_regs[tdep->ppc_lr_regnum].addr = cache->base + fdata.lr_offset;
+ else if (fdata.lr_register != -1)
+ cache->saved_regs[tdep->ppc_lr_regnum].realreg = fdata.lr_register;
/* The PC is found in the link register. */
- cache->saved_regs[gdbarch_pc_regnum (current_gdbarch)] =
+ cache->saved_regs[gdbarch_pc_regnum (gdbarch)] =
cache->saved_regs[tdep->ppc_lr_regnum];
/* If != 0, fdata.vrsave_offset is the offset from the frame that
if (fdata.alloca_reg < 0)
/* If no alloca register used, then fi->frame is the value of the
%sp for this frame, and it is good enough. */
- cache->initial_sp = frame_unwind_register_unsigned
- (next_frame, gdbarch_sp_regnum (current_gdbarch));
+ cache->initial_sp
+ = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch));
else
- cache->initial_sp = frame_unwind_register_unsigned (next_frame,
- fdata.alloca_reg);
+ cache->initial_sp
+ = get_frame_register_unsigned (this_frame, fdata.alloca_reg);
return cache;
}
static void
-rs6000_frame_this_id (struct frame_info *next_frame, void **this_cache,
+rs6000_frame_this_id (struct frame_info *this_frame, void **this_cache,
struct frame_id *this_id)
{
- struct rs6000_frame_cache *info = rs6000_frame_cache (next_frame,
+ struct rs6000_frame_cache *info = rs6000_frame_cache (this_frame,
this_cache);
- (*this_id) = frame_id_build (info->base,
- frame_func_unwind (next_frame, NORMAL_FRAME));
+ /* This marks the outermost frame. */
+ if (info->base == 0)
+ return;
+
+ (*this_id) = frame_id_build (info->base, get_frame_func (this_frame));
}
-static void
-rs6000_frame_prev_register (struct frame_info *next_frame,
- void **this_cache,
- int regnum, int *optimizedp,
- enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnump, gdb_byte *valuep)
+static struct value *
+rs6000_frame_prev_register (struct frame_info *this_frame,
+ void **this_cache, int regnum)
{
- struct rs6000_frame_cache *info = rs6000_frame_cache (next_frame,
+ struct rs6000_frame_cache *info = rs6000_frame_cache (this_frame,
this_cache);
- trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
- optimizedp, lvalp, addrp, realnump, valuep);
+ return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
}
static const struct frame_unwind rs6000_frame_unwind =
{
NORMAL_FRAME,
rs6000_frame_this_id,
- rs6000_frame_prev_register
+ rs6000_frame_prev_register,
+ NULL,
+ default_frame_sniffer
};
-
-static const struct frame_unwind *
-rs6000_frame_sniffer (struct frame_info *next_frame)
-{
- return &rs6000_frame_unwind;
-}
-
\f
static CORE_ADDR
-rs6000_frame_base_address (struct frame_info *next_frame,
- void **this_cache)
+rs6000_frame_base_address (struct frame_info *this_frame, void **this_cache)
{
- struct rs6000_frame_cache *info = rs6000_frame_cache (next_frame,
+ struct rs6000_frame_cache *info = rs6000_frame_cache (this_frame,
this_cache);
return info->initial_sp;
}
};
static const struct frame_base *
-rs6000_frame_base_sniffer (struct frame_info *next_frame)
+rs6000_frame_base_sniffer (struct frame_info *this_frame)
{
return &rs6000_frame_base;
}
+/* DWARF-2 frame support. Used to handle the detection of
+ clobbered registers during function calls. */
+
+static void
+ppc_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
+ struct dwarf2_frame_state_reg *reg,
+ struct frame_info *this_frame)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ /* PPC32 and PPC64 ABI's are the same regarding volatile and
+ non-volatile registers. We will use the same code for both. */
+
+ /* Call-saved GP registers. */
+ if ((regnum >= tdep->ppc_gp0_regnum + 14
+ && regnum <= tdep->ppc_gp0_regnum + 31)
+ || (regnum == tdep->ppc_gp0_regnum + 1))
+ reg->how = DWARF2_FRAME_REG_SAME_VALUE;
+
+ /* Call-clobbered GP registers. */
+ if ((regnum >= tdep->ppc_gp0_regnum + 3
+ && regnum <= tdep->ppc_gp0_regnum + 12)
+ || (regnum == tdep->ppc_gp0_regnum))
+ reg->how = DWARF2_FRAME_REG_UNDEFINED;
+
+ /* Deal with FP registers, if supported. */
+ if (tdep->ppc_fp0_regnum >= 0)
+ {
+ /* Call-saved FP registers. */
+ if ((regnum >= tdep->ppc_fp0_regnum + 14
+ && regnum <= tdep->ppc_fp0_regnum + 31))
+ reg->how = DWARF2_FRAME_REG_SAME_VALUE;
+
+ /* Call-clobbered FP registers. */
+ if ((regnum >= tdep->ppc_fp0_regnum
+ && regnum <= tdep->ppc_fp0_regnum + 13))
+ reg->how = DWARF2_FRAME_REG_UNDEFINED;
+ }
+
+ /* Deal with ALTIVEC registers, if supported. */
+ if (tdep->ppc_vr0_regnum > 0 && tdep->ppc_vrsave_regnum > 0)
+ {
+ /* Call-saved Altivec registers. */
+ if ((regnum >= tdep->ppc_vr0_regnum + 20
+ && regnum <= tdep->ppc_vr0_regnum + 31)
+ || regnum == tdep->ppc_vrsave_regnum)
+ reg->how = DWARF2_FRAME_REG_SAME_VALUE;
+
+ /* Call-clobbered Altivec registers. */
+ if ((regnum >= tdep->ppc_vr0_regnum
+ && regnum <= tdep->ppc_vr0_regnum + 19))
+ reg->how = DWARF2_FRAME_REG_UNDEFINED;
+ }
+
+ /* Handle PC register and Stack Pointer correctly. */
+ if (regnum == gdbarch_pc_regnum (gdbarch))
+ reg->how = DWARF2_FRAME_REG_RA;
+ else if (regnum == gdbarch_sp_regnum (gdbarch))
+ reg->how = DWARF2_FRAME_REG_CFA;
+}
+
+
/* Initialize the current architecture based on INFO. If possible, re-use an
architecture from ARCHES, which is a list of architectures already created
during this debugging session.
{
struct gdbarch *gdbarch;
struct gdbarch_tdep *tdep;
- int wordsize, from_xcoff_exec, from_elf_exec, i, off;
- struct reg *regs;
- const struct variant *v;
+ int wordsize, from_xcoff_exec, from_elf_exec;
enum bfd_architecture arch;
unsigned long mach;
bfd abfd;
- int sysv_abi;
asection *sect;
+ enum auto_boolean soft_float_flag = powerpc_soft_float_global;
+ int soft_float;
+ enum powerpc_vector_abi vector_abi = powerpc_vector_abi_global;
+ int have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0, have_dfp = 0,
+ have_vsx = 0;
+ int tdesc_wordsize = -1;
+ const struct target_desc *tdesc = info.target_desc;
+ struct tdesc_arch_data *tdesc_data = NULL;
+ int num_pseudoregs = 0;
+ int cur_reg;
+
+ /* INFO may refer to a binary that is not of the PowerPC architecture,
+ e.g. when debugging a stand-alone SPE executable on a Cell/B.E. system.
+ In this case, we must not attempt to infer properties of the (PowerPC
+ side) of the target system from properties of that executable. Trust
+ the target description instead. */
+ if (info.abfd
+ && bfd_get_arch (info.abfd) != bfd_arch_powerpc
+ && bfd_get_arch (info.abfd) != bfd_arch_rs6000)
+ info.abfd = NULL;
from_xcoff_exec = info.abfd && info.abfd->format == bfd_object &&
bfd_get_flavour (info.abfd) == bfd_target_xcoff_flavour;
from_elf_exec = info.abfd && info.abfd->format == bfd_object &&
bfd_get_flavour (info.abfd) == bfd_target_elf_flavour;
- sysv_abi = info.abfd && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour;
-
/* Check word size. If INFO is from a binary file, infer it from
that, else choose a likely default. */
if (from_xcoff_exec)
else
wordsize = 4;
}
+ else if (tdesc_has_registers (tdesc))
+ wordsize = -1;
else
{
if (info.bfd_arch_info != NULL && info.bfd_arch_info->bits_per_word != 0)
wordsize = 4;
}
+ /* Get the architecture and machine from the BFD. */
+ arch = info.bfd_arch_info->arch;
+ mach = info.bfd_arch_info->mach;
+
+ /* For e500 executables, the apuinfo section is of help here. Such
+ section contains the identifier and revision number of each
+ Application-specific Processing Unit that is present on the
+ chip. The content of the section is determined by the assembler
+ which looks at each instruction and determines which unit (and
+ which version of it) can execute it. In our case we just look for
+ the existance of the section. */
+
+ if (info.abfd)
+ {
+ sect = bfd_get_section_by_name (info.abfd, ".PPC.EMB.apuinfo");
+ if (sect)
+ {
+ arch = info.bfd_arch_info->arch;
+ mach = bfd_mach_ppc_e500;
+ bfd_default_set_arch_mach (&abfd, arch, mach);
+ info.bfd_arch_info = bfd_get_arch_info (&abfd);
+ }
+ }
+
+ /* Find a default target description which describes our register
+ layout, if we do not already have one. */
+ if (! tdesc_has_registers (tdesc))
+ {
+ const struct variant *v;
+
+ /* Choose variant. */
+ v = find_variant_by_arch (arch, mach);
+ if (!v)
+ return NULL;
+
+ tdesc = *v->tdesc;
+ }
+
+ gdb_assert (tdesc_has_registers (tdesc));
+
+ /* Check any target description for validity. */
+ if (tdesc_has_registers (tdesc))
+ {
+ static const char *const gprs[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
+ };
+ static const char *const segment_regs[] = {
+ "sr0", "sr1", "sr2", "sr3", "sr4", "sr5", "sr6", "sr7",
+ "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15"
+ };
+ const struct tdesc_feature *feature;
+ int i, valid_p;
+ static const char *const msr_names[] = { "msr", "ps" };
+ static const char *const cr_names[] = { "cr", "cnd" };
+ static const char *const ctr_names[] = { "ctr", "cnt" };
+
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.core");
+ if (feature == NULL)
+ return NULL;
+
+ tdesc_data = tdesc_data_alloc ();
+
+ valid_p = 1;
+ for (i = 0; i < ppc_num_gprs; i++)
+ valid_p &= tdesc_numbered_register (feature, tdesc_data, i, gprs[i]);
+ valid_p &= tdesc_numbered_register (feature, tdesc_data, PPC_PC_REGNUM,
+ "pc");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data, PPC_LR_REGNUM,
+ "lr");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data, PPC_XER_REGNUM,
+ "xer");
+
+ /* Allow alternate names for these registers, to accomodate GDB's
+ historic naming. */
+ valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
+ PPC_MSR_REGNUM, msr_names);
+ valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
+ PPC_CR_REGNUM, cr_names);
+ valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
+ PPC_CTR_REGNUM, ctr_names);
+
+ if (!valid_p)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ return NULL;
+ }
+
+ have_mq = tdesc_numbered_register (feature, tdesc_data, PPC_MQ_REGNUM,
+ "mq");
+
+ tdesc_wordsize = tdesc_register_size (feature, "pc") / 8;
+ if (wordsize == -1)
+ wordsize = tdesc_wordsize;
+
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.fpu");
+ if (feature != NULL)
+ {
+ static const char *const fprs[] = {
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
+ };
+ valid_p = 1;
+ for (i = 0; i < ppc_num_fprs; i++)
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ PPC_F0_REGNUM + i, fprs[i]);
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ PPC_FPSCR_REGNUM, "fpscr");
+
+ if (!valid_p)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ return NULL;
+ }
+ have_fpu = 1;
+ }
+ else
+ have_fpu = 0;
+
+ /* The DFP pseudo-registers will be available when there are floating
+ point registers. */
+ have_dfp = have_fpu;
+
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.altivec");
+ if (feature != NULL)
+ {
+ static const char *const vector_regs[] = {
+ "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
+ "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
+ "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
+ "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
+ };
+
+ valid_p = 1;
+ for (i = 0; i < ppc_num_gprs; i++)
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ PPC_VR0_REGNUM + i,
+ vector_regs[i]);
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ PPC_VSCR_REGNUM, "vscr");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ PPC_VRSAVE_REGNUM, "vrsave");
+
+ if (have_spe || !valid_p)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ return NULL;
+ }
+ have_altivec = 1;
+ }
+ else
+ have_altivec = 0;
+
+ /* Check for POWER7 VSX registers support. */
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.vsx");
+
+ if (feature != NULL)
+ {
+ static const char *const vsx_regs[] = {
+ "vs0h", "vs1h", "vs2h", "vs3h", "vs4h", "vs5h",
+ "vs6h", "vs7h", "vs8h", "vs9h", "vs10h", "vs11h",
+ "vs12h", "vs13h", "vs14h", "vs15h", "vs16h", "vs17h",
+ "vs18h", "vs19h", "vs20h", "vs21h", "vs22h", "vs23h",
+ "vs24h", "vs25h", "vs26h", "vs27h", "vs28h", "vs29h",
+ "vs30h", "vs31h"
+ };
+
+ valid_p = 1;
+
+ for (i = 0; i < ppc_num_vshrs; i++)
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ PPC_VSR0_UPPER_REGNUM + i,
+ vsx_regs[i]);
+ if (!valid_p)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ return NULL;
+ }
+
+ have_vsx = 1;
+ }
+ else
+ have_vsx = 0;
+
+ /* On machines supporting the SPE APU, the general-purpose registers
+ are 64 bits long. There are SIMD vector instructions to treat them
+ as pairs of floats, but the rest of the instruction set treats them
+ as 32-bit registers, and only operates on their lower halves.
+
+ In the GDB regcache, we treat their high and low halves as separate
+ registers. The low halves we present as the general-purpose
+ registers, and then we have pseudo-registers that stitch together
+ the upper and lower halves and present them as pseudo-registers.
+
+ Thus, the target description is expected to supply the upper
+ halves separately. */
+
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.spe");
+ if (feature != NULL)
+ {
+ static const char *const upper_spe[] = {
+ "ev0h", "ev1h", "ev2h", "ev3h",
+ "ev4h", "ev5h", "ev6h", "ev7h",
+ "ev8h", "ev9h", "ev10h", "ev11h",
+ "ev12h", "ev13h", "ev14h", "ev15h",
+ "ev16h", "ev17h", "ev18h", "ev19h",
+ "ev20h", "ev21h", "ev22h", "ev23h",
+ "ev24h", "ev25h", "ev26h", "ev27h",
+ "ev28h", "ev29h", "ev30h", "ev31h"
+ };
+
+ valid_p = 1;
+ for (i = 0; i < ppc_num_gprs; i++)
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ PPC_SPE_UPPER_GP0_REGNUM + i,
+ upper_spe[i]);
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ PPC_SPE_ACC_REGNUM, "acc");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ PPC_SPE_FSCR_REGNUM, "spefscr");
+
+ if (have_mq || have_fpu || !valid_p)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ return NULL;
+ }
+ have_spe = 1;
+ }
+ else
+ have_spe = 0;
+ }
+
+ /* If we have a 64-bit binary on a 32-bit target, complain. Also
+ complain for a 32-bit binary on a 64-bit target; we do not yet
+ support that. For instance, the 32-bit ABI routines expect
+ 32-bit GPRs.
+
+ As long as there isn't an explicit target description, we'll
+ choose one based on the BFD architecture and get a word size
+ matching the binary (probably powerpc:common or
+ powerpc:common64). So there is only trouble if a 64-bit target
+ supplies a 64-bit description while debugging a 32-bit
+ binary. */
+ if (tdesc_wordsize != -1 && tdesc_wordsize != wordsize)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ return NULL;
+ }
+
+#ifdef HAVE_ELF
+ if (soft_float_flag == AUTO_BOOLEAN_AUTO && from_elf_exec)
+ {
+ switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU,
+ Tag_GNU_Power_ABI_FP))
+ {
+ case 1:
+ soft_float_flag = AUTO_BOOLEAN_FALSE;
+ break;
+ case 2:
+ soft_float_flag = AUTO_BOOLEAN_TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (vector_abi == POWERPC_VEC_AUTO && from_elf_exec)
+ {
+ switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU,
+ Tag_GNU_Power_ABI_Vector))
+ {
+ case 1:
+ vector_abi = POWERPC_VEC_GENERIC;
+ break;
+ case 2:
+ vector_abi = POWERPC_VEC_ALTIVEC;
+ break;
+ case 3:
+ vector_abi = POWERPC_VEC_SPE;
+ break;
+ default:
+ break;
+ }
+ }
+#endif
+
+ if (soft_float_flag == AUTO_BOOLEAN_TRUE)
+ soft_float = 1;
+ else if (soft_float_flag == AUTO_BOOLEAN_FALSE)
+ soft_float = 0;
+ else
+ soft_float = !have_fpu;
+
+ /* If we have a hard float binary or setting but no floating point
+ registers, downgrade to soft float anyway. We're still somewhat
+ useful in this scenario. */
+ if (!soft_float && !have_fpu)
+ soft_float = 1;
+
+ /* Similarly for vector registers. */
+ if (vector_abi == POWERPC_VEC_ALTIVEC && !have_altivec)
+ vector_abi = POWERPC_VEC_GENERIC;
+
+ if (vector_abi == POWERPC_VEC_SPE && !have_spe)
+ vector_abi = POWERPC_VEC_GENERIC;
+
+ if (vector_abi == POWERPC_VEC_AUTO)
+ {
+ if (have_altivec)
+ vector_abi = POWERPC_VEC_ALTIVEC;
+ else if (have_spe)
+ vector_abi = POWERPC_VEC_SPE;
+ else
+ vector_abi = POWERPC_VEC_GENERIC;
+ }
+
+ /* Do not limit the vector ABI based on available hardware, since we
+ do not yet know what hardware we'll decide we have. Yuck! FIXME! */
+
/* Find a candidate among extant architectures. */
for (arches = gdbarch_list_lookup_by_info (arches, &info);
arches != NULL;
meaningful, because 64-bit CPUs can run in 32-bit mode. So, perform
separate word size check. */
tdep = gdbarch_tdep (arches->gdbarch);
+ if (tdep && tdep->soft_float != soft_float)
+ continue;
+ if (tdep && tdep->vector_abi != vector_abi)
+ continue;
if (tdep && tdep->wordsize == wordsize)
- return arches->gdbarch;
+ {
+ if (tdesc_data != NULL)
+ tdesc_data_cleanup (tdesc_data);
+ return arches->gdbarch;
+ }
}
/* None found, create a new architecture from INFO, whose bfd_arch_info
- "set arch" trust blindly
- GDB startup useless but harmless */
- if (!from_xcoff_exec)
- {
- arch = info.bfd_arch_info->arch;
- mach = info.bfd_arch_info->mach;
- }
- else
- {
- arch = bfd_arch_powerpc;
- bfd_default_set_arch_mach (&abfd, arch, 0);
- info.bfd_arch_info = bfd_get_arch_info (&abfd);
- mach = info.bfd_arch_info->mach;
- }
tdep = XCALLOC (1, struct gdbarch_tdep);
tdep->wordsize = wordsize;
-
- /* For e500 executables, the apuinfo section is of help here. Such
- section contains the identifier and revision number of each
- Application-specific Processing Unit that is present on the
- chip. The content of the section is determined by the assembler
- which looks at each instruction and determines which unit (and
- which version of it) can execute it. In our case we just look for
- the existance of the section. */
-
- if (info.abfd)
- {
- sect = bfd_get_section_by_name (info.abfd, ".PPC.EMB.apuinfo");
- if (sect)
- {
- arch = info.bfd_arch_info->arch;
- mach = bfd_mach_ppc_e500;
- bfd_default_set_arch_mach (&abfd, arch, mach);
- info.bfd_arch_info = bfd_get_arch_info (&abfd);
- }
- }
+ tdep->soft_float = soft_float;
+ tdep->vector_abi = vector_abi;
gdbarch = gdbarch_alloc (&info, tdep);
- /* Initialize the number of real and pseudo registers in each variant. */
- init_variants ();
-
- /* Choose variant. */
- v = find_variant_by_arch (arch, mach);
- if (!v)
- return NULL;
-
- tdep->regs = v->regs;
-
- tdep->ppc_gp0_regnum = 0;
- tdep->ppc_toc_regnum = 2;
- tdep->ppc_ps_regnum = 65;
- tdep->ppc_cr_regnum = 66;
- tdep->ppc_lr_regnum = 67;
- tdep->ppc_ctr_regnum = 68;
- tdep->ppc_xer_regnum = 69;
- if (v->mach == bfd_mach_ppc_601)
- tdep->ppc_mq_regnum = 124;
- else if (arch == bfd_arch_rs6000)
- tdep->ppc_mq_regnum = 70;
- else
- tdep->ppc_mq_regnum = -1;
- tdep->ppc_fp0_regnum = 32;
- tdep->ppc_fpscr_regnum = (arch == bfd_arch_rs6000) ? 71 : 70;
- tdep->ppc_sr0_regnum = 71;
- tdep->ppc_vr0_regnum = -1;
- tdep->ppc_vrsave_regnum = -1;
- tdep->ppc_ev0_upper_regnum = -1;
- tdep->ppc_ev0_regnum = -1;
- tdep->ppc_ev31_regnum = -1;
- tdep->ppc_acc_regnum = -1;
- tdep->ppc_spefscr_regnum = -1;
-
- set_gdbarch_pc_regnum (gdbarch, 64);
- set_gdbarch_sp_regnum (gdbarch, 1);
- set_gdbarch_deprecated_fp_regnum (gdbarch, 1);
- set_gdbarch_fp0_regnum (gdbarch, 32);
+ tdep->ppc_gp0_regnum = PPC_R0_REGNUM;
+ tdep->ppc_toc_regnum = PPC_R0_REGNUM + 2;
+ tdep->ppc_ps_regnum = PPC_MSR_REGNUM;
+ tdep->ppc_cr_regnum = PPC_CR_REGNUM;
+ tdep->ppc_lr_regnum = PPC_LR_REGNUM;
+ tdep->ppc_ctr_regnum = PPC_CTR_REGNUM;
+ tdep->ppc_xer_regnum = PPC_XER_REGNUM;
+ tdep->ppc_mq_regnum = have_mq ? PPC_MQ_REGNUM : -1;
+
+ tdep->ppc_fp0_regnum = have_fpu ? PPC_F0_REGNUM : -1;
+ tdep->ppc_fpscr_regnum = have_fpu ? PPC_FPSCR_REGNUM : -1;
+ tdep->ppc_vsr0_upper_regnum = have_vsx ? PPC_VSR0_UPPER_REGNUM : -1;
+ tdep->ppc_vr0_regnum = have_altivec ? PPC_VR0_REGNUM : -1;
+ tdep->ppc_vrsave_regnum = have_altivec ? PPC_VRSAVE_REGNUM : -1;
+ tdep->ppc_ev0_upper_regnum = have_spe ? PPC_SPE_UPPER_GP0_REGNUM : -1;
+ tdep->ppc_acc_regnum = have_spe ? PPC_SPE_ACC_REGNUM : -1;
+ tdep->ppc_spefscr_regnum = have_spe ? PPC_SPE_FSCR_REGNUM : -1;
+
+ set_gdbarch_pc_regnum (gdbarch, PPC_PC_REGNUM);
+ set_gdbarch_sp_regnum (gdbarch, PPC_R0_REGNUM + 1);
+ set_gdbarch_deprecated_fp_regnum (gdbarch, PPC_R0_REGNUM + 1);
+ set_gdbarch_fp0_regnum (gdbarch, tdep->ppc_fp0_regnum);
set_gdbarch_register_sim_regno (gdbarch, rs6000_register_sim_regno);
- if (sysv_abi && wordsize == 8)
+
+ /* The XML specification for PowerPC sensibly calls the MSR "msr".
+ GDB traditionally called it "ps", though, so let GDB add an
+ alias. */
+ set_gdbarch_ps_regnum (gdbarch, tdep->ppc_ps_regnum);
+
+ if (wordsize == 8)
set_gdbarch_return_value (gdbarch, ppc64_sysv_abi_return_value);
- else if (sysv_abi && wordsize == 4)
- set_gdbarch_return_value (gdbarch, ppc_sysv_abi_return_value);
else
- set_gdbarch_return_value (gdbarch, rs6000_return_value);
+ set_gdbarch_return_value (gdbarch, ppc_sysv_abi_return_value);
/* Set lr_frame_offset. */
if (wordsize == 8)
tdep->lr_frame_offset = 16;
- else if (sysv_abi)
- tdep->lr_frame_offset = 4;
else
- tdep->lr_frame_offset = 8;
-
- if (v->arch == bfd_arch_rs6000)
- tdep->ppc_sr0_regnum = -1;
- else if (v->arch == bfd_arch_powerpc)
- switch (v->mach)
- {
- case bfd_mach_ppc:
- tdep->ppc_sr0_regnum = -1;
- tdep->ppc_vr0_regnum = 71;
- tdep->ppc_vrsave_regnum = 104;
- break;
- case bfd_mach_ppc_7400:
- tdep->ppc_vr0_regnum = 119;
- tdep->ppc_vrsave_regnum = 152;
- break;
- case bfd_mach_ppc_e500:
- tdep->ppc_toc_regnum = -1;
- tdep->ppc_ev0_upper_regnum = 32;
- tdep->ppc_ev0_regnum = 73;
- tdep->ppc_ev31_regnum = 104;
- tdep->ppc_acc_regnum = 71;
- tdep->ppc_spefscr_regnum = 72;
- tdep->ppc_fp0_regnum = -1;
- tdep->ppc_fpscr_regnum = -1;
- tdep->ppc_sr0_regnum = -1;
- set_gdbarch_pseudo_register_read (gdbarch, e500_pseudo_register_read);
- set_gdbarch_pseudo_register_write (gdbarch, e500_pseudo_register_write);
- set_gdbarch_register_reggroup_p (gdbarch, e500_register_reggroup_p);
- break;
+ tdep->lr_frame_offset = 4;
- case bfd_mach_ppc64:
- case bfd_mach_ppc_620:
- case bfd_mach_ppc_630:
- case bfd_mach_ppc_a35:
- case bfd_mach_ppc_rs64ii:
- case bfd_mach_ppc_rs64iii:
- /* These processor's register sets don't have segment registers. */
- tdep->ppc_sr0_regnum = -1;
- break;
- }
- else
- internal_error (__FILE__, __LINE__,
- _("rs6000_gdbarch_init: "
- "received unexpected BFD 'arch' value"));
+ if (have_spe || have_dfp || have_vsx)
+ {
+ set_gdbarch_pseudo_register_read (gdbarch, rs6000_pseudo_register_read);
+ set_gdbarch_pseudo_register_write (gdbarch, rs6000_pseudo_register_write);
+ }
set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
- /* Sanity check on registers. */
- gdb_assert (strcmp (tdep->regs[tdep->ppc_gp0_regnum].name, "r0") == 0);
-
/* Select instruction printer. */
if (arch == bfd_arch_rs6000)
set_gdbarch_print_insn (gdbarch, print_insn_rs6000);
else
set_gdbarch_print_insn (gdbarch, gdb_print_insn_powerpc);
- set_gdbarch_num_regs (gdbarch, v->nregs);
- set_gdbarch_num_pseudo_regs (gdbarch, v->npregs);
- set_gdbarch_register_name (gdbarch, rs6000_register_name);
- set_gdbarch_register_type (gdbarch, rs6000_register_type);
- set_gdbarch_register_reggroup_p (gdbarch, rs6000_register_reggroup_p);
+ set_gdbarch_num_regs (gdbarch, PPC_NUM_REGS);
+
+ if (have_spe)
+ num_pseudoregs += 32;
+ if (have_dfp)
+ num_pseudoregs += 16;
+ if (have_vsx)
+ /* Include both VSX and Extended FP registers. */
+ num_pseudoregs += 96;
+
+ set_gdbarch_num_pseudo_regs (gdbarch, num_pseudoregs);
set_gdbarch_ptr_bit (gdbarch, wordsize * TARGET_CHAR_BIT);
set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
set_gdbarch_long_long_bit (gdbarch, 8 * TARGET_CHAR_BIT);
set_gdbarch_float_bit (gdbarch, 4 * TARGET_CHAR_BIT);
set_gdbarch_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
- if (sysv_abi)
- set_gdbarch_long_double_bit (gdbarch, 16 * TARGET_CHAR_BIT);
- else
- set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
+ set_gdbarch_long_double_bit (gdbarch, 16 * TARGET_CHAR_BIT);
set_gdbarch_char_signed (gdbarch, 0);
set_gdbarch_frame_align (gdbarch, rs6000_frame_align);
- if (sysv_abi && wordsize == 8)
+ if (wordsize == 8)
/* PPC64 SYSV. */
set_gdbarch_frame_red_zone_size (gdbarch, 288);
- else if (!sysv_abi && wordsize == 4)
- /* PowerOpen / AIX 32 bit. The saved area or red zone consists of
- 19 4 byte GPRS + 18 8 byte FPRs giving a total of 220 bytes.
- Problem is, 220 isn't frame (16 byte) aligned. Round it up to
- 224. */
- set_gdbarch_frame_red_zone_size (gdbarch, 224);
set_gdbarch_convert_register_p (gdbarch, rs6000_convert_register_p);
set_gdbarch_register_to_value (gdbarch, rs6000_register_to_value);
set_gdbarch_stab_reg_to_regnum (gdbarch, rs6000_stab_reg_to_regnum);
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, rs6000_dwarf2_reg_to_regnum);
- if (sysv_abi && wordsize == 4)
+ if (wordsize == 4)
set_gdbarch_push_dummy_call (gdbarch, ppc_sysv_abi_push_dummy_call);
- else if (sysv_abi && wordsize == 8)
+ else if (wordsize == 8)
set_gdbarch_push_dummy_call (gdbarch, ppc64_sysv_abi_push_dummy_call);
- else
- set_gdbarch_push_dummy_call (gdbarch, rs6000_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_skip_main_prologue (gdbarch, rs6000_skip_main_prologue);
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
set_gdbarch_breakpoint_from_pc (gdbarch, rs6000_breakpoint_from_pc);
+ /* The value of symbols of type N_SO and N_FUN maybe null when
+ it shouldn't be. */
+ set_gdbarch_sofun_address_maybe_missing (gdbarch, 1);
+
/* Handles single stepping of atomic sequences. */
- set_gdbarch_software_single_step (gdbarch, deal_with_atomic_sequence);
+ set_gdbarch_software_single_step (gdbarch, ppc_deal_with_atomic_sequence);
- /* Handle the 64-bit SVR4 minimal-symbol convention of using "FN"
- for the descriptor and ".FN" for the entry-point -- a user
- specifying "break FN" will unexpectedly end up with a breakpoint
- on the descriptor and not the function. This architecture method
- transforms any breakpoints on descriptors into breakpoints on the
- corresponding entry point. */
- if (sysv_abi && wordsize == 8)
- set_gdbarch_adjust_breakpoint_address (gdbarch, ppc64_sysv_abi_adjust_breakpoint_address);
-
/* Not sure on this. FIXMEmgo */
set_gdbarch_frame_args_skip (gdbarch, 8);
- if (!sysv_abi)
- {
- /* Handle RS/6000 function pointers (which are really function
- descriptors). */
- set_gdbarch_convert_from_func_ptr_addr (gdbarch,
- rs6000_convert_from_func_ptr_addr);
- }
-
/* Helpers for function argument information. */
set_gdbarch_fetch_pointer_argument (gdbarch, rs6000_fetch_pointer_argument);
set_gdbarch_skip_trampoline_code (gdbarch, rs6000_skip_trampoline_code);
/* Hook in the DWARF CFI frame unwinder. */
- frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
+ dwarf2_append_unwinders (gdbarch);
dwarf2_frame_set_adjust_regnum (gdbarch, rs6000_adjust_frame_regnum);
+ /* 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_hw_singlestep (gdbarch,
+ ppc_displaced_step_hw_singlestep);
+ 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;
gdbarch_init_osabi (info, gdbarch);
switch (info.osabi)
{
case GDB_OSABI_LINUX:
- /* FIXME: pgilliam/2005-10-21: Assume all PowerPC 64-bit linux systems
- have altivec registers. If not, ptrace will fail the first time it's
- called to access one and will not be called again. This wart will
- be removed when Daniel Jacobowitz's proposal for autodetecting target
- registers is implemented. */
- if ((v->arch == bfd_arch_powerpc) && ((v->mach)== bfd_mach_ppc64))
- {
- tdep->ppc_vr0_regnum = 71;
- tdep->ppc_vrsave_regnum = 104;
- }
- /* Fall Thru */
case GDB_OSABI_NETBSD_AOUT:
case GDB_OSABI_NETBSD_ELF:
case GDB_OSABI_UNKNOWN:
set_gdbarch_unwind_pc (gdbarch, rs6000_unwind_pc);
- frame_unwind_append_sniffer (gdbarch, rs6000_frame_sniffer);
- set_gdbarch_unwind_dummy_id (gdbarch, rs6000_unwind_dummy_id);
+ frame_unwind_append_unwinder (gdbarch, &rs6000_frame_unwind);
+ set_gdbarch_dummy_id (gdbarch, rs6000_dummy_id);
frame_base_append_sniffer (gdbarch, rs6000_frame_base_sniffer);
break;
default:
set_gdbarch_believe_pcc_promotion (gdbarch, 1);
set_gdbarch_unwind_pc (gdbarch, rs6000_unwind_pc);
- frame_unwind_append_sniffer (gdbarch, rs6000_frame_sniffer);
- set_gdbarch_unwind_dummy_id (gdbarch, rs6000_unwind_dummy_id);
+ frame_unwind_append_unwinder (gdbarch, &rs6000_frame_unwind);
+ set_gdbarch_dummy_id (gdbarch, rs6000_dummy_id);
frame_base_append_sniffer (gdbarch, rs6000_frame_base_sniffer);
}
- init_sim_regno_table (gdbarch);
+ set_tdesc_pseudo_register_type (gdbarch, rs6000_pseudo_register_type);
+ set_tdesc_pseudo_register_reggroup_p (gdbarch,
+ rs6000_pseudo_register_reggroup_p);
+ tdesc_use_registers (gdbarch, tdesc, tdesc_data);
+
+ /* Override the normal target description method to make the SPE upper
+ halves anonymous. */
+ set_gdbarch_register_name (gdbarch, rs6000_register_name);
+
+ /* Choose register numbers for all supported pseudo-registers. */
+ tdep->ppc_ev0_regnum = -1;
+ tdep->ppc_dl0_regnum = -1;
+ tdep->ppc_vsr0_regnum = -1;
+ tdep->ppc_efpr0_regnum = -1;
+
+ cur_reg = gdbarch_num_regs (gdbarch);
+
+ if (have_spe)
+ {
+ tdep->ppc_ev0_regnum = cur_reg;
+ cur_reg += 32;
+ }
+ if (have_dfp)
+ {
+ tdep->ppc_dl0_regnum = cur_reg;
+ cur_reg += 16;
+ }
+ if (have_vsx)
+ {
+ tdep->ppc_vsr0_regnum = cur_reg;
+ cur_reg += 64;
+ tdep->ppc_efpr0_regnum = cur_reg;
+ cur_reg += 32;
+ }
+
+ gdb_assert (gdbarch_num_regs (gdbarch)
+ + gdbarch_num_pseudo_regs (gdbarch) == cur_reg);
return gdbarch;
}
static void
-rs6000_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
+rs6000_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
if (tdep == NULL)
return;
/* FIXME: Dump gdbarch_tdep. */
}
+/* PowerPC-specific commands. */
+
+static void
+set_powerpc_command (char *args, int from_tty)
+{
+ printf_unfiltered (_("\
+\"set powerpc\" must be followed by an appropriate subcommand.\n"));
+ help_list (setpowerpccmdlist, "set powerpc ", all_commands, gdb_stdout);
+}
+
+static void
+show_powerpc_command (char *args, int from_tty)
+{
+ cmd_show_list (showpowerpccmdlist, from_tty, "");
+}
+
+static void
+powerpc_set_soft_float (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ struct gdbarch_info info;
+
+ /* Update the architecture. */
+ gdbarch_info_init (&info);
+ if (!gdbarch_update_p (info))
+ internal_error (__FILE__, __LINE__, "could not update architecture");
+}
+
+static void
+powerpc_set_vector_abi (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ struct gdbarch_info info;
+ enum powerpc_vector_abi vector_abi;
+
+ for (vector_abi = POWERPC_VEC_AUTO;
+ vector_abi != POWERPC_VEC_LAST;
+ vector_abi++)
+ if (strcmp (powerpc_vector_abi_string,
+ powerpc_vector_strings[vector_abi]) == 0)
+ {
+ powerpc_vector_abi_global = vector_abi;
+ break;
+ }
+
+ if (vector_abi == POWERPC_VEC_LAST)
+ internal_error (__FILE__, __LINE__, _("Invalid vector ABI accepted: %s."),
+ powerpc_vector_abi_string);
+
+ /* Update the architecture. */
+ gdbarch_info_init (&info);
+ if (!gdbarch_update_p (info))
+ internal_error (__FILE__, __LINE__, "could not update architecture");
+}
+
/* Initialization code. */
extern initialize_file_ftype _initialize_rs6000_tdep; /* -Wmissing-prototypes */
{
gdbarch_register (bfd_arch_rs6000, rs6000_gdbarch_init, rs6000_dump_tdep);
gdbarch_register (bfd_arch_powerpc, rs6000_gdbarch_init, rs6000_dump_tdep);
+
+ /* Initialize the standard target descriptions. */
+ initialize_tdesc_powerpc_32 ();
+ initialize_tdesc_powerpc_altivec32 ();
+ initialize_tdesc_powerpc_vsx32 ();
+ initialize_tdesc_powerpc_403 ();
+ initialize_tdesc_powerpc_403gc ();
+ initialize_tdesc_powerpc_405 ();
+ initialize_tdesc_powerpc_505 ();
+ initialize_tdesc_powerpc_601 ();
+ initialize_tdesc_powerpc_602 ();
+ initialize_tdesc_powerpc_603 ();
+ initialize_tdesc_powerpc_604 ();
+ initialize_tdesc_powerpc_64 ();
+ initialize_tdesc_powerpc_altivec64 ();
+ initialize_tdesc_powerpc_vsx64 ();
+ initialize_tdesc_powerpc_7400 ();
+ initialize_tdesc_powerpc_750 ();
+ initialize_tdesc_powerpc_860 ();
+ initialize_tdesc_powerpc_e500 ();
+ initialize_tdesc_rs6000 ();
+
+ /* Add root prefix command for all "set powerpc"/"show powerpc"
+ commands. */
+ add_prefix_cmd ("powerpc", no_class, set_powerpc_command,
+ _("Various PowerPC-specific commands."),
+ &setpowerpccmdlist, "set powerpc ", 0, &setlist);
+
+ add_prefix_cmd ("powerpc", no_class, show_powerpc_command,
+ _("Various PowerPC-specific commands."),
+ &showpowerpccmdlist, "show powerpc ", 0, &showlist);
+
+ /* Add a command to allow the user to force the ABI. */
+ add_setshow_auto_boolean_cmd ("soft-float", class_support,
+ &powerpc_soft_float_global,
+ _("Set whether to use a soft-float ABI."),
+ _("Show whether to use a soft-float ABI."),
+ NULL,
+ powerpc_set_soft_float, NULL,
+ &setpowerpccmdlist, &showpowerpccmdlist);
+
+ add_setshow_enum_cmd ("vector-abi", class_support, powerpc_vector_strings,
+ &powerpc_vector_abi_string,
+ _("Set the vector ABI."),
+ _("Show the vector ABI."),
+ NULL, powerpc_set_vector_abi, NULL,
+ &setpowerpccmdlist, &showpowerpccmdlist);
}