X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Frs6000-tdep.c;h=1add49897f8b04fa51241153febb63b96ea9b31d;hb=90681dabc79316d382aae5e932303f61bd705b16;hp=62ec07feddc4e9bcafd52fabf3693d480472956d;hpb=0b30217134add051e159a192066a1e568ebd837f;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index 62ec07fedd..1add49897f 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -1,7 +1,6 @@ /* Target-dependent code for GDB, the GNU debugger. - Copyright (C) 1986-1987, 1989, 1991-2012 Free Software Foundation, - Inc. + Copyright (C) 1986-2016 Free Software Foundation, Inc. This file is part of GDB. @@ -21,6 +20,7 @@ #include "defs.h" #include "frame.h" #include "inferior.h" +#include "infrun.h" #include "symtab.h" #include "target.h" #include "gdbcore.h" @@ -40,8 +40,9 @@ #include "dwarf2-frame.h" #include "target-descriptions.h" #include "user-regs.h" +#include "record-full.h" +#include "auxv.h" -#include "libbfd.h" /* for bfd_default_set_arch_mach */ #include "coff/internal.h" /* for libcoff.h */ #include "libcoff.h" /* for xcoff_data */ #include "coff/xcoff.h" @@ -49,17 +50,22 @@ #include "elf-bfd.h" #include "elf/ppc.h" +#include "elf/ppc64.h" #include "solib-svr4.h" #include "ppc-tdep.h" +#include "ppc-ravenscar-thread.h" -#include "gdb_assert.h" #include "dis-asm.h" #include "trad-frame.h" #include "frame-unwind.h" #include "frame-base.h" +#include "ax.h" +#include "ax-gdb.h" +#include + #include "features/rs6000/powerpc-32.c" #include "features/rs6000/powerpc-altivec32.c" #include "features/rs6000/powerpc-vsx32.c" @@ -108,7 +114,7 @@ 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[] = +static const char *const powerpc_vector_strings[] = { "auto", "generic", @@ -325,7 +331,7 @@ init_sim_regno_table (struct gdbarch *arch) 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 +#ifdef WITH_PPC_SIM /* Now handle all special-purpose registers. Verify that they haven't mistakenly been assigned numbers by any of the above code. */ @@ -504,7 +510,8 @@ ppc_supply_gregset (const struct regset *regset, struct regcache *regcache, { struct gdbarch *gdbarch = get_regcache_arch (regcache); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - const struct ppc_reg_offsets *offsets = regset->descr; + const struct ppc_reg_offsets *offsets + = (const struct ppc_reg_offsets *) regset->regmap; size_t offset; int regsize; @@ -516,27 +523,31 @@ ppc_supply_gregset (const struct regset *regset, struct regcache *regcache, for (i = tdep->ppc_gp0_regnum, offset = offsets->r0_offset; i < tdep->ppc_gp0_regnum + ppc_num_gprs; i++, offset += gpr_size) - ppc_supply_reg (regcache, i, gregs, offset, gpr_size); + ppc_supply_reg (regcache, i, (const gdb_byte *) gregs, offset, + gpr_size); ppc_supply_reg (regcache, gdbarch_pc_regnum (gdbarch), - gregs, offsets->pc_offset, gpr_size); + (const gdb_byte *) gregs, offsets->pc_offset, gpr_size); ppc_supply_reg (regcache, tdep->ppc_ps_regnum, - gregs, offsets->ps_offset, gpr_size); + (const gdb_byte *) gregs, offsets->ps_offset, gpr_size); ppc_supply_reg (regcache, tdep->ppc_lr_regnum, - gregs, offsets->lr_offset, gpr_size); + (const gdb_byte *) gregs, offsets->lr_offset, gpr_size); ppc_supply_reg (regcache, tdep->ppc_ctr_regnum, - gregs, offsets->ctr_offset, gpr_size); + (const gdb_byte *) gregs, offsets->ctr_offset, gpr_size); ppc_supply_reg (regcache, tdep->ppc_cr_regnum, - gregs, offsets->cr_offset, offsets->xr_size); + (const gdb_byte *) gregs, offsets->cr_offset, + offsets->xr_size); ppc_supply_reg (regcache, tdep->ppc_xer_regnum, - gregs, offsets->xer_offset, offsets->xr_size); + (const gdb_byte *) gregs, offsets->xer_offset, + offsets->xr_size); ppc_supply_reg (regcache, tdep->ppc_mq_regnum, - gregs, offsets->mq_offset, offsets->xr_size); + (const gdb_byte *) gregs, offsets->mq_offset, + offsets->xr_size); return; } offset = ppc_greg_offset (gdbarch, tdep, offsets, regnum, ®size); - ppc_supply_reg (regcache, regnum, gregs, offset, regsize); + ppc_supply_reg (regcache, regnum, (const gdb_byte *) gregs, offset, regsize); } /* Supply register REGNUM in the floating-point register set REGSET @@ -556,7 +567,7 @@ ppc_supply_fpregset (const struct regset *regset, struct regcache *regcache, return; tdep = gdbarch_tdep (gdbarch); - offsets = regset->descr; + offsets = (const struct ppc_reg_offsets *) regset->regmap; if (regnum == -1) { int i; @@ -564,15 +575,16 @@ ppc_supply_fpregset (const struct regset *regset, struct regcache *regcache, for (i = tdep->ppc_fp0_regnum, offset = offsets->f0_offset; i < tdep->ppc_fp0_regnum + ppc_num_fprs; i++, offset += 8) - ppc_supply_reg (regcache, i, fpregs, offset, 8); + ppc_supply_reg (regcache, i, (const gdb_byte *) fpregs, offset, 8); ppc_supply_reg (regcache, tdep->ppc_fpscr_regnum, - fpregs, offsets->fpscr_offset, offsets->fpscr_size); + (const gdb_byte *) fpregs, offsets->fpscr_offset, + offsets->fpscr_size); return; } offset = ppc_fpreg_offset (tdep, offsets, regnum); - ppc_supply_reg (regcache, regnum, fpregs, offset, + ppc_supply_reg (regcache, regnum, (const gdb_byte *) fpregs, offset, regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8); } @@ -599,12 +611,12 @@ ppc_supply_vsxregset (const struct regset *regset, struct regcache *regcache, for (i = tdep->ppc_vsr0_upper_regnum; i < tdep->ppc_vsr0_upper_regnum + 32; i++) - ppc_supply_reg (regcache, i, vsxregs, 0, 8); + ppc_supply_reg (regcache, i, (const gdb_byte *) vsxregs, 0, 8); return; } else - ppc_supply_reg (regcache, regnum, vsxregs, 0, 8); + ppc_supply_reg (regcache, regnum, (const gdb_byte *) vsxregs, 0, 8); } /* Supply register REGNUM in the Altivec register set REGSET @@ -624,7 +636,7 @@ ppc_supply_vrregset (const struct regset *regset, struct regcache *regcache, return; tdep = gdbarch_tdep (gdbarch); - offsets = regset->descr; + offsets = (const struct ppc_reg_offsets *) regset->regmap; if (regnum == -1) { int i; @@ -632,23 +644,23 @@ ppc_supply_vrregset (const struct regset *regset, struct regcache *regcache, 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, i, (const gdb_byte *) vrregs, offset, 16); ppc_supply_reg (regcache, (tdep->ppc_vrsave_regnum - 1), - vrregs, offsets->vscr_offset, 4); + (const gdb_byte *) vrregs, offsets->vscr_offset, 4); ppc_supply_reg (regcache, tdep->ppc_vrsave_regnum, - vrregs, offsets->vrsave_offset, 4); + (const gdb_byte *) 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); + ppc_supply_reg (regcache, regnum, (const gdb_byte *) vrregs, offset, 16); else ppc_supply_reg (regcache, regnum, - vrregs, offset, 4); + (const gdb_byte *) vrregs, offset, 4); } /* Collect register REGNUM in the general-purpose register set @@ -663,7 +675,8 @@ ppc_collect_gregset (const struct regset *regset, { struct gdbarch *gdbarch = get_regcache_arch (regcache); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - const struct ppc_reg_offsets *offsets = regset->descr; + const struct ppc_reg_offsets *offsets + = (const struct ppc_reg_offsets *) regset->regmap; size_t offset; int regsize; @@ -675,27 +688,30 @@ ppc_collect_gregset (const struct regset *regset, for (i = tdep->ppc_gp0_regnum, offset = offsets->r0_offset; i < tdep->ppc_gp0_regnum + ppc_num_gprs; i++, offset += gpr_size) - ppc_collect_reg (regcache, i, gregs, offset, gpr_size); + ppc_collect_reg (regcache, i, (gdb_byte *) gregs, offset, gpr_size); ppc_collect_reg (regcache, gdbarch_pc_regnum (gdbarch), - gregs, offsets->pc_offset, gpr_size); + (gdb_byte *) gregs, offsets->pc_offset, gpr_size); ppc_collect_reg (regcache, tdep->ppc_ps_regnum, - gregs, offsets->ps_offset, gpr_size); + (gdb_byte *) gregs, offsets->ps_offset, gpr_size); ppc_collect_reg (regcache, tdep->ppc_lr_regnum, - gregs, offsets->lr_offset, gpr_size); + (gdb_byte *) gregs, offsets->lr_offset, gpr_size); ppc_collect_reg (regcache, tdep->ppc_ctr_regnum, - gregs, offsets->ctr_offset, gpr_size); + (gdb_byte *) gregs, offsets->ctr_offset, gpr_size); ppc_collect_reg (regcache, tdep->ppc_cr_regnum, - gregs, offsets->cr_offset, offsets->xr_size); + (gdb_byte *) gregs, offsets->cr_offset, + offsets->xr_size); ppc_collect_reg (regcache, tdep->ppc_xer_regnum, - gregs, offsets->xer_offset, offsets->xr_size); + (gdb_byte *) gregs, offsets->xer_offset, + offsets->xr_size); ppc_collect_reg (regcache, tdep->ppc_mq_regnum, - gregs, offsets->mq_offset, offsets->xr_size); + (gdb_byte *) gregs, offsets->mq_offset, + offsets->xr_size); return; } offset = ppc_greg_offset (gdbarch, tdep, offsets, regnum, ®size); - ppc_collect_reg (regcache, regnum, gregs, offset, regsize); + ppc_collect_reg (regcache, regnum, (gdb_byte *) gregs, offset, regsize); } /* Collect register REGNUM in the floating-point register set @@ -717,7 +733,7 @@ ppc_collect_fpregset (const struct regset *regset, return; tdep = gdbarch_tdep (gdbarch); - offsets = regset->descr; + offsets = (const struct ppc_reg_offsets *) regset->regmap; if (regnum == -1) { int i; @@ -725,15 +741,16 @@ ppc_collect_fpregset (const struct regset *regset, for (i = tdep->ppc_fp0_regnum, offset = offsets->f0_offset; i < tdep->ppc_fp0_regnum + ppc_num_fprs; i++, offset += 8) - ppc_collect_reg (regcache, i, fpregs, offset, 8); + ppc_collect_reg (regcache, i, (gdb_byte *) fpregs, offset, 8); ppc_collect_reg (regcache, tdep->ppc_fpscr_regnum, - fpregs, offsets->fpscr_offset, offsets->fpscr_size); + (gdb_byte *) fpregs, offsets->fpscr_offset, + offsets->fpscr_size); return; } offset = ppc_fpreg_offset (tdep, offsets, regnum); - ppc_collect_reg (regcache, regnum, fpregs, offset, + ppc_collect_reg (regcache, regnum, (gdb_byte *) fpregs, offset, regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8); } @@ -762,12 +779,12 @@ ppc_collect_vsxregset (const struct regset *regset, for (i = tdep->ppc_vsr0_upper_regnum; i < tdep->ppc_vsr0_upper_regnum + 32; i++) - ppc_collect_reg (regcache, i, vsxregs, 0, 8); + ppc_collect_reg (regcache, i, (gdb_byte *) vsxregs, 0, 8); return; } else - ppc_collect_reg (regcache, regnum, vsxregs, 0, 8); + ppc_collect_reg (regcache, regnum, (gdb_byte *) vsxregs, 0, 8); } @@ -790,7 +807,7 @@ ppc_collect_vrregset (const struct regset *regset, return; tdep = gdbarch_tdep (gdbarch); - offsets = regset->descr; + offsets = (const struct ppc_reg_offsets *) regset->regmap; if (regnum == -1) { int i; @@ -798,23 +815,23 @@ ppc_collect_vrregset (const struct regset *regset, 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); + ppc_collect_reg (regcache, i, (gdb_byte *) vrregs, offset, 16); ppc_collect_reg (regcache, (tdep->ppc_vrsave_regnum - 1), - vrregs, offsets->vscr_offset, 4); + (gdb_byte *) vrregs, offsets->vscr_offset, 4); ppc_collect_reg (regcache, tdep->ppc_vrsave_regnum, - vrregs, offsets->vrsave_offset, 4); + (gdb_byte *) 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); + ppc_collect_reg (regcache, regnum, (gdb_byte *) vrregs, offset, 16); else ppc_collect_reg (regcache, regnum, - vrregs, offset, 4); + (gdb_byte *) vrregs, offset, 4); } @@ -871,14 +888,14 @@ insn_changes_sp_or_jumps (unsigned long insn) limit for the size of an epilogue. */ static int -rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) +rs6000_in_function_epilogue_frame_p (struct frame_info *curfrm, + 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; - struct frame_info *curfrm; /* Find the search limits based on function boundaries and hard limit. */ @@ -891,8 +908,6 @@ rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) epilogue_end = pc + PPC_MAX_EPILOGUE_INSTRUCTIONS * PPC_INSN_SIZE; if (epilogue_end > func_end) epilogue_end = func_end; - curfrm = get_current_frame (); - /* Scan forward until next 'blr'. */ for (scan_pc = pc; scan_pc < epilogue_end; scan_pc += PPC_INSN_SIZE) @@ -933,6 +948,15 @@ rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) return 0; } +/* Implement the stack_frame_destroyed_p gdbarch method. */ + +static int +rs6000_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + return rs6000_in_function_epilogue_frame_p (get_current_frame (), + gdbarch, pc); +} + /* Get the ith function argument for the current function. */ static CORE_ADDR rs6000_fetch_pointer_argument (struct frame_info *frame, int argi, @@ -943,7 +967,7 @@ rs6000_fetch_pointer_argument (struct frame_info *frame, int argi, /* Sequence of bytes for breakpoint instruction. */ -const static unsigned char * +static const unsigned char * rs6000_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr, int *bp_size) { @@ -964,6 +988,61 @@ rs6000_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr, #define BXL_INSN 0x4c000000 #define BP_INSN 0x7C000008 +/* Instruction masks used during single-stepping of atomic + sequences. */ +#define LWARX_MASK 0xfc0007fe +#define LWARX_INSTRUCTION 0x7c000028 +#define LDARX_INSTRUCTION 0x7c0000A8 +#define STWCX_MASK 0xfc0007ff +#define STWCX_INSTRUCTION 0x7c00012d +#define STDCX_INSTRUCTION 0x7c0001ad + +/* We can't displaced step atomic sequences. Otherwise this is just + like simple_displaced_step_copy_insn. */ + +static struct displaced_step_closure * +ppc_displaced_step_copy_insn (struct gdbarch *gdbarch, + CORE_ADDR from, CORE_ADDR to, + struct regcache *regs) +{ + size_t len = gdbarch_max_insn_length (gdbarch); + gdb_byte *buf = (gdb_byte *) xmalloc (len); + struct cleanup *old_chain = make_cleanup (xfree, buf); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + int insn; + + read_memory (from, buf, len); + + insn = extract_signed_integer (buf, PPC_INSN_SIZE, byte_order); + + /* Assume all atomic sequences start with a lwarx/ldarx instruction. */ + if ((insn & LWARX_MASK) == LWARX_INSTRUCTION + || (insn & LWARX_MASK) == LDARX_INSTRUCTION) + { + if (debug_displaced) + { + fprintf_unfiltered (gdb_stdlog, + "displaced: can't displaced step " + "atomic sequence at %s\n", + paddress (gdbarch, from)); + } + do_cleanups (old_chain); + return NULL; + } + + write_memory (to, buf, len); + + if (debug_displaced) + { + fprintf_unfiltered (gdb_stdlog, "displaced: copy %s->%s: ", + paddress (gdbarch, from), paddress (gdbarch, to)); + displaced_step_dump_bytes (gdb_stdlog, buf, len); + } + + discard_cleanups (old_chain); + return (struct displaced_step_closure *) buf; +} + /* Fix up the state of registers and memory after having single-stepped a displaced instruction. */ static void @@ -973,8 +1052,7 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch, struct regcache *regs) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - /* Since we use simple_displaced_step_copy_insn, our closure is a - copy of the instruction. */ + /* Our closure is a copy of the instruction. */ ULONGEST insn = extract_unsigned_integer ((gdb_byte *) closure, PPC_INSN_SIZE, byte_order); ULONGEST opcode = 0; @@ -1067,14 +1145,6 @@ ppc_displaced_step_hw_singlestep (struct gdbarch *gdbarch, return 1; } -/* Instruction masks used during single-stepping of atomic sequences. */ -#define LWARX_MASK 0xfc0007fe -#define LWARX_INSTRUCTION 0x7c000028 -#define LDARX_INSTRUCTION 0x7c0000A8 -#define STWCX_MASK 0xfc0007ff -#define STWCX_INSTRUCTION 0x7c00012d -#define STDCX_INSTRUCTION 0x7c0001ad - /* Checks for an atomic sequence of instructions beginning with a LWARX/LDARX instruction and ending with a STWCX/STDCX instruction. If such a sequence is found, attempt to step through it. A breakpoint is placed at the end of @@ -1095,7 +1165,6 @@ ppc_deal_with_atomic_sequence (struct frame_info *frame) 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. */ @@ -1616,7 +1685,19 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, continue; } - else if ((op & 0xffff0000) == 0x60000000) + else if ((op & 0xffff0000) == 0x3c4c0000 + || (op & 0xffff0000) == 0x3c400000 + || (op & 0xffff0000) == 0x38420000) + { + /* . 0: addis 2,12,.TOC.-0b@ha + . addi 2,2,.TOC.-0b@l + or + . lis 2,.TOC.@ha + . addi 2,2,.TOC.@l + used by ELFv2 global entry points to set up r2. */ + continue; + } + else if (op == 0x60000000) { /* nop */ /* Allow nops in the prologue, but do not consider them to @@ -1627,8 +1708,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, } else if ((op & 0xffff0000) == 0x3c000000) - { /* addis 0,0,NUM, used - for >= 32k frames */ + { /* addis 0,0,NUM, used for >= 32k frames */ fdata->offset = (op & 0x0000ffff) << 16; fdata->frameless = 0; r0_contains_arg = 0; @@ -1636,8 +1716,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, } else if ((op & 0xffff0000) == 0x60000000) - { /* ori 0,0,NUM, 2nd ha - lf of >= 32k frames */ + { /* ori 0,0,NUM, 2nd half of >= 32k frames */ fdata->offset |= (op & 0x0000ffff); fdata->frameless = 0; r0_contains_arg = 0; @@ -1822,6 +1901,15 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, /* 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 */ @@ -2098,7 +2186,7 @@ rs6000_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) CORE_ADDR post_prologue_pc = skip_prologue_using_sal (gdbarch, func_addr); if (post_prologue_pc != 0) - return max (pc, post_prologue_pc); + return std::max (pc, post_prologue_pc); } /* Can't determine prologue from the symbol table, need to examine @@ -2143,15 +2231,15 @@ rs6000_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) { 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); + struct bound_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)) + if (s.minsym != NULL + && MSYMBOL_LINKAGE_NAME (s.minsym) != NULL + && (strcmp (MSYMBOL_LINKAGE_NAME (s.minsym), "__eabi") == 0 + || strcmp (MSYMBOL_LINKAGE_NAME (s.minsym), "___eabi") == 0)) pc += 4; } return pc; @@ -2189,9 +2277,9 @@ rs6000_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr) static int rs6000_in_solib_return_trampoline (struct gdbarch *gdbarch, - CORE_ADDR pc, char *name) + CORE_ADDR pc, const char *name) { - return name && !strncmp (name, "@FIX", 4); + return name && startswith (name, "@FIX"); } /* Skip code that the user doesn't want to see when stepping: @@ -2217,7 +2305,7 @@ 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; + struct bound_minimal_symbol msymbol; static unsigned trampoline_code[] = { @@ -2233,9 +2321,9 @@ rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc) /* Check for bigtoc fixup code. */ msymbol = lookup_minimal_symbol_by_pc (pc); - if (msymbol + if (msymbol.minsym && rs6000_in_solib_return_trampoline (gdbarch, pc, - SYMBOL_LINKAGE_NAME (msymbol))) + MSYMBOL_LINKAGE_NAME (msymbol.minsym))) { /* Double-check that the third instruction from PC is relative "b". */ op = read_memory_integer (pc + 8, 4, byte_order); @@ -2577,7 +2665,7 @@ e500_move_ev_register (move_ev_register_func move, struct gdbarch *arch = get_regcache_arch (regcache); struct gdbarch_tdep *tdep = gdbarch_tdep (arch); int reg_index; - gdb_byte *byte_buffer = buffer; + gdb_byte *byte_buffer = (gdb_byte *) buffer; enum register_status status; gdb_assert (IS_SPE_PSEUDOREG (tdep, ev_reg)); @@ -2606,13 +2694,13 @@ e500_move_ev_register (move_ev_register_func move, static enum register_status do_regcache_raw_read (struct regcache *regcache, int regnum, void *buffer) { - return regcache_raw_read (regcache, regnum, buffer); + return regcache_raw_read (regcache, regnum, (gdb_byte *) buffer); } static enum register_status do_regcache_raw_write (struct regcache *regcache, int regnum, void *buffer) { - regcache_raw_write (regcache, regnum, buffer); + regcache_raw_write (regcache, regnum, (const gdb_byte *) buffer); return REG_VALID; } @@ -2653,10 +2741,10 @@ dfp_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, else { status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum + - 2 * reg_index + 1, buffer + 8); + 2 * reg_index + 1, buffer); if (status == REG_VALID) status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum + - 2 * reg_index, buffer); + 2 * reg_index, buffer + 8); } return status; @@ -2682,9 +2770,9 @@ dfp_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, else { regcache_raw_write (regcache, tdep->ppc_fp0_regnum + - 2 * reg_index + 1, buffer + 8); + 2 * reg_index + 1, buffer); regcache_raw_write (regcache, tdep->ppc_fp0_regnum + - 2 * reg_index, buffer); + 2 * reg_index, buffer + 8); } } @@ -2760,10 +2848,12 @@ efpr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int reg_index = reg_nr - tdep->ppc_efpr0_regnum; + int offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8; /* 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); + return regcache_raw_read_part (regcache, tdep->ppc_vr0_regnum + reg_index, + offset, register_size (gdbarch, reg_nr), + buffer); } /* Write method for POWER7 Extended FP pseudo-registers. */ @@ -2773,10 +2863,12 @@ efpr_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int reg_index = reg_nr - tdep->ppc_efpr0_regnum; + int offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8; /* 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); + regcache_raw_write_part (regcache, tdep->ppc_vr0_regnum + reg_index, + offset, register_size (gdbarch, reg_nr), + buffer); } static enum register_status @@ -2829,6 +2921,62 @@ rs6000_pseudo_register_write (struct gdbarch *gdbarch, gdbarch_register_name (gdbarch, reg_nr), reg_nr); } +static int +rs6000_ax_pseudo_register_collect (struct gdbarch *gdbarch, + struct agent_expr *ax, int reg_nr) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + if (IS_SPE_PSEUDOREG (tdep, reg_nr)) + { + int reg_index = reg_nr - tdep->ppc_ev0_regnum; + ax_reg_mask (ax, tdep->ppc_gp0_regnum + reg_index); + ax_reg_mask (ax, tdep->ppc_ev0_upper_regnum + reg_index); + } + else if (IS_DFP_PSEUDOREG (tdep, reg_nr)) + { + int reg_index = reg_nr - tdep->ppc_dl0_regnum; + ax_reg_mask (ax, tdep->ppc_fp0_regnum + 2 * reg_index); + ax_reg_mask (ax, tdep->ppc_fp0_regnum + 2 * reg_index + 1); + } + else if (IS_VSX_PSEUDOREG (tdep, reg_nr)) + { + int reg_index = reg_nr - tdep->ppc_vsr0_regnum; + if (reg_index > 31) + { + ax_reg_mask (ax, tdep->ppc_vr0_regnum + reg_index - 32); + } + else + { + ax_reg_mask (ax, tdep->ppc_fp0_regnum + reg_index); + ax_reg_mask (ax, tdep->ppc_vsr0_upper_regnum + reg_index); + } + } + else if (IS_EFP_PSEUDOREG (tdep, reg_nr)) + { + int reg_index = reg_nr - tdep->ppc_efpr0_regnum; + ax_reg_mask (ax, tdep->ppc_vr0_regnum + reg_index); + } + else + internal_error (__FILE__, __LINE__, + _("rs6000_pseudo_register_collect: " + "called on unexpected register '%s' (%d)"), + gdbarch_register_name (gdbarch, reg_nr), reg_nr); + return 0; +} + + +static void +rs6000_gen_return_address (struct gdbarch *gdbarch, + struct agent_expr *ax, struct axs_value *value, + CORE_ADDR scope) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + value->type = register_type (gdbarch, tdep->ppc_lr_regnum); + value->kind = axs_lvalue_register; + value->u.reg = tdep->ppc_lr_regnum; +} + + /* Convert a DBX STABS register number to a GDB register number. */ static int rs6000_stab_reg_to_regnum (struct gdbarch *gdbarch, int num) @@ -2845,7 +2993,7 @@ rs6000_stab_reg_to_regnum (struct gdbarch *gdbarch, int num) else if (77 <= num && num <= 108) return tdep->ppc_vr0_regnum + (num - 77); else if (1200 <= num && num < 1200 + 32) - return tdep->ppc_ev0_regnum + (num - 1200); + return tdep->ppc_ev0_upper_regnum + (num - 1200); else switch (num) { @@ -2887,7 +3035,7 @@ rs6000_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int num) else if (1124 <= num && num < 1124 + 32) return tdep->ppc_vr0_regnum + (num - 1124); else if (1200 <= num && num < 1200 + 32) - return tdep->ppc_ev0_regnum + (num - 1200); + return tdep->ppc_ev0_upper_regnum + (num - 1200); else switch (num) { @@ -3054,7 +3202,7 @@ static struct variant variants[] = {"rs2", "IBM POWER RS2", bfd_arch_rs6000, bfd_mach_rs6k_rs2, &tdesc_rs6000}, - {0, 0, 0, 0, 0} + {0, 0, (enum bfd_architecture) 0, 0, 0} }; /* Return the variant corresponding to architecture ARCH and machine number @@ -3075,21 +3223,6 @@ find_variant_by_arch (enum bfd_architecture arch, unsigned long mach) static int gdb_print_insn_powerpc (bfd_vma memaddr, disassemble_info *info) { - if (!info->disassembler_options) - { - /* When debugging E500 binaries and disassembling code containing - E500-specific (SPE) instructions, one sometimes sees AltiVec - instructions instead. The opcode spaces for SPE instructions - and AltiVec instructions overlap, and specifiying the "any" cpu - looks for AltiVec instructions first. If we know we're - debugging an E500 binary, however, we can specify the "e500x2" - cpu and get much more sane disassembly output. */ - if (info->mach == bfd_mach_ppc_e500) - info->disassembler_options = "e500x2"; - else - info->disassembler_options = "any"; - } - if (info->endian == BFD_ENDIAN_BIG) return print_insn_big_powerpc (memaddr, info); else @@ -3116,6 +3249,13 @@ struct rs6000_frame_cache CORE_ADDR base; CORE_ADDR initial_sp; struct trad_frame_saved_reg *saved_regs; + + /* Set BASE_P to true if this frame cache is properly initialized. + Otherwise set to false because some registers or memory cannot + collected. */ + int base_p; + /* Cache PC for building unavailable frame. */ + CORE_ADDR pc; }; static struct rs6000_frame_cache * @@ -3127,27 +3267,39 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache) enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); struct rs6000_framedata fdata; int wordsize = tdep->wordsize; - CORE_ADDR func, pc; + CORE_ADDR func = 0, pc = 0; if ((*this_cache) != NULL) - return (*this_cache); + return (struct rs6000_frame_cache *) (*this_cache); cache = FRAME_OBSTACK_ZALLOC (struct rs6000_frame_cache); (*this_cache) = cache; + cache->pc = 0; cache->saved_regs = trad_frame_alloc_saved_regs (this_frame); - 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. */ - - /* NOTE: cagney/2002-04-14: The ->frame points to the inner-most - address of the current frame. Things might be easier if the - ->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 = get_frame_register_unsigned - (this_frame, gdbarch_sp_regnum (gdbarch)); + TRY + { + func = get_frame_func (this_frame); + cache->pc = func; + pc = get_frame_pc (this_frame); + skip_prologue (gdbarch, func, pc, &fdata); + + /* Figure out the parent's stack pointer. */ + + /* NOTE: cagney/2002-04-14: The ->frame points to the inner-most + address of the current frame. Things might be easier if the + ->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 = get_frame_register_unsigned + (this_frame, gdbarch_sp_regnum (gdbarch)); + } + CATCH (ex, RETURN_MASK_ERROR) + { + if (ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); + return (struct rs6000_frame_cache *) (*this_cache); + } + END_CATCH /* If the function appears to be frameless, check a couple of likely indicators that we have simply failed to find the frame setup. @@ -3181,9 +3333,14 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache) } if (!fdata.frameless) - /* Frameless really means stackless. */ - cache->base - = read_memory_unsigned_integer (cache->base, wordsize, byte_order); + { + /* Frameless really means stackless. */ + ULONGEST backchain; + + if (safe_read_memory_unsigned_integer (cache->base, wordsize, + byte_order, &backchain)) + cache->base = (CORE_ADDR) backchain; + } trad_frame_set_value (cache->saved_regs, gdbarch_sp_regnum (gdbarch), cache->base); @@ -3248,12 +3405,14 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache) { int i; CORE_ADDR ev_addr = cache->base + fdata.ev_offset; + CORE_ADDR off = (byte_order == BFD_ENDIAN_BIG ? 4 : 0); + for (i = fdata.saved_ev; i < ppc_num_gprs; i++) { cache->saved_regs[tdep->ppc_ev0_regnum + i].addr = ev_addr; - cache->saved_regs[tdep->ppc_gp0_regnum + i].addr = ev_addr + 4; + cache->saved_regs[tdep->ppc_gp0_regnum + i].addr = ev_addr + off; ev_addr += register_size (gdbarch, tdep->ppc_ev0_regnum); - } + } } } @@ -3289,6 +3448,7 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache) cache->initial_sp = get_frame_register_unsigned (this_frame, fdata.alloca_reg); + cache->base_p = 1; return cache; } @@ -3298,6 +3458,13 @@ rs6000_frame_this_id (struct frame_info *this_frame, void **this_cache, { struct rs6000_frame_cache *info = rs6000_frame_cache (this_frame, this_cache); + + if (!info->base_p) + { + (*this_id) = frame_id_build_unavailable_stack (info->pc); + return; + } + /* This marks the outermost frame. */ if (info->base == 0) return; @@ -3323,6 +3490,106 @@ static const struct frame_unwind rs6000_frame_unwind = NULL, default_frame_sniffer }; + +/* Allocate and initialize a frame cache for an epilogue frame. + SP is restored and prev-PC is stored in LR. */ + +static struct rs6000_frame_cache * +rs6000_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache) +{ + struct rs6000_frame_cache *cache; + struct gdbarch *gdbarch = get_frame_arch (this_frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + if (*this_cache) + return (struct rs6000_frame_cache *) *this_cache; + + cache = FRAME_OBSTACK_ZALLOC (struct rs6000_frame_cache); + (*this_cache) = cache; + cache->saved_regs = trad_frame_alloc_saved_regs (this_frame); + + TRY + { + /* At this point the stack looks as if we just entered the + function, and the return address is stored in LR. */ + CORE_ADDR sp, lr; + + sp = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch)); + lr = get_frame_register_unsigned (this_frame, tdep->ppc_lr_regnum); + + cache->base = sp; + cache->initial_sp = sp; + + trad_frame_set_value (cache->saved_regs, + gdbarch_pc_regnum (gdbarch), lr); + } + CATCH (ex, RETURN_MASK_ERROR) + { + if (ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); + } + END_CATCH + + return cache; +} + +/* Implementation of frame_unwind.this_id, as defined in frame_unwind.h. + Return the frame ID of an epilogue frame. */ + +static void +rs6000_epilogue_frame_this_id (struct frame_info *this_frame, + void **this_cache, struct frame_id *this_id) +{ + CORE_ADDR pc; + struct rs6000_frame_cache *info = + rs6000_epilogue_frame_cache (this_frame, this_cache); + + pc = get_frame_func (this_frame); + if (info->base == 0) + (*this_id) = frame_id_build_unavailable_stack (pc); + else + (*this_id) = frame_id_build (info->base, pc); +} + +/* Implementation of frame_unwind.prev_register, as defined in frame_unwind.h. + Return the register value of REGNUM in previous frame. */ + +static struct value * +rs6000_epilogue_frame_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) +{ + struct rs6000_frame_cache *info = + rs6000_epilogue_frame_cache (this_frame, this_cache); + return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum); +} + +/* Implementation of frame_unwind.sniffer, as defined in frame_unwind.h. + Check whether this an epilogue frame. */ + +static int +rs6000_epilogue_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_prologue_cache) +{ + if (frame_relative_level (this_frame) == 0) + return rs6000_in_function_epilogue_frame_p (this_frame, + get_frame_arch (this_frame), + get_frame_pc (this_frame)); + else + return 0; +} + +/* Frame unwinder for epilogue frame. This is required for reverse step-over + a function without debug information. */ + +static const struct frame_unwind rs6000_epilogue_frame_unwind = +{ + NORMAL_FRAME, + default_frame_unwind_stop_reason, + rs6000_epilogue_frame_this_id, rs6000_epilogue_frame_prev_register, + NULL, + rs6000_epilogue_frame_sniffer +}; static CORE_ADDR @@ -3442,7 +3709,7 @@ bfd_uses_spe_extensions (bfd *abfd) return 0; size = bfd_get_section_size (sect); - contents = xmalloc (size); + contents = (gdb_byte *) xmalloc (size); if (!bfd_get_section_contents (abfd, sect, contents, 0, size)) { xfree (contents); @@ -3527,109 +3794,2235 @@ bfd_uses_spe_extensions (bfd *abfd) 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. - - Called e.g. at program startup, when reading a core file, and when reading - a binary file. */ +/* These are macros for parsing instruction fields (I.1.6.28) */ + +#define PPC_FIELD(value, from, len) \ + (((value) >> (32 - (from) - (len))) & ((1 << (len)) - 1)) +#define PPC_SEXT(v, bs) \ + ((((CORE_ADDR) (v) & (((CORE_ADDR) 1 << (bs)) - 1)) \ + ^ ((CORE_ADDR) 1 << ((bs) - 1))) \ + - ((CORE_ADDR) 1 << ((bs) - 1))) +#define PPC_OP6(insn) PPC_FIELD (insn, 0, 6) +#define PPC_EXTOP(insn) PPC_FIELD (insn, 21, 10) +#define PPC_RT(insn) PPC_FIELD (insn, 6, 5) +#define PPC_RS(insn) PPC_FIELD (insn, 6, 5) +#define PPC_RA(insn) PPC_FIELD (insn, 11, 5) +#define PPC_RB(insn) PPC_FIELD (insn, 16, 5) +#define PPC_NB(insn) PPC_FIELD (insn, 16, 5) +#define PPC_VRT(insn) PPC_FIELD (insn, 6, 5) +#define PPC_FRT(insn) PPC_FIELD (insn, 6, 5) +#define PPC_SPR(insn) (PPC_FIELD (insn, 11, 5) \ + | (PPC_FIELD (insn, 16, 5) << 5)) +#define PPC_BO(insn) PPC_FIELD (insn, 6, 5) +#define PPC_T(insn) PPC_FIELD (insn, 6, 5) +#define PPC_D(insn) PPC_SEXT (PPC_FIELD (insn, 16, 16), 16) +#define PPC_DS(insn) PPC_SEXT (PPC_FIELD (insn, 16, 14), 14) +#define PPC_DQ(insn) PPC_SEXT (PPC_FIELD (insn, 16, 12), 12) +#define PPC_BIT(insn,n) ((insn & (1 << (31 - (n)))) ? 1 : 0) +#define PPC_OE(insn) PPC_BIT (insn, 21) +#define PPC_RC(insn) PPC_BIT (insn, 31) +#define PPC_Rc(insn) PPC_BIT (insn, 21) +#define PPC_LK(insn) PPC_BIT (insn, 31) +#define PPC_TX(insn) PPC_BIT (insn, 31) +#define PPC_LEV(insn) PPC_FIELD (insn, 20, 7) + +#define PPC_XT(insn) ((PPC_TX (insn) << 5) | PPC_T (insn)) +#define PPC_XER_NB(xer) (xer & 0x7f) + +/* Record Vector-Scalar Registers. + For VSR less than 32, it's represented by an FPR and an VSR-upper register. + Otherwise, it's just a VR register. Record them accordingly. */ -static struct gdbarch * -rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) +static int +ppc_record_vsr (struct regcache *regcache, struct gdbarch_tdep *tdep, int vsr) { - struct gdbarch *gdbarch; - struct gdbarch_tdep *tdep; - int wordsize, from_xcoff_exec, from_elf_exec; - 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 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; + if (vsr < 0 || vsr >= 64) + return -1; - from_elf_exec = info.abfd && info.abfd->format == bfd_object && - 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) - { - if (bfd_xcoff_is_xcoff64 (info.abfd)) - wordsize = 8; - else - wordsize = 4; - } - else if (from_elf_exec) + if (vsr >= 32) { - if (elf_elfheader (info.abfd)->e_ident[EI_CLASS] == ELFCLASS64) - wordsize = 8; - else - wordsize = 4; + if (tdep->ppc_vr0_regnum >= 0) + record_full_arch_list_add_reg (regcache, tdep->ppc_vr0_regnum + vsr - 32); } - else if (tdesc_has_registers (tdesc)) - wordsize = -1; else { - if (info.bfd_arch_info != NULL && info.bfd_arch_info->bits_per_word != 0) - wordsize = info.bfd_arch_info->bits_per_word / - info.bfd_arch_info->bits_per_byte; - else - wordsize = 4; + if (tdep->ppc_fp0_regnum >= 0) + record_full_arch_list_add_reg (regcache, tdep->ppc_fp0_regnum + vsr); + if (tdep->ppc_vsr0_upper_regnum >= 0) + record_full_arch_list_add_reg (regcache, + tdep->ppc_vsr0_upper_regnum + vsr); } - /* Get the architecture and machine from the BFD. */ - arch = info.bfd_arch_info->arch; - mach = info.bfd_arch_info->mach; + return 0; +} - /* 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. Grovel through the section - looking for relevant e500 APUs. */ +/* Parse and record instructions primary opcode-4 at ADDR. + Return 0 if successful. */ - if (bfd_uses_spe_extensions (info.abfd)) +static int +ppc_process_record_op4 (struct gdbarch *gdbarch, struct regcache *regcache, + CORE_ADDR addr, uint32_t insn) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int ext = PPC_FIELD (insn, 21, 11); + int vra = PPC_FIELD (insn, 11, 5); + + switch (ext & 0x3f) { - 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); + case 32: /* Vector Multiply-High-Add Signed Halfword Saturate */ + case 33: /* Vector Multiply-High-Round-Add Signed Halfword Saturate */ + case 39: /* Vector Multiply-Sum Unsigned Halfword Saturate */ + case 41: /* Vector Multiply-Sum Signed Halfword Saturate */ + record_full_arch_list_add_reg (regcache, PPC_VSCR_REGNUM); + /* FALL-THROUGH */ + case 42: /* Vector Select */ + case 43: /* Vector Permute */ + case 59: /* Vector Permute Right-indexed */ + case 44: /* Vector Shift Left Double by Octet Immediate */ + case 45: /* Vector Permute and Exclusive-OR */ + case 60: /* Vector Add Extended Unsigned Quadword Modulo */ + case 61: /* Vector Add Extended & write Carry Unsigned Quadword */ + case 62: /* Vector Subtract Extended Unsigned Quadword Modulo */ + case 63: /* Vector Subtract Extended & write Carry Unsigned Quadword */ + case 34: /* Vector Multiply-Low-Add Unsigned Halfword Modulo */ + case 35: /* Vector Multiply-Sum Unsigned Doubleword Modulo */ + case 36: /* Vector Multiply-Sum Unsigned Byte Modulo */ + case 37: /* Vector Multiply-Sum Mixed Byte Modulo */ + case 38: /* Vector Multiply-Sum Unsigned Halfword Modulo */ + case 40: /* Vector Multiply-Sum Signed Halfword Modulo */ + case 46: /* Vector Multiply-Add Single-Precision */ + case 47: /* Vector Negative Multiply-Subtract Single-Precision */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_vr0_regnum + PPC_VRT (insn)); + return 0; + + case 48: /* Multiply-Add High Doubleword */ + case 49: /* Multiply-Add High Doubleword Unsigned */ + case 51: /* Multiply-Add Low Doubleword */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RT (insn)); + return 0; } - /* Find a default target description which describes our register - layout, if we do not already have one. */ - if (! tdesc_has_registers (tdesc)) + switch ((ext & 0x1ff)) { - const struct variant *v; + case 385: + if (vra != 0 /* Decimal Convert To Signed Quadword */ + && vra != 2 /* Decimal Convert From Signed Quadword */ + && vra != 4 /* Decimal Convert To Zoned */ + && vra != 5 /* Decimal Convert To National */ + && vra != 6 /* Decimal Convert From Zoned */ + && vra != 7 /* Decimal Convert From National */ + && vra != 31) /* Decimal Set Sign */ + break; + /* 5.16 Decimal Integer Arithmetic Instructions */ + case 1: /* Decimal Add Modulo */ + case 65: /* Decimal Subtract Modulo */ - /* Choose variant. */ - v = find_variant_by_arch (arch, mach); - if (!v) - return NULL; + case 193: /* Decimal Shift */ + case 129: /* Decimal Unsigned Shift */ + case 449: /* Decimal Shift and Round */ - tdesc = *v->tdesc; + case 257: /* Decimal Truncate */ + case 321: /* Decimal Unsigned Truncate */ + + /* Bit-21 should be set. */ + if (!PPC_BIT (insn, 21)) + break; + + record_full_arch_list_add_reg (regcache, + tdep->ppc_vr0_regnum + PPC_VRT (insn)); + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + return 0; + } + + /* Bit-21 is used for RC */ + switch (ext & 0x3ff) + { + case 6: /* Vector Compare Equal To Unsigned Byte */ + case 70: /* Vector Compare Equal To Unsigned Halfword */ + case 134: /* Vector Compare Equal To Unsigned Word */ + case 199: /* Vector Compare Equal To Unsigned Doubleword */ + case 774: /* Vector Compare Greater Than Signed Byte */ + case 838: /* Vector Compare Greater Than Signed Halfword */ + case 902: /* Vector Compare Greater Than Signed Word */ + case 967: /* Vector Compare Greater Than Signed Doubleword */ + case 518: /* Vector Compare Greater Than Unsigned Byte */ + case 646: /* Vector Compare Greater Than Unsigned Word */ + case 582: /* Vector Compare Greater Than Unsigned Halfword */ + case 711: /* Vector Compare Greater Than Unsigned Doubleword */ + case 966: /* Vector Compare Bounds Single-Precision */ + case 198: /* Vector Compare Equal To Single-Precision */ + case 454: /* Vector Compare Greater Than or Equal To Single-Precision */ + case 710: /* Vector Compare Greater Than Single-Precision */ + case 7: /* Vector Compare Not Equal Byte */ + case 71: /* Vector Compare Not Equal Halfword */ + case 135: /* Vector Compare Not Equal Word */ + case 263: /* Vector Compare Not Equal or Zero Byte */ + case 327: /* Vector Compare Not Equal or Zero Halfword */ + case 391: /* Vector Compare Not Equal or Zero Word */ + if (PPC_Rc (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + record_full_arch_list_add_reg (regcache, + tdep->ppc_vr0_regnum + PPC_VRT (insn)); + return 0; + } + + if (ext == 1538) + { + switch (vra) + { + case 0: /* Vector Count Leading Zero Least-Significant Bits + Byte */ + case 1: /* Vector Count Trailing Zero Least-Significant Bits + Byte */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RT (insn)); + return 0; + + case 6: /* Vector Negate Word */ + case 7: /* Vector Negate Doubleword */ + case 8: /* Vector Parity Byte Word */ + case 9: /* Vector Parity Byte Doubleword */ + case 10: /* Vector Parity Byte Quadword */ + case 16: /* Vector Extend Sign Byte To Word */ + case 17: /* Vector Extend Sign Halfword To Word */ + case 24: /* Vector Extend Sign Byte To Doubleword */ + case 25: /* Vector Extend Sign Halfword To Doubleword */ + case 26: /* Vector Extend Sign Word To Doubleword */ + case 28: /* Vector Count Trailing Zeros Byte */ + case 29: /* Vector Count Trailing Zeros Halfword */ + case 30: /* Vector Count Trailing Zeros Word */ + case 31: /* Vector Count Trailing Zeros Doubleword */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_vr0_regnum + PPC_VRT (insn)); + return 0; + } + } + + switch (ext) + { + case 142: /* Vector Pack Unsigned Halfword Unsigned Saturate */ + case 206: /* Vector Pack Unsigned Word Unsigned Saturate */ + case 270: /* Vector Pack Signed Halfword Unsigned Saturate */ + case 334: /* Vector Pack Signed Word Unsigned Saturate */ + case 398: /* Vector Pack Signed Halfword Signed Saturate */ + case 462: /* Vector Pack Signed Word Signed Saturate */ + case 1230: /* Vector Pack Unsigned Doubleword Unsigned Saturate */ + case 1358: /* Vector Pack Signed Doubleword Unsigned Saturate */ + case 1486: /* Vector Pack Signed Doubleword Signed Saturate */ + case 512: /* Vector Add Unsigned Byte Saturate */ + case 576: /* Vector Add Unsigned Halfword Saturate */ + case 640: /* Vector Add Unsigned Word Saturate */ + case 768: /* Vector Add Signed Byte Saturate */ + case 832: /* Vector Add Signed Halfword Saturate */ + case 896: /* Vector Add Signed Word Saturate */ + case 1536: /* Vector Subtract Unsigned Byte Saturate */ + case 1600: /* Vector Subtract Unsigned Halfword Saturate */ + case 1664: /* Vector Subtract Unsigned Word Saturate */ + case 1792: /* Vector Subtract Signed Byte Saturate */ + case 1856: /* Vector Subtract Signed Halfword Saturate */ + case 1920: /* Vector Subtract Signed Word Saturate */ + + case 1544: /* Vector Sum across Quarter Unsigned Byte Saturate */ + case 1800: /* Vector Sum across Quarter Signed Byte Saturate */ + case 1608: /* Vector Sum across Quarter Signed Halfword Saturate */ + case 1672: /* Vector Sum across Half Signed Word Saturate */ + case 1928: /* Vector Sum across Signed Word Saturate */ + case 970: /* Vector Convert To Signed Fixed-Point Word Saturate */ + case 906: /* Vector Convert To Unsigned Fixed-Point Word Saturate */ + record_full_arch_list_add_reg (regcache, PPC_VSCR_REGNUM); + /* FALL-THROUGH */ + case 12: /* Vector Merge High Byte */ + case 14: /* Vector Pack Unsigned Halfword Unsigned Modulo */ + case 76: /* Vector Merge High Halfword */ + case 78: /* Vector Pack Unsigned Word Unsigned Modulo */ + case 140: /* Vector Merge High Word */ + case 268: /* Vector Merge Low Byte */ + case 332: /* Vector Merge Low Halfword */ + case 396: /* Vector Merge Low Word */ + case 526: /* Vector Unpack High Signed Byte */ + case 590: /* Vector Unpack High Signed Halfword */ + case 654: /* Vector Unpack Low Signed Byte */ + case 718: /* Vector Unpack Low Signed Halfword */ + case 782: /* Vector Pack Pixel */ + case 846: /* Vector Unpack High Pixel */ + case 974: /* Vector Unpack Low Pixel */ + case 1102: /* Vector Pack Unsigned Doubleword Unsigned Modulo */ + case 1614: /* Vector Unpack High Signed Word */ + case 1676: /* Vector Merge Odd Word */ + case 1742: /* Vector Unpack Low Signed Word */ + case 1932: /* Vector Merge Even Word */ + case 524: /* Vector Splat Byte */ + case 588: /* Vector Splat Halfword */ + case 652: /* Vector Splat Word */ + case 780: /* Vector Splat Immediate Signed Byte */ + case 844: /* Vector Splat Immediate Signed Halfword */ + case 908: /* Vector Splat Immediate Signed Word */ + case 452: /* Vector Shift Left */ + case 708: /* Vector Shift Right */ + case 1036: /* Vector Shift Left by Octet */ + case 1100: /* Vector Shift Right by Octet */ + case 0: /* Vector Add Unsigned Byte Modulo */ + case 64: /* Vector Add Unsigned Halfword Modulo */ + case 128: /* Vector Add Unsigned Word Modulo */ + case 192: /* Vector Add Unsigned Doubleword Modulo */ + case 256: /* Vector Add Unsigned Quadword Modulo */ + case 320: /* Vector Add & write Carry Unsigned Quadword */ + case 384: /* Vector Add and Write Carry-Out Unsigned Word */ + case 8: /* Vector Multiply Odd Unsigned Byte */ + case 72: /* Vector Multiply Odd Unsigned Halfword */ + case 136: /* Vector Multiply Odd Unsigned Word */ + case 264: /* Vector Multiply Odd Signed Byte */ + case 328: /* Vector Multiply Odd Signed Halfword */ + case 392: /* Vector Multiply Odd Signed Word */ + case 520: /* Vector Multiply Even Unsigned Byte */ + case 584: /* Vector Multiply Even Unsigned Halfword */ + case 648: /* Vector Multiply Even Unsigned Word */ + case 776: /* Vector Multiply Even Signed Byte */ + case 840: /* Vector Multiply Even Signed Halfword */ + case 904: /* Vector Multiply Even Signed Word */ + case 137: /* Vector Multiply Unsigned Word Modulo */ + case 1024: /* Vector Subtract Unsigned Byte Modulo */ + case 1088: /* Vector Subtract Unsigned Halfword Modulo */ + case 1152: /* Vector Subtract Unsigned Word Modulo */ + case 1216: /* Vector Subtract Unsigned Doubleword Modulo */ + case 1280: /* Vector Subtract Unsigned Quadword Modulo */ + case 1344: /* Vector Subtract & write Carry Unsigned Quadword */ + case 1408: /* Vector Subtract and Write Carry-Out Unsigned Word */ + case 1282: /* Vector Average Signed Byte */ + case 1346: /* Vector Average Signed Halfword */ + case 1410: /* Vector Average Signed Word */ + case 1026: /* Vector Average Unsigned Byte */ + case 1090: /* Vector Average Unsigned Halfword */ + case 1154: /* Vector Average Unsigned Word */ + case 258: /* Vector Maximum Signed Byte */ + case 322: /* Vector Maximum Signed Halfword */ + case 386: /* Vector Maximum Signed Word */ + case 450: /* Vector Maximum Signed Doubleword */ + case 2: /* Vector Maximum Unsigned Byte */ + case 66: /* Vector Maximum Unsigned Halfword */ + case 130: /* Vector Maximum Unsigned Word */ + case 194: /* Vector Maximum Unsigned Doubleword */ + case 770: /* Vector Minimum Signed Byte */ + case 834: /* Vector Minimum Signed Halfword */ + case 898: /* Vector Minimum Signed Word */ + case 962: /* Vector Minimum Signed Doubleword */ + case 514: /* Vector Minimum Unsigned Byte */ + case 578: /* Vector Minimum Unsigned Halfword */ + case 642: /* Vector Minimum Unsigned Word */ + case 706: /* Vector Minimum Unsigned Doubleword */ + case 1028: /* Vector Logical AND */ + case 1668: /* Vector Logical Equivalent */ + case 1092: /* Vector Logical AND with Complement */ + case 1412: /* Vector Logical NAND */ + case 1348: /* Vector Logical OR with Complement */ + case 1156: /* Vector Logical OR */ + case 1284: /* Vector Logical NOR */ + case 1220: /* Vector Logical XOR */ + case 4: /* Vector Rotate Left Byte */ + case 132: /* Vector Rotate Left Word VX-form */ + case 68: /* Vector Rotate Left Halfword */ + case 196: /* Vector Rotate Left Doubleword */ + case 260: /* Vector Shift Left Byte */ + case 388: /* Vector Shift Left Word */ + case 324: /* Vector Shift Left Halfword */ + case 1476: /* Vector Shift Left Doubleword */ + case 516: /* Vector Shift Right Byte */ + case 644: /* Vector Shift Right Word */ + case 580: /* Vector Shift Right Halfword */ + case 1732: /* Vector Shift Right Doubleword */ + case 772: /* Vector Shift Right Algebraic Byte */ + case 900: /* Vector Shift Right Algebraic Word */ + case 836: /* Vector Shift Right Algebraic Halfword */ + case 964: /* Vector Shift Right Algebraic Doubleword */ + case 10: /* Vector Add Single-Precision */ + case 74: /* Vector Subtract Single-Precision */ + case 1034: /* Vector Maximum Single-Precision */ + case 1098: /* Vector Minimum Single-Precision */ + case 842: /* Vector Convert From Signed Fixed-Point Word */ + case 778: /* Vector Convert From Unsigned Fixed-Point Word */ + case 714: /* Vector Round to Single-Precision Integer toward -Infinity */ + case 522: /* Vector Round to Single-Precision Integer Nearest */ + case 650: /* Vector Round to Single-Precision Integer toward +Infinity */ + case 586: /* Vector Round to Single-Precision Integer toward Zero */ + case 394: /* Vector 2 Raised to the Exponent Estimate Floating-Point */ + case 458: /* Vector Log Base 2 Estimate Floating-Point */ + case 266: /* Vector Reciprocal Estimate Single-Precision */ + case 330: /* Vector Reciprocal Square Root Estimate Single-Precision */ + case 1288: /* Vector AES Cipher */ + case 1289: /* Vector AES Cipher Last */ + case 1352: /* Vector AES Inverse Cipher */ + case 1353: /* Vector AES Inverse Cipher Last */ + case 1480: /* Vector AES SubBytes */ + case 1730: /* Vector SHA-512 Sigma Doubleword */ + case 1666: /* Vector SHA-256 Sigma Word */ + case 1032: /* Vector Polynomial Multiply-Sum Byte */ + case 1160: /* Vector Polynomial Multiply-Sum Word */ + case 1096: /* Vector Polynomial Multiply-Sum Halfword */ + case 1224: /* Vector Polynomial Multiply-Sum Doubleword */ + case 1292: /* Vector Gather Bits by Bytes by Doubleword */ + case 1794: /* Vector Count Leading Zeros Byte */ + case 1858: /* Vector Count Leading Zeros Halfword */ + case 1922: /* Vector Count Leading Zeros Word */ + case 1986: /* Vector Count Leading Zeros Doubleword */ + case 1795: /* Vector Population Count Byte */ + case 1859: /* Vector Population Count Halfword */ + case 1923: /* Vector Population Count Word */ + case 1987: /* Vector Population Count Doubleword */ + case 1356: /* Vector Bit Permute Quadword */ + case 1484: /* Vector Bit Permute Doubleword */ + case 513: /* Vector Multiply-by-10 Unsigned Quadword */ + case 1: /* Vector Multiply-by-10 & write Carry Unsigned + Quadword */ + case 577: /* Vector Multiply-by-10 Extended Unsigned Quadword */ + case 65: /* Vector Multiply-by-10 Extended & write Carry + Unsigned Quadword */ + case 1027: /* Vector Absolute Difference Unsigned Byte */ + case 1091: /* Vector Absolute Difference Unsigned Halfword */ + case 1155: /* Vector Absolute Difference Unsigned Word */ + case 1796: /* Vector Shift Right Variable */ + case 1860: /* Vector Shift Left Variable */ + case 133: /* Vector Rotate Left Word then Mask Insert */ + case 197: /* Vector Rotate Left Doubleword then Mask Insert */ + case 389: /* Vector Rotate Left Word then AND with Mask */ + case 453: /* Vector Rotate Left Doubleword then AND with Mask */ + case 525: /* Vector Extract Unsigned Byte */ + case 589: /* Vector Extract Unsigned Halfword */ + case 653: /* Vector Extract Unsigned Word */ + case 717: /* Vector Extract Doubleword */ + case 781: /* Vector Insert Byte */ + case 845: /* Vector Insert Halfword */ + case 909: /* Vector Insert Word */ + case 973: /* Vector Insert Doubleword */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_vr0_regnum + PPC_VRT (insn)); + return 0; + + case 1549: /* Vector Extract Unsigned Byte Left-Indexed */ + case 1613: /* Vector Extract Unsigned Halfword Left-Indexed */ + case 1677: /* Vector Extract Unsigned Word Left-Indexed */ + case 1805: /* Vector Extract Unsigned Byte Right-Indexed */ + case 1869: /* Vector Extract Unsigned Halfword Right-Indexed */ + case 1933: /* Vector Extract Unsigned Word Right-Indexed */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RT (insn)); + return 0; + + case 1604: /* Move To Vector Status and Control Register */ + record_full_arch_list_add_reg (regcache, PPC_VSCR_REGNUM); + return 0; + case 1540: /* Move From Vector Status and Control Register */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_vr0_regnum + PPC_VRT (insn)); + return 0; + case 833: /* Decimal Copy Sign */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_vr0_regnum + PPC_VRT (insn)); + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + return 0; + } + + fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x " + "at %s, 4-%d.\n", insn, paddress (gdbarch, addr), ext); + return -1; +} + +/* Parse and record instructions of primary opcode-19 at ADDR. + Return 0 if successful. */ + +static int +ppc_process_record_op19 (struct gdbarch *gdbarch, struct regcache *regcache, + CORE_ADDR addr, uint32_t insn) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int ext = PPC_EXTOP (insn); + + switch (ext & 0x01f) + { + case 2: /* Add PC Immediate Shifted */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RT (insn)); + return 0; + } + + switch (ext) + { + case 0: /* Move Condition Register Field */ + case 33: /* Condition Register NOR */ + case 129: /* Condition Register AND with Complement */ + case 193: /* Condition Register XOR */ + case 225: /* Condition Register NAND */ + case 257: /* Condition Register AND */ + case 289: /* Condition Register Equivalent */ + case 417: /* Condition Register OR with Complement */ + case 449: /* Condition Register OR */ + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + return 0; + + case 16: /* Branch Conditional */ + case 560: /* Branch Conditional to Branch Target Address Register */ + if ((PPC_BO (insn) & 0x4) == 0) + record_full_arch_list_add_reg (regcache, tdep->ppc_ctr_regnum); + /* FALL-THROUGH */ + case 528: /* Branch Conditional to Count Register */ + if (PPC_LK (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_lr_regnum); + return 0; + + case 150: /* Instruction Synchronize */ + /* Do nothing. */ + return 0; + } + + fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x " + "at %s, 19-%d.\n", insn, paddress (gdbarch, addr), ext); + return -1; +} + +/* Parse and record instructions of primary opcode-31 at ADDR. + Return 0 if successful. */ + +static int +ppc_process_record_op31 (struct gdbarch *gdbarch, struct regcache *regcache, + CORE_ADDR addr, uint32_t insn) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int ext = PPC_EXTOP (insn); + int tmp, nr, nb, i; + CORE_ADDR at_dcsz, ea = 0; + ULONGEST rb, ra, xer; + int size = 0; + + /* These instructions have OE bit. */ + switch (ext & 0x1ff) + { + /* These write RT and XER. Update CR if RC is set. */ + case 8: /* Subtract from carrying */ + case 10: /* Add carrying */ + case 136: /* Subtract from extended */ + case 138: /* Add extended */ + case 200: /* Subtract from zero extended */ + case 202: /* Add to zero extended */ + case 232: /* Subtract from minus one extended */ + case 234: /* Add to minus one extended */ + /* CA is always altered, but SO/OV are only altered when OE=1. + In any case, XER is always altered. */ + record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum); + if (PPC_RC (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RT (insn)); + return 0; + + /* These write RT. Update CR if RC is set and update XER if OE is set. */ + case 40: /* Subtract from */ + case 104: /* Negate */ + case 233: /* Multiply low doubleword */ + case 235: /* Multiply low word */ + case 266: /* Add */ + case 393: /* Divide Doubleword Extended Unsigned */ + case 395: /* Divide Word Extended Unsigned */ + case 425: /* Divide Doubleword Extended */ + case 427: /* Divide Word Extended */ + case 457: /* Divide Doubleword Unsigned */ + case 459: /* Divide Word Unsigned */ + case 489: /* Divide Doubleword */ + case 491: /* Divide Word */ + if (PPC_OE (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum); + /* FALL-THROUGH */ + case 9: /* Multiply High Doubleword Unsigned */ + case 11: /* Multiply High Word Unsigned */ + case 73: /* Multiply High Doubleword */ + case 75: /* Multiply High Word */ + if (PPC_RC (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RT (insn)); + return 0; + } + + if ((ext & 0x1f) == 15) + { + /* Integer Select. bit[16:20] is used for BC. */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RT (insn)); + return 0; + } + + if ((ext & 0xff) == 170) + { + /* Add Extended using alternate carry bits */ + record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum); + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RT (insn)); + return 0; + } + + switch (ext) + { + case 78: /* Determine Leftmost Zero Byte */ + if (PPC_RC (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum); + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RT (insn)); + return 0; + + /* These only write RT. */ + case 19: /* Move from condition register */ + /* Move From One Condition Register Field */ + case 74: /* Add and Generate Sixes */ + case 74 | 0x200: /* Add and Generate Sixes (bit-21 dont-care) */ + case 302: /* Move From Branch History Rolling Buffer */ + case 339: /* Move From Special Purpose Register */ + case 371: /* Move From Time Base [Phased-Out] */ + case 309: /* Load Doubleword Monitored Indexed */ + case 128: /* Set Boolean */ + case 755: /* Deliver A Random Number */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RT (insn)); + return 0; + + /* These only write to RA. */ + case 51: /* Move From VSR Doubleword */ + case 115: /* Move From VSR Word and Zero */ + case 122: /* Population count bytes */ + case 378: /* Population count words */ + case 506: /* Population count doublewords */ + case 154: /* Parity Word */ + case 186: /* Parity Doubleword */ + case 252: /* Bit Permute Doubleword */ + case 282: /* Convert Declets To Binary Coded Decimal */ + case 314: /* Convert Binary Coded Decimal To Declets */ + case 508: /* Compare bytes */ + case 307: /* Move From VSR Lower Doubleword */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn)); + return 0; + + /* These write CR and optional RA. */ + case 792: /* Shift Right Algebraic Word */ + case 794: /* Shift Right Algebraic Doubleword */ + case 824: /* Shift Right Algebraic Word Immediate */ + case 826: /* Shift Right Algebraic Doubleword Immediate (413) */ + case 826 | 1: /* Shift Right Algebraic Doubleword Immediate (413) */ + record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum); + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn)); + /* FALL-THROUGH */ + case 0: /* Compare */ + case 32: /* Compare logical */ + case 144: /* Move To Condition Register Fields */ + /* Move To One Condition Register Field */ + case 192: /* Compare Ranged Byte */ + case 224: /* Compare Equal Byte */ + case 576: /* Move XER to CR Extended */ + case 902: /* Paste (should always fail due to single-stepping and + the memory location might not be accessible, so + record only CR) */ + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + return 0; + + /* These write to RT. Update RA if 'update indexed.' */ + case 53: /* Load Doubleword with Update Indexed */ + case 119: /* Load Byte and Zero with Update Indexed */ + case 311: /* Load Halfword and Zero with Update Indexed */ + case 55: /* Load Word and Zero with Update Indexed */ + case 375: /* Load Halfword Algebraic with Update Indexed */ + case 373: /* Load Word Algebraic with Update Indexed */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn)); + /* FALL-THROUGH */ + case 21: /* Load Doubleword Indexed */ + case 52: /* Load Byte And Reserve Indexed */ + case 116: /* Load Halfword And Reserve Indexed */ + case 20: /* Load Word And Reserve Indexed */ + case 84: /* Load Doubleword And Reserve Indexed */ + case 87: /* Load Byte and Zero Indexed */ + case 279: /* Load Halfword and Zero Indexed */ + case 23: /* Load Word and Zero Indexed */ + case 343: /* Load Halfword Algebraic Indexed */ + case 341: /* Load Word Algebraic Indexed */ + case 790: /* Load Halfword Byte-Reverse Indexed */ + case 534: /* Load Word Byte-Reverse Indexed */ + case 532: /* Load Doubleword Byte-Reverse Indexed */ + case 582: /* Load Word Atomic */ + case 614: /* Load Doubleword Atomic */ + case 265: /* Modulo Unsigned Doubleword */ + case 777: /* Modulo Signed Doubleword */ + case 267: /* Modulo Unsigned Word */ + case 779: /* Modulo Signed Word */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RT (insn)); + return 0; + + case 597: /* Load String Word Immediate */ + case 533: /* Load String Word Indexed */ + if (ext == 597) + { + nr = PPC_NB (insn); + if (nr == 0) + nr = 32; + } + else + { + regcache_raw_read_unsigned (regcache, tdep->ppc_xer_regnum, &xer); + nr = PPC_XER_NB (xer); + } + + nr = (nr + 3) >> 2; + + /* If n=0, the contents of register RT are undefined. */ + if (nr == 0) + nr = 1; + + for (i = 0; i < nr; i++) + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + + ((PPC_RT (insn) + i) & 0x1f)); + return 0; + + case 276: /* Load Quadword And Reserve Indexed */ + tmp = tdep->ppc_gp0_regnum + (PPC_RT (insn) & ~1); + record_full_arch_list_add_reg (regcache, tmp); + record_full_arch_list_add_reg (regcache, tmp + 1); + return 0; + + /* These write VRT. */ + case 6: /* Load Vector for Shift Left Indexed */ + case 38: /* Load Vector for Shift Right Indexed */ + case 7: /* Load Vector Element Byte Indexed */ + case 39: /* Load Vector Element Halfword Indexed */ + case 71: /* Load Vector Element Word Indexed */ + case 103: /* Load Vector Indexed */ + case 359: /* Load Vector Indexed LRU */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_vr0_regnum + PPC_VRT (insn)); + return 0; + + /* These write FRT. Update RA if 'update indexed.' */ + case 567: /* Load Floating-Point Single with Update Indexed */ + case 631: /* Load Floating-Point Double with Update Indexed */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn)); + /* FALL-THROUGH */ + case 535: /* Load Floating-Point Single Indexed */ + case 599: /* Load Floating-Point Double Indexed */ + case 855: /* Load Floating-Point as Integer Word Algebraic Indexed */ + case 887: /* Load Floating-Point as Integer Word and Zero Indexed */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_fp0_regnum + PPC_FRT (insn)); + return 0; + + case 791: /* Load Floating-Point Double Pair Indexed */ + tmp = tdep->ppc_fp0_regnum + (PPC_FRT (insn) & ~1); + record_full_arch_list_add_reg (regcache, tmp); + record_full_arch_list_add_reg (regcache, tmp + 1); + return 0; + + case 179: /* Move To VSR Doubleword */ + case 211: /* Move To VSR Word Algebraic */ + case 243: /* Move To VSR Word and Zero */ + case 588: /* Load VSX Scalar Doubleword Indexed */ + case 524: /* Load VSX Scalar Single-Precision Indexed */ + case 76: /* Load VSX Scalar as Integer Word Algebraic Indexed */ + case 12: /* Load VSX Scalar as Integer Word and Zero Indexed */ + case 844: /* Load VSX Vector Doubleword*2 Indexed */ + case 332: /* Load VSX Vector Doubleword & Splat Indexed */ + case 780: /* Load VSX Vector Word*4 Indexed */ + case 268: /* Load VSX Vector Indexed */ + case 364: /* Load VSX Vector Word & Splat Indexed */ + case 812: /* Load VSX Vector Halfword*8 Indexed */ + case 876: /* Load VSX Vector Byte*16 Indexed */ + case 269: /* Load VSX Vector with Length */ + case 301: /* Load VSX Vector Left-justified with Length */ + case 781: /* Load VSX Scalar as Integer Byte & Zero Indexed */ + case 813: /* Load VSX Scalar as Integer Halfword & Zero Indexed */ + case 403: /* Move To VSR Word & Splat */ + case 435: /* Move To VSR Double Doubleword */ + ppc_record_vsr (regcache, tdep, PPC_XT (insn)); + return 0; + + /* These write RA. Update CR if RC is set. */ + case 24: /* Shift Left Word */ + case 26: /* Count Leading Zeros Word */ + case 27: /* Shift Left Doubleword */ + case 28: /* AND */ + case 58: /* Count Leading Zeros Doubleword */ + case 60: /* AND with Complement */ + case 124: /* NOR */ + case 284: /* Equivalent */ + case 316: /* XOR */ + case 476: /* NAND */ + case 412: /* OR with Complement */ + case 444: /* OR */ + case 536: /* Shift Right Word */ + case 539: /* Shift Right Doubleword */ + case 922: /* Extend Sign Halfword */ + case 954: /* Extend Sign Byte */ + case 986: /* Extend Sign Word */ + case 538: /* Count Trailing Zeros Word */ + case 570: /* Count Trailing Zeros Doubleword */ + case 890: /* Extend-Sign Word and Shift Left Immediate (445) */ + case 890 | 1: /* Extend-Sign Word and Shift Left Immediate (445) */ + if (PPC_RC (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn)); + return 0; + + /* Store memory. */ + case 181: /* Store Doubleword with Update Indexed */ + case 183: /* Store Word with Update Indexed */ + case 247: /* Store Byte with Update Indexed */ + case 439: /* Store Half Word with Update Indexed */ + case 695: /* Store Floating-Point Single with Update Indexed */ + case 759: /* Store Floating-Point Double with Update Indexed */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn)); + /* FALL-THROUGH */ + case 135: /* Store Vector Element Byte Indexed */ + case 167: /* Store Vector Element Halfword Indexed */ + case 199: /* Store Vector Element Word Indexed */ + case 231: /* Store Vector Indexed */ + case 487: /* Store Vector Indexed LRU */ + case 716: /* Store VSX Scalar Doubleword Indexed */ + case 140: /* Store VSX Scalar as Integer Word Indexed */ + case 652: /* Store VSX Scalar Single-Precision Indexed */ + case 972: /* Store VSX Vector Doubleword*2 Indexed */ + case 908: /* Store VSX Vector Word*4 Indexed */ + case 149: /* Store Doubleword Indexed */ + case 151: /* Store Word Indexed */ + case 215: /* Store Byte Indexed */ + case 407: /* Store Half Word Indexed */ + case 694: /* Store Byte Conditional Indexed */ + case 726: /* Store Halfword Conditional Indexed */ + case 150: /* Store Word Conditional Indexed */ + case 214: /* Store Doubleword Conditional Indexed */ + case 182: /* Store Quadword Conditional Indexed */ + case 662: /* Store Word Byte-Reverse Indexed */ + case 918: /* Store Halfword Byte-Reverse Indexed */ + case 660: /* Store Doubleword Byte-Reverse Indexed */ + case 663: /* Store Floating-Point Single Indexed */ + case 727: /* Store Floating-Point Double Indexed */ + case 919: /* Store Floating-Point Double Pair Indexed */ + case 983: /* Store Floating-Point as Integer Word Indexed */ + case 396: /* Store VSX Vector Indexed */ + case 940: /* Store VSX Vector Halfword*8 Indexed */ + case 1004: /* Store VSX Vector Byte*16 Indexed */ + case 909: /* Store VSX Scalar as Integer Byte Indexed */ + case 941: /* Store VSX Scalar as Integer Halfword Indexed */ + if (ext == 694 || ext == 726 || ext == 150 || ext == 214 || ext == 182) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + + ra = 0; + if (PPC_RA (insn) != 0) + regcache_raw_read_unsigned (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn), &ra); + regcache_raw_read_unsigned (regcache, + tdep->ppc_gp0_regnum + PPC_RB (insn), &rb); + ea = ra + rb; + + switch (ext) + { + case 183: /* Store Word with Update Indexed */ + case 199: /* Store Vector Element Word Indexed */ + case 140: /* Store VSX Scalar as Integer Word Indexed */ + case 652: /* Store VSX Scalar Single-Precision Indexed */ + case 151: /* Store Word Indexed */ + case 150: /* Store Word Conditional Indexed */ + case 662: /* Store Word Byte-Reverse Indexed */ + case 663: /* Store Floating-Point Single Indexed */ + case 695: /* Store Floating-Point Single with Update Indexed */ + case 983: /* Store Floating-Point as Integer Word Indexed */ + size = 4; + break; + case 247: /* Store Byte with Update Indexed */ + case 135: /* Store Vector Element Byte Indexed */ + case 215: /* Store Byte Indexed */ + case 694: /* Store Byte Conditional Indexed */ + case 909: /* Store VSX Scalar as Integer Byte Indexed */ + size = 1; + break; + case 439: /* Store Halfword with Update Indexed */ + case 167: /* Store Vector Element Halfword Indexed */ + case 407: /* Store Halfword Indexed */ + case 726: /* Store Halfword Conditional Indexed */ + case 918: /* Store Halfword Byte-Reverse Indexed */ + case 941: /* Store VSX Scalar as Integer Halfword Indexed */ + size = 2; + break; + case 181: /* Store Doubleword with Update Indexed */ + case 716: /* Store VSX Scalar Doubleword Indexed */ + case 149: /* Store Doubleword Indexed */ + case 214: /* Store Doubleword Conditional Indexed */ + case 660: /* Store Doubleword Byte-Reverse Indexed */ + case 727: /* Store Floating-Point Double Indexed */ + case 759: /* Store Floating-Point Double with Update Indexed */ + size = 8; + break; + case 972: /* Store VSX Vector Doubleword*2 Indexed */ + case 908: /* Store VSX Vector Word*4 Indexed */ + case 182: /* Store Quadword Conditional Indexed */ + case 231: /* Store Vector Indexed */ + case 487: /* Store Vector Indexed LRU */ + case 919: /* Store Floating-Point Double Pair Indexed */ + case 396: /* Store VSX Vector Indexed */ + case 940: /* Store VSX Vector Halfword*8 Indexed */ + case 1004: /* Store VSX Vector Byte*16 Indexed */ + size = 16; + break; + default: + gdb_assert (0); + } + + /* Align address for Store Vector instructions. */ + switch (ext) + { + case 167: /* Store Vector Element Halfword Indexed */ + addr = addr & ~0x1ULL; + break; + + case 199: /* Store Vector Element Word Indexed */ + addr = addr & ~0x3ULL; + break; + + case 231: /* Store Vector Indexed */ + case 487: /* Store Vector Indexed LRU */ + addr = addr & ~0xfULL; + break; + } + + record_full_arch_list_add_mem (addr, size); + return 0; + + case 397: /* Store VSX Vector with Length */ + case 429: /* Store VSX Vector Left-justified with Length */ + if (PPC_RA (insn) != 0) + regcache_raw_read_unsigned (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn), &ea); + regcache_raw_read_unsigned (regcache, + tdep->ppc_gp0_regnum + PPC_RB (insn), &rb); + /* Store up to 16 bytes. */ + nb = (rb & 0xff) > 16 ? 16 : (rb & 0xff); + if (nb > 0) + record_full_arch_list_add_mem (ea, nb); + return 0; + + case 710: /* Store Word Atomic */ + case 742: /* Store Doubleword Atomic */ + if (PPC_RA (insn) != 0) + regcache_raw_read_unsigned (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn), &ea); + switch (ext) + { + case 710: /* Store Word Atomic */ + size = 8; + break; + case 742: /* Store Doubleword Atomic */ + size = 16; + break; + default: + gdb_assert (0); + } + record_full_arch_list_add_mem (ea, size); + return 0; + + case 725: /* Store String Word Immediate */ + ra = 0; + if (PPC_RA (insn) != 0) + regcache_raw_read_unsigned (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn), &ra); + ea += ra; + + nb = PPC_NB (insn); + if (nb == 0) + nb = 32; + + record_full_arch_list_add_mem (ea, nb); + + return 0; + + case 661: /* Store String Word Indexed */ + ra = 0; + if (PPC_RA (insn) != 0) + regcache_raw_read_unsigned (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn), &ra); + ea += ra; + + regcache_raw_read_unsigned (regcache, tdep->ppc_xer_regnum, &xer); + nb = PPC_XER_NB (xer); + + if (nb != 0) + { + regcache_raw_read_unsigned (regcache, + tdep->ppc_gp0_regnum + PPC_RB (insn), + &rb); + ea += rb; + record_full_arch_list_add_mem (ea, nb); + } + + return 0; + + case 467: /* Move To Special Purpose Register */ + switch (PPC_SPR (insn)) + { + case 1: /* XER */ + record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum); + return 0; + case 8: /* LR */ + record_full_arch_list_add_reg (regcache, tdep->ppc_lr_regnum); + return 0; + case 9: /* CTR */ + record_full_arch_list_add_reg (regcache, tdep->ppc_ctr_regnum); + return 0; + case 256: /* VRSAVE */ + record_full_arch_list_add_reg (regcache, tdep->ppc_vrsave_regnum); + return 0; + } + + goto UNKNOWN_OP; + + case 147: /* Move To Split Little Endian */ + record_full_arch_list_add_reg (regcache, tdep->ppc_ps_regnum); + return 0; + + case 512: /* Move to Condition Register from XER */ + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum); + return 0; + + case 4: /* Trap Word */ + case 68: /* Trap Doubleword */ + case 430: /* Clear BHRB */ + case 598: /* Synchronize */ + case 62: /* Wait for Interrupt */ + case 30: /* Wait */ + case 22: /* Instruction Cache Block Touch */ + case 854: /* Enforce In-order Execution of I/O */ + case 246: /* Data Cache Block Touch for Store */ + case 54: /* Data Cache Block Store */ + case 86: /* Data Cache Block Flush */ + case 278: /* Data Cache Block Touch */ + case 758: /* Data Cache Block Allocate */ + case 982: /* Instruction Cache Block Invalidate */ + case 774: /* Copy */ + case 838: /* CP_Abort */ + return 0; + + case 654: /* Transaction Begin */ + case 686: /* Transaction End */ + case 750: /* Transaction Suspend or Resume */ + case 782: /* Transaction Abort Word Conditional */ + case 814: /* Transaction Abort Doubleword Conditional */ + case 846: /* Transaction Abort Word Conditional Immediate */ + case 878: /* Transaction Abort Doubleword Conditional Immediate */ + case 910: /* Transaction Abort */ + record_full_arch_list_add_reg (regcache, tdep->ppc_ps_regnum); + /* FALL-THROUGH */ + case 718: /* Transaction Check */ + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + return 0; + + case 1014: /* Data Cache Block set to Zero */ + if (target_auxv_search (¤t_target, AT_DCACHEBSIZE, &at_dcsz) <= 0 + || at_dcsz == 0) + at_dcsz = 128; /* Assume 128-byte cache line size (POWER8) */ + + ra = 0; + if (PPC_RA (insn) != 0) + regcache_raw_read_unsigned (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn), &ra); + regcache_raw_read_unsigned (regcache, + tdep->ppc_gp0_regnum + PPC_RB (insn), &rb); + ea = (ra + rb) & ~((ULONGEST) (at_dcsz - 1)); + record_full_arch_list_add_mem (ea, at_dcsz); + return 0; + } + +UNKNOWN_OP: + fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x " + "at %s, 31-%d.\n", insn, paddress (gdbarch, addr), ext); + return -1; +} + +/* Parse and record instructions of primary opcode-59 at ADDR. + Return 0 if successful. */ + +static int +ppc_process_record_op59 (struct gdbarch *gdbarch, struct regcache *regcache, + CORE_ADDR addr, uint32_t insn) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int ext = PPC_EXTOP (insn); + + switch (ext & 0x1f) + { + case 18: /* Floating Divide */ + case 20: /* Floating Subtract */ + case 21: /* Floating Add */ + case 22: /* Floating Square Root */ + case 24: /* Floating Reciprocal Estimate */ + case 25: /* Floating Multiply */ + case 26: /* Floating Reciprocal Square Root Estimate */ + case 28: /* Floating Multiply-Subtract */ + case 29: /* Floating Multiply-Add */ + case 30: /* Floating Negative Multiply-Subtract */ + case 31: /* Floating Negative Multiply-Add */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_fp0_regnum + PPC_FRT (insn)); + if (PPC_RC (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + + return 0; + } + + switch (ext) + { + case 2: /* DFP Add */ + case 3: /* DFP Quantize */ + case 34: /* DFP Multiply */ + case 35: /* DFP Reround */ + case 67: /* DFP Quantize Immediate */ + case 99: /* DFP Round To FP Integer With Inexact */ + case 227: /* DFP Round To FP Integer Without Inexact */ + case 258: /* DFP Convert To DFP Long! */ + case 290: /* DFP Convert To Fixed */ + case 514: /* DFP Subtract */ + case 546: /* DFP Divide */ + case 770: /* DFP Round To DFP Short! */ + case 802: /* DFP Convert From Fixed */ + case 834: /* DFP Encode BCD To DPD */ + if (PPC_RC (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + record_full_arch_list_add_reg (regcache, + tdep->ppc_fp0_regnum + PPC_FRT (insn)); + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + return 0; + + case 130: /* DFP Compare Ordered */ + case 162: /* DFP Test Exponent */ + case 194: /* DFP Test Data Class */ + case 226: /* DFP Test Data Group */ + case 642: /* DFP Compare Unordered */ + case 674: /* DFP Test Significance */ + case 675: /* DFP Test Significance Immediate */ + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + return 0; + + case 66: /* DFP Shift Significand Left Immediate */ + case 98: /* DFP Shift Significand Right Immediate */ + case 322: /* DFP Decode DPD To BCD */ + case 354: /* DFP Extract Biased Exponent */ + case 866: /* DFP Insert Biased Exponent */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_fp0_regnum + PPC_FRT (insn)); + if (PPC_RC (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + return 0; + + case 846: /* Floating Convert From Integer Doubleword Single */ + case 974: /* Floating Convert From Integer Doubleword Unsigned + Single */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_fp0_regnum + PPC_FRT (insn)); + if (PPC_RC (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + + return 0; + } + + fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x " + "at %s, 59-%d.\n", insn, paddress (gdbarch, addr), ext); + return -1; +} + +/* Parse and record instructions of primary opcode-60 at ADDR. + Return 0 if successful. */ + +static int +ppc_process_record_op60 (struct gdbarch *gdbarch, struct regcache *regcache, + CORE_ADDR addr, uint32_t insn) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int ext = PPC_EXTOP (insn); + + switch (ext >> 2) + { + case 0: /* VSX Scalar Add Single-Precision */ + case 32: /* VSX Scalar Add Double-Precision */ + case 24: /* VSX Scalar Divide Single-Precision */ + case 56: /* VSX Scalar Divide Double-Precision */ + case 176: /* VSX Scalar Copy Sign Double-Precision */ + case 33: /* VSX Scalar Multiply-Add Double-Precision */ + case 41: /* ditto */ + case 1: /* VSX Scalar Multiply-Add Single-Precision */ + case 9: /* ditto */ + case 160: /* VSX Scalar Maximum Double-Precision */ + case 168: /* VSX Scalar Minimum Double-Precision */ + case 49: /* VSX Scalar Multiply-Subtract Double-Precision */ + case 57: /* ditto */ + case 17: /* VSX Scalar Multiply-Subtract Single-Precision */ + case 25: /* ditto */ + case 48: /* VSX Scalar Multiply Double-Precision */ + case 16: /* VSX Scalar Multiply Single-Precision */ + case 161: /* VSX Scalar Negative Multiply-Add Double-Precision */ + case 169: /* ditto */ + case 129: /* VSX Scalar Negative Multiply-Add Single-Precision */ + case 137: /* ditto */ + case 177: /* VSX Scalar Negative Multiply-Subtract Double-Precision */ + case 185: /* ditto */ + case 145: /* VSX Scalar Negative Multiply-Subtract Single-Precision */ + case 153: /* ditto */ + case 40: /* VSX Scalar Subtract Double-Precision */ + case 8: /* VSX Scalar Subtract Single-Precision */ + case 96: /* VSX Vector Add Double-Precision */ + case 64: /* VSX Vector Add Single-Precision */ + case 120: /* VSX Vector Divide Double-Precision */ + case 88: /* VSX Vector Divide Single-Precision */ + case 97: /* VSX Vector Multiply-Add Double-Precision */ + case 105: /* ditto */ + case 65: /* VSX Vector Multiply-Add Single-Precision */ + case 73: /* ditto */ + case 224: /* VSX Vector Maximum Double-Precision */ + case 192: /* VSX Vector Maximum Single-Precision */ + case 232: /* VSX Vector Minimum Double-Precision */ + case 200: /* VSX Vector Minimum Single-Precision */ + case 113: /* VSX Vector Multiply-Subtract Double-Precision */ + case 121: /* ditto */ + case 81: /* VSX Vector Multiply-Subtract Single-Precision */ + case 89: /* ditto */ + case 112: /* VSX Vector Multiply Double-Precision */ + case 80: /* VSX Vector Multiply Single-Precision */ + case 225: /* VSX Vector Negative Multiply-Add Double-Precision */ + case 233: /* ditto */ + case 193: /* VSX Vector Negative Multiply-Add Single-Precision */ + case 201: /* ditto */ + case 241: /* VSX Vector Negative Multiply-Subtract Double-Precision */ + case 249: /* ditto */ + case 209: /* VSX Vector Negative Multiply-Subtract Single-Precision */ + case 217: /* ditto */ + case 104: /* VSX Vector Subtract Double-Precision */ + case 72: /* VSX Vector Subtract Single-Precision */ + case 128: /* VSX Scalar Maximum Type-C Double-Precision */ + case 136: /* VSX Scalar Minimum Type-C Double-Precision */ + case 144: /* VSX Scalar Maximum Type-J Double-Precision */ + case 152: /* VSX Scalar Minimum Type-J Double-Precision */ + case 3: /* VSX Scalar Compare Equal Double-Precision */ + case 11: /* VSX Scalar Compare Greater Than Double-Precision */ + case 19: /* VSX Scalar Compare Greater Than or Equal + Double-Precision */ + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + /* FALL-THROUGH */ + case 240: /* VSX Vector Copy Sign Double-Precision */ + case 208: /* VSX Vector Copy Sign Single-Precision */ + case 130: /* VSX Logical AND */ + case 138: /* VSX Logical AND with Complement */ + case 186: /* VSX Logical Equivalence */ + case 178: /* VSX Logical NAND */ + case 170: /* VSX Logical OR with Complement */ + case 162: /* VSX Logical NOR */ + case 146: /* VSX Logical OR */ + case 154: /* VSX Logical XOR */ + case 18: /* VSX Merge High Word */ + case 50: /* VSX Merge Low Word */ + case 10: /* VSX Permute Doubleword Immediate (DM=0) */ + case 10 | 0x20: /* VSX Permute Doubleword Immediate (DM=1) */ + case 10 | 0x40: /* VSX Permute Doubleword Immediate (DM=2) */ + case 10 | 0x60: /* VSX Permute Doubleword Immediate (DM=3) */ + case 2: /* VSX Shift Left Double by Word Immediate (SHW=0) */ + case 2 | 0x20: /* VSX Shift Left Double by Word Immediate (SHW=1) */ + case 2 | 0x40: /* VSX Shift Left Double by Word Immediate (SHW=2) */ + case 2 | 0x60: /* VSX Shift Left Double by Word Immediate (SHW=3) */ + case 216: /* VSX Vector Insert Exponent Single-Precision */ + case 248: /* VSX Vector Insert Exponent Double-Precision */ + case 26: /* VSX Vector Permute */ + case 58: /* VSX Vector Permute Right-indexed */ + case 213: /* VSX Vector Test Data Class Single-Precision (DC=0) */ + case 213 | 0x8: /* VSX Vector Test Data Class Single-Precision (DC=1) */ + case 245: /* VSX Vector Test Data Class Double-Precision (DC=0) */ + case 245 | 0x8: /* VSX Vector Test Data Class Double-Precision (DC=1) */ + ppc_record_vsr (regcache, tdep, PPC_XT (insn)); + return 0; + + case 61: /* VSX Scalar Test for software Divide Double-Precision */ + case 125: /* VSX Vector Test for software Divide Double-Precision */ + case 93: /* VSX Vector Test for software Divide Single-Precision */ + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + return 0; + + case 35: /* VSX Scalar Compare Unordered Double-Precision */ + case 43: /* VSX Scalar Compare Ordered Double-Precision */ + case 59: /* VSX Scalar Compare Exponents Double-Precision */ + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + return 0; + } + + switch ((ext >> 2) & 0x7f) /* Mask out Rc-bit. */ + { + case 99: /* VSX Vector Compare Equal To Double-Precision */ + case 67: /* VSX Vector Compare Equal To Single-Precision */ + case 115: /* VSX Vector Compare Greater Than or + Equal To Double-Precision */ + case 83: /* VSX Vector Compare Greater Than or + Equal To Single-Precision */ + case 107: /* VSX Vector Compare Greater Than Double-Precision */ + case 75: /* VSX Vector Compare Greater Than Single-Precision */ + if (PPC_Rc (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + ppc_record_vsr (regcache, tdep, PPC_XT (insn)); + return 0; + } + + switch (ext >> 1) + { + case 265: /* VSX Scalar round Double-Precision to + Single-Precision and Convert to + Single-Precision format */ + case 344: /* VSX Scalar truncate Double-Precision to + Integer and Convert to Signed Integer + Doubleword format with Saturate */ + case 88: /* VSX Scalar truncate Double-Precision to + Integer and Convert to Signed Integer Word + Format with Saturate */ + case 328: /* VSX Scalar truncate Double-Precision integer + and Convert to Unsigned Integer Doubleword + Format with Saturate */ + case 72: /* VSX Scalar truncate Double-Precision to + Integer and Convert to Unsigned Integer Word + Format with Saturate */ + case 329: /* VSX Scalar Convert Single-Precision to + Double-Precision format */ + case 376: /* VSX Scalar Convert Signed Integer + Doubleword to floating-point format and + Round to Double-Precision format */ + case 312: /* VSX Scalar Convert Signed Integer + Doubleword to floating-point format and + round to Single-Precision */ + case 360: /* VSX Scalar Convert Unsigned Integer + Doubleword to floating-point format and + Round to Double-Precision format */ + case 296: /* VSX Scalar Convert Unsigned Integer + Doubleword to floating-point format and + Round to Single-Precision */ + case 73: /* VSX Scalar Round to Double-Precision Integer + Using Round to Nearest Away */ + case 107: /* VSX Scalar Round to Double-Precision Integer + Exact using Current rounding mode */ + case 121: /* VSX Scalar Round to Double-Precision Integer + Using Round toward -Infinity */ + case 105: /* VSX Scalar Round to Double-Precision Integer + Using Round toward +Infinity */ + case 89: /* VSX Scalar Round to Double-Precision Integer + Using Round toward Zero */ + case 90: /* VSX Scalar Reciprocal Estimate Double-Precision */ + case 26: /* VSX Scalar Reciprocal Estimate Single-Precision */ + case 281: /* VSX Scalar Round to Single-Precision */ + case 74: /* VSX Scalar Reciprocal Square Root Estimate + Double-Precision */ + case 10: /* VSX Scalar Reciprocal Square Root Estimate + Single-Precision */ + case 75: /* VSX Scalar Square Root Double-Precision */ + case 11: /* VSX Scalar Square Root Single-Precision */ + case 393: /* VSX Vector round Double-Precision to + Single-Precision and Convert to + Single-Precision format */ + case 472: /* VSX Vector truncate Double-Precision to + Integer and Convert to Signed Integer + Doubleword format with Saturate */ + case 216: /* VSX Vector truncate Double-Precision to + Integer and Convert to Signed Integer Word + Format with Saturate */ + case 456: /* VSX Vector truncate Double-Precision to + Integer and Convert to Unsigned Integer + Doubleword format with Saturate */ + case 200: /* VSX Vector truncate Double-Precision to + Integer and Convert to Unsigned Integer Word + Format with Saturate */ + case 457: /* VSX Vector Convert Single-Precision to + Double-Precision format */ + case 408: /* VSX Vector truncate Single-Precision to + Integer and Convert to Signed Integer + Doubleword format with Saturate */ + case 152: /* VSX Vector truncate Single-Precision to + Integer and Convert to Signed Integer Word + Format with Saturate */ + case 392: /* VSX Vector truncate Single-Precision to + Integer and Convert to Unsigned Integer + Doubleword format with Saturate */ + case 136: /* VSX Vector truncate Single-Precision to + Integer and Convert to Unsigned Integer Word + Format with Saturate */ + case 504: /* VSX Vector Convert and round Signed Integer + Doubleword to Double-Precision format */ + case 440: /* VSX Vector Convert and round Signed Integer + Doubleword to Single-Precision format */ + case 248: /* VSX Vector Convert Signed Integer Word to + Double-Precision format */ + case 184: /* VSX Vector Convert and round Signed Integer + Word to Single-Precision format */ + case 488: /* VSX Vector Convert and round Unsigned + Integer Doubleword to Double-Precision format */ + case 424: /* VSX Vector Convert and round Unsigned + Integer Doubleword to Single-Precision format */ + case 232: /* VSX Vector Convert and round Unsigned + Integer Word to Double-Precision format */ + case 168: /* VSX Vector Convert and round Unsigned + Integer Word to Single-Precision format */ + case 201: /* VSX Vector Round to Double-Precision + Integer using round to Nearest Away */ + case 235: /* VSX Vector Round to Double-Precision + Integer Exact using Current rounding mode */ + case 249: /* VSX Vector Round to Double-Precision + Integer using round toward -Infinity */ + case 233: /* VSX Vector Round to Double-Precision + Integer using round toward +Infinity */ + case 217: /* VSX Vector Round to Double-Precision + Integer using round toward Zero */ + case 218: /* VSX Vector Reciprocal Estimate Double-Precision */ + case 154: /* VSX Vector Reciprocal Estimate Single-Precision */ + case 137: /* VSX Vector Round to Single-Precision Integer + Using Round to Nearest Away */ + case 171: /* VSX Vector Round to Single-Precision Integer + Exact Using Current rounding mode */ + case 185: /* VSX Vector Round to Single-Precision Integer + Using Round toward -Infinity */ + case 169: /* VSX Vector Round to Single-Precision Integer + Using Round toward +Infinity */ + case 153: /* VSX Vector Round to Single-Precision Integer + Using round toward Zero */ + case 202: /* VSX Vector Reciprocal Square Root Estimate + Double-Precision */ + case 138: /* VSX Vector Reciprocal Square Root Estimate + Single-Precision */ + case 203: /* VSX Vector Square Root Double-Precision */ + case 139: /* VSX Vector Square Root Single-Precision */ + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + /* FALL-THROUGH */ + case 345: /* VSX Scalar Absolute Value Double-Precision */ + case 267: /* VSX Scalar Convert Scalar Single-Precision to + Vector Single-Precision format Non-signalling */ + case 331: /* VSX Scalar Convert Single-Precision to + Double-Precision format Non-signalling */ + case 361: /* VSX Scalar Negative Absolute Value Double-Precision */ + case 377: /* VSX Scalar Negate Double-Precision */ + case 473: /* VSX Vector Absolute Value Double-Precision */ + case 409: /* VSX Vector Absolute Value Single-Precision */ + case 489: /* VSX Vector Negative Absolute Value Double-Precision */ + case 425: /* VSX Vector Negative Absolute Value Single-Precision */ + case 505: /* VSX Vector Negate Double-Precision */ + case 441: /* VSX Vector Negate Single-Precision */ + case 164: /* VSX Splat Word */ + case 165: /* VSX Vector Extract Unsigned Word */ + case 181: /* VSX Vector Insert Word */ + ppc_record_vsr (regcache, tdep, PPC_XT (insn)); + return 0; + + case 298: /* VSX Scalar Test Data Class Single-Precision */ + case 362: /* VSX Scalar Test Data Class Double-Precision */ + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + /* FALL-THROUGH */ + case 106: /* VSX Scalar Test for software Square Root + Double-Precision */ + case 234: /* VSX Vector Test for software Square Root + Double-Precision */ + case 170: /* VSX Vector Test for software Square Root + Single-Precision */ + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + return 0; + + case 347: + switch (PPC_FIELD (insn, 11, 5)) + { + case 0: /* VSX Scalar Extract Exponent Double-Precision */ + case 1: /* VSX Scalar Extract Significand Double-Precision */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RT (insn)); + return 0; + case 16: /* VSX Scalar Convert Half-Precision format to + Double-Precision format */ + case 17: /* VSX Scalar round & Convert Double-Precision format + to Half-Precision format */ + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + ppc_record_vsr (regcache, tdep, PPC_XT (insn)); + return 0; + } + break; + + case 475: + switch (PPC_FIELD (insn, 11, 5)) + { + case 24: /* VSX Vector Convert Half-Precision format to + Single-Precision format */ + case 25: /* VSX Vector round and Convert Single-Precision format + to Half-Precision format */ + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + /* FALL-THROUGH */ + case 0: /* VSX Vector Extract Exponent Double-Precision */ + case 1: /* VSX Vector Extract Significand Double-Precision */ + case 7: /* VSX Vector Byte-Reverse Halfword */ + case 8: /* VSX Vector Extract Exponent Single-Precision */ + case 9: /* VSX Vector Extract Significand Single-Precision */ + case 15: /* VSX Vector Byte-Reverse Word */ + case 23: /* VSX Vector Byte-Reverse Doubleword */ + case 31: /* VSX Vector Byte-Reverse Quadword */ + ppc_record_vsr (regcache, tdep, PPC_XT (insn)); + return 0; + } + break; + } + + switch (ext) + { + case 360: /* VSX Vector Splat Immediate Byte */ + if (PPC_FIELD (insn, 11, 2) == 0) + { + ppc_record_vsr (regcache, tdep, PPC_XT (insn)); + return 0; + } + break; + case 918: /* VSX Scalar Insert Exponent Double-Precision */ + ppc_record_vsr (regcache, tdep, PPC_XT (insn)); + return 0; + } + + if (((ext >> 3) & 0x3) == 3) /* VSX Select */ + { + ppc_record_vsr (regcache, tdep, PPC_XT (insn)); + return 0; + } + + fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x " + "at %s, 60-%d.\n", insn, paddress (gdbarch, addr), ext); + return -1; +} + +/* Parse and record instructions of primary opcode-61 at ADDR. + Return 0 if successful. */ + +static int +ppc_process_record_op61 (struct gdbarch *gdbarch, struct regcache *regcache, + CORE_ADDR addr, uint32_t insn) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + ULONGEST ea = 0; + int size; + + switch (insn & 0x3) + { + case 0: /* Store Floating-Point Double Pair */ + case 2: /* Store VSX Scalar Doubleword */ + case 3: /* Store VSX Scalar Single */ + if (PPC_RA (insn) != 0) + regcache_raw_read_unsigned (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn), + &ea); + ea += PPC_DS (insn) << 2; + switch (insn & 0x3) + { + case 0: /* Store Floating-Point Double Pair */ + size = 16; + break; + case 2: /* Store VSX Scalar Doubleword */ + size = 8; + break; + case 3: /* Store VSX Scalar Single */ + size = 4; + break; + default: + gdb_assert (0); + } + record_full_arch_list_add_mem (ea, size); + return 0; + } + + switch (insn & 0x7) + { + case 1: /* Load VSX Vector */ + ppc_record_vsr (regcache, tdep, PPC_XT (insn)); + return 0; + case 5: /* Store VSX Vector */ + if (PPC_RA (insn) != 0) + regcache_raw_read_unsigned (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn), + &ea); + ea += PPC_DQ (insn) << 4; + record_full_arch_list_add_mem (ea, 16); + return 0; + } + + fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x " + "at %s.\n", insn, paddress (gdbarch, addr)); + return -1; +} + +/* Parse and record instructions of primary opcode-63 at ADDR. + Return 0 if successful. */ + +static int +ppc_process_record_op63 (struct gdbarch *gdbarch, struct regcache *regcache, + CORE_ADDR addr, uint32_t insn) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int ext = PPC_EXTOP (insn); + int tmp; + + switch (ext & 0x1f) + { + case 18: /* Floating Divide */ + case 20: /* Floating Subtract */ + case 21: /* Floating Add */ + case 22: /* Floating Square Root */ + case 24: /* Floating Reciprocal Estimate */ + case 25: /* Floating Multiply */ + case 26: /* Floating Reciprocal Square Root Estimate */ + case 28: /* Floating Multiply-Subtract */ + case 29: /* Floating Multiply-Add */ + case 30: /* Floating Negative Multiply-Subtract */ + case 31: /* Floating Negative Multiply-Add */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_fp0_regnum + PPC_FRT (insn)); + if (PPC_RC (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + return 0; + + case 23: /* Floating Select */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_fp0_regnum + PPC_FRT (insn)); + if (PPC_RC (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + return 0; + } + + switch (ext & 0xff) + { + case 5: /* VSX Scalar Round to Quad-Precision Integer */ + case 37: /* VSX Scalar Round Quad-Precision to Double-Extended + Precision */ + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + ppc_record_vsr (regcache, tdep, PPC_VRT (insn) + 32); + return 0; + } + + switch (ext) + { + case 2: /* DFP Add Quad */ + case 3: /* DFP Quantize Quad */ + case 34: /* DFP Multiply Quad */ + case 35: /* DFP Reround Quad */ + case 67: /* DFP Quantize Immediate Quad */ + case 99: /* DFP Round To FP Integer With Inexact Quad */ + case 227: /* DFP Round To FP Integer Without Inexact Quad */ + case 258: /* DFP Convert To DFP Extended Quad */ + case 514: /* DFP Subtract Quad */ + case 546: /* DFP Divide Quad */ + case 770: /* DFP Round To DFP Long Quad */ + case 802: /* DFP Convert From Fixed Quad */ + case 834: /* DFP Encode BCD To DPD Quad */ + if (PPC_RC (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + tmp = tdep->ppc_fp0_regnum + (PPC_FRT (insn) & ~1); + record_full_arch_list_add_reg (regcache, tmp); + record_full_arch_list_add_reg (regcache, tmp + 1); + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + return 0; + + case 130: /* DFP Compare Ordered Quad */ + case 162: /* DFP Test Exponent Quad */ + case 194: /* DFP Test Data Class Quad */ + case 226: /* DFP Test Data Group Quad */ + case 642: /* DFP Compare Unordered Quad */ + case 674: /* DFP Test Significance Quad */ + case 675: /* DFP Test Significance Immediate Quad */ + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + return 0; + + case 66: /* DFP Shift Significand Left Immediate Quad */ + case 98: /* DFP Shift Significand Right Immediate Quad */ + case 322: /* DFP Decode DPD To BCD Quad */ + case 866: /* DFP Insert Biased Exponent Quad */ + tmp = tdep->ppc_fp0_regnum + (PPC_FRT (insn) & ~1); + record_full_arch_list_add_reg (regcache, tmp); + record_full_arch_list_add_reg (regcache, tmp + 1); + if (PPC_RC (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + return 0; + + case 290: /* DFP Convert To Fixed Quad */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_fp0_regnum + PPC_FRT (insn)); + if (PPC_RC (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + return 0; + + case 354: /* DFP Extract Biased Exponent Quad */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_fp0_regnum + PPC_FRT (insn)); + if (PPC_RC (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + return 0; + + case 12: /* Floating Round to Single-Precision */ + case 14: /* Floating Convert To Integer Word */ + case 15: /* Floating Convert To Integer Word + with round toward Zero */ + case 142: /* Floating Convert To Integer Word Unsigned */ + case 143: /* Floating Convert To Integer Word Unsigned + with round toward Zero */ + case 392: /* Floating Round to Integer Nearest */ + case 424: /* Floating Round to Integer Toward Zero */ + case 456: /* Floating Round to Integer Plus */ + case 488: /* Floating Round to Integer Minus */ + case 814: /* Floating Convert To Integer Doubleword */ + case 815: /* Floating Convert To Integer Doubleword + with round toward Zero */ + case 846: /* Floating Convert From Integer Doubleword */ + case 942: /* Floating Convert To Integer Doubleword Unsigned */ + case 943: /* Floating Convert To Integer Doubleword Unsigned + with round toward Zero */ + case 974: /* Floating Convert From Integer Doubleword Unsigned */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_fp0_regnum + PPC_FRT (insn)); + if (PPC_RC (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + return 0; + + case 583: + switch (PPC_FIELD (insn, 11, 5)) + { + case 1: /* Move From FPSCR & Clear Enables */ + case 20: /* Move From FPSCR Control & set DRN */ + case 21: /* Move From FPSCR Control & set DRN Immediate */ + case 22: /* Move From FPSCR Control & set RN */ + case 23: /* Move From FPSCR Control & set RN Immediate */ + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + case 0: /* Move From FPSCR */ + case 24: /* Move From FPSCR Lightweight */ + if (PPC_FIELD (insn, 11, 5) == 0 && PPC_RC (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + record_full_arch_list_add_reg (regcache, + tdep->ppc_fp0_regnum + + PPC_FRT (insn)); + return 0; + } + break; + + case 8: /* Floating Copy Sign */ + case 40: /* Floating Negate */ + case 72: /* Floating Move Register */ + case 136: /* Floating Negative Absolute Value */ + case 264: /* Floating Absolute Value */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_fp0_regnum + PPC_FRT (insn)); + if (PPC_RC (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + return 0; + + case 838: /* Floating Merge Odd Word */ + case 966: /* Floating Merge Even Word */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_fp0_regnum + PPC_FRT (insn)); + return 0; + + case 38: /* Move To FPSCR Bit 1 */ + case 70: /* Move To FPSCR Bit 0 */ + case 134: /* Move To FPSCR Field Immediate */ + case 711: /* Move To FPSCR Fields */ + if (PPC_RC (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + return 0; + + case 0: /* Floating Compare Unordered */ + case 32: /* Floating Compare Ordered */ + case 64: /* Move to Condition Register from FPSCR */ + case 132: /* VSX Scalar Compare Ordered Quad-Precision */ + case 164: /* VSX Scalar Compare Exponents Quad-Precision */ + case 644: /* VSX Scalar Compare Unordered Quad-Precision */ + case 708: /* VSX Scalar Test Data Class Quad-Precision */ + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + /* FALL-THROUGH */ + case 128: /* Floating Test for software Divide */ + case 160: /* Floating Test for software Square Root */ + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + return 0; + + case 4: /* VSX Scalar Add Quad-Precision */ + case 36: /* VSX Scalar Multiply Quad-Precision */ + case 388: /* VSX Scalar Multiply-Add Quad-Precision */ + case 420: /* VSX Scalar Multiply-Subtract Quad-Precision */ + case 452: /* VSX Scalar Negative Multiply-Add Quad-Precision */ + case 484: /* VSX Scalar Negative Multiply-Subtract + Quad-Precision */ + case 516: /* VSX Scalar Subtract Quad-Precision */ + case 548: /* VSX Scalar Divide Quad-Precision */ + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + /* FALL-THROUGH */ + case 100: /* VSX Scalar Copy Sign Quad-Precision */ + case 868: /* VSX Scalar Insert Exponent Quad-Precision */ + ppc_record_vsr (regcache, tdep, PPC_VRT (insn) + 32); + return 0; + + case 804: + switch (PPC_FIELD (insn, 11, 5)) + { + case 27: /* VSX Scalar Square Root Quad-Precision */ + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + /* FALL-THROUGH */ + case 0: /* VSX Scalar Absolute Quad-Precision */ + case 2: /* VSX Scalar Extract Exponent Quad-Precision */ + case 8: /* VSX Scalar Negative Absolute Quad-Precision */ + case 16: /* VSX Scalar Negate Quad-Precision */ + case 18: /* VSX Scalar Extract Significand Quad-Precision */ + ppc_record_vsr (regcache, tdep, PPC_VRT (insn) + 32); + return 0; + } + break; + + case 836: + switch (PPC_FIELD (insn, 11, 5)) + { + case 1: /* VSX Scalar truncate & Convert Quad-Precision format + to Unsigned Word format */ + case 2: /* VSX Scalar Convert Unsigned Doubleword format to + Quad-Precision format */ + case 9: /* VSX Scalar truncate & Convert Quad-Precision format + to Signed Word format */ + case 10: /* VSX Scalar Convert Signed Doubleword format to + Quad-Precision format */ + case 17: /* VSX Scalar truncate & Convert Quad-Precision format + to Unsigned Doubleword format */ + case 20: /* VSX Scalar round & Convert Quad-Precision format to + Double-Precision format */ + case 22: /* VSX Scalar Convert Double-Precision format to + Quad-Precision format */ + case 25: /* VSX Scalar truncate & Convert Quad-Precision format + to Signed Doubleword format */ + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + ppc_record_vsr (regcache, tdep, PPC_VRT (insn) + 32); + return 0; + } + } + + fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x " + "at %s, 63-%d.\n", insn, paddress (gdbarch, addr), ext); + return -1; +} + +/* Parse the current instruction and record the values of the registers and + memory that will be changed in current instruction to "record_arch_list". + Return -1 if something wrong. */ + +int +ppc_process_record (struct gdbarch *gdbarch, struct regcache *regcache, + CORE_ADDR addr) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + uint32_t insn; + int op6, tmp, i; + + insn = read_memory_unsigned_integer (addr, 4, byte_order); + op6 = PPC_OP6 (insn); + + switch (op6) + { + case 2: /* Trap Doubleword Immediate */ + case 3: /* Trap Word Immediate */ + /* Do nothing. */ + break; + + case 4: + if (ppc_process_record_op4 (gdbarch, regcache, addr, insn) != 0) + return -1; + break; + + case 17: /* System call */ + if (PPC_LEV (insn) != 0) + goto UNKNOWN_OP; + + if (tdep->ppc_syscall_record != NULL) + { + if (tdep->ppc_syscall_record (regcache) != 0) + return -1; + } + else + { + printf_unfiltered (_("no syscall record support\n")); + return -1; + } + break; + + case 7: /* Multiply Low Immediate */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RT (insn)); + break; + + case 8: /* Subtract From Immediate Carrying */ + record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum); + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RT (insn)); + break; + + case 10: /* Compare Logical Immediate */ + case 11: /* Compare Immediate */ + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + break; + + case 13: /* Add Immediate Carrying and Record */ + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + /* FALL-THROUGH */ + case 12: /* Add Immediate Carrying */ + record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum); + /* FALL-THROUGH */ + case 14: /* Add Immediate */ + case 15: /* Add Immediate Shifted */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RT (insn)); + break; + + case 16: /* Branch Conditional */ + if ((PPC_BO (insn) & 0x4) == 0) + record_full_arch_list_add_reg (regcache, tdep->ppc_ctr_regnum); + /* FALL-THROUGH */ + case 18: /* Branch */ + if (PPC_LK (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_lr_regnum); + break; + + case 19: + if (ppc_process_record_op19 (gdbarch, regcache, addr, insn) != 0) + return -1; + break; + + case 20: /* Rotate Left Word Immediate then Mask Insert */ + case 21: /* Rotate Left Word Immediate then AND with Mask */ + case 23: /* Rotate Left Word then AND with Mask */ + case 30: /* Rotate Left Doubleword Immediate then Clear Left */ + /* Rotate Left Doubleword Immediate then Clear Right */ + /* Rotate Left Doubleword Immediate then Clear */ + /* Rotate Left Doubleword then Clear Left */ + /* Rotate Left Doubleword then Clear Right */ + /* Rotate Left Doubleword Immediate then Mask Insert */ + if (PPC_RC (insn)) + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn)); + break; + + case 28: /* AND Immediate */ + case 29: /* AND Immediate Shifted */ + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + /* FALL-THROUGH */ + case 24: /* OR Immediate */ + case 25: /* OR Immediate Shifted */ + case 26: /* XOR Immediate */ + case 27: /* XOR Immediate Shifted */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn)); + break; + + case 31: + if (ppc_process_record_op31 (gdbarch, regcache, addr, insn) != 0) + return -1; + break; + + case 33: /* Load Word and Zero with Update */ + case 35: /* Load Byte and Zero with Update */ + case 41: /* Load Halfword and Zero with Update */ + case 43: /* Load Halfword Algebraic with Update */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn)); + /* FALL-THROUGH */ + case 32: /* Load Word and Zero */ + case 34: /* Load Byte and Zero */ + case 40: /* Load Halfword and Zero */ + case 42: /* Load Halfword Algebraic */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RT (insn)); + break; + + case 46: /* Load Multiple Word */ + for (i = PPC_RT (insn); i < 32; i++) + record_full_arch_list_add_reg (regcache, tdep->ppc_gp0_regnum + i); + break; + + case 56: /* Load Quadword */ + tmp = tdep->ppc_gp0_regnum + (PPC_RT (insn) & ~1); + record_full_arch_list_add_reg (regcache, tmp); + record_full_arch_list_add_reg (regcache, tmp + 1); + break; + + case 49: /* Load Floating-Point Single with Update */ + case 51: /* Load Floating-Point Double with Update */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn)); + /* FALL-THROUGH */ + case 48: /* Load Floating-Point Single */ + case 50: /* Load Floating-Point Double */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_fp0_regnum + PPC_FRT (insn)); + break; + + case 47: /* Store Multiple Word */ + { + ULONGEST addr = 0; + + if (PPC_RA (insn) != 0) + regcache_raw_read_unsigned (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn), + &addr); + + addr += PPC_D (insn); + record_full_arch_list_add_mem (addr, 4 * (32 - PPC_RS (insn))); + } + break; + + case 37: /* Store Word with Update */ + case 39: /* Store Byte with Update */ + case 45: /* Store Halfword with Update */ + case 53: /* Store Floating-Point Single with Update */ + case 55: /* Store Floating-Point Double with Update */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn)); + /* FALL-THROUGH */ + case 36: /* Store Word */ + case 38: /* Store Byte */ + case 44: /* Store Halfword */ + case 52: /* Store Floating-Point Single */ + case 54: /* Store Floating-Point Double */ + { + ULONGEST addr = 0; + int size = -1; + + if (PPC_RA (insn) != 0) + regcache_raw_read_unsigned (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn), + &addr); + addr += PPC_D (insn); + + if (op6 == 36 || op6 == 37 || op6 == 52 || op6 == 53) + size = 4; + else if (op6 == 54 || op6 == 55) + size = 8; + else if (op6 == 44 || op6 == 45) + size = 2; + else if (op6 == 38 || op6 == 39) + size = 1; + else + gdb_assert (0); + + record_full_arch_list_add_mem (addr, size); + } + break; + + case 57: + switch (insn & 0x3) + { + case 0: /* Load Floating-Point Double Pair */ + tmp = tdep->ppc_fp0_regnum + (PPC_RT (insn) & ~1); + record_full_arch_list_add_reg (regcache, tmp); + record_full_arch_list_add_reg (regcache, tmp + 1); + break; + case 2: /* Load VSX Scalar Doubleword */ + case 3: /* Load VSX Scalar Single */ + ppc_record_vsr (regcache, tdep, PPC_VRT (insn) + 32); + break; + default: + goto UNKNOWN_OP; + } + break; + + case 58: /* Load Doubleword */ + /* Load Doubleword with Update */ + /* Load Word Algebraic */ + if (PPC_FIELD (insn, 30, 2) > 2) + goto UNKNOWN_OP; + + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RT (insn)); + if (PPC_BIT (insn, 31)) + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn)); + break; + + case 59: + if (ppc_process_record_op59 (gdbarch, regcache, addr, insn) != 0) + return -1; + break; + + case 60: + if (ppc_process_record_op60 (gdbarch, regcache, addr, insn) != 0) + return -1; + break; + + case 61: + if (ppc_process_record_op61 (gdbarch, regcache, addr, insn) != 0) + return -1; + break; + + case 62: /* Store Doubleword */ + /* Store Doubleword with Update */ + /* Store Quadword with Update */ + { + ULONGEST addr = 0; + int size; + int sub2 = PPC_FIELD (insn, 30, 2); + + if (sub2 > 2) + goto UNKNOWN_OP; + + if (PPC_RA (insn) != 0) + regcache_raw_read_unsigned (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn), + &addr); + + size = (sub2 == 2) ? 16 : 8; + + addr += PPC_DS (insn) << 2; + record_full_arch_list_add_mem (addr, size); + + if (op6 == 62 && sub2 == 1) + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + + PPC_RA (insn)); + + break; + } + + case 63: + if (ppc_process_record_op63 (gdbarch, regcache, addr, insn) != 0) + return -1; + break; + + default: +UNKNOWN_OP: + fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x " + "at %s, %d.\n", insn, paddress (gdbarch, addr), op6); + return -1; + } + + if (record_full_arch_list_add_reg (regcache, PPC_PC_REGNUM)) + return -1; + if (record_full_arch_list_add_end ()) + return -1; + return 0; +} + +/* 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. + + Called e.g. at program startup, when reading a core file, and when reading + a binary file. */ + +static struct gdbarch * +rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) +{ + struct gdbarch *gdbarch; + struct gdbarch_tdep *tdep; + int wordsize, from_xcoff_exec, from_elf_exec; + enum bfd_architecture arch; + unsigned long mach; + bfd abfd; + enum auto_boolean soft_float_flag = powerpc_soft_float_global; + int soft_float; + enum powerpc_vector_abi vector_abi = powerpc_vector_abi_global; + enum powerpc_elf_abi elf_abi = POWERPC_ELF_AUTO; + 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; + + /* Check word size. If INFO is from a binary file, infer it from + that, else choose a likely default. */ + if (from_xcoff_exec) + { + if (bfd_xcoff_is_xcoff64 (info.abfd)) + wordsize = 8; + else + wordsize = 4; + } + else if (from_elf_exec) + { + if (elf_elfheader (info.abfd)->e_ident[EI_CLASS] == ELFCLASS64) + wordsize = 8; + 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 = (info.bfd_arch_info->bits_per_word + / info.bfd_arch_info->bits_per_byte); + else + 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. Grovel through the section + looking for relevant e500 APUs. */ + + if (bfd_uses_spe_extensions (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 + 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)); @@ -3643,10 +6036,6 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) "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" }; @@ -3853,6 +6242,21 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) } #ifdef HAVE_ELF + if (from_elf_exec) + { + switch (elf_elfheader (info.abfd)->e_flags & EF_PPC64_ABI) + { + case 1: + elf_abi = POWERPC_ELF_V1; + break; + case 2: + elf_abi = POWERPC_ELF_V2; + break; + default: + break; + } + } + if (soft_float_flag == AUTO_BOOLEAN_AUTO && from_elf_exec) { switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU, @@ -3889,6 +6293,21 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) } #endif + /* At this point, the only supported ELF-based 64-bit little-endian + operating system is GNU/Linux, and this uses the ELFv2 ABI by + default. All other supported ELF-based operating systems use the + ELFv1 ABI by default. Therefore, if the ABI marker is missing, + e.g. because we run a legacy binary, or have attached to a process + and have not found any associated binary file, set the default + according to this heuristic. */ + if (elf_abi == POWERPC_ELF_AUTO) + { + if (wordsize == 8 && info.byte_order == BFD_ENDIAN_LITTLE) + elf_abi = POWERPC_ELF_V2; + else + elf_abi = POWERPC_ELF_V1; + } + if (soft_float_flag == AUTO_BOOLEAN_TRUE) soft_float = 1; else if (soft_float_flag == AUTO_BOOLEAN_FALSE) @@ -3931,6 +6350,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) 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->elf_abi != elf_abi) + continue; if (tdep && tdep->soft_float != soft_float) continue; if (tdep && tdep->vector_abi != vector_abi) @@ -3951,8 +6372,9 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) - "set arch" trust blindly - GDB startup useless but harmless */ - tdep = XCALLOC (1, struct gdbarch_tdep); + tdep = XCNEW (struct gdbarch_tdep); tdep->wordsize = wordsize; + tdep->elf_abi = elf_abi; tdep->soft_float = soft_float; tdep->vector_abi = vector_abi; @@ -3978,7 +6400,6 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) 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); @@ -4003,8 +6424,12 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_pseudo_register_read (gdbarch, rs6000_pseudo_register_read); set_gdbarch_pseudo_register_write (gdbarch, rs6000_pseudo_register_write); + set_gdbarch_ax_pseudo_register_collect (gdbarch, + rs6000_ax_pseudo_register_collect); } + set_gdbarch_gen_return_address (gdbarch, rs6000_gen_return_address); + set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1); /* Select instruction printer. */ @@ -4053,7 +6478,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_push_dummy_call (gdbarch, ppc64_sysv_abi_push_dummy_call); set_gdbarch_skip_prologue (gdbarch, rs6000_skip_prologue); - set_gdbarch_in_function_epilogue_p (gdbarch, rs6000_in_function_epilogue_p); + set_gdbarch_stack_frame_destroyed_p (gdbarch, rs6000_stack_frame_destroyed_p); set_gdbarch_skip_main_prologue (gdbarch, rs6000_skip_main_prologue); set_gdbarch_inner_than (gdbarch, core_addr_lessthan); @@ -4086,7 +6511,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Setup displaced stepping. */ set_gdbarch_displaced_step_copy_insn (gdbarch, - simple_displaced_step_copy_insn); + ppc_displaced_step_copy_insn); set_gdbarch_displaced_step_hw_singlestep (gdbarch, ppc_displaced_step_hw_singlestep); set_gdbarch_displaced_step_fixup (gdbarch, ppc_displaced_step_fixup); @@ -4099,7 +6524,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Hook in ABI-specific overrides, if they have been registered. */ info.target_desc = tdesc; - info.tdep_info = (void *) tdesc_data; + info.tdep_info = tdesc_data; gdbarch_init_osabi (info, gdbarch); switch (info.osabi) @@ -4109,6 +6534,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) case GDB_OSABI_NETBSD_ELF: case GDB_OSABI_UNKNOWN: set_gdbarch_unwind_pc (gdbarch, rs6000_unwind_pc); + frame_unwind_append_unwinder (gdbarch, &rs6000_epilogue_frame_unwind); 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); @@ -4117,6 +6543,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_believe_pcc_promotion (gdbarch, 1); set_gdbarch_unwind_pc (gdbarch, rs6000_unwind_pc); + frame_unwind_append_unwinder (gdbarch, &rs6000_epilogue_frame_unwind); 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); @@ -4160,6 +6587,12 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) gdb_assert (gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch) == cur_reg); + /* Register the ravenscar_arch_ops. */ + if (mach == bfd_mach_ppc_e500) + register_e500_ravenscar_ops (gdbarch); + else + register_ppc_ravenscar_ops (gdbarch); + return gdbarch; } @@ -4207,7 +6640,7 @@ powerpc_set_vector_abi (char *args, int from_tty, struct cmd_list_element *c) { struct gdbarch_info info; - enum powerpc_vector_abi vector_abi; + int vector_abi; for (vector_abi = POWERPC_VEC_AUTO; vector_abi != POWERPC_VEC_LAST; @@ -4215,7 +6648,7 @@ powerpc_set_vector_abi (char *args, int from_tty, if (strcmp (powerpc_vector_abi_string, powerpc_vector_strings[vector_abi]) == 0) { - powerpc_vector_abi_global = vector_abi; + powerpc_vector_abi_global = (enum powerpc_vector_abi) vector_abi; break; } @@ -4239,6 +6672,75 @@ show_powerpc_exact_watchpoints (struct ui_file *file, int from_tty, fprintf_filtered (file, _("Use of exact watchpoints is %s.\n"), value); } +/* Read a PPC instruction from memory. */ + +static unsigned int +read_insn (struct frame_info *frame, CORE_ADDR pc) +{ + struct gdbarch *gdbarch = get_frame_arch (frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + + return read_memory_unsigned_integer (pc, 4, byte_order); +} + +/* Return non-zero if the instructions at PC match the series + described in PATTERN, or zero otherwise. PATTERN is an array of + 'struct ppc_insn_pattern' objects, terminated by an entry whose + mask is zero. + + When the match is successful, fill INSN[i] with what PATTERN[i] + matched. If PATTERN[i] is optional, and the instruction wasn't + present, set INSN[i] to 0 (which is not a valid PPC instruction). + INSN should have as many elements as PATTERN. Note that, if + PATTERN contains optional instructions which aren't present in + memory, then INSN will have holes, so INSN[i] isn't necessarily the + i'th instruction in memory. */ + +int +ppc_insns_match_pattern (struct frame_info *frame, CORE_ADDR pc, + struct ppc_insn_pattern *pattern, + unsigned int *insns) +{ + int i; + unsigned int insn; + + for (i = 0, insn = 0; pattern[i].mask; i++) + { + if (insn == 0) + insn = read_insn (frame, pc); + insns[i] = 0; + if ((insn & pattern[i].mask) == pattern[i].data) + { + insns[i] = insn; + pc += 4; + insn = 0; + } + else if (!pattern[i].optional) + return 0; + } + + return 1; +} + +/* Return the 'd' field of the d-form instruction INSN, properly + sign-extended. */ + +CORE_ADDR +ppc_insn_d_field (unsigned int insn) +{ + return ((((CORE_ADDR) insn & 0xffff) ^ 0x8000) - 0x8000); +} + +/* Return the 'ds' field of the ds-form instruction INSN, with the two + zero bits concatenated at the right, and properly + sign-extended. */ + +CORE_ADDR +ppc_insn_ds_field (unsigned int insn) +{ + return ((((CORE_ADDR) insn & 0xfffc) ^ 0x8000) - 0x8000); +} + /* Initialization code. */ /* -Wmissing-prototypes */