2008-01-18 Luis Machado * rs6000-tdep.c (rs6000_gdbarch_init): Add support for Decimal128 pseudo-registers. (rs6000_pseudo_register_type): Returns the correct type for Decimal128 pseudo-registers. (rs6000_pseudo_register_reggroup_p): Returns the correct register group for Decimal128 pseudo-registers. (ppc_pseudo_register_read): New function. (ppc_pseudo_register_write): New function. * ppc-tdep.h: Add new variables ppc_dl0_upper_regnum, ppc_dl0_regnum and ppc_dl15_regnum. * printcmd.c: Fix displaying of DFP types as hex. * features/rs6000/powerpc-64.c: Regenerate. * features/rs6000/powerpc-32.c: Regenerate. * features/rs6000/powerpc-64.xml: Add decimal128 feature. * features/rs6000/powerpc-32.xml: Add decimal128 feature. * features/rs6000/power-dfp128.xml: New file. * testsuite/gdb.arch/powerpc-d128-regs.exp: New testcase expect file. * testsuite/gdb.arch/powerpc-d128-regs.c: New testcase source file. * doc/gdb.textinfo: Add new powerpc dfp128 feature documentation. Index: gdb/rs6000-tdep.c =================================================================== --- gdb.orig/rs6000-tdep.c 2008-01-18 05:15:36.000000000 -0800 +++ gdb/rs6000-tdep.c 2008-01-18 05:15:57.000000000 -0800 @@ -2384,6 +2384,20 @@ return spe_regnames[regno - tdep->ppc_ev0_regnum]; } + /* Check if the decimal128 pseudo-registers are available. */ + if (tdep->ppc_dl0_regnum >= 0 + && tdep->ppc_dl0_regnum <= regno + && regno < tdep->ppc_dl0_regnum + 16) + { + 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,12 +2409,19 @@ { 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); + /* These are the e500 pseudo-registers. */ + if (tdep->ppc_ev0_regnum >= 0 + && regnum >= tdep->ppc_ev0_regnum + && regnum < tdep->ppc_ev0_regnum + 32) + return rs6000_builtin_type_vec64 (gdbarch); + + /* These are the ppc decimal128 pseudo-registers. */ + if (tdep->ppc_dl0_regnum >= 0 + && regnum >= tdep->ppc_dl0_regnum + && regnum < tdep->ppc_dl0_regnum + 16) + return builtin_type (current_gdbarch)->builtin_declong;; - return rs6000_builtin_type_vec64 (gdbarch); + return NULL; } /* Is REGNUM a member of REGGROUP? */ @@ -2410,10 +2431,17 @@ { 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); + /* These are the e500 pseudo-registers. */ + if (tdep->ppc_ev0_regnum < 0 + && regnum < tdep->ppc_ev0_regnum + && regnum >= tdep->ppc_ev0_regnum + 32) + return -1; + + /* These are the ppc decimal128 pseudo-registers. */ + if (tdep->ppc_dl0_regnum < 0 + && regnum < tdep->ppc_dl0_regnum + && regnum >= tdep->ppc_dl0_regnum + 16) + return -1; if (group == all_reggroup || group == vector_reggroup) return 1; @@ -2556,6 +2584,89 @@ gdbarch_register_name (gdbarch, reg_nr), reg_nr); } +/* 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 *regcache_arch = get_regcache_arch (regcache); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int reg_index; + gdb_byte *byte_buffer = buffer; + + gdb_assert (regcache_arch == gdbarch); + + if (tdep->ppc_dl0_regnum <= reg_nr + && reg_nr < tdep->ppc_dl0_regnum + 16) + { + reg_index = reg_nr - tdep->ppc_dl0_regnum; + + if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG) + { + /* Read two FP registers to form a whole dl register. */ + regcache_raw_read (regcache, tdep->ppc_dl0_upper_regnum + + 2 * reg_index, byte_buffer); + regcache_raw_read (regcache, tdep->ppc_dl0_upper_regnum + + 2 * reg_index + 1, byte_buffer + 8); + } + else + { + regcache_raw_read (regcache, tdep->ppc_dl0_upper_regnum + + 2 * reg_index + 1, byte_buffer + 8); + regcache_raw_read (regcache, tdep->ppc_dl0_upper_regnum + + 2 * reg_index, byte_buffer); + } + } + else + internal_error (__FILE__, __LINE__, + _("ppc_pseudo_register_read: " + "called on unexpected register '%s' (%d)"), + gdbarch_register_name (gdbarch, reg_nr), reg_nr); +} + +/* 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 *regcache_arch = get_regcache_arch (regcache); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int reg_index; + const gdb_byte *byte_buffer = buffer; + + gdb_assert (regcache_arch == gdbarch); + + if (tdep->ppc_dl0_regnum <= reg_nr + && reg_nr < tdep->ppc_dl0_regnum + 16) + { + reg_index = reg_nr - tdep->ppc_dl0_regnum; + + if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG) + { + /* Write each half of the dl register into a separate + FP register. */ + regcache_raw_write (regcache, tdep->ppc_dl0_upper_regnum + + 2 * reg_index, byte_buffer); + regcache_raw_write (regcache, tdep->ppc_dl0_upper_regnum + + 2 * reg_index + 1, byte_buffer + 8); + } + else + { + regcache_raw_write (regcache, tdep->ppc_dl0_upper_regnum + + 2 * reg_index + 1, byte_buffer + 8); + regcache_raw_write (regcache, tdep->ppc_dl0_upper_regnum + + 2 * reg_index, byte_buffer); + } + } + else + internal_error (__FILE__, __LINE__, + _("ppc_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 (struct gdbarch *gdbarch, int num) @@ -3174,7 +3285,8 @@ 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_dfp128 = 0; int tdesc_wordsize = -1; const struct target_desc *tdesc = info.target_desc; struct tdesc_arch_data *tdesc_data = NULL; @@ -3380,6 +3492,12 @@ else have_altivec = 0; + feature = tdesc_find_feature (tdesc, + "org.gnu.gdb.power.dfp128"); + + if (feature != NULL) + have_dfp128 = 1; + /* On machines supporting the SPE APU, the general-purpose registers are 64 bits long. There are SIMD vector instructions to treat them as pairs of floats, but the rest of the instruction set treats them @@ -3568,6 +3686,7 @@ tdep->ppc_ev0_upper_regnum = have_spe ? PPC_SPE_UPPER_GP0_REGNUM : -1; tdep->ppc_acc_regnum = have_spe ? PPC_SPE_ACC_REGNUM : -1; tdep->ppc_spefscr_regnum = have_spe ? PPC_SPE_FSCR_REGNUM : -1; + tdep->ppc_dl0_upper_regnum = have_dfp128 ? PPC_F0_REGNUM : -1; set_gdbarch_pc_regnum (gdbarch, PPC_PC_REGNUM); set_gdbarch_sp_regnum (gdbarch, PPC_R0_REGNUM + 1); @@ -3600,6 +3719,11 @@ set_gdbarch_pseudo_register_read (gdbarch, e500_pseudo_register_read); set_gdbarch_pseudo_register_write (gdbarch, e500_pseudo_register_write); } + else if (have_dfp128) + { + set_gdbarch_pseudo_register_read (gdbarch, ppc_pseudo_register_read); + set_gdbarch_pseudo_register_write (gdbarch, ppc_pseudo_register_write); + } set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1); @@ -3610,7 +3734,12 @@ 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); + + if (have_spe) + set_gdbarch_num_pseudo_regs (gdbarch, 32); + else + if (have_dfp128) + set_gdbarch_num_pseudo_regs (gdbarch, 16); set_gdbarch_ptr_bit (gdbarch, wordsize * TARGET_CHAR_BIT); set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT); @@ -3734,6 +3863,10 @@ 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_dfp128 ? gdbarch_num_regs (gdbarch) : -1; + tdep->ppc_dl15_regnum = have_dfp128 ? tdep->ppc_dl0_regnum + 15 : -1; + return gdbarch; } Index: gdb/ppc-tdep.h =================================================================== --- gdb.orig/ppc-tdep.h 2008-01-18 05:15:36.000000000 -0800 +++ gdb/ppc-tdep.h 2008-01-18 05:15:57.000000000 -0800 @@ -205,6 +205,11 @@ int ppc_acc_regnum; /* SPE 'acc' register */ int ppc_spefscr_regnum; /* SPE 'spefscr' register */ + /* Decimal 128 registers. */ + int ppc_dl0_regnum; /* First Decimal128 argument register pair. */ + int ppc_dl15_regnum; /* Last Decimal128 argument register pair. */ + int ppc_dl0_upper_regnum; /* First FPR upper half register for dl0. */ + /* Offset to ABI specific location where link register is saved. */ int lr_frame_offset; Index: gdb/features/rs6000/powerpc-64.c =================================================================== --- gdb.orig/features/rs6000/powerpc-64.c 2008-01-18 05:15:36.000000000 -0800 +++ gdb/features/rs6000/powerpc-64.c 2008-01-18 07:29:24.000000000 -0800 @@ -160,5 +160,7 @@ tdesc_create_reg (feature, "vscr", 103, 1, "vector", 32, "int"); tdesc_create_reg (feature, "vrsave", 104, 1, "vector", 32, "int"); + feature = tdesc_create_feature (result, "org.gnu.gdb.power.dfp128"); + tdesc_powerpc_64 = result; } Index: gdb/features/rs6000/powerpc-32.c =================================================================== --- gdb.orig/features/rs6000/powerpc-32.c 2008-01-18 05:15:36.000000000 -0800 +++ gdb/features/rs6000/powerpc-32.c 2008-01-18 05:15:57.000000000 -0800 @@ -160,5 +160,7 @@ tdesc_create_reg (feature, "vscr", 103, 1, "vector", 32, "int"); tdesc_create_reg (feature, "vrsave", 104, 1, "vector", 32, "int"); + feature = tdesc_create_feature (result, "org.gnu.gdb.power.dfp128"); + tdesc_powerpc_32 = result; } Index: gdb/doc/gdb.texinfo =================================================================== --- gdb.orig/doc/gdb.texinfo 2008-01-18 05:15:36.000000000 -0800 +++ gdb/doc/gdb.texinfo 2008-01-18 05:15:57.000000000 -0800 @@ -26654,6 +26654,13 @@ these to present registers @samp{ev0} through @samp{ev31} to the user. +The @samp{org.gnu.gdb.power.dfp128} feature is optional and is aimed at targets +that support DFP types. It should contain registers @samp{dl0} through +@samp{dl15}. Each @samp{dl} register is actually a pair of 64-bit floating +point registers, so, for example, @samp{dl0} is composed by joining @samp{f0} +and @samp{f1}. @value{GDBN} will combine the pair of floating +point registers to present a single @samp{dl} register. + @include gpl.texi @raisesections Index: gdb/testsuite/gdb.arch/powerpc-d128-regs.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gdb/testsuite/gdb.arch/powerpc-d128-regs.c 2008-01-18 05:15:57.000000000 -0800 @@ -0,0 +1,25 @@ +/* This file is part of GDB, the GNU debugger. + + Copyright 2008 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Tests ppc decimal128 pseudo-registers. */ + +int main(void) +{ + _Decimal128 d128 = 1.2345678910dl; + + return 0; +} Index: gdb/testsuite/gdb.arch/powerpc-d128-regs.exp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gdb/testsuite/gdb.arch/powerpc-d128-regs.exp 2008-01-18 05:15:57.000000000 -0800 @@ -0,0 +1,77 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2008 +# Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@gnu.org + +# Testcase for ppc decimal128 pseudo-registers. + +if $tracelevel then { + strace $tracelevel +} + +if ![istarget "powerpc64-*"] then { + verbose "Skipping powerpc Decimal128 pseudo-registers testcase." + return +} + +set testfile "powerpc-d128-regs" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {quiet debug}] != "" } { + untested powerpc-d128-regs.exp + return -1 +} + +# Start with a fresh gdb. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if { ![runto main] } then { + fail "run to main" + return +} + +if [gdb_test "show arch" ".*currently powerpc:common.*" "Checking for PPC arch"] { + return -1; +} + +gdb_test "next" "" + +for {set i 0} {$i < 16} {incr i 1} { +gdb_test "set \$dl$i=d128" "" "Set dl$i register" + +gdb_test "print \$dl$i" "\\\$$decimal = 1\.2345678910" "Print dl$i register as DFP" + +gdb_test "info reg dl$i" \ + "dl$i\[ \]*0x2205800000000000000000049c5de09c\[\t\]*1\.2345678910" \ + "Print dl$i register with the info reg command" + +gdb_test "info reg f[expr 2*$i]" \ + "f[expr 2*$i]\[ \]*8\.608957309287334e\-145\[\t\]*\\(raw 0x2205800000000000\\)" \ + "Testing lower half of dl$i register" + +gdb_test "info reg f[expr 2*$i+1]" \ + "f[expr 2*$i+1]\[ \]*9\.7841140127686122e\-314\[\t\]*\\(raw 0x000000049c5de09c\\)" \ + "Testing upper half of dl$i register" + +} Index: gdb/printcmd.c =================================================================== --- gdb.orig/printcmd.c 2008-01-18 05:15:36.000000000 -0800 +++ gdb/printcmd.c 2008-01-18 05:15:57.000000000 -0800 @@ -326,7 +326,8 @@ if (len > sizeof(LONGEST) && (TYPE_CODE (type) == TYPE_CODE_INT - || TYPE_CODE (type) == TYPE_CODE_ENUM)) + || TYPE_CODE (type) == TYPE_CODE_ENUM + || TYPE_CODE (type) == TYPE_CODE_DECFLOAT)) { switch (format) { Index: gdb/features/rs6000/powerpc-32.xml =================================================================== --- gdb.orig/features/rs6000/powerpc-32.xml 2008-01-18 05:15:36.000000000 -0800 +++ gdb/features/rs6000/powerpc-32.xml 2008-01-18 05:15:57.000000000 -0800 @@ -14,4 +14,5 @@ + Index: gdb/features/rs6000/powerpc-64.xml =================================================================== --- gdb.orig/features/rs6000/powerpc-64.xml 2008-01-18 05:15:36.000000000 -0800 +++ gdb/features/rs6000/powerpc-64.xml 2008-01-18 05:15:57.000000000 -0800 @@ -14,4 +14,5 @@ + Index: gdb/features/rs6000/power-dfp128.xml =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gdb/features/rs6000/power-dfp128.xml 2008-01-18 05:15:36.000000000 -0800 @@ -0,0 +1,9 @@ + + + + +