/* Target-dependent code for GDB, the GNU debugger.
- Copyright (C) 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
- Free Software Foundation, Inc.
+ Copyright (C) 1986-1987, 1989, 1991-2012 Free Software Foundation,
+ Inc.
This file is part of GDB.
#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"
/* 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)
+ && (regnum) < (tdep)->ppc_efpr0_regnum + ppc_num_efprs)
/* The list of available "set powerpc ..." and "show powerpc ..."
commands. */
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[] =
+static const char *const powerpc_vector_strings[] =
{
"auto",
"generic",
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. */
+/* To be used by skip_prologue. */
struct rs6000_framedata
{
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 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 */
/* Return non-zero if the architecture described by GDBARCH has
VSX registers (vsr0 --- vsr63). */
-int
+static int
ppc_vsx_support_p (struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
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
{
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;
}
/* Fix up the state of registers and memory after having single-stepped
a displaced instruction. */
-void
+static void
ppc_displaced_step_fixup (struct gdbarch *gdbarch,
- struct displaced_step_closure *closure,
- CORE_ADDR from, CORE_ADDR to,
- struct regcache *regs)
+ struct displaced_step_closure *closure,
+ CORE_ADDR from, CORE_ADDR to,
+ struct regcache *regs)
{
+ 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);
+ PPC_INSN_SIZE, byte_order);
ULONGEST opcode = 0;
/* Offset for non PC-relative instructions. */
LONGEST offset = PPC_INSN_SIZE;
if (debug_displaced)
fprintf_unfiltered (gdb_stdlog,
- "displaced: (ppc) fixup (0x%s, 0x%s)\n",
- paddr_nz (from), paddr_nz (to));
+ "displaced: (ppc) fixup (%s, %s)\n",
+ paddress (gdbarch, from), paddress (gdbarch, to));
/* Handle PC-relative branch instructions. */
if (debug_displaced)
fprintf_unfiltered
(gdb_stdlog,
- "displaced: (ppc) branch instruction: 0x%s\n"
- "displaced: (ppc) adjusted PC from 0x%s to 0x%s\n",
- paddr_nz (insn), paddr_nz (current_pc),
- paddr_nz (from + offset));
+ "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),
+ regcache_cooked_write_unsigned (regs,
+ gdbarch_pc_regnum (gdbarch),
from + offset);
}
}
from + PPC_INSN_SIZE);
if (debug_displaced)
fprintf_unfiltered (gdb_stdlog,
- "displaced: (ppc) adjusted LR to 0x%s\n",
- paddr_nz (from + PPC_INSN_SIZE));
+ "displaced: (ppc) adjusted LR to %s\n",
+ paddress (gdbarch, from + PPC_INSN_SIZE));
}
}
from + offset);
}
+/* 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)
+{
+ return 1;
+}
+
/* Instruction masks used during single-stepping of atomic sequences. */
#define LWARX_MASK 0xfc0007fe
#define LWARX_INSTRUCTION 0x7c000028
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 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 & BRANCH_MASK) == BC_INSN)
{
- int immediate = ((insn & ~3) << 16) >> 16;
- int absolute = ((insn >> 1) & 1);
+ int immediate = ((insn & 0xfffc) ^ 0x8000) - 0x8000;
+ int absolute = insn & 2;
if (bc_insn_count >= 1)
return 0; /* More than one conditional branch found, fallback
if (absolute)
breaks[1] = immediate;
else
- breaks[1] = pc + immediate;
+ breaks[1] = loc + immediate;
bc_insn_count++;
last_breakpoint++;
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;
/* Check for duplicated breakpoints. Check also for a breakpoint
- placed (branch instruction's destination) at the stwcx/stdcx
- instruction, this resets the reservation and take us back to the
- lwarx/ldarx instruction at the beginning of the atomic sequence. */
- if (last_breakpoint && ((breaks[1] == breaks[0])
- || (breaks[1] == closing_insn)))
+ placed (branch instruction's destination) anywhere in sequence. */
+ if (last_breakpoint
+ && (breaks[1] == breaks[0]
+ || (breaks[1] >= pc && breaks[1] <= closing_insn)))
last_breakpoint = 0;
/* 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;
}
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.
+/* 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
#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.
- 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
- */
+ - vrsave_offset is the offset of the saved vrsave register. */
static CORE_ADDR
skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
int r0_contains_arg = 0;
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->nosavedpc = 1;
fdata->lr_register = -1;
+ pc = rs6000_skip_stack_check (gdbarch, pc);
+ if (pc >= lim_pc)
+ pc = lim_pc;
+
for (;; pc += 4)
{
/* Sometimes it isn't clear if an instruction is a prologue
instruction or not. When we encounter one of these ambiguous
cases, we'll set prev_insn_was_prologue_insn to 0 (false).
- Otherwise, we'll assume that it really is a prologue instruction. */
+ Otherwise, we'll assume that it really is a prologue instruction. */
if (prev_insn_was_prologue_insn)
last_prologue_pc = pc;
/* 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 */
/* nop */
/* Allow nops in the prologue, but do not consider them to
be part of the prologue unless followed by other prologue
- instructions. */
+ instructions. */
prev_insn_was_prologue_insn = 0;
continue;
}
else if ((op & 0xfc000001) == 0x48000001)
{ /* bl foo,
- to save fprs??? */
+ to save fprs??? */
fdata->frameless = 0;
/* 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))
+ if (lr_reg != -1 && bl_to_blrl_insn_p (pc, op, byte_order))
{
fdata->used_bl = 1;
continue;
struct symtab_and_line prologue_sal = find_pc_line (orig_pc, 0);
struct symtab_and_line this_sal = find_pc_line (pc, 0);
- if ((prologue_sal.line == 0) || (prologue_sal.line != this_sal.line))
+ if ((prologue_sal.line == 0)
+ || (prologue_sal.line != this_sal.line))
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,
and nothing else). If the next is not a nop, this branch
- was part of the function prologue. */
+ was part of the function prologue. */
if (op == 0x4def7b82 || op == 0) /* crorc 15, 15, 15 */
- break; /* don't skip over
- this branch */
+ break; /* Don't skip over
+ this branch. */
fdata->used_bl = 1;
continue;
}
else if ((op & 0xfc1f016a) == 0x7c01016e)
{ /* stwux rX,r1,rY */
- /* no way to figure out what r1 is going to be */
+ /* No way to figure out what r1 is going to be. */
fdata->frameless = 0;
offset = fdata->offset;
continue;
}
else if ((op & 0xfc1f016a) == 0x7c01016a)
{ /* stdux rX,r1,rY */
- /* no way to figure out what r1 is going to be */
+ /* No way to figure out what r1 is going to be. */
fdata->frameless = 0;
offset = fdata->offset;
continue;
}
/* Load up minimal toc pointer. Do not treat an epilogue restore
of r31 as a minimal TOC load. */
- else if (((op >> 22) == 0x20f || /* l r31,... or l r30,... */
- (op >> 22) == 0x3af) /* ld r31,... or ld r30,... */
+ else if (((op >> 22) == 0x20f || /* l r31,... or l r30,... */
+ (op >> 22) == 0x3af) /* ld r31,... or ld r30,... */
&& !framep
&& !minimal_toc_loaded)
{
else if ((op & 0xfc0007fe) == 0x7c000378 && /* mr(.) Rx,Ry */
(((op >> 21) & 31) >= 3) && /* R3 >= Ry >= R10 */
(((op >> 21) & 31) <= 10) &&
- ((long) ((op >> 16) & 31) >= fdata->saved_gpr)) /* Rx: local var reg */
+ ((long) ((op >> 16) & 31)
+ >= fdata->saved_gpr)) /* Rx: local var reg */
{
continue;
/* Set up frame pointer */
}
+ else if (op == 0x603d0000) /* oril r29, r1, 0x0 */
+ {
+ fdata->frameless = 0;
+ framep = 1;
+ fdata->alloca_reg = (tdep->ppc_gp0_regnum + 29);
+ continue;
+
+ /* Another way to set up the frame pointer. */
+ }
else if (op == 0x603f0000 /* oril r31, r1, 0x0 */
|| op == 0x7c3f0b78)
{ /* mr r31, r1 */
vr_saved_offset = SIGNED_SHORT (op);
/* This insn by itself is not part of the prologue, unless
- if part of the pair of insns mentioned above. So do not
+ if part of the pair of insns mentioned above. So do not
record this insn as part of the prologue yet. */
prev_insn_was_prologue_insn = 0;
}
#if 0
/* I have problems with skipping over __main() that I need to address
- * sometime. Previously, I used to use misc_function_vector which
+ * sometime. Previously, I used to use misc_function_vector which
* didn't work as well as I wanted to be. -MGO */
/* If the first thing after skipping a prolog is a branch to a function,
if ((op & 0xfc000001) == 0x48000001)
- { /* bl foo, an initializer function? */
- op = read_memory_integer (pc + 4, 4);
+ { /* bl foo, an initializer function? */
+ op = read_memory_integer (pc + 4, 4, byte_order);
if (op == 0x4def7b82)
{ /* cror 0xf, 0xf, 0xf (nop) */
rs6000_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
struct rs6000_framedata frame;
- CORE_ADDR limit_pc, func_addr;
+ CORE_ADDR limit_pc, func_addr, func_end_addr = 0;
/* 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 (find_pc_partial_function (pc, NULL, &func_addr, &func_end_addr))
{
- CORE_ADDR post_prologue_pc = skip_prologue_using_sal (func_addr);
+ CORE_ADDR post_prologue_pc
+ = skip_prologue_using_sal (gdbarch, func_addr);
if (post_prologue_pc != 0)
return max (pc, post_prologue_pc);
}
/* Find an upper limit on the function prologue using the debug
information. If the debug information could not be used to provide
that bound, then use an arbitrary large number as the upper bound. */
- limit_pc = skip_prologue_using_sal (pc);
+ limit_pc = skip_prologue_using_sal (gdbarch, pc);
if (limit_pc == 0)
limit_pc = pc + 100; /* Magic. */
+ /* Do not allow limit_pc to be past the function end, if we know
+ where that end is... */
+ if (func_end_addr && limit_pc > func_end_addr)
+ limit_pc = func_end_addr;
+
pc = skip_prologue (gdbarch, pc, limit_pc, &frame);
return pc;
}
address of the instruction following that call. Otherwise, it simply
returns PC. */
-CORE_ADDR
+static CORE_ADDR
rs6000_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
+ 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);
+ op = extract_unsigned_integer (buf, 4, byte_order);
if ((op & BL_MASK) == BL_INSTRUCTION)
{
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)
+static int
+rs6000_in_solib_return_trampoline (struct gdbarch *gdbarch,
+ CORE_ADDR pc, const char *name)
{
return name && !strncmp (name, "@FIX", 4);
}
Result is desired PC to step until, or NULL if we are not in
code that should be skipped. */
-CORE_ADDR
+static CORE_ADDR
rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame));
+ 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;
/* Check for bigtoc fixup code. */
msymbol = lookup_minimal_symbol_by_pc (pc);
if (msymbol
- && rs6000_in_solib_return_trampoline (pc, SYMBOL_LINKAGE_NAME (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);
+ op = read_memory_integer (pc + 8, 4, byte_order);
if ((op & 0xfc000003) == 0x48000000)
{
/* Extract bits 6-29 as a signed 24-bit relative word address and
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_unsigned_integer (ii, tdep->wordsize); /* (r11) value */
+ ii = get_frame_register_unsigned (frame, 11); /* r11 holds destination
+ addr. */
+ 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;
}
if (!tdep->ppc_builtin_type_vec128)
{
+ 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];
struct type *t;
- t = init_composite_type ("__ppc_builtin_type_vec128", TYPE_CODE_UNION);
- append_composite_type_field (t, "uint128", builtin_type_uint128);
+ 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 (gdbarch)->builtin_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;
}
&& regnum >= tdep->ppc_fp0_regnum
&& regnum < tdep->ppc_fp0_regnum + ppc_num_fprs
&& TYPE_CODE (type) == TYPE_CODE_FLT
- && TYPE_LENGTH (type) != TYPE_LENGTH (builtin_type_double));
+ && TYPE_LENGTH (type)
+ != TYPE_LENGTH (builtin_type (gdbarch)->builtin_double));
}
-static void
+static int
rs6000_register_to_value (struct frame_info *frame,
int regnum,
struct type *type,
- gdb_byte *to)
+ gdb_byte *to,
+ int *optimizedp, int *unavailablep)
{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
gdb_byte from[MAX_REGISTER_SIZE];
gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
- get_frame_register (frame, regnum, from);
- convert_typed_floating (from, builtin_type_double, to, type);
+ if (!get_frame_register_bytes (frame, regnum, 0,
+ register_size (gdbarch, regnum),
+ from, optimizedp, unavailablep))
+ return 0;
+
+ convert_typed_floating (from, builtin_type (gdbarch)->builtin_double,
+ to, type);
+ *optimizedp = *unavailablep = 0;
+ return 1;
}
static void
struct type *type,
const gdb_byte *from)
{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
gdb_byte to[MAX_REGISTER_SIZE];
gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
- convert_typed_floating (from, type, to, builtin_type_double);
+ convert_typed_floating (from, type,
+ to, builtin_type (gdbarch)->builtin_double);
put_frame_register (frame, regnum, to);
}
+ /* The type of a function that moves the value of REG between CACHE
+ or BUF --- in either direction. */
+typedef enum register_status (*move_ev_register_func) (struct regcache *,
+ int, void *);
+
/* Move SPE vector register values between a 64-bit buffer and the two
32-bit raw register halves in a regcache. This function handles
both splitting a 64-bit value into two 32-bit halves, and joining
MOVE, since this function can't tell at compile-time which of
REGCACHE or BUFFER is acting as the source of the data. If C had
co-variant type qualifiers, ... */
-static void
-e500_move_ev_register (void (*move) (struct regcache *regcache,
- int regnum, gdb_byte *buf),
- struct regcache *regcache, int ev_reg,
- gdb_byte *buffer)
+
+static enum register_status
+e500_move_ev_register (move_ev_register_func move,
+ struct regcache *regcache, int ev_reg, void *buffer)
{
struct gdbarch *arch = get_regcache_arch (regcache);
struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
int reg_index;
gdb_byte *byte_buffer = buffer;
+ enum register_status status;
gdb_assert (IS_SPE_PSEUDOREG (tdep, ev_reg));
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);
+ status = move (regcache, tdep->ppc_ev0_upper_regnum + reg_index,
+ byte_buffer);
+ if (status == REG_VALID)
+ status = move (regcache, tdep->ppc_gp0_regnum + reg_index,
+ byte_buffer + 4);
}
else
{
- move (regcache, tdep->ppc_gp0_regnum + reg_index, byte_buffer);
- move (regcache, tdep->ppc_ev0_upper_regnum + reg_index, byte_buffer + 4);
+ status = move (regcache, tdep->ppc_gp0_regnum + reg_index, byte_buffer);
+ if (status == REG_VALID)
+ status = move (regcache, tdep->ppc_ev0_upper_regnum + reg_index,
+ byte_buffer + 4);
}
+
+ return status;
}
-static void
+static enum register_status
+do_regcache_raw_read (struct regcache *regcache, int regnum, void *buffer)
+{
+ return regcache_raw_read (regcache, regnum, buffer);
+}
+
+static enum register_status
+do_regcache_raw_write (struct regcache *regcache, int regnum, void *buffer)
+{
+ regcache_raw_write (regcache, regnum, buffer);
+
+ return REG_VALID;
+}
+
+static enum register_status
e500_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
int reg_nr, gdb_byte *buffer)
{
- e500_move_ev_register (regcache_raw_read, regcache, reg_nr, buffer);
+ return e500_move_ev_register (do_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);
+ e500_move_ev_register (do_regcache_raw_write, regcache,
+ reg_nr, (void *) buffer);
}
/* Read method for DFP pseudo-registers. */
-static void
+static enum register_status
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;
+ enum register_status status;
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);
+ status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+ 2 * reg_index, buffer);
+ if (status == REG_VALID)
+ status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+ 2 * reg_index + 1, buffer + 8);
}
else
{
- 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);
+ status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+ 2 * reg_index + 1, buffer + 8);
+ if (status == REG_VALID)
+ status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+ 2 * reg_index, buffer);
}
+
+ return status;
}
/* Write method for DFP pseudo-registers. */
}
/* Read method for POWER7 VSX pseudo-registers. */
-static void
+static enum register_status
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;
+ enum register_status status;
/* Read the portion that overlaps the VMX registers. */
if (reg_index > 31)
- regcache_raw_read (regcache, tdep->ppc_vr0_regnum +
- reg_index - 32, buffer);
+ status = 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);
+ status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+ reg_index, buffer);
+ if (status == REG_VALID)
+ status = 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);
+ status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+ reg_index, buffer + 8);
+ if (status == REG_VALID)
+ status = regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
+ reg_index, buffer);
}
+
+ return status;
}
/* Write method for POWER7 VSX pseudo-registers. */
}
/* Read method for POWER7 Extended FP pseudo-registers. */
-static void
+static enum register_status
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);
+ /* Read the portion that overlaps the VMX register. */
+ return regcache_raw_read_part (regcache, tdep->ppc_vr0_regnum + reg_index, 0,
+ register_size (gdbarch, reg_nr), buffer);
}
/* Write method for POWER7 Extended FP pseudo-registers. */
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);
+ /* Write the portion that overlaps the VMX register. */
+ regcache_raw_write_part (regcache, tdep->ppc_vr0_regnum + reg_index, 0,
+ register_size (gdbarch, reg_nr), buffer);
}
-static void
-rs6000_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+static enum register_status
+rs6000_pseudo_register_read (struct gdbarch *gdbarch,
+ struct regcache *regcache,
int reg_nr, gdb_byte *buffer)
{
struct gdbarch *regcache_arch = get_regcache_arch (regcache);
gdb_assert (regcache_arch == gdbarch);
if (IS_SPE_PSEUDOREG (tdep, reg_nr))
- e500_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+ return 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);
+ return 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);
+ return 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);
+ return efpr_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
else
internal_error (__FILE__, __LINE__,
_("rs6000_pseudo_register_read: "
bfd_mach_rs6k, &tdesc_rs6000},
{"403", "IBM PowerPC 403", bfd_arch_powerpc,
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, &tdesc_powerpc_601},
{"602", "Motorola PowerPC 602", bfd_arch_powerpc,
static int
gdb_print_insn_powerpc (bfd_vma memaddr, disassemble_info *info)
{
- if (!info->disassembler_options)
- info->disassembler_options = "any";
-
if (info->endian == BFD_ENDIAN_BIG)
return print_insn_big_powerpc (memaddr, info);
else
struct rs6000_frame_cache *cache;
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;
if (!fdata.frameless)
/* Frameless really means stackless. */
- cache->base = read_memory_unsigned_integer (cache->base, wordsize);
+ cache->base
+ = read_memory_unsigned_integer (cache->base, wordsize, byte_order);
trad_frame_set_value (cache->saved_regs,
gdbarch_sp_regnum (gdbarch), cache->base);
}
/* if != -1, fdata.saved_ev is the smallest number of saved_ev.
- All vr's from saved_ev to ev31 are saved. ????? */
+ All vr's from saved_ev to ev31 are saved. ????? */
if (tdep->ppc_ev0_regnum != -1)
{
if (fdata.saved_ev >= 0)
/* If != 0, fdata.cr_offset is the offset from the frame that
holds the CR. */
if (fdata.cr_offset != 0)
- cache->saved_regs[tdep->ppc_cr_regnum].addr = cache->base + fdata.cr_offset;
+ cache->saved_regs[tdep->ppc_cr_regnum].addr
+ = cache->base + fdata.cr_offset;
/* If != 0, fdata.lr_offset is the offset from the frame that
holds the LR. */
if (fdata.lr_offset != 0)
- cache->saved_regs[tdep->ppc_lr_regnum].addr = cache->base + fdata.lr_offset;
+ 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. */
/* If != 0, fdata.vrsave_offset is the offset from the frame that
holds the VRSAVE. */
if (fdata.vrsave_offset != 0)
- cache->saved_regs[tdep->ppc_vrsave_regnum].addr = cache->base + fdata.vrsave_offset;
+ cache->saved_regs[tdep->ppc_vrsave_regnum].addr
+ = cache->base + fdata.vrsave_offset;
if (fdata.alloca_reg < 0)
/* If no alloca register used, then fi->frame is the value of the
static const struct frame_unwind rs6000_frame_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
rs6000_frame_this_id,
rs6000_frame_prev_register,
NULL,
}
+/* Return true if a .gnu_attributes section exists in BFD and it
+ indicates we are using SPE extensions OR if a .PPC.EMB.apuinfo
+ section exists in BFD and it indicates that SPE extensions are in
+ use. Check the .gnu.attributes section first, as the binary might be
+ compiled for SPE, but not actually using SPE instructions. */
+
+static int
+bfd_uses_spe_extensions (bfd *abfd)
+{
+ asection *sect;
+ gdb_byte *contents = NULL;
+ bfd_size_type size;
+ gdb_byte *ptr;
+ int success = 0;
+ int vector_abi;
+
+ if (!abfd)
+ return 0;
+
+#ifdef HAVE_ELF
+ /* Using Tag_GNU_Power_ABI_Vector here is a bit of a hack, as the user
+ could be using the SPE vector abi without actually using any spe
+ bits whatsoever. But it's close enough for now. */
+ vector_abi = bfd_elf_get_obj_attr_int (abfd, OBJ_ATTR_GNU,
+ Tag_GNU_Power_ABI_Vector);
+ if (vector_abi == 3)
+ return 1;
+#endif
+
+ sect = bfd_get_section_by_name (abfd, ".PPC.EMB.apuinfo");
+ if (!sect)
+ return 0;
+
+ size = bfd_get_section_size (sect);
+ contents = xmalloc (size);
+ if (!bfd_get_section_contents (abfd, sect, contents, 0, size))
+ {
+ xfree (contents);
+ return 0;
+ }
+
+ /* Parse the .PPC.EMB.apuinfo section. The layout is as follows:
+
+ struct {
+ uint32 name_len;
+ uint32 data_len;
+ uint32 type;
+ char name[name_len rounded up to 4-byte alignment];
+ char data[data_len];
+ };
+
+ Technically, there's only supposed to be one such structure in a
+ given apuinfo section, but the linker is not always vigilant about
+ merging apuinfo sections from input files. Just go ahead and parse
+ them all, exiting early when we discover the binary uses SPE
+ insns.
+
+ It's not specified in what endianness the information in this
+ section is stored. Assume that it's the endianness of the BFD. */
+ ptr = contents;
+ while (1)
+ {
+ unsigned int name_len;
+ unsigned int data_len;
+ unsigned int type;
+
+ /* If we can't read the first three fields, we're done. */
+ if (size < 12)
+ break;
+
+ name_len = bfd_get_32 (abfd, ptr);
+ name_len = (name_len + 3) & ~3U; /* Round to 4 bytes. */
+ data_len = bfd_get_32 (abfd, ptr + 4);
+ type = bfd_get_32 (abfd, ptr + 8);
+ ptr += 12;
+
+ /* The name must be "APUinfo\0". */
+ if (name_len != 8
+ && strcmp ((const char *) ptr, "APUinfo") != 0)
+ break;
+ ptr += name_len;
+
+ /* The type must be 2. */
+ if (type != 2)
+ break;
+
+ /* The data is stored as a series of uint32. The upper half of
+ each uint32 indicates the particular APU used and the lower
+ half indicates the revision of that APU. We just care about
+ the upper half. */
+
+ /* Not 4-byte quantities. */
+ if (data_len & 3U)
+ break;
+
+ while (data_len)
+ {
+ unsigned int apuinfo = bfd_get_32 (abfd, ptr);
+ unsigned int apu = apuinfo >> 16;
+ ptr += 4;
+ data_len -= 4;
+
+ /* The SPE APU is 0x100; the SPEFP APU is 0x101. Accept
+ either. */
+ if (apu == 0x100 || apu == 0x101)
+ {
+ success = 1;
+ data_len = 0;
+ }
+ }
+
+ if (success)
+ break;
+ }
+
+ xfree (contents);
+ return success;
+}
+
/* 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.
enum bfd_architecture arch;
unsigned long mach;
bfd abfd;
- 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 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;
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. */
+ which version of it) can execute it. Grovel through the section
+ looking for relevant e500 APUs. */
- if (info.abfd)
+ if (bfd_uses_spe_extensions (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);
- }
+ 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
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_pseudo_register_write (gdbarch,
+ rs6000_pseudo_register_write);
}
set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
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. */
+ it shouldn't be. */
set_gdbarch_sofun_address_maybe_missing (gdbarch, 1);
/* Handles single stepping of atomic sequences. */
set_gdbarch_software_single_step (gdbarch, ppc_deal_with_atomic_sequence);
- /* Not sure on this. FIXMEmgo */
+ /* Not sure on this. FIXMEmgo */
set_gdbarch_frame_args_skip (gdbarch, 8);
/* Helpers for function argument information. */
/* 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;
gdb_assert (gdbarch_num_regs (gdbarch)
+ gdbarch_num_pseudo_regs (gdbarch) == cur_reg);
- /* Setup displaced stepping. */
- set_gdbarch_displaced_step_copy_insn (gdbarch,
- simple_displaced_step_copy_insn);
- set_gdbarch_displaced_step_fixup (gdbarch, ppc_displaced_step_fixup);
- set_gdbarch_displaced_step_free_closure (gdbarch,
- simple_displaced_step_free_closure);
- set_gdbarch_displaced_step_location (gdbarch,
- displaced_step_at_entry_point);
-
- set_gdbarch_max_insn_length (gdbarch, PPC_INSN_SIZE);
-
return gdbarch;
}
/* Update the architecture. */
gdbarch_info_init (&info);
if (!gdbarch_update_p (info))
- internal_error (__FILE__, __LINE__, "could not update architecture");
+ internal_error (__FILE__, __LINE__, _("could not update architecture"));
}
static void
/* Update the architecture. */
gdbarch_info_init (&info);
if (!gdbarch_update_p (info))
- internal_error (__FILE__, __LINE__, "could not update architecture");
+ internal_error (__FILE__, __LINE__, _("could not update architecture"));
+}
+
+/* Show the current setting of the exact watchpoints flag. */
+
+static void
+show_powerpc_exact_watchpoints (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+ fprintf_filtered (file, _("Use of exact watchpoints is %s.\n"), value);
}
/* Initialization code. */
-extern initialize_file_ftype _initialize_rs6000_tdep; /* -Wmissing-prototypes */
+/* -Wmissing-prototypes */
+extern initialize_file_ftype _initialize_rs6000_tdep;
void
_initialize_rs6000_tdep (void)
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 ();
_("Show the vector ABI."),
NULL, powerpc_set_vector_abi, NULL,
&setpowerpccmdlist, &showpowerpccmdlist);
+
+ add_setshow_boolean_cmd ("exact-watchpoints", class_support,
+ &target_exact_watchpoints,
+ _("\
+Set whether to use just one debug register for watchpoints on scalars."),
+ _("\
+Show whether to use just one debug register for watchpoints on scalars."),
+ _("\
+If true, GDB will use only one debug register when watching a variable of\n\
+scalar type, thus assuming that the variable is accessed through the address\n\
+of its first byte."),
+ NULL, show_powerpc_exact_watchpoints,
+ &setpowerpccmdlist, &showpowerpccmdlist);
}