X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Frs6000-tdep.c;h=fc12619a7b06ecec9da7e01845672681c0291402;hb=40887e1a6e8bc0dfb421662f40c1a2c356c8b36d;hp=9cb560a169e065fa6c6b73486c406ac7554edff9;hpb=67d57894593345f23efe728f00b0a8c72216b962;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index 9cb560a169..fc12619a7b 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -1,7 +1,7 @@ /* Target-dependent code for GDB, the GNU debugger. Copyright (C) 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This file is part of GDB. @@ -78,6 +78,16 @@ #include "features/rs6000/powerpc-e500.c" #include "features/rs6000/rs6000.c" +/* Determine if regnum is an SPE pseudo-register. */ +#define IS_SPE_PSEUDOREG(tdep, regnum) ((tdep)->ppc_ev0_regnum >= 0 \ + && (regnum) >= (tdep)->ppc_ev0_regnum \ + && (regnum) < (tdep)->ppc_ev0_regnum + 32) + +/* Determine if regnum is a decimal float pseudo-register. */ +#define IS_DFP_PSEUDOREG(tdep, regnum) ((tdep)->ppc_dl0_regnum >= 0 \ + && (regnum) >= (tdep)->ppc_dl0_regnum \ + && (regnum) < (tdep)->ppc_dl0_regnum + 16) + /* The list of available "set powerpc ..." and "show powerpc ..." commands. */ static struct cmd_list_element *setpowerpccmdlist = NULL; @@ -157,14 +167,14 @@ CORE_ADDR (*rs6000_find_toc_address_hook) (CORE_ADDR) = NULL; static CORE_ADDR branch_dest (struct frame_info *frame, int opcode, int instr, CORE_ADDR pc, CORE_ADDR safety); -static CORE_ADDR skip_prologue (CORE_ADDR, CORE_ADDR, +static CORE_ADDR skip_prologue (struct gdbarch *, CORE_ADDR, CORE_ADDR, struct rs6000_framedata *); /* Is REGNO an AltiVec register? Return 1 if so, 0 otherwise. */ int -altivec_register_p (int regno) +altivec_register_p (struct gdbarch *gdbarch, int regno) { - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); if (tdep->ppc_vr0_regnum < 0 || tdep->ppc_vrsave_regnum < 0) return 0; else @@ -174,14 +184,12 @@ altivec_register_p (int regno) /* Return true if REGNO is an SPE register, false otherwise. */ int -spe_register_p (int regno) +spe_register_p (struct gdbarch *gdbarch, int regno) { - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); /* Is it a reference to EV0 -- EV31, and do we have those? */ - if (tdep->ppc_ev0_regnum >= 0 - && tdep->ppc_ev31_regnum >= 0 - && tdep->ppc_ev0_regnum <= regno && regno <= tdep->ppc_ev31_regnum) + if (IS_SPE_PSEUDOREG (tdep, regno)) return 1; /* Is it a reference to one of the raw upper GPR halves? */ @@ -342,17 +350,17 @@ init_sim_regno_table (struct gdbarch *arch) /* Given a GDB register number REG, return the corresponding SIM register number. */ static int -rs6000_register_sim_regno (int reg) +rs6000_register_sim_regno (struct gdbarch *gdbarch, int reg) { - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int sim_regno; if (tdep->sim_regno == NULL) - init_sim_regno_table (current_gdbarch); + init_sim_regno_table (gdbarch); gdb_assert (0 <= reg - && reg <= gdbarch_num_regs (current_gdbarch) - + gdbarch_num_pseudo_regs (current_gdbarch)); + && reg <= gdbarch_num_regs (gdbarch) + + gdbarch_num_pseudo_regs (gdbarch)); sim_regno = tdep->sim_regno[reg]; if (sim_regno >= 0) @@ -754,7 +762,7 @@ read_memory_addr (CORE_ADDR memaddr, int len) } static CORE_ADDR -rs6000_skip_prologue (CORE_ADDR pc) +rs6000_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) { struct rs6000_framedata frame; CORE_ADDR limit_pc, func_addr; @@ -779,7 +787,7 @@ rs6000_skip_prologue (CORE_ADDR pc) if (limit_pc == 0) limit_pc = pc + 100; /* Magic. */ - pc = skip_prologue (pc, limit_pc, &frame); + pc = skip_prologue (gdbarch, pc, limit_pc, &frame); return pc; } @@ -1251,7 +1259,8 @@ bl_to_blrl_insn_p (CORE_ADDR pc, int insn) */ static CORE_ADDR -skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata) +skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, + struct rs6000_framedata *fdata) { CORE_ADDR orig_pc = pc; CORE_ADDR last_prologue_pc = pc; @@ -1272,8 +1281,8 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata) int prev_insn_was_prologue_insn = 1; int num_skip_non_prologue_insns = 0; int r0_contains_arg = 0; - const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (current_gdbarch); - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (gdbarch); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); memset (fdata, 0, sizeof (struct rs6000_framedata)); fdata->saved_gpr = -1; @@ -2370,9 +2379,7 @@ rs6000_register_name (struct gdbarch *gdbarch, int regno) return ""; /* Check if the SPE pseudo registers are available. */ - if (tdep->ppc_ev0_regnum >= 0 - && tdep->ppc_ev0_regnum <= regno - && regno < tdep->ppc_ev0_regnum + ppc_num_gprs) + if (IS_SPE_PSEUDOREG (tdep, regno)) { static const char *const spe_regnames[] = { "ev0", "ev1", "ev2", "ev3", "ev4", "ev5", "ev6", "ev7", @@ -2383,6 +2390,18 @@ rs6000_register_name (struct gdbarch *gdbarch, int regno) return spe_regnames[regno - tdep->ppc_ev0_regnum]; } + /* Check if the decimal128 pseudo-registers are available. */ + if (IS_DFP_PSEUDOREG (tdep, regno)) + { + static const char *const dfp128_regnames[] = { + "dl0", "dl1", "dl2", "dl3", + "dl4", "dl5", "dl6", "dl7", + "dl8", "dl9", "dl10", "dl11", + "dl12", "dl13", "dl14", "dl15" + }; + return dfp128_regnames[regno - tdep->ppc_dl0_regnum]; + } + return tdesc_register_name (gdbarch, regno); } @@ -2395,11 +2414,15 @@ rs6000_pseudo_register_type (struct gdbarch *gdbarch, int regnum) struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); /* These are the only pseudo-registers we support. */ - gdb_assert (tdep->ppc_ev0_regnum >= 0 - && regnum >= tdep->ppc_ev0_regnum - && regnum < tdep->ppc_ev0_regnum + 32); + gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum) + || IS_DFP_PSEUDOREG (tdep, regnum)); - return rs6000_builtin_type_vec64 (gdbarch); + /* These are the e500 pseudo-registers. */ + if (IS_SPE_PSEUDOREG (tdep, regnum)) + return rs6000_builtin_type_vec64 (gdbarch); + else + /* Could only be the ppc decimal128 pseudo-registers. */ + return builtin_type (gdbarch)->builtin_declong; } /* Is REGNUM a member of REGGROUP? */ @@ -2410,23 +2433,25 @@ rs6000_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum, struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); /* These are the only pseudo-registers we support. */ - gdb_assert (tdep->ppc_ev0_regnum >= 0 - && regnum >= tdep->ppc_ev0_regnum - && regnum < tdep->ppc_ev0_regnum + 32); + gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum) + || IS_DFP_PSEUDOREG (tdep, regnum)); - if (group == all_reggroup || group == vector_reggroup) - return 1; + /* These are the e500 pseudo-registers. */ + if (IS_SPE_PSEUDOREG (tdep, regnum)) + return group == all_reggroup || group == vector_reggroup; else - return 0; + /* Could only be the ppc decimal128 pseudo-registers. */ + return group == all_reggroup || group == float_reggroup; } /* The register format for RS/6000 floating point registers is always double, we need a conversion if the memory format is float. */ static int -rs6000_convert_register_p (int regnum, struct type *type) +rs6000_convert_register_p (struct gdbarch *gdbarch, int regnum, + struct type *type) { - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); return (tdep->ppc_fp0_regnum >= 0 && regnum >= tdep->ppc_fp0_regnum @@ -2497,8 +2522,7 @@ e500_move_ev_register (void (*move) (struct regcache *regcache, int reg_index; gdb_byte *byte_buffer = buffer; - gdb_assert (tdep->ppc_ev0_regnum <= ev_reg - && ev_reg < tdep->ppc_ev0_regnum + ppc_num_gprs); + gdb_assert (IS_SPE_PSEUDOREG (tdep, ev_reg)); reg_index = ev_reg - tdep->ppc_ev0_regnum; @@ -2517,48 +2541,118 @@ e500_move_ev_register (void (*move) (struct regcache *regcache, static void e500_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int reg_nr, gdb_byte *buffer) +{ + e500_move_ev_register (regcache_raw_read, regcache, reg_nr, buffer); +} + +static void +e500_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, + int reg_nr, const gdb_byte *buffer) +{ + e500_move_ev_register ((void (*) (struct regcache *, int, gdb_byte *)) + regcache_raw_write, + regcache, reg_nr, (gdb_byte *) buffer); +} + +/* Read method for PPC pseudo-registers. Currently this is handling the + 16 decimal128 registers that map into 16 pairs of FP registers. */ +static void +ppc_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, + int reg_nr, gdb_byte *buffer) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int reg_index = reg_nr - tdep->ppc_dl0_regnum; + + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + { + /* Read two FP registers to form a whole dl register. */ + regcache_raw_read (regcache, tdep->ppc_fp0_regnum + + 2 * reg_index, buffer); + regcache_raw_read (regcache, tdep->ppc_fp0_regnum + + 2 * reg_index + 1, buffer + 8); + } + else + { + regcache_raw_read (regcache, tdep->ppc_fp0_regnum + + 2 * reg_index + 1, buffer + 8); + regcache_raw_read (regcache, tdep->ppc_fp0_regnum + + 2 * reg_index, buffer); + } +} + +/* Write method for PPC pseudo-registers. Currently this is handling the + 16 decimal128 registers that map into 16 pairs of FP registers. */ +static void +ppc_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, + int reg_nr, const gdb_byte *buffer) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int reg_index = reg_nr - tdep->ppc_dl0_regnum; + + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + { + /* Write each half of the dl register into a separate + FP register. */ + regcache_raw_write (regcache, tdep->ppc_fp0_regnum + + 2 * reg_index, buffer); + regcache_raw_write (regcache, tdep->ppc_fp0_regnum + + 2 * reg_index + 1, buffer + 8); + } + else + { + regcache_raw_write (regcache, tdep->ppc_fp0_regnum + + 2 * reg_index + 1, buffer + 8); + regcache_raw_write (regcache, tdep->ppc_fp0_regnum + + 2 * reg_index, buffer); + } +} + +static void +rs6000_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, + int reg_nr, gdb_byte *buffer) { struct gdbarch *regcache_arch = get_regcache_arch (regcache); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); gdb_assert (regcache_arch == gdbarch); - - if (tdep->ppc_ev0_regnum <= reg_nr - && reg_nr < tdep->ppc_ev0_regnum + ppc_num_gprs) - e500_move_ev_register (regcache_raw_read, regcache, reg_nr, buffer); + + if (IS_SPE_PSEUDOREG (tdep, reg_nr)) + e500_pseudo_register_read (gdbarch, regcache, reg_nr, buffer); + else if (IS_DFP_PSEUDOREG (tdep, reg_nr)) + ppc_pseudo_register_read (gdbarch, regcache, reg_nr, buffer); else internal_error (__FILE__, __LINE__, - _("e500_pseudo_register_read: " - "called on unexpected register '%s' (%d)"), - gdbarch_register_name (gdbarch, reg_nr), reg_nr); + _("rs6000_pseudo_register_read: " + "called on unexpected register '%s' (%d)"), + gdbarch_register_name (gdbarch, reg_nr), reg_nr); } static void -e500_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, - int reg_nr, const gdb_byte *buffer) +rs6000_pseudo_register_write (struct gdbarch *gdbarch, + struct regcache *regcache, + int reg_nr, const gdb_byte *buffer) { struct gdbarch *regcache_arch = get_regcache_arch (regcache); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); gdb_assert (regcache_arch == gdbarch); - - if (tdep->ppc_ev0_regnum <= reg_nr - && reg_nr < tdep->ppc_ev0_regnum + ppc_num_gprs) - e500_move_ev_register ((void (*) (struct regcache *, int, gdb_byte *)) - regcache_raw_write, - regcache, reg_nr, (gdb_byte *) buffer); + + if (IS_SPE_PSEUDOREG (tdep, reg_nr)) + e500_pseudo_register_write (gdbarch, regcache, reg_nr, buffer); + else if (IS_DFP_PSEUDOREG (tdep, reg_nr)) + ppc_pseudo_register_write (gdbarch, regcache, reg_nr, buffer); else internal_error (__FILE__, __LINE__, - _("e500_pseudo_register_read: " - "called on unexpected register '%s' (%d)"), - gdbarch_register_name (gdbarch, reg_nr), reg_nr); + _("rs6000_pseudo_register_write: " + "called on unexpected register '%s' (%d)"), + gdbarch_register_name (gdbarch, reg_nr), reg_nr); } /* Convert a DBX STABS register number to a GDB register number. */ static int -rs6000_stab_reg_to_regnum (int num) +rs6000_stab_reg_to_regnum (struct gdbarch *gdbarch, int num) { - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); if (0 <= num && num <= 31) return tdep->ppc_gp0_regnum + num; @@ -2598,9 +2692,9 @@ rs6000_stab_reg_to_regnum (int num) /* Convert a Dwarf 2 register number to a GDB register number. */ static int -rs6000_dwarf2_reg_to_regnum (int num) +rs6000_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int num) { - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); if (0 <= num && num <= 31) return tdep->ppc_gp0_regnum + num; @@ -2835,7 +2929,7 @@ gdb_print_insn_powerpc (bfd_vma memaddr, disassemble_info *info) if (!info->disassembler_options) info->disassembler_options = "any"; - if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG) + if (info->endian == BFD_ENDIAN_BIG) return print_insn_big_powerpc (memaddr, info); else return print_insn_little_powerpc (memaddr, info); @@ -2881,7 +2975,7 @@ rs6000_frame_cache (struct frame_info *next_frame, void **this_cache) func = frame_func_unwind (next_frame, NORMAL_FRAME); pc = frame_pc_unwind (next_frame); - skip_prologue (func, pc, &fdata); + skip_prologue (gdbarch, func, pc, &fdata); /* Figure out the parent's stack pointer. */ @@ -2984,7 +3078,7 @@ rs6000_frame_cache (struct frame_info *next_frame, void **this_cache) /* if != -1, fdata.saved_ev is the smallest number of saved_ev. All vr's from saved_ev to ev31 are saved. ????? */ - if (tdep->ppc_ev0_regnum != -1 && tdep->ppc_ev31_regnum != -1) + if (tdep->ppc_ev0_regnum != -1) { if (fdata.saved_ev >= 0) { @@ -3144,9 +3238,9 @@ ppc_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, } /* Handle PC register and Stack Pointer correctly. */ - if (regnum == gdbarch_pc_regnum (current_gdbarch)) + if (regnum == gdbarch_pc_regnum (gdbarch)) reg->how = DWARF2_FRAME_REG_RA; - else if (regnum == gdbarch_sp_regnum (current_gdbarch)) + else if (regnum == gdbarch_sp_regnum (gdbarch)) reg->how = DWARF2_FRAME_REG_CFA; } @@ -3172,11 +3266,11 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) 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; + int have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0, have_dfp = 0; int tdesc_wordsize = -1; const struct target_desc *tdesc = info.target_desc; struct tdesc_arch_data *tdesc_data = NULL; - int num_sprs = 0; + int num_pseudoregs = 0; from_xcoff_exec = info.abfd && info.abfd->format == bfd_object && bfd_get_flavour (info.abfd) == bfd_target_xcoff_flavour; @@ -3347,6 +3441,10 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) else have_fpu = 0; + /* The DFP pseudo-registers will be available when there are floating + point registers. */ + have_dfp = have_fpu; + feature = tdesc_find_feature (tdesc, "org.gnu.gdb.power.altivec"); if (feature != NULL) @@ -3593,10 +3691,10 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) else tdep->lr_frame_offset = 8; - if (have_spe) + if (have_spe || have_dfp) { - set_gdbarch_pseudo_register_read (gdbarch, e500_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, e500_pseudo_register_write); + set_gdbarch_pseudo_register_read (gdbarch, rs6000_pseudo_register_read); + set_gdbarch_pseudo_register_write (gdbarch, rs6000_pseudo_register_write); } set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1); @@ -3607,8 +3705,14 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) else set_gdbarch_print_insn (gdbarch, gdb_print_insn_powerpc); - set_gdbarch_num_regs (gdbarch, PPC_NUM_REGS + num_sprs); - set_gdbarch_num_pseudo_regs (gdbarch, have_spe ? 32 : 0); + set_gdbarch_num_regs (gdbarch, PPC_NUM_REGS); + + if (have_spe) + num_pseudoregs += 32; + if (have_dfp) + num_pseudoregs += 16; + + set_gdbarch_num_pseudo_regs (gdbarch, num_pseudoregs); set_gdbarch_ptr_bit (gdbarch, wordsize * TARGET_CHAR_BIT); set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT); @@ -3730,7 +3834,13 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Recording the numbering of pseudo registers. */ tdep->ppc_ev0_regnum = have_spe ? gdbarch_num_regs (gdbarch) : -1; - tdep->ppc_ev31_regnum = have_spe ? tdep->ppc_ev0_regnum + 31 : -1; + + /* Set the register number for _Decimal128 pseudo-registers. */ + tdep->ppc_dl0_regnum = have_dfp? gdbarch_num_regs (gdbarch) : -1; + + if (have_dfp && have_spe) + /* Put the _Decimal128 pseudo-registers after the SPE registers. */ + tdep->ppc_dl0_regnum += 32; return gdbarch; }