/* 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
+ 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.
This file is part of GDB.
#include "sim-regno.h"
#include "gdb/sim-ppc.h"
#include "reggroups.h"
+#include "dwarf2-frame.h"
#include "libbfd.h" /* for bfd_default_set_arch_mach */
#include "coff/internal.h" /* for libcoff.h */
CORE_ADDR (*rs6000_find_toc_address_hook) (CORE_ADDR) = NULL;
-/* Hook to set the current architecture when starting a child process.
- rs6000-nat.c sets this. */
-
-void (*rs6000_set_host_arch_hook) (int) = NULL;
-
/* Static function prototypes */
-static CORE_ADDR branch_dest (int opcode, int instr, CORE_ADDR pc,
- CORE_ADDR safety);
+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 *);
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
int sim_regno;
- gdb_assert (0 <= reg && reg <= NUM_REGS + NUM_PSEUDO_REGS);
+ gdb_assert (0 <= reg
+ && reg <= gdbarch_num_regs (current_gdbarch)
+ + gdbarch_num_pseudo_regs (current_gdbarch));
sim_regno = tdep->sim_regno[reg];
if (sim_regno >= 0)
ppc_supply_reg (regcache, i, gregs, offset);
}
- if (regnum == -1 || regnum == PC_REGNUM)
- ppc_supply_reg (regcache, PC_REGNUM, gregs, offsets->pc_offset);
+ if (regnum == -1 || regnum == gdbarch_pc_regnum (current_gdbarch))
+ ppc_supply_reg (regcache, gdbarch_pc_regnum (current_gdbarch),
+ gregs, offsets->pc_offset);
if (regnum == -1 || regnum == tdep->ppc_ps_regnum)
ppc_supply_reg (regcache, tdep->ppc_ps_regnum,
gregs, offsets->ps_offset);
ppc_collect_reg (regcache, i, gregs, offset);
}
- if (regnum == -1 || regnum == PC_REGNUM)
- ppc_collect_reg (regcache, PC_REGNUM, gregs, offsets->pc_offset);
+ if (regnum == -1 || regnum == gdbarch_pc_regnum (current_gdbarch))
+ ppc_collect_reg (regcache, gdbarch_pc_regnum (current_gdbarch),
+ gregs, offsets->pc_offset);
if (regnum == -1 || regnum == tdep->ppc_ps_regnum)
ppc_collect_reg (regcache, tdep->ppc_ps_regnum,
gregs, offsets->ps_offset);
rs6000_skip_prologue (CORE_ADDR pc)
{
struct rs6000_framedata frame;
- pc = skip_prologue (pc, 0, &frame);
+ CORE_ADDR limit_pc, func_addr;
+
+ /* 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 (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. */
+
+ /* 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. */
+
+ pc = skip_prologue (pc, limit_pc, &frame);
return pc;
}
{
if (!safe_frame_unwind_memory (curfrm, scan_pc, insn_buf, PPC_INSN_SIZE))
return 0;
- insn = extract_signed_integer (insn_buf, PPC_INSN_SIZE);
+ insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE);
if (insn == 0x4e800020)
break;
if (insn_changes_sp_or_jumps (insn))
{
if (!safe_frame_unwind_memory (curfrm, scan_pc, insn_buf, PPC_INSN_SIZE))
return 0;
- insn = extract_signed_integer (insn_buf, PPC_INSN_SIZE);
+ insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE);
if (insn_changes_sp_or_jumps (insn))
return 1;
}
return 0;
}
-
-/* Fill in fi->saved_regs */
-
-struct frame_extra_info
-{
- /* Functions calling alloca() change the value of the stack
- pointer. We need to use initial stack pointer (which is saved in
- r31 by gcc) in such cases. If a compiler emits traceback table,
- then we should use the alloca register specified in traceback
- table. FIXME. */
- CORE_ADDR initial_sp; /* initial stack pointer. */
-};
-
/* Get the ith function argument for the current function. */
static CORE_ADDR
rs6000_fetch_pointer_argument (struct frame_info *frame, int argi,
/* Calculate the destination of a branch/jump. Return -1 if not a branch. */
static CORE_ADDR
-branch_dest (int opcode, int instr, CORE_ADDR pc, CORE_ADDR safety)
+branch_dest (struct frame_info *frame, int opcode, int instr,
+ CORE_ADDR pc, CORE_ADDR safety)
{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame));
CORE_ADDR dest;
int immediate;
int absolute;
if (ext_op == 16) /* br conditional register */
{
- dest = read_register (gdbarch_tdep (current_gdbarch)->ppc_lr_regnum) & ~3;
+ 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 < TEXT_SEGMENT_BASE)
- {
- struct frame_info *fi;
-
- fi = get_current_frame ();
- if (fi != NULL)
- dest = read_memory_addr (get_frame_base (fi) + SIG_FRAME_PC_OFFSET,
- gdbarch_tdep (current_gdbarch)->wordsize);
- }
+ if (dest < tdep->text_segment_base)
+ dest = read_memory_addr (get_frame_base (frame) + SIG_FRAME_PC_OFFSET,
+ tdep->wordsize);
}
else if (ext_op == 528) /* br cond to count reg */
{
- dest = read_register (gdbarch_tdep (current_gdbarch)->ppc_ctr_regnum) & ~3;
+ dest = get_frame_register_unsigned (frame, tdep->ppc_ctr_regnum) & ~3;
/* 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 < TEXT_SEGMENT_BASE)
- dest = read_register (gdbarch_tdep (current_gdbarch)->ppc_lr_regnum) & ~3;
+ if (dest < tdep->text_segment_base)
+ dest = get_frame_register_unsigned (frame, tdep->ppc_lr_regnum) & ~3;
}
else
return -1;
default:
return -1;
}
- return (dest < TEXT_SEGMENT_BASE) ? safety : dest;
+ return (dest < tdep->text_segment_base) ? safety : dest;
}
static unsigned char big_breakpoint[] = { 0x7d, 0x82, 0x10, 0x08 };
static unsigned char little_breakpoint[] = { 0x08, 0x10, 0x82, 0x7d };
*bp_size = 4;
- if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+ if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
return big_breakpoint;
else
return little_breakpoint;
}
-/* AIX does not support PT_STEP. Simulate it. */
+/* Instruction masks used during single-stepping of atomic sequences. */
+#define LWARX_MASK 0xfc0007fe
+#define LWARX_INSTRUCTION 0x7c000028
+#define LDARX_INSTRUCTION 0x7c0000A8
+#define STWCX_MASK 0xfc0007ff
+#define STWCX_INSTRUCTION 0x7c00012d
+#define STDCX_INSTRUCTION 0x7c0001ad
+#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)
+{
+ 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_count;
+ int index;
+ int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed). */
+ const int atomic_sequence_length = 16; /* Instruction sequence length. */
+ int opcode; /* Branch instruction's OPcode. */
+ int bc_insn_count = 0; /* Conditional branch instruction count. */
+
+ /* Assume all atomic sequences start with a lwarx/ldarx instruction. */
+ if ((insn & LWARX_MASK) != LWARX_INSTRUCTION
+ && (insn & LWARX_MASK) != LDARX_INSTRUCTION)
+ return 0;
-void
-rs6000_software_single_step (enum target_signal signal,
- int insert_breakpoints_p)
+ /* Assume that no atomic sequence is longer than "atomic_sequence_length"
+ instructions. */
+ for (insn_count = 0; insn_count < atomic_sequence_length; ++insn_count)
+ {
+ loc += PPC_INSN_SIZE;
+ insn = read_memory_integer (loc, PPC_INSN_SIZE);
+
+ /* 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 (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 ((insn & STWCX_MASK) == STWCX_INSTRUCTION
+ || (insn & STWCX_MASK) == STDCX_INSTRUCTION)
+ break;
+ }
+
+ /* Assume that the atomic sequence ends with a stwcx/stdcx instruction. */
+ if ((insn & STWCX_MASK) != STWCX_INSTRUCTION
+ && (insn & STWCX_MASK) != STDCX_INSTRUCTION)
+ return 0;
+
+ closing_insn = loc;
+ loc += PPC_INSN_SIZE;
+ insn = read_memory_integer (loc, PPC_INSN_SIZE);
+
+ /* 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)))
+ last_breakpoint = 0;
+
+ /* Effectively inserts the breakpoints. */
+ for (index = 0; index <= last_breakpoint; index++)
+ insert_single_step_breakpoint (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;
CORE_ADDR breaks[2];
int opcode;
- if (insert_breakpoints_p)
- {
- loc = read_pc ();
+ loc = get_frame_pc (frame);
- insn = read_memory_integer (loc, 4);
+ insn = read_memory_integer (loc, 4);
- breaks[0] = loc + breakp_sz;
- opcode = insn >> 26;
- breaks[1] = branch_dest (opcode, insn, loc, breaks[0]);
+ 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]);
- /* Don't put two breakpoints on the same address. */
- if (breaks[1] == breaks[0])
- breaks[1] = -1;
+ /* Don't put two breakpoints on the same address. */
+ if (breaks[1] == breaks[0])
+ breaks[1] = -1;
- for (ii = 0; ii < 2; ++ii)
- {
- /* ignore invalid breakpoint. */
- if (breaks[ii] == -1)
- continue;
- insert_single_step_breakpoint (breaks[ii]);
- }
+ for (ii = 0; ii < 2; ++ii)
+ {
+ /* ignore invalid breakpoint. */
+ if (breaks[ii] == -1)
+ continue;
+ insert_single_step_breakpoint (breaks[ii]);
}
- else
- remove_single_step_breakpoints ();
errno = 0; /* FIXME, don't ignore errors! */
/* What errors? {read,write}_memory call error(). */
+ return 1;
}
of the prologue is expensive. */
static int max_skip_non_prologue_insns = 10;
-/* Given PC representing the starting address of a function, and
- LIM_PC which is the (sloppy) limit to which to scan when looking
- for a prologue, attempt to further refine this limit by using
- the line data in the symbol table. If successful, a better guess
- on where the prologue ends is returned, otherwise the previous
- value of lim_pc is returned. */
-
-/* FIXME: cagney/2004-02-14: This function and logic have largely been
- superseded by skip_prologue_using_sal. */
-
-static CORE_ADDR
-refine_prologue_limit (CORE_ADDR pc, CORE_ADDR lim_pc)
-{
- struct symtab_and_line prologue_sal;
-
- prologue_sal = find_pc_line (pc, 0);
- if (prologue_sal.line != 0)
- {
- int i;
- CORE_ADDR addr = prologue_sal.end;
-
- /* Handle the case in which compiler's optimizer/scheduler
- has moved instructions into the prologue. We scan ahead
- in the function looking for address ranges whose corresponding
- line number is less than or equal to the first one that we
- found for the function. (It can be less than when the
- scheduler puts a body instruction before the first prologue
- instruction.) */
- for (i = 2 * max_skip_non_prologue_insns;
- i > 0 && (lim_pc == 0 || addr < lim_pc);
- i--)
- {
- struct symtab_and_line sal;
-
- sal = find_pc_line (addr, 0);
- if (sal.line == 0)
- break;
- if (sal.line <= prologue_sal.line
- && sal.symtab == prologue_sal.symtab)
- {
- prologue_sal = sal;
- }
- addr = sal.end;
- }
-
- if (lim_pc == 0 || prologue_sal.end < lim_pc)
- lim_pc = prologue_sal.end;
- }
- return lim_pc;
-}
-
/* 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
return 0;
}
+/* Assuming that INSN is a "bl" instruction located at PC, return
+ nonzero if the destination of the branch is a "blrl" instruction.
+
+ This sequence is sometimes found in certain function prologues.
+ It allows the function to load the LR register with a value that
+ they can use to access PIC data using PC-relative offsets. */
+
+static int
+bl_to_blrl_insn_p (CORE_ADDR pc, int insn)
+{
+ CORE_ADDR dest;
+ int immediate;
+ int absolute;
+ int dest_insn;
+
+ absolute = (int) ((insn >> 1) & 1);
+ immediate = ((insn & ~3) << 6) >> 6;
+ if (absolute)
+ dest = immediate;
+ else
+ dest = pc + immediate;
+
+ dest_insn = read_memory_integer (dest, 4);
+ if ((dest_insn & 0xfc00ffff) == 0x4c000021) /* blrl */
+ return 1;
+
+ return 0;
+}
+
static CORE_ADDR
skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
{
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);
-
- /* Attempt to find the end of the prologue when no limit is specified.
- Note that refine_prologue_limit() has been written so that it may
- be used to "refine" the limits of non-zero PC values too, but this
- is only safe if we 1) trust the line information provided by the
- compiler and 2) iterate enough to actually find the end of the
- prologue.
-
- It may become a good idea at some point (for both performance and
- accuracy) to unconditionally call refine_prologue_limit(). But,
- until we can make a clear determination that this is beneficial,
- we'll play it safe and only use it to obtain a limit when none
- has been specified. */
- if (lim_pc == 0)
- lim_pc = refine_prologue_limit (pc, lim_pc);
memset (fdata, 0, sizeof (struct rs6000_framedata));
fdata->saved_gpr = -1;
last_prologue_pc = pc;
/* Stop scanning if we've hit the limit. */
- if (lim_pc != 0 && pc >= lim_pc)
+ if (pc >= lim_pc)
break;
prev_insn_was_prologue_insn = 1;
/* Fetch the instruction and convert it to an integer. */
if (target_read_memory (pc, buf, 4))
break;
- op = extract_signed_integer (buf, 4);
+ op = extract_unsigned_integer (buf, 4);
if ((op & 0xfc1fffff) == 0x7c0802a6)
{ /* mflr Rx */
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))
+ continue;
+
/* Don't skip over the subroutine call if it is not within
the first three instructions of the prologue and either
we have no line table information or the line info tells
offset = fdata->offset;
continue;
}
- /* Load up minimal toc pointer */
+ else if ((op & 0xffff0000) == 0x38210000)
+ { /* addi r1,r1,SIMM */
+ fdata->frameless = 0;
+ fdata->offset += SIGNED_SHORT (op);
+ 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,... */
+ && !framep
&& !minimal_toc_loaded)
{
minimal_toc_loaded = 1;
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
- && (lr_reg == -1 || fdata->nosavedpc == 0))
+ if (fdata->frameless == 0 && fdata->nosavedpc == 0)
break;
if (op == 0x4e800020 /* blr */
struct value *arg = 0;
struct type *type;
- CORE_ADDR saved_sp;
+ ULONGEST saved_sp;
/* The calling convention this function implements assumes the
processor has floating-point registers. We shouldn't be using it
else
{
/* Argument can fit in one register. No problem. */
- int adj = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? reg_size - len : 0;
+ 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);
ran_out_of_registers_for_arguments:
- saved_sp = read_sp ();
+ regcache_cooked_read_unsigned (regcache,
+ gdbarch_sp_regnum (current_gdbarch),
+ &saved_sp);
/* Location for 8 parameters are always reserved. */
sp -= wordsize * 8;
to use this area. So, update %sp first before doing anything
else. */
- regcache_raw_write_signed (regcache, SP_REGNUM, sp);
+ 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. */
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, SP_REGNUM, sp);
+ regcache_raw_write_signed (regcache, gdbarch_sp_regnum (current_gdbarch), sp);
/* Set back chain properly. */
store_unsigned_integer (tmp_buffer, wordsize, saved_sp);
regcache_raw_write_signed (regcache, tdep->ppc_toc_regnum, tocvalue);
}
- target_store_registers (-1);
+ target_store_registers (regcache, -1);
return sp;
}
branches, meaning that the link register doesn't get set.
Therefore, GDB's usual step_over_function () mechanism won't work.
- Instead, use the IN_SOLIB_RETURN_TRAMPOLINE and
- SKIP_TRAMPOLINE_CODE hooks in handle_inferior_event() to skip past
+ Instead, use the gdbarch_skip_trampoline_code and
+ gdbarch_skip_trampoline_code hooks in handle_inferior_event() to skip past
@FIX code. */
int
code that should be skipped. */
CORE_ADDR
-rs6000_skip_trampoline_code (CORE_ADDR pc)
+rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
{
unsigned int ii, op;
int rel;
}
/* If pc is in a shared library trampoline, return its target. */
- solib_target_pc = find_solib_trampoline_target (pc);
+ solib_target_pc = find_solib_trampoline_target (frame, pc);
if (solib_target_pc)
return solib_target_pc;
if (op != trampoline_code[ii])
return 0;
}
- ii = read_register (11); /* r11 holds destination addr */
+ ii = get_frame_register_unsigned (frame, 11); /* r11 holds destination addr */
pc = read_memory_addr (ii, gdbarch_tdep (current_gdbarch)->wordsize); /* (r11) value */
return pc;
}
+/* ISA-specific vector types. */
+
+static struct type *
+rs6000_builtin_type_vec64 (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (!tdep->ppc_builtin_type_vec64)
+ {
+ /* The type we're building is this: */
+#if 0
+ union __gdb_builtin_type_vec64
+ {
+ int64_t uint64;
+ float v2_float[2];
+ int32_t v2_int32[2];
+ int16_t v4_int16[4];
+ int8_t v8_int8[8];
+ };
+#endif
+
+ struct type *t;
+
+ t = init_composite_type ("__ppc_builtin_type_vec64", TYPE_CODE_UNION);
+ append_composite_type_field (t, "uint64", builtin_type_int64);
+ append_composite_type_field (t, "v2_float",
+ init_vector_type (builtin_type_float, 2));
+ append_composite_type_field (t, "v2_int32",
+ init_vector_type (builtin_type_int32, 2));
+ append_composite_type_field (t, "v4_int16",
+ init_vector_type (builtin_type_int16, 4));
+ append_composite_type_field (t, "v8_int8",
+ init_vector_type (builtin_type_int8, 8));
+
+ TYPE_FLAGS (t) |= TYPE_FLAG_VECTOR;
+ TYPE_NAME (t) = "ppc_builtin_type_vec64";
+ tdep->ppc_builtin_type_vec64 = t;
+ }
+
+ return tdep->ppc_builtin_type_vec64;
+}
+
+static struct type *
+rs6000_builtin_type_vec128 (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (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
+
+ struct type *t;
+
+ t = init_composite_type ("__ppc_builtin_type_vec128", TYPE_CODE_UNION);
+ append_composite_type_field (t, "uint128", builtin_type_int128);
+ append_composite_type_field (t, "v4_float",
+ init_vector_type (builtin_type_float, 4));
+ append_composite_type_field (t, "v4_int32",
+ init_vector_type (builtin_type_int32, 4));
+ append_composite_type_field (t, "v8_int16",
+ init_vector_type (builtin_type_int16, 8));
+ append_composite_type_field (t, "v16_int8",
+ init_vector_type (builtin_type_int8, 16));
+
+ TYPE_FLAGS (t) |= TYPE_FLAG_VECTOR;
+ 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 builtin_type_uint32;
case 8:
if (tdep->ppc_ev0_regnum <= n && n <= tdep->ppc_ev31_regnum)
- return builtin_type_vec64;
+ return rs6000_builtin_type_vec64 (gdbarch);
else
return builtin_type_uint64;
break;
case 16:
- return builtin_type_vec128;
+ return rs6000_builtin_type_vec128 (gdbarch);
break;
default:
internal_error (__FILE__, __LINE__, _("Register %d size %d unknown"),
int vector_p;
int general_p;
- if (REGISTER_NAME (regnum) == NULL
- || *REGISTER_NAME (regnum) == '\0')
+ if (gdbarch_register_name (current_gdbarch, regnum) == NULL
+ || *gdbarch_register_name (current_gdbarch, regnum) == '\0')
return 0;
if (group == all_reggroup)
return 1;
|| regnum == tdep->ppc_lr_regnum
|| regnum == tdep->ppc_ctr_regnum
|| regnum == tdep->ppc_xer_regnum
- || regnum == PC_REGNUM);
+ || regnum == gdbarch_pc_regnum (current_gdbarch));
if (group == general_reggroup)
return general_p;
reg_index = ev_reg - tdep->ppc_ev0_regnum;
- if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+ if (gdbarch_byte_order (current_gdbarch) == 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);
else
switch (num)
{
+ case 64:
+ return tdep->ppc_cr_regnum;
case 67:
return tdep->ppc_vrsave_regnum - 1; /* vscr */
case 99:
}
}
-/* Hook called when a new child process is started. */
+/* Translate a .eh_frame register to DWARF register, or adjust a
+ .debug_frame register. */
-void
-rs6000_create_inferior (int pid)
-{
- if (rs6000_set_host_arch_hook)
- rs6000_set_host_arch_hook (pid);
+static int
+rs6000_adjust_frame_regnum (struct gdbarch *gdbarch, int num, int eh_frame_p)
+{
+ /* GCC releases before 3.4 use GCC internal register numbering in
+ .debug_frame (and .debug_info, et cetera). The numbering is
+ different from the standard SysV numbering for everything except
+ for GPRs and FPRs. We can not detect this problem in most cases
+ - to get accurate debug info for variables living in lr, ctr, v0,
+ et cetera, use a newer version of GCC. But we must detect
+ one important case - lr is in column 65 in .debug_frame output,
+ instead of 108.
+
+ GCC 3.4, and the "hammer" branch, have a related problem. They
+ record lr register saves in .debug_frame as 108, but still record
+ the return column as 65. We fix that up too.
+
+ We can do this because 65 is assigned to fpsr, and GCC never
+ generates debug info referring to it. To add support for
+ handwritten debug info that restores fpsr, we would need to add a
+ producer version check to this. */
+ if (!eh_frame_p)
+ {
+ if (num == 65)
+ return 108;
+ else
+ return num;
+ }
+
+ /* .eh_frame is GCC specific. For binary compatibility, it uses GCC
+ internal register numbering; translate that to the standard DWARF2
+ register numbering. */
+ if (0 <= num && num <= 63) /* r0-r31,fp0-fp31 */
+ return num;
+ else if (68 <= num && num <= 75) /* cr0-cr8 */
+ return num - 68 + 86;
+ else if (77 <= num && num <= 108) /* vr0-vr31 */
+ return num - 77 + 1124;
+ else
+ switch (num)
+ {
+ case 64: /* mq */
+ return 100;
+ case 65: /* lr */
+ return 108;
+ case 66: /* ctr */
+ return 109;
+ case 76: /* xer */
+ return 101;
+ case 109: /* vrsave */
+ return 356;
+ case 110: /* vscr */
+ return 67;
+ case 111: /* spe_acc */
+ return 99;
+ case 112: /* spefscr */
+ return 612;
+ default:
+ return num;
+ }
}
\f
/* Support for CONVERT_FROM_FUNC_PTR_ADDR (ARCH, ADDR, TARG).
return addr;
/* ADDR is in the data space, so it's a special function pointer. */
- return read_memory_addr (addr, gdbarch_tdep (current_gdbarch)->wordsize);
+ return read_memory_addr (addr, gdbarch_tdep (gdbarch)->wordsize);
}
\f
static int
gdb_print_insn_powerpc (bfd_vma memaddr, disassemble_info *info)
{
- if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+ if (!info->disassembler_options)
+ info->disassembler_options = "any";
+
+ if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
return print_insn_big_powerpc (memaddr, info);
else
return print_insn_little_powerpc (memaddr, info);
static CORE_ADDR
rs6000_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
- return frame_unwind_register_unsigned (next_frame, PC_REGNUM);
+ return frame_unwind_register_unsigned (next_frame,
+ gdbarch_pc_regnum (current_gdbarch));
}
static struct frame_id
rs6000_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
- return frame_id_build (frame_unwind_register_unsigned (next_frame,
- SP_REGNUM),
- frame_pc_unwind (next_frame));
+ return frame_id_build (frame_unwind_register_unsigned
+ (next_frame, gdbarch_sp_regnum (current_gdbarch)),
+ frame_pc_unwind (next_frame));
}
struct rs6000_frame_cache
(*this_cache) = cache;
cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
- func = frame_func_unwind (next_frame);
+ func = frame_func_unwind (next_frame, NORMAL_FRAME);
pc = frame_pc_unwind (next_frame);
skip_prologue (func, pc, &fdata);
->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, SP_REGNUM);
+ cache->base = frame_unwind_register_unsigned
+ (next_frame, gdbarch_sp_regnum (current_gdbarch));
/* If the function appears to be frameless, check a couple of likely
indicators that we have simply failed to find the frame setup.
if (make_frame)
{
fdata.frameless = 0;
- fdata.lr_offset = wordsize;
+ fdata.lr_offset = tdep->lr_frame_offset;
}
}
/* Frameless really means stackless. */
cache->base = read_memory_addr (cache->base, wordsize);
- trad_frame_set_value (cache->saved_regs, SP_REGNUM, cache->base);
+ trad_frame_set_value (cache->saved_regs,
+ gdbarch_sp_regnum (current_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 (fdata.lr_offset != 0)
cache->saved_regs[tdep->ppc_lr_regnum].addr = cache->base + fdata.lr_offset;
/* The PC is found in the link register. */
- cache->saved_regs[PC_REGNUM] = cache->saved_regs[tdep->ppc_lr_regnum];
+ cache->saved_regs[gdbarch_pc_regnum (current_gdbarch)] =
+ cache->saved_regs[tdep->ppc_lr_regnum];
/* If != 0, fdata.vrsave_offset is the offset from the frame that
holds the VRSAVE. */
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, SP_REGNUM);
+ cache->initial_sp = frame_unwind_register_unsigned
+ (next_frame, gdbarch_sp_regnum (current_gdbarch));
else
cache->initial_sp = frame_unwind_register_unsigned (next_frame,
fdata.alloca_reg);
{
struct rs6000_frame_cache *info = rs6000_frame_cache (next_frame,
this_cache);
- (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame));
+ (*this_id) = frame_id_build (info->base,
+ frame_func_unwind (next_frame, NORMAL_FRAME));
}
static void
info.bfd_arch_info = bfd_get_arch_info (&abfd);
mach = info.bfd_arch_info->mach;
}
- tdep = xmalloc (sizeof (struct gdbarch_tdep));
+ tdep = XCALLOC (1, struct gdbarch_tdep);
tdep->wordsize = wordsize;
/* For e500 executables, the apuinfo section is of help here. Such
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);
set_gdbarch_register_sim_regno (gdbarch, rs6000_register_sim_regno);
if (sysv_abi && wordsize == 8)
set_gdbarch_return_value (gdbarch, ppc64_sysv_abi_return_value);
else
set_gdbarch_print_insn (gdbarch, gdb_print_insn_powerpc);
- set_gdbarch_write_pc (gdbarch, generic_target_write_pc);
-
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_inner_than (gdbarch, core_addr_lessthan);
set_gdbarch_breakpoint_from_pc (gdbarch, rs6000_breakpoint_from_pc);
+ /* Handles single stepping of atomic sequences. */
+ set_gdbarch_software_single_step (gdbarch, 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
/* Helpers for function argument information. */
set_gdbarch_fetch_pointer_argument (gdbarch, rs6000_fetch_pointer_argument);
+ /* Trampoline. */
+ set_gdbarch_in_solib_return_trampoline
+ (gdbarch, rs6000_in_solib_return_trampoline);
+ 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_frame_set_adjust_regnum (gdbarch, rs6000_adjust_frame_regnum);
+
/* Hook in ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch);