diff options
25 files changed, 1431 insertions, 251 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 3d0de47..dc6a776 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,90 @@ 2010-01-04 Ulrich Weigand <uweigand@de.ibm.com> + * features/Makefile (WHICH): Add s390-linux32, s390-linux64, + and s390x-linux64. + (s390-linux32-expedite): Define. + (s390-linux64-expedite): Define. + (s390x-linux64-expedite): Define. + * features/s390-acr.xml: New file. + * features/s390-fpr.xml: New file. + * features/s390-core32.xml: New file. + * features/s390-core64.xml: New file. + * features/s390x-core64.xml: New file. + * features/s390-linux32.xml: New file. + * features/s390-linux64.xml: New file. + * features/s390x-linux64.xml: New file. + * features/s390-linux32.c: New generated file. + * features/s390-linux64.c: New generated file. + * features/s390x-linux64.c: New generated file. + + * regformats/s390-linux32.dat: New generated file. + * regformats/s390-linux64.dat: New generated file. + * regformats/s390x-linux64.dat: New generated file. + * regformats/reg-s390.dat: Remove. + * regformats/reg-s390x.dat: Remove. + + * s390-nat.c: Include "auxv.h" and <elf.h>. + (HWCAP_S390_HIGH_GPRS): Define if undefined. + (s390_target_wordsize): New function. + (s390_auxv_parse): Likewise. + (s390_get_hwcap): Likewise. + (s390_read_description): Likewise. + (_initialize_s390_nat): Install s390_auxv_parse and + s390_read_description. + + * s390-tdep.c: Include "features/s390-linux32.c", + "features/s390-linux64.c", and "features/s390x-linux64.c". + (struct gdbarch_tdep): Add gpr_full_regnum, pc_regnum, and cc_regnum. + (s390_register_call_saved): New function. + (s390_register_name): Remove. + (s390_register_type): Remove. + (s390_dwarf_regmap): Add lower half GPR pseudo DWARF CFI regnums. + (s390_dwarf_reg_to_regnum): Remap GPR regnums to full GPRs. + (s390_adjust_frame_regnum): Remap GPR regnums to lower halves for CFI. + (s390_pseudo_register_name): New function. + (s390_pseudo_register_type): New function. + (s390_pseudo_register_read): Handle both 32-bit and 64-bit cases. + Handle full GPR pesudos and varying pseudo register numbers. + (s390_pseudo_register_write): Likewise + (s390x_pseudo_register_read): Remove. + (s390x_pseudo_register_write): Likewise. + (s390_register_group): Remove. + (s390_pseudo_register_group): New function. + (s390_regmap_gregset): Add GPR upper halves. + (s390x_regmap_gregset): Likewise. + (s390_regmap_fpregset): Likewise. + (s390_regmap_upper): New global variable. + (s390_upper_regset): New global variable. + (s390_upper_regset_sections): New global variable. + (s390_regset_from_core_section): Handle GPR upper halves. + (s390_core_read_description): New function. + (s390_prologue_frame_unwind_cache): Set up ABI call-saved/clobbered + register information. Handle varying pseudo register numbers. + (s390_backchain_frame_unwind_cache): Likewise. + (s390_frame_prev_register): Unwind full GPRs to show lower halves. + (s390_stub_frame_unwind_cache): Handle varying pseudo register numbers. + (s390_sigtramp_frame_unwind_cache): Unwind PSWM and PSWA as well as + PC and CC pseudos. Unwind upper halves and full GPRs as appropriate. + Handle varying pseudo register numbers. + (s390_unwind_pc): Handle varying pseudo register numbers. + (s390_dwarf2_prev_register): New function. + (s390_dwarf2_frame_init_reg): Set up ABI call-saved/clobbered + register information. Handle varying pseudo register numbers. + Install s390_dwarf2_prev_register to unwind full GPRs. + (s390_gdbarch_init): Handle target descriptions. Assign varying + pseudo register numbers. Install s390_adjust_frame_regnum. + (_initialize_s390_tdep): Initialize target descriptions. + + * s390-tdep.h (S390_R0_UPPER_REGNUM .. S390_R15_UPPER_REGNUM): Define. + (S390_NUM_REGS): Redefine to include upper half registers. + (S390_PC_REGNUM, S390_CC_REGNUM): Remove. + (S390_NUM_PSEUDO_REGS, S390_NUM_TOTAL_REGS): Likewise. + (tdesc_s390_linux32): Add declaration. + (tdesc_s390_linux64): Likewise. + (tdesc_s390x_linux64): Likewise. + +2010-01-04 Ulrich Weigand <uweigand@de.ibm.com> + * regset.h (struct core_regset_section): Add HUMAN_NAME. * i386-linux-tdep.c (i386_linux_regset_sections): Fill in HUMAN_NAME. * ppc-linux-tdep.c (ppc_linux_vsx_regset_sections): Likewise. diff --git a/gdb/features/Makefile b/gdb/features/Makefile index 5b1e691..8aa553e 100644 --- a/gdb/features/Makefile +++ b/gdb/features/Makefile @@ -34,7 +34,8 @@ WHICH = arm-with-iwmmxt arm-with-vfpv2 arm-with-vfpv3 arm-with-neon \ mips-linux mips64-linux \ rs6000/powerpc-32l rs6000/powerpc-altivec32l rs6000/powerpc-e500l \ rs6000/powerpc-64l rs6000/powerpc-altivec64l rs6000/powerpc-vsx32l \ - rs6000/powerpc-vsx64l rs6000/powerpc-cell32l rs6000/powerpc-cell64l + rs6000/powerpc-vsx64l rs6000/powerpc-cell32l rs6000/powerpc-cell64l \ + s390-linux32 s390-linux64 s390x-linux64 # Record which registers should be sent to GDB by default after stop. arm-expedite = r11,sp,pc @@ -43,6 +44,9 @@ mips64-expedite = r29,pc powerpc-expedite = r1,pc rs6000/powerpc-cell32l-expedite = r1,pc,r0,orig_r3,r4 rs6000/powerpc-cell64l-expedite = r1,pc,r0,orig_r3,r4 +s390-linux32-expedite = r14,r15,pswa +s390-linux64-expedite = r14l,r15l,pswa +s390x-linux64-expedite = r14,r15,pswa XSLTPROC = xsltproc diff --git a/gdb/features/s390-acr.xml b/gdb/features/s390-acr.xml new file mode 100644 index 0000000..9bf3326 --- /dev/null +++ b/gdb/features/s390-acr.xml @@ -0,0 +1,26 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2010 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE feature SYSTEM "gdb-target.dtd"> +<feature name="org.gnu.gdb.s390.acr"> + <reg name="acr0" bitsize="32" type="uint32" group="access"/> + <reg name="acr1" bitsize="32" type="uint32" group="access"/> + <reg name="acr2" bitsize="32" type="uint32" group="access"/> + <reg name="acr3" bitsize="32" type="uint32" group="access"/> + <reg name="acr4" bitsize="32" type="uint32" group="access"/> + <reg name="acr5" bitsize="32" type="uint32" group="access"/> + <reg name="acr6" bitsize="32" type="uint32" group="access"/> + <reg name="acr7" bitsize="32" type="uint32" group="access"/> + <reg name="acr8" bitsize="32" type="uint32" group="access"/> + <reg name="acr9" bitsize="32" type="uint32" group="access"/> + <reg name="acr10" bitsize="32" type="uint32" group="access"/> + <reg name="acr11" bitsize="32" type="uint32" group="access"/> + <reg name="acr12" bitsize="32" type="uint32" group="access"/> + <reg name="acr13" bitsize="32" type="uint32" group="access"/> + <reg name="acr14" bitsize="32" type="uint32" group="access"/> + <reg name="acr15" bitsize="32" type="uint32" group="access"/> +</feature> diff --git a/gdb/features/s390-core32.xml b/gdb/features/s390-core32.xml new file mode 100644 index 0000000..5a752e8 --- /dev/null +++ b/gdb/features/s390-core32.xml @@ -0,0 +1,28 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2010 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE feature SYSTEM "gdb-target.dtd"> +<feature name="org.gnu.gdb.s390.core"> + <reg name="pswm" bitsize="32" type="uint32" group="psw" save-restore="no"/> + <reg name="pswa" bitsize="32" type="uint32" group="psw" save-restore="no"/> + <reg name="r0" bitsize="32" type="uint32" group="general"/> + <reg name="r1" bitsize="32" type="uint32" group="general"/> + <reg name="r2" bitsize="32" type="uint32" group="general"/> + <reg name="r3" bitsize="32" type="uint32" group="general"/> + <reg name="r4" bitsize="32" type="uint32" group="general"/> + <reg name="r5" bitsize="32" type="uint32" group="general"/> + <reg name="r6" bitsize="32" type="uint32" group="general"/> + <reg name="r7" bitsize="32" type="uint32" group="general"/> + <reg name="r8" bitsize="32" type="uint32" group="general"/> + <reg name="r9" bitsize="32" type="uint32" group="general"/> + <reg name="r10" bitsize="32" type="uint32" group="general"/> + <reg name="r11" bitsize="32" type="uint32" group="general"/> + <reg name="r12" bitsize="32" type="uint32" group="general"/> + <reg name="r13" bitsize="32" type="uint32" group="general"/> + <reg name="r14" bitsize="32" type="uint32" group="general"/> + <reg name="r15" bitsize="32" type="uint32" group="general"/> +</feature> diff --git a/gdb/features/s390-core64.xml b/gdb/features/s390-core64.xml new file mode 100644 index 0000000..43bd9be --- /dev/null +++ b/gdb/features/s390-core64.xml @@ -0,0 +1,45 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2010 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE feature SYSTEM "gdb-target.dtd"> +<feature name="org.gnu.gdb.s390.core"> + <reg name="pswm" bitsize="32" type="uint32" group="psw" save-restore="no"/> + <reg name="pswa" bitsize="32" type="uint32" group="psw" save-restore="no"/> + <reg name="r0h" bitsize="32" type="uint32" group="upper"/> + <reg name="r0l" bitsize="32" type="uint32" group="lower"/> + <reg name="r1h" bitsize="32" type="uint32" group="upper"/> + <reg name="r1l" bitsize="32" type="uint32" group="lower"/> + <reg name="r2h" bitsize="32" type="uint32" group="upper"/> + <reg name="r2l" bitsize="32" type="uint32" group="lower"/> + <reg name="r3h" bitsize="32" type="uint32" group="upper"/> + <reg name="r3l" bitsize="32" type="uint32" group="lower"/> + <reg name="r4h" bitsize="32" type="uint32" group="upper"/> + <reg name="r4l" bitsize="32" type="uint32" group="lower"/> + <reg name="r5h" bitsize="32" type="uint32" group="upper"/> + <reg name="r5l" bitsize="32" type="uint32" group="lower"/> + <reg name="r6h" bitsize="32" type="uint32" group="upper"/> + <reg name="r6l" bitsize="32" type="uint32" group="lower"/> + <reg name="r7h" bitsize="32" type="uint32" group="upper"/> + <reg name="r7l" bitsize="32" type="uint32" group="lower"/> + <reg name="r8h" bitsize="32" type="uint32" group="upper"/> + <reg name="r8l" bitsize="32" type="uint32" group="lower"/> + <reg name="r9h" bitsize="32" type="uint32" group="upper"/> + <reg name="r9l" bitsize="32" type="uint32" group="lower"/> + <reg name="r10h" bitsize="32" type="uint32" group="upper"/> + <reg name="r10l" bitsize="32" type="uint32" group="lower"/> + <reg name="r11h" bitsize="32" type="uint32" group="upper"/> + <reg name="r11l" bitsize="32" type="uint32" group="lower"/> + <reg name="r12h" bitsize="32" type="uint32" group="upper"/> + <reg name="r12l" bitsize="32" type="uint32" group="lower"/> + <reg name="r13h" bitsize="32" type="uint32" group="upper"/> + <reg name="r13l" bitsize="32" type="uint32" group="lower"/> + <reg name="r14h" bitsize="32" type="uint32" group="upper"/> + <reg name="r14l" bitsize="32" type="uint32" group="lower"/> + <reg name="r15h" bitsize="32" type="uint32" group="upper"/> + <reg name="r15l" bitsize="32" type="uint32" group="lower"/> +</feature> + diff --git a/gdb/features/s390-fpr.xml b/gdb/features/s390-fpr.xml new file mode 100644 index 0000000..8a9599a --- /dev/null +++ b/gdb/features/s390-fpr.xml @@ -0,0 +1,27 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2010 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE feature SYSTEM "gdb-target.dtd"> +<feature name="org.gnu.gdb.s390.fpr"> + <reg name="fpc" bitsize="32" type="uint32" group="float"/> + <reg name="f0" bitsize="64" type="ieee_double" group="float"/> + <reg name="f1" bitsize="64" type="ieee_double" group="float"/> + <reg name="f2" bitsize="64" type="ieee_double" group="float"/> + <reg name="f3" bitsize="64" type="ieee_double" group="float"/> + <reg name="f4" bitsize="64" type="ieee_double" group="float"/> + <reg name="f5" bitsize="64" type="ieee_double" group="float"/> + <reg name="f6" bitsize="64" type="ieee_double" group="float"/> + <reg name="f7" bitsize="64" type="ieee_double" group="float"/> + <reg name="f8" bitsize="64" type="ieee_double" group="float"/> + <reg name="f9" bitsize="64" type="ieee_double" group="float"/> + <reg name="f10" bitsize="64" type="ieee_double" group="float"/> + <reg name="f11" bitsize="64" type="ieee_double" group="float"/> + <reg name="f12" bitsize="64" type="ieee_double" group="float"/> + <reg name="f13" bitsize="64" type="ieee_double" group="float"/> + <reg name="f14" bitsize="64" type="ieee_double" group="float"/> + <reg name="f15" bitsize="64" type="ieee_double" group="float"/> +</feature> diff --git a/gdb/features/s390-linux32.c b/gdb/features/s390-linux32.c new file mode 100644 index 0000000..0ff3868 --- /dev/null +++ b/gdb/features/s390-linux32.c @@ -0,0 +1,74 @@ +/* THIS FILE IS GENERATED. Original: s390-linux32.xml */ + +#include "defs.h" +#include "target-descriptions.h" + +struct target_desc *tdesc_s390_linux32; +static void +initialize_tdesc_s390_linux32 (void) +{ + struct target_desc *result = allocate_target_description (); + struct tdesc_feature *feature; + struct tdesc_type *field_type, *type; + + set_tdesc_architecture (result, bfd_scan_arch ("s390:31-bit")); + + feature = tdesc_create_feature (result, "org.gnu.gdb.s390.core"); + tdesc_create_reg (feature, "pswm", 0, 0, "psw", 32, "uint32"); + tdesc_create_reg (feature, "pswa", 1, 0, "psw", 32, "uint32"); + tdesc_create_reg (feature, "r0", 2, 1, "general", 32, "uint32"); + tdesc_create_reg (feature, "r1", 3, 1, "general", 32, "uint32"); + tdesc_create_reg (feature, "r2", 4, 1, "general", 32, "uint32"); + tdesc_create_reg (feature, "r3", 5, 1, "general", 32, "uint32"); + tdesc_create_reg (feature, "r4", 6, 1, "general", 32, "uint32"); + tdesc_create_reg (feature, "r5", 7, 1, "general", 32, "uint32"); + tdesc_create_reg (feature, "r6", 8, 1, "general", 32, "uint32"); + tdesc_create_reg (feature, "r7", 9, 1, "general", 32, "uint32"); + tdesc_create_reg (feature, "r8", 10, 1, "general", 32, "uint32"); + tdesc_create_reg (feature, "r9", 11, 1, "general", 32, "uint32"); + tdesc_create_reg (feature, "r10", 12, 1, "general", 32, "uint32"); + tdesc_create_reg (feature, "r11", 13, 1, "general", 32, "uint32"); + tdesc_create_reg (feature, "r12", 14, 1, "general", 32, "uint32"); + tdesc_create_reg (feature, "r13", 15, 1, "general", 32, "uint32"); + tdesc_create_reg (feature, "r14", 16, 1, "general", 32, "uint32"); + tdesc_create_reg (feature, "r15", 17, 1, "general", 32, "uint32"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.s390.acr"); + tdesc_create_reg (feature, "acr0", 18, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr1", 19, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr2", 20, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr3", 21, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr4", 22, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr5", 23, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr6", 24, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr7", 25, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr8", 26, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr9", 27, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr10", 28, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr11", 29, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr12", 30, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr13", 31, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr14", 32, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr15", 33, 1, "access", 32, "uint32"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.s390.fpr"); + tdesc_create_reg (feature, "fpc", 34, 1, "float", 32, "uint32"); + tdesc_create_reg (feature, "f0", 35, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f1", 36, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f2", 37, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f3", 38, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f4", 39, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f5", 40, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f6", 41, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f7", 42, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f8", 43, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f9", 44, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f10", 45, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f11", 46, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f12", 47, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f13", 48, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f14", 49, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f15", 50, 1, "float", 64, "ieee_double"); + + tdesc_s390_linux32 = result; +} diff --git a/gdb/features/s390-linux32.xml b/gdb/features/s390-linux32.xml new file mode 100644 index 0000000..45153fd --- /dev/null +++ b/gdb/features/s390-linux32.xml @@ -0,0 +1,17 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2010 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!-- S/390 31-bit user-level code on a machine operating + in ESA/390 architecture mode. --> + +<!DOCTYPE target SYSTEM "gdb-target.dtd"> +<target> + <architecture>s390:31-bit</architecture> + <xi:include href="s390-core32.xml"/> + <xi:include href="s390-acr.xml"/> + <xi:include href="s390-fpr.xml"/> +</target> diff --git a/gdb/features/s390-linux64.c b/gdb/features/s390-linux64.c new file mode 100644 index 0000000..1e39fc3 --- /dev/null +++ b/gdb/features/s390-linux64.c @@ -0,0 +1,90 @@ +/* THIS FILE IS GENERATED. Original: s390-linux64.xml */ + +#include "defs.h" +#include "target-descriptions.h" + +struct target_desc *tdesc_s390_linux64; +static void +initialize_tdesc_s390_linux64 (void) +{ + struct target_desc *result = allocate_target_description (); + struct tdesc_feature *feature; + struct tdesc_type *field_type, *type; + + set_tdesc_architecture (result, bfd_scan_arch ("s390:31-bit")); + + feature = tdesc_create_feature (result, "org.gnu.gdb.s390.core"); + tdesc_create_reg (feature, "pswm", 0, 0, "psw", 32, "uint32"); + tdesc_create_reg (feature, "pswa", 1, 0, "psw", 32, "uint32"); + tdesc_create_reg (feature, "r0h", 2, 1, "upper", 32, "uint32"); + tdesc_create_reg (feature, "r0l", 3, 1, "lower", 32, "uint32"); + tdesc_create_reg (feature, "r1h", 4, 1, "upper", 32, "uint32"); + tdesc_create_reg (feature, "r1l", 5, 1, "lower", 32, "uint32"); + tdesc_create_reg (feature, "r2h", 6, 1, "upper", 32, "uint32"); + tdesc_create_reg (feature, "r2l", 7, 1, "lower", 32, "uint32"); + tdesc_create_reg (feature, "r3h", 8, 1, "upper", 32, "uint32"); + tdesc_create_reg (feature, "r3l", 9, 1, "lower", 32, "uint32"); + tdesc_create_reg (feature, "r4h", 10, 1, "upper", 32, "uint32"); + tdesc_create_reg (feature, "r4l", 11, 1, "lower", 32, "uint32"); + tdesc_create_reg (feature, "r5h", 12, 1, "upper", 32, "uint32"); + tdesc_create_reg (feature, "r5l", 13, 1, "lower", 32, "uint32"); + tdesc_create_reg (feature, "r6h", 14, 1, "upper", 32, "uint32"); + tdesc_create_reg (feature, "r6l", 15, 1, "lower", 32, "uint32"); + tdesc_create_reg (feature, "r7h", 16, 1, "upper", 32, "uint32"); + tdesc_create_reg (feature, "r7l", 17, 1, "lower", 32, "uint32"); + tdesc_create_reg (feature, "r8h", 18, 1, "upper", 32, "uint32"); + tdesc_create_reg (feature, "r8l", 19, 1, "lower", 32, "uint32"); + tdesc_create_reg (feature, "r9h", 20, 1, "upper", 32, "uint32"); + tdesc_create_reg (feature, "r9l", 21, 1, "lower", 32, "uint32"); + tdesc_create_reg (feature, "r10h", 22, 1, "upper", 32, "uint32"); + tdesc_create_reg (feature, "r10l", 23, 1, "lower", 32, "uint32"); + tdesc_create_reg (feature, "r11h", 24, 1, "upper", 32, "uint32"); + tdesc_create_reg (feature, "r11l", 25, 1, "lower", 32, "uint32"); + tdesc_create_reg (feature, "r12h", 26, 1, "upper", 32, "uint32"); + tdesc_create_reg (feature, "r12l", 27, 1, "lower", 32, "uint32"); + tdesc_create_reg (feature, "r13h", 28, 1, "upper", 32, "uint32"); + tdesc_create_reg (feature, "r13l", 29, 1, "lower", 32, "uint32"); + tdesc_create_reg (feature, "r14h", 30, 1, "upper", 32, "uint32"); + tdesc_create_reg (feature, "r14l", 31, 1, "lower", 32, "uint32"); + tdesc_create_reg (feature, "r15h", 32, 1, "upper", 32, "uint32"); + tdesc_create_reg (feature, "r15l", 33, 1, "lower", 32, "uint32"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.s390.acr"); + tdesc_create_reg (feature, "acr0", 34, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr1", 35, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr2", 36, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr3", 37, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr4", 38, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr5", 39, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr6", 40, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr7", 41, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr8", 42, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr9", 43, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr10", 44, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr11", 45, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr12", 46, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr13", 47, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr14", 48, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr15", 49, 1, "access", 32, "uint32"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.s390.fpr"); + tdesc_create_reg (feature, "fpc", 50, 1, "float", 32, "uint32"); + tdesc_create_reg (feature, "f0", 51, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f1", 52, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f2", 53, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f3", 54, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f4", 55, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f5", 56, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f6", 57, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f7", 58, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f8", 59, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f9", 60, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f10", 61, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f11", 62, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f12", 63, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f13", 64, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f14", 65, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f15", 66, 1, "float", 64, "ieee_double"); + + tdesc_s390_linux64 = result; +} diff --git a/gdb/features/s390-linux64.xml b/gdb/features/s390-linux64.xml new file mode 100644 index 0000000..10bb036 --- /dev/null +++ b/gdb/features/s390-linux64.xml @@ -0,0 +1,17 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2010 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!-- S/390 31-bit user-level code on a machine operating + in z/Architecture mode. --> + +<!DOCTYPE target SYSTEM "gdb-target.dtd"> +<target> + <architecture>s390:31-bit</architecture> + <xi:include href="s390-core64.xml"/> + <xi:include href="s390-acr.xml"/> + <xi:include href="s390-fpr.xml"/> +</target> diff --git a/gdb/features/s390x-core64.xml b/gdb/features/s390x-core64.xml new file mode 100644 index 0000000..34659c9 --- /dev/null +++ b/gdb/features/s390x-core64.xml @@ -0,0 +1,28 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2010 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE feature SYSTEM "gdb-target.dtd"> +<feature name="org.gnu.gdb.s390.core"> + <reg name="pswm" bitsize="64" type="uint64" group="psw" save-restore="no"/> + <reg name="pswa" bitsize="64" type="uint64" group="psw" save-restore="no"/> + <reg name="r0" bitsize="64" type="uint64" group="general"/> + <reg name="r1" bitsize="64" type="uint64" group="general"/> + <reg name="r2" bitsize="64" type="uint64" group="general"/> + <reg name="r3" bitsize="64" type="uint64" group="general"/> + <reg name="r4" bitsize="64" type="uint64" group="general"/> + <reg name="r5" bitsize="64" type="uint64" group="general"/> + <reg name="r6" bitsize="64" type="uint64" group="general"/> + <reg name="r7" bitsize="64" type="uint64" group="general"/> + <reg name="r8" bitsize="64" type="uint64" group="general"/> + <reg name="r9" bitsize="64" type="uint64" group="general"/> + <reg name="r10" bitsize="64" type="uint64" group="general"/> + <reg name="r11" bitsize="64" type="uint64" group="general"/> + <reg name="r12" bitsize="64" type="uint64" group="general"/> + <reg name="r13" bitsize="64" type="uint64" group="general"/> + <reg name="r14" bitsize="64" type="uint64" group="general"/> + <reg name="r15" bitsize="64" type="uint64" group="general"/> +</feature> diff --git a/gdb/features/s390x-linux64.c b/gdb/features/s390x-linux64.c new file mode 100644 index 0000000..91d2da9 --- /dev/null +++ b/gdb/features/s390x-linux64.c @@ -0,0 +1,74 @@ +/* THIS FILE IS GENERATED. Original: s390x-linux64.xml */ + +#include "defs.h" +#include "target-descriptions.h" + +struct target_desc *tdesc_s390x_linux64; +static void +initialize_tdesc_s390x_linux64 (void) +{ + struct target_desc *result = allocate_target_description (); + struct tdesc_feature *feature; + struct tdesc_type *field_type, *type; + + set_tdesc_architecture (result, bfd_scan_arch ("s390:64-bit")); + + feature = tdesc_create_feature (result, "org.gnu.gdb.s390.core"); + tdesc_create_reg (feature, "pswm", 0, 0, "psw", 64, "uint64"); + tdesc_create_reg (feature, "pswa", 1, 0, "psw", 64, "uint64"); + tdesc_create_reg (feature, "r0", 2, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "r1", 3, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "r2", 4, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "r3", 5, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "r4", 6, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "r5", 7, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "r6", 8, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "r7", 9, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "r8", 10, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "r9", 11, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "r10", 12, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "r11", 13, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "r12", 14, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "r13", 15, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "r14", 16, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "r15", 17, 1, "general", 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.s390.acr"); + tdesc_create_reg (feature, "acr0", 18, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr1", 19, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr2", 20, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr3", 21, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr4", 22, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr5", 23, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr6", 24, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr7", 25, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr8", 26, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr9", 27, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr10", 28, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr11", 29, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr12", 30, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr13", 31, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr14", 32, 1, "access", 32, "uint32"); + tdesc_create_reg (feature, "acr15", 33, 1, "access", 32, "uint32"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.s390.fpr"); + tdesc_create_reg (feature, "fpc", 34, 1, "float", 32, "uint32"); + tdesc_create_reg (feature, "f0", 35, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f1", 36, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f2", 37, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f3", 38, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f4", 39, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f5", 40, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f6", 41, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f7", 42, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f8", 43, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f9", 44, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f10", 45, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f11", 46, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f12", 47, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f13", 48, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f14", 49, 1, "float", 64, "ieee_double"); + tdesc_create_reg (feature, "f15", 50, 1, "float", 64, "ieee_double"); + + tdesc_s390x_linux64 = result; +} diff --git a/gdb/features/s390x-linux64.xml b/gdb/features/s390x-linux64.xml new file mode 100644 index 0000000..f3700a4 --- /dev/null +++ b/gdb/features/s390x-linux64.xml @@ -0,0 +1,16 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2010 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!-- S/390 64-bit user-level code. --> + +<!DOCTYPE target SYSTEM "gdb-target.dtd"> +<target> + <architecture>s390:64-bit</architecture> + <xi:include href="s390x-core64.xml"/> + <xi:include href="s390-acr.xml"/> + <xi:include href="s390-fpr.xml"/> +</target> diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 53181bd..3ec151c 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,30 @@ +2010-01-04 Ulrich Weigand <uweigand@de.ibm.com> + + * Makefile.in (clean): Remove new generated files. + (reg-s390.o, reg-s390.c): Remove rules. + (reg-s390x.o, reg-s390x.c): Likewise. + (s390-linux32.o, s390-linux32.c): Add rules. + (s390-linux64.o, s390-linux64.c): Likewise. + (s390x-linux64.o, s390x-linux64.c): Likewise. + * configure.srv (s390*-*-linux*): Update srv_regobj and srv_xmlfiles. + * linux-s390-low.c: Include <elf.h>. + (HWCAP_S390_HIGH_GPRS): Define if undefined. + (init_registers_s390): Remove prototype. + (init_registers_s390x): Likewise. + (init_registers_s390_linux32): Add prototype. + (init_registers_s390_linux64): Likewise. + (init_registers_s390x_linux64): Likewise. + (s390_num_regs_3264): New define. + (s390_regmap_3264): New global variable. + (s390_cannot_fetch_register): Remove obsolete check. + (s390_cannot_store_register): Likewise. + (s390_collect_ptrace_register): Handle upper/lower register halves. + (s390_supply_ptrace_register): Likewise. + (s390_fill_gregset): Update to register number changes. + (s390_get_hwcap): New routine. + (s390_arch_setup): Detect 32-bit process running on 64-bit system. + Install appropriate regmap and register set. + 2010-01-01 Joel Brobecker <brobecker@adacore.com> * server.c (gdbserver_version): Update copyright year to 2010. diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in index 079f233..5bf82e2 100644 --- a/gdb/gdbserver/Makefile.in +++ b/gdb/gdbserver/Makefile.in @@ -215,6 +215,7 @@ clean: rm -f powerpc-isa205-32l.c powerpc-isa205-64l.c rm -f powerpc-isa205-altivec32l.c powerpc-isa205-vsx32l.c powerpc-isa205-altivec64l.c rm -f powerpc-isa205-vsx64l.c + rm -f s390-linux32.c s390-linux64.c s390x-linux64.c rm -f xml-builtin.c stamp-xml maintainer-clean realclean distclean: clean @@ -413,12 +414,15 @@ powerpc-isa205-altivec64l.c : $(srcdir)/../regformats/rs6000/powerpc-isa205-alti powerpc-isa205-vsx64l.o : powerpc-isa205-vsx64l.c $(regdef_h) powerpc-isa205-vsx64l.c : $(srcdir)/../regformats/rs6000/powerpc-isa205-vsx64l.dat $(regdat_sh) $(SHELL) $(regdat_sh) $(srcdir)/../regformats/rs6000/powerpc-isa205-vsx64l.dat powerpc-isa205-vsx64l.c -reg-s390.o : reg-s390.c $(regdef_h) -reg-s390.c : $(srcdir)/../regformats/reg-s390.dat $(regdat_sh) - $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-s390.dat reg-s390.c -reg-s390x.o : reg-s390x.c $(regdef_h) -reg-s390x.c : $(srcdir)/../regformats/reg-s390x.dat $(regdat_sh) - $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-s390x.dat reg-s390x.c +s390-linux32.o : s390-linux32.c $(regdef_h) +s390-linux32.c : $(srcdir)/../regformats/s390-linux32.dat $(regdat_sh) + $(SHELL) $(regdat_sh) $(srcdir)/../regformats/s390-linux32.dat s390-linux32.c +s390-linux64.o : s390-linux64.c $(regdef_h) +s390-linux64.c : $(srcdir)/../regformats/s390-linux64.dat $(regdat_sh) + $(SHELL) $(regdat_sh) $(srcdir)/../regformats/s390-linux64.dat s390-linux64.c +s390x-linux64.o : s390x-linux64.c $(regdef_h) +s390x-linux64.c : $(srcdir)/../regformats/s390x-linux64.dat $(regdat_sh) + $(SHELL) $(regdat_sh) $(srcdir)/../regformats/s390x-linux64.dat s390x-linux64.c reg-sh.o : reg-sh.c $(regdef_h) reg-sh.c : $(srcdir)/../regformats/reg-sh.dat $(regdat_sh) $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-sh.dat reg-sh.c diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv index 1814b0e..f6d92b3 100644 --- a/gdb/gdbserver/configure.srv +++ b/gdb/gdbserver/configure.srv @@ -176,8 +176,18 @@ case "${target}" in srv_linux_regsets=yes srv_linux_thread_db=yes ;; - s390*-*-linux*) srv_regobj="reg-s390.o reg-s390x.o" + s390*-*-linux*) srv_regobj="s390-linux32.o" + srv_regobj="${srv_regobj} s390-linux64.o" + srv_regobj="${srv_regobj} s390x-linux64.o" srv_tgtobj="linux-low.o linux-s390-low.o" + srv_xmlfiles="s390-linux32.xml" + srv_xmlfiles="${srv_xmlfiles} s390-linux64.xml" + srv_xmlfiles="${srv_xmlfiles} s390x-linux64.xml" + srv_xmlfiles="${srv_xmlfiles} s390-core32.xml" + srv_xmlfiles="${srv_xmlfiles} s390-core64.xml" + srv_xmlfiles="${srv_xmlfiles} s390x-core64.xml" + srv_xmlfiles="${srv_xmlfiles} s390-acr.xml" + srv_xmlfiles="${srv_xmlfiles} s390-fpr.xml" srv_linux_usrregs=yes srv_linux_regsets=yes srv_linux_thread_db=yes diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c index 0407cad..64b1065 100644 --- a/gdb/gdbserver/linux-s390-low.c +++ b/gdb/gdbserver/linux-s390-low.c @@ -24,12 +24,18 @@ #include "linux-low.h" #include <asm/ptrace.h> +#include <elf.h> -/* Defined in auto-generated file reg-s390.c. */ -void init_registers_s390 (void); -/* Defined in auto-generated file reg-s390x.c. */ -void init_registers_s390x (void); +#ifndef HWCAP_S390_HIGH_GPRS +#define HWCAP_S390_HIGH_GPRS 512 +#endif +/* Defined in auto-generated file s390-linux32.c. */ +void init_registers_s390_linux32 (void); +/* Defined in auto-generated file s390-linux64.c. */ +void init_registers_s390_linux64 (void); +/* Defined in auto-generated file s390x-linux64.c. */ +void init_registers_s390x_linux64 (void); #define s390_num_regs 51 @@ -61,21 +67,41 @@ static int s390_regmap[] = { #endif }; +#ifdef __s390x__ +#define s390_num_regs_3264 67 + +static int s390_regmap_3264[] = { + PT_PSWMASK, PT_PSWADDR, + + PT_GPR0, PT_GPR0, PT_GPR1, PT_GPR1, PT_GPR2, PT_GPR2, PT_GPR3, PT_GPR3, + PT_GPR4, PT_GPR4, PT_GPR5, PT_GPR5, PT_GPR6, PT_GPR6, PT_GPR7, PT_GPR7, + PT_GPR8, PT_GPR8, PT_GPR9, PT_GPR9, PT_GPR10, PT_GPR10, PT_GPR11, PT_GPR11, + PT_GPR12, PT_GPR12, PT_GPR13, PT_GPR13, PT_GPR14, PT_GPR14, PT_GPR15, PT_GPR15, + + PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3, + PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7, + PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11, + PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15, + + PT_FPC, + + PT_FPR0, PT_FPR1, PT_FPR2, PT_FPR3, + PT_FPR4, PT_FPR5, PT_FPR6, PT_FPR7, + PT_FPR8, PT_FPR9, PT_FPR10, PT_FPR11, + PT_FPR12, PT_FPR13, PT_FPR14, PT_FPR15, +}; +#endif + + static int s390_cannot_fetch_register (int regno) { - if (s390_regmap[regno] == -1) - return 1; - return 0; } static int s390_cannot_store_register (int regno) { - if (s390_regmap[regno] == -1) - return 1; - return 0; } @@ -85,17 +111,25 @@ s390_collect_ptrace_register (int regno, char *buf) int size = register_size (regno); if (size < sizeof (long)) { + int regaddr = the_low_target.regmap[regno]; + memset (buf, 0, sizeof (long)); - if (regno == find_regno ("pswa") - || (regno >= find_regno ("r0") && regno <= find_regno ("r15"))) + if ((regno ^ 1) < the_low_target.num_regs + && the_low_target.regmap[regno ^ 1] == regaddr) + { + collect_register (regno & ~1, buf); + collect_register ((regno & ~1) + 1, buf + sizeof (long) - size); + } + else if (regaddr == PT_PSWADDR + || (regaddr >= PT_GPR0 && regaddr <= PT_GPR15)) collect_register (regno, buf + sizeof (long) - size); else collect_register (regno, buf); /* When debugging a 32-bit inferior on a 64-bit host, make sure the 31-bit addressing mode bit is set in the PSW mask. */ - if (regno == find_regno ("pswm")) + if (regaddr == PT_PSWMASK) buf[size] |= 0x80; } else @@ -108,8 +142,16 @@ s390_supply_ptrace_register (int regno, const char *buf) int size = register_size (regno); if (size < sizeof (long)) { - if (regno == find_regno ("pswa") - || (regno >= find_regno ("r0") && regno <= find_regno ("r15"))) + int regaddr = the_low_target.regmap[regno]; + + if ((regno ^ 1) < the_low_target.num_regs + && the_low_target.regmap[regno ^ 1] == regaddr) + { + supply_register (regno & ~1, buf); + supply_register ((regno & ~1) + 1, buf + sizeof (long) - size); + } + else if (regaddr == PT_PSWADDR + || (regaddr >= PT_GPR0 && regaddr <= PT_GPR15)) supply_register (regno, buf + sizeof (long) - size); else supply_register (regno, buf); @@ -125,8 +167,15 @@ static void s390_fill_gregset (void *buf) { int i; - for (i = 0; i < 34; i++) - s390_collect_ptrace_register (i, (char *) buf + s390_regmap[i]); + for (i = 0; i < the_low_target.num_regs; i++) + { + if (the_low_target.regmap[i] < PT_PSWMASK + || the_low_target.regmap[i] > PT_ACR15) + continue; + + s390_collect_ptrace_register (i, (char *) buf + + the_low_target.regmap[i]); + } } struct regset_info target_regsets[] = { @@ -176,12 +225,43 @@ s390_set_pc (CORE_ADDR newpc) } } +#ifdef __s390x__ +static unsigned long +s390_get_hwcap (void) +{ + int wordsize = register_size (0); + unsigned char *data = alloca (2 * wordsize); + int offset = 0; + + while ((*the_target->read_auxv) (offset, data, 2 * wordsize) == 2 * wordsize) + { + if (wordsize == 4) + { + unsigned int *data_p = (unsigned int *)data; + if (data_p[0] == AT_HWCAP) + return data_p[1]; + } + else + { + unsigned long *data_p = (unsigned long *)data; + if (data_p[0] == AT_HWCAP) + return data_p[1]; + } + + offset += 2 * wordsize; + } + + return 0; +} +#endif static void s390_arch_setup (void) { /* Assume 31-bit inferior process. */ - init_registers_s390 (); + init_registers_s390_linux32 (); + the_low_target.num_regs = s390_num_regs; + the_low_target.regmap = s390_regmap; /* On a 64-bit host, check the low bit of the (31-bit) PSWM -- if this is one, we actually have a 64-bit inferior. */ @@ -190,7 +270,16 @@ s390_arch_setup (void) unsigned int pswm; collect_register_by_name ("pswm", &pswm); if (pswm & 1) - init_registers_s390x (); + init_registers_s390x_linux64 (); + + /* For a 31-bit inferior, check whether the kernel supports + using the full 64-bit GPRs. */ + else if (s390_get_hwcap () & HWCAP_S390_HIGH_GPRS) + { + init_registers_s390_linux64 (); + the_low_target.num_regs = s390_num_regs_3264; + the_low_target.regmap = s390_regmap_3264; + } } #endif } diff --git a/gdb/regformats/reg-s390.dat b/gdb/regformats/s390-linux32.dat index 79e07b96..d0ac867 100644 --- a/gdb/regformats/reg-s390.dat +++ b/gdb/regformats/s390-linux32.dat @@ -1,4 +1,6 @@ -name:s390 +# DO NOT EDIT: generated from s390-linux32.xml +name:s390_linux32 +xmltarget:s390-linux32.xml expedite:r14,r15,pswa 32:pswm 32:pswa diff --git a/gdb/regformats/s390-linux64.dat b/gdb/regformats/s390-linux64.dat new file mode 100644 index 0000000..95265f0 --- /dev/null +++ b/gdb/regformats/s390-linux64.dat @@ -0,0 +1,71 @@ +# DO NOT EDIT: generated from s390-linux64.xml +name:s390_linux64 +xmltarget:s390-linux64.xml +expedite:r14l,r15l,pswa +32:pswm +32:pswa +32:r0h +32:r0l +32:r1h +32:r1l +32:r2h +32:r2l +32:r3h +32:r3l +32:r4h +32:r4l +32:r5h +32:r5l +32:r6h +32:r6l +32:r7h +32:r7l +32:r8h +32:r8l +32:r9h +32:r9l +32:r10h +32:r10l +32:r11h +32:r11l +32:r12h +32:r12l +32:r13h +32:r13l +32:r14h +32:r14l +32:r15h +32:r15l +32:acr0 +32:acr1 +32:acr2 +32:acr3 +32:acr4 +32:acr5 +32:acr6 +32:acr7 +32:acr8 +32:acr9 +32:acr10 +32:acr11 +32:acr12 +32:acr13 +32:acr14 +32:acr15 +32:fpc +64:f0 +64:f1 +64:f2 +64:f3 +64:f4 +64:f5 +64:f6 +64:f7 +64:f8 +64:f9 +64:f10 +64:f11 +64:f12 +64:f13 +64:f14 +64:f15 diff --git a/gdb/regformats/reg-s390x.dat b/gdb/regformats/s390x-linux64.dat index 81ce403..1126940 100644 --- a/gdb/regformats/reg-s390x.dat +++ b/gdb/regformats/s390x-linux64.dat @@ -1,4 +1,6 @@ -name:s390x +# DO NOT EDIT: generated from s390x-linux64.xml +name:s390x_linux64 +xmltarget:s390x-linux64.xml expedite:r14,r15,pswa 64:pswm 64:pswa diff --git a/gdb/s390-nat.c b/gdb/s390-nat.c index c67777e..3af42ff 100644 --- a/gdb/s390-nat.c +++ b/gdb/s390-nat.c @@ -25,6 +25,7 @@ #include "inferior.h" #include "target.h" #include "linux-nat.h" +#include "auxv.h" #include "s390-tdep.h" @@ -33,6 +34,11 @@ #include <asm/types.h> #include <sys/procfs.h> #include <sys/ucontext.h> +#include <elf.h> + +#ifndef HWCAP_S390_HIGH_GPRS +#define HWCAP_S390_HIGH_GPRS 512 +#endif /* Map registers to gregset/ptrace offsets. @@ -389,6 +395,83 @@ s390_region_ok_for_hw_watchpoint (CORE_ADDR addr, int cnt) return 1; } +static int +s390_target_wordsize (void) +{ + int wordsize = 4; + + /* Check for 64-bit inferior process. This is the case when the host is + 64-bit, and in addition bit 32 of the PSW mask is set. */ +#ifdef __s390x__ + long pswm; + + errno = 0; + pswm = (long) ptrace (PTRACE_PEEKUSER, s390_inferior_tid (), PT_PSWMASK, 0); + if (errno == 0 && (pswm & 0x100000000ul) != 0) + wordsize = 8; +#endif + + return wordsize; +} + +static int +s390_auxv_parse (struct target_ops *ops, gdb_byte **readptr, + gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp) +{ + int sizeof_auxv_field = s390_target_wordsize (); + enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch); + gdb_byte *ptr = *readptr; + + if (endptr == ptr) + return 0; + + if (endptr - ptr < sizeof_auxv_field * 2) + return -1; + + *typep = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order); + ptr += sizeof_auxv_field; + *valp = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order); + ptr += sizeof_auxv_field; + + *readptr = ptr; + return 1; +} + +#ifdef __s390x__ +static unsigned long +s390_get_hwcap (void) +{ + CORE_ADDR field; + + if (target_auxv_search (¤t_target, AT_HWCAP, &field)) + return (unsigned long) field; + + return 0; +} +#endif + +static const struct target_desc * +s390_read_description (struct target_ops *ops) +{ +#ifdef __s390x__ + /* If GDB itself is compiled as 64-bit, we are running on a machine in + z/Architecture mode. If the target is running in 64-bit addressing + mode, report s390x architecture. If the target is running in 31-bit + addressing mode, but the kernel supports using 64-bit registers in + that mode, report s390 architecture with 64-bit GPRs. */ + + if (s390_target_wordsize () == 8) + return tdesc_s390x_linux64; + + if (s390_get_hwcap () & HWCAP_S390_HIGH_GPRS) + return tdesc_s390_linux64; +#endif + + /* If GDB itself is compiled as 31-bit, or if we're running a 31-bit inferior + on a 64-bit kernel that does not support using 64-bit registers in 31-bit + mode, report s390 architecture with 32-bit GPRs. */ + return tdesc_s390_linux32; +} void _initialize_s390_nat (void); @@ -412,6 +495,10 @@ _initialize_s390_nat (void) t->to_insert_watchpoint = s390_insert_watchpoint; t->to_remove_watchpoint = s390_remove_watchpoint; + /* Detect target architecture. */ + t->to_read_description = s390_read_description; + t->to_auxv_parse = s390_auxv_parse; + /* Register the target. */ linux_nat_add_target (t); linux_nat_set_new_thread (t, s390_fix_watch_points); diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c index 93bfebf..e7dc48d 100644 --- a/gdb/s390-tdep.c +++ b/gdb/s390-tdep.c @@ -46,6 +46,10 @@ #include "s390-tdep.h" +#include "features/s390-linux32.c" +#include "features/s390-linux64.c" +#include "features/s390x-linux64.c" + /* The tdep structure. */ @@ -54,6 +58,11 @@ struct gdbarch_tdep /* ABI version. */ enum { ABI_LINUX_S390, ABI_LINUX_ZSERIES } abi; + /* Pseudo register numbers. */ + int gpr_full_regnum; + int pc_regnum; + int cc_regnum; + /* Core file register sets. */ const struct regset *gregset; int sizeof_gregset; @@ -63,56 +72,36 @@ struct gdbarch_tdep }; -/* Return the name of register REGNUM. */ -static const char * -s390_register_name (struct gdbarch *gdbarch, int regnum) +/* ABI call-saved register information. */ + +static int +s390_register_call_saved (struct gdbarch *gdbarch, int regnum) { - static const char *register_names[S390_NUM_TOTAL_REGS] = + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + switch (tdep->abi) { - /* Program Status Word. */ - "pswm", "pswa", - /* General Purpose Registers. */ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", - /* Access Registers. */ - "acr0", "acr1", "acr2", "acr3", "acr4", "acr5", "acr6", "acr7", - "acr8", "acr9", "acr10", "acr11", "acr12", "acr13", "acr14", "acr15", - /* Floating Point Control Word. */ - "fpc", - /* Floating Point Registers. */ - "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", - "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", - /* Pseudo registers. */ - "pc", "cc", - }; - - gdb_assert (regnum >= 0 && regnum < S390_NUM_TOTAL_REGS); - return register_names[regnum]; -} - -/* Return the GDB type object for the "standard" data type of data in - register REGNUM. */ -static struct type * -s390_register_type (struct gdbarch *gdbarch, int regnum) -{ - if (regnum == S390_PSWM_REGNUM || regnum == S390_PSWA_REGNUM) - return builtin_type (gdbarch)->builtin_long; - if (regnum >= S390_R0_REGNUM && regnum <= S390_R15_REGNUM) - return builtin_type (gdbarch)->builtin_long; - if (regnum >= S390_A0_REGNUM && regnum <= S390_A15_REGNUM) - return builtin_type (gdbarch)->builtin_int; - if (regnum == S390_FPC_REGNUM) - return builtin_type (gdbarch)->builtin_int; - if (regnum >= S390_F0_REGNUM && regnum <= S390_F15_REGNUM) - return builtin_type (gdbarch)->builtin_double; - if (regnum == S390_PC_REGNUM) - return builtin_type (gdbarch)->builtin_func_ptr; - if (regnum == S390_CC_REGNUM) - return builtin_type (gdbarch)->builtin_int; + case ABI_LINUX_S390: + if ((regnum >= S390_R6_REGNUM && regnum <= S390_R15_REGNUM) + || regnum == S390_F4_REGNUM || regnum == S390_F6_REGNUM + || regnum == S390_A0_REGNUM) + return 1; - internal_error (__FILE__, __LINE__, _("invalid regnum")); + break; + + case ABI_LINUX_ZSERIES: + if ((regnum >= S390_R6_REGNUM && regnum <= S390_R15_REGNUM) + || (regnum >= S390_F8_REGNUM && regnum <= S390_F15_REGNUM) + || (regnum >= S390_A0_REGNUM && regnum <= S390_A1_REGNUM)) + return 1; + + break; + } + + return 0; } + /* DWARF Register Mapping. */ static int s390_dwarf_regmap[] = @@ -141,7 +130,13 @@ static int s390_dwarf_regmap[] = /* Program Status Word. */ S390_PSWM_REGNUM, - S390_PSWA_REGNUM + S390_PSWA_REGNUM, + + /* GPR Lower Half Access. */ + S390_R0_REGNUM, S390_R1_REGNUM, S390_R2_REGNUM, S390_R3_REGNUM, + S390_R4_REGNUM, S390_R5_REGNUM, S390_R6_REGNUM, S390_R7_REGNUM, + S390_R8_REGNUM, S390_R9_REGNUM, S390_R10_REGNUM, S390_R11_REGNUM, + S390_R12_REGNUM, S390_R13_REGNUM, S390_R14_REGNUM, S390_R15_REGNUM, }; /* Convert DWARF register number REG to the appropriate register @@ -149,117 +144,172 @@ static int s390_dwarf_regmap[] = static int s390_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) { - int regnum = -1; + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* In a 32-on-64 debug scenario, debug info refers to the full 64-bit + GPRs. Note that call frame information still refers to the 32-bit + lower halves, because s390_adjust_frame_regnum uses register numbers + 66 .. 81 to access GPRs. */ + if (tdep->gpr_full_regnum != -1 && reg >= 0 && reg < 16) + return tdep->gpr_full_regnum + reg; if (reg >= 0 && reg < ARRAY_SIZE (s390_dwarf_regmap)) - regnum = s390_dwarf_regmap[reg]; + return s390_dwarf_regmap[reg]; - if (regnum == -1) - warning (_("Unmapped DWARF Register #%d encountered."), reg); + warning (_("Unmapped DWARF Register #%d encountered."), reg); + return -1; +} - return regnum; +/* Translate a .eh_frame register to DWARF register, or adjust a + .debug_frame register. */ +static int +s390_adjust_frame_regnum (struct gdbarch *gdbarch, int num, int eh_frame_p) +{ + /* See s390_dwarf_reg_to_regnum for comments. */ + return (num >= 0 && num < 16)? num + 66 : num; } -/* Pseudo registers - PC and condition code. */ -static void -s390_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, - int regnum, gdb_byte *buf) +/* Pseudo registers. */ + +static const char * +s390_pseudo_register_name (struct gdbarch *gdbarch, int regnum) { - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - ULONGEST val; + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - switch (regnum) - { - case S390_PC_REGNUM: - regcache_raw_read_unsigned (regcache, S390_PSWA_REGNUM, &val); - store_unsigned_integer (buf, 4, byte_order, val & 0x7fffffff); - break; + if (regnum == tdep->pc_regnum) + return "pc"; - case S390_CC_REGNUM: - regcache_raw_read_unsigned (regcache, S390_PSWM_REGNUM, &val); - store_unsigned_integer (buf, 4, byte_order, (val >> 12) & 3); - break; + if (regnum == tdep->cc_regnum) + return "cc"; - default: - internal_error (__FILE__, __LINE__, _("invalid regnum")); + if (tdep->gpr_full_regnum != -1 + && regnum >= tdep->gpr_full_regnum + && regnum < tdep->gpr_full_regnum + 16) + { + static const char *full_name[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" + }; + return full_name[regnum - tdep->gpr_full_regnum]; } + + internal_error (__FILE__, __LINE__, _("invalid regnum")); } -static void -s390_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, - int regnum, const gdb_byte *buf) +static struct type * +s390_pseudo_register_type (struct gdbarch *gdbarch, int regnum) { - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - ULONGEST val, psw; + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - switch (regnum) - { - case S390_PC_REGNUM: - val = extract_unsigned_integer (buf, 4, byte_order); - regcache_raw_read_unsigned (regcache, S390_PSWA_REGNUM, &psw); - psw = (psw & 0x80000000) | (val & 0x7fffffff); - regcache_raw_write_unsigned (regcache, S390_PSWA_REGNUM, psw); - break; + if (regnum == tdep->pc_regnum) + return builtin_type (gdbarch)->builtin_func_ptr; - case S390_CC_REGNUM: - val = extract_unsigned_integer (buf, 4, byte_order); - regcache_raw_read_unsigned (regcache, S390_PSWM_REGNUM, &psw); - psw = (psw & ~((ULONGEST)3 << 12)) | ((val & 3) << 12); - regcache_raw_write_unsigned (regcache, S390_PSWM_REGNUM, psw); - break; + if (regnum == tdep->cc_regnum) + return builtin_type (gdbarch)->builtin_int; - default: - internal_error (__FILE__, __LINE__, _("invalid regnum")); - } + if (tdep->gpr_full_regnum != -1 + && regnum >= tdep->gpr_full_regnum + && regnum < tdep->gpr_full_regnum + 16) + return builtin_type (gdbarch)->builtin_uint64; + + internal_error (__FILE__, __LINE__, _("invalid regnum")); } static void -s390x_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, - int regnum, gdb_byte *buf) +s390_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, + int regnum, gdb_byte *buf) { + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + int regsize = register_size (gdbarch, regnum); ULONGEST val; - switch (regnum) + if (regnum == tdep->pc_regnum) { - case S390_PC_REGNUM: - regcache_raw_read (regcache, S390_PSWA_REGNUM, buf); - break; + regcache_raw_read_unsigned (regcache, S390_PSWA_REGNUM, &val); + if (register_size (gdbarch, S390_PSWA_REGNUM) == 4) + val &= 0x7fffffff; + store_unsigned_integer (buf, regsize, byte_order, val); + return; + } - case S390_CC_REGNUM: + if (regnum == tdep->cc_regnum) + { regcache_raw_read_unsigned (regcache, S390_PSWM_REGNUM, &val); - store_unsigned_integer (buf, 4, byte_order, (val >> 44) & 3); - break; + if (register_size (gdbarch, S390_PSWA_REGNUM) == 4) + val = (val >> 12) & 3; + else + val = (val >> 44) & 3; + store_unsigned_integer (buf, regsize, byte_order, val); + return; + } - default: - internal_error (__FILE__, __LINE__, _("invalid regnum")); + if (tdep->gpr_full_regnum != -1 + && regnum >= tdep->gpr_full_regnum + && regnum < tdep->gpr_full_regnum + 16) + { + ULONGEST val_upper; + regnum -= tdep->gpr_full_regnum; + + regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + regnum, &val); + regcache_raw_read_unsigned (regcache, S390_R0_UPPER_REGNUM + regnum, + &val_upper); + val |= val_upper << 32; + store_unsigned_integer (buf, regsize, byte_order, val); + return; } + + internal_error (__FILE__, __LINE__, _("invalid regnum")); } static void -s390x_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, - int regnum, const gdb_byte *buf) +s390_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, + int regnum, const gdb_byte *buf) { + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + int regsize = register_size (gdbarch, regnum); ULONGEST val, psw; - switch (regnum) + if (regnum == tdep->pc_regnum) { - case S390_PC_REGNUM: - regcache_raw_write (regcache, S390_PSWA_REGNUM, buf); - break; + val = extract_unsigned_integer (buf, regsize, byte_order); + if (register_size (gdbarch, S390_PSWA_REGNUM) == 4) + { + regcache_raw_read_unsigned (regcache, S390_PSWA_REGNUM, &psw); + val = (psw & 0x80000000) | (val & 0x7fffffff); + } + regcache_raw_write_unsigned (regcache, S390_PSWA_REGNUM, val); + return; + } - case S390_CC_REGNUM: - val = extract_unsigned_integer (buf, 4, byte_order); + if (regnum == tdep->cc_regnum) + { + val = extract_unsigned_integer (buf, regsize, byte_order); regcache_raw_read_unsigned (regcache, S390_PSWM_REGNUM, &psw); - psw = (psw & ~((ULONGEST)3 << 44)) | ((val & 3) << 44); - regcache_raw_write_unsigned (regcache, S390_PSWM_REGNUM, psw); - break; + if (register_size (gdbarch, S390_PSWA_REGNUM) == 4) + val = (psw & ~((ULONGEST)3 << 12)) | ((val & 3) << 12); + else + val = (psw & ~((ULONGEST)3 << 44)) | ((val & 3) << 44); + regcache_raw_write_unsigned (regcache, S390_PSWM_REGNUM, val); + return; + } - default: - internal_error (__FILE__, __LINE__, _("invalid regnum")); + if (tdep->gpr_full_regnum != -1 + && regnum >= tdep->gpr_full_regnum + && regnum < tdep->gpr_full_regnum + 16) + { + regnum -= tdep->gpr_full_regnum; + val = extract_unsigned_integer (buf, regsize, byte_order); + regcache_raw_write_unsigned (regcache, S390_R0_REGNUM + regnum, + val & 0xffffffff); + regcache_raw_write_unsigned (regcache, S390_R0_UPPER_REGNUM + regnum, + val >> 32); + return; } + + internal_error (__FILE__, __LINE__, _("invalid regnum")); } /* 'float' values are stored in the upper half of floating-point @@ -281,26 +331,15 @@ s390_value_from_register (struct type *type, int regnum, /* Register groups. */ static int -s390_register_reggroup_p (struct gdbarch *gdbarch, int regnum, - struct reggroup *group) +s390_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum, + struct reggroup *group) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - /* Registers displayed via 'info regs'. */ - if (group == general_reggroup) - return (regnum >= S390_R0_REGNUM && regnum <= S390_R15_REGNUM) - || regnum == S390_PC_REGNUM - || regnum == S390_CC_REGNUM; - - /* Registers displayed via 'info float'. */ - if (group == float_reggroup) - return (regnum >= S390_F0_REGNUM && regnum <= S390_F15_REGNUM) - || regnum == S390_FPC_REGNUM; - - /* Registers that need to be saved/restored in order to + /* PC and CC pseudo registers need to be saved/restored in order to push or pop frames. */ if (group == save_reggroup || group == restore_reggroup) - return regnum != S390_PSWM_REGNUM && regnum != S390_PSWA_REGNUM; + return regnum == tdep->pc_regnum || regnum == tdep->cc_regnum; return default_register_reggroup_p (gdbarch, regnum, group); } @@ -327,10 +366,14 @@ int s390_regmap_gregset[S390_NUM_REGS] = /* Floating Point Registers. */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* GPR Uppper Halves. */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }; int s390x_regmap_gregset[S390_NUM_REGS] = { + /* Program Status Word. */ 0x00, 0x08, /* General Purpose Registers. */ 0x10, 0x18, 0x20, 0x28, @@ -347,6 +390,11 @@ int s390x_regmap_gregset[S390_NUM_REGS] = /* Floating Point Registers. */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* GPR Uppper Halves. */ + 0x10, 0x18, 0x20, 0x28, + 0x30, 0x38, 0x40, 0x48, + 0x50, 0x58, 0x60, 0x68, + 0x70, 0x78, 0x80, 0x88, }; int s390_regmap_fpregset[S390_NUM_REGS] = @@ -366,6 +414,31 @@ int s390_regmap_fpregset[S390_NUM_REGS] = 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78, 0x80, + /* GPR Uppper Halves. */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +}; + +int s390_regmap_upper[S390_NUM_REGS] = +{ + /* Program Status Word. */ + -1, -1, + /* General Purpose Registers. */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + /* Access Registers. */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + /* Floating Point Control Word. */ + -1, + /* Floating Point Registers. */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + /* GPR Uppper Halves. */ + 0x00, 0x04, 0x08, 0x0c, + 0x10, 0x14, 0x18, 0x1c, + 0x20, 0x24, 0x28, 0x2c, + 0x30, 0x34, 0x38, 0x3c, }; /* Supply register REGNUM from the register set REGSET to register cache @@ -421,6 +494,20 @@ static const struct regset s390_fpregset = { s390_collect_regset }; +static const struct regset s390_upper_regset = { + s390_regmap_upper, + s390_supply_regset, + s390_collect_regset +}; + +static struct core_regset_section s390_upper_regset_sections[] = +{ + { ".reg", s390_sizeof_gregset, "general-purpose" }, + { ".reg2", s390_sizeof_fpregset, "floating-point" }, + { ".reg-s390-high-gprs", 16*4, "s390 GPR upper halves" }, + { NULL, 0} +}; + /* Return the appropriate register set for the core section identified by SECT_NAME and SECT_SIZE. */ static const struct regset * @@ -435,9 +522,34 @@ s390_regset_from_core_section (struct gdbarch *gdbarch, if (strcmp (sect_name, ".reg2") == 0 && sect_size >= tdep->sizeof_fpregset) return tdep->fpregset; + if (strcmp (sect_name, ".reg-s390-high-gprs") == 0 && sect_size >= 16*4) + return &s390_upper_regset; + return NULL; } +static const struct target_desc * +s390_core_read_description (struct gdbarch *gdbarch, + struct target_ops *target, bfd *abfd) +{ + asection *high_gprs = bfd_get_section_by_name (abfd, ".reg-s390-high-gprs"); + asection *section = bfd_get_section_by_name (abfd, ".reg"); + if (!section) + return NULL; + + switch (bfd_section_size (abfd, section)) + { + case s390_sizeof_gregset: + return high_gprs? tdesc_s390_linux64 : tdesc_s390_linux32; + + case s390x_sizeof_gregset: + return tdesc_s390x_linux64; + + default: + return NULL; + } +} + /* Decoding S/390 instructions. */ @@ -1448,42 +1560,40 @@ s390_prologue_frame_unwind_cache (struct frame_info *this_frame, prev_sp = get_frame_register_unsigned (this_frame, frame_pointer) + size; cfa = prev_sp + 16*word_size + 32; + /* Set up ABI call-saved/call-clobbered registers. */ + for (i = 0; i < S390_NUM_REGS; i++) + if (!s390_register_call_saved (gdbarch, i)) + trad_frame_set_unknown (info->saved_regs, i); + + /* CC is always call-clobbered. */ + trad_frame_set_unknown (info->saved_regs, tdep->cc_regnum); + /* Record the addresses of all register spill slots the prologue parser has recognized. Consider only registers defined as call-saved by the ABI; for call-clobbered registers the parser may have recognized spurious stores. */ - for (i = 6; i <= 15; i++) - if (data.gpr_slot[i] != 0) + for (i = 0; i < 16; i++) + if (s390_register_call_saved (gdbarch, S390_R0_REGNUM + i) + && data.gpr_slot[i] != 0) info->saved_regs[S390_R0_REGNUM + i].addr = cfa - data.gpr_slot[i]; - switch (tdep->abi) - { - case ABI_LINUX_S390: - if (data.fpr_slot[4] != 0) - info->saved_regs[S390_F4_REGNUM].addr = cfa - data.fpr_slot[4]; - if (data.fpr_slot[6] != 0) - info->saved_regs[S390_F6_REGNUM].addr = cfa - data.fpr_slot[6]; - break; - - case ABI_LINUX_ZSERIES: - for (i = 8; i <= 15; i++) - if (data.fpr_slot[i] != 0) - info->saved_regs[S390_F0_REGNUM + i].addr = cfa - data.fpr_slot[i]; - break; - } + for (i = 0; i < 16; i++) + if (s390_register_call_saved (gdbarch, S390_F0_REGNUM + i) + && data.fpr_slot[i] != 0) + info->saved_regs[S390_F0_REGNUM + i].addr = cfa - data.fpr_slot[i]; /* Function return will set PC to %r14. */ - info->saved_regs[S390_PC_REGNUM] = info->saved_regs[S390_RETADDR_REGNUM]; + info->saved_regs[tdep->pc_regnum] = info->saved_regs[S390_RETADDR_REGNUM]; /* In frameless functions, we unwind simply by moving the return address to the PC. However, if we actually stored to the save area, use that -- we might only think the function frameless because we're in the middle of the prologue ... */ if (size == 0 - && !trad_frame_addr_p (info->saved_regs, S390_PC_REGNUM)) + && !trad_frame_addr_p (info->saved_regs, tdep->pc_regnum)) { - info->saved_regs[S390_PC_REGNUM].realreg = S390_RETADDR_REGNUM; + info->saved_regs[tdep->pc_regnum].realreg = S390_RETADDR_REGNUM; } /* Another sanity check: unless this is a frameless function, @@ -1493,7 +1603,7 @@ s390_prologue_frame_unwind_cache (struct frame_info *this_frame, if (size > 0) { if (!trad_frame_addr_p (info->saved_regs, S390_SP_REGNUM) - || !trad_frame_addr_p (info->saved_regs, S390_PC_REGNUM)) + || !trad_frame_addr_p (info->saved_regs, tdep->pc_regnum)) prev_sp = -1; } @@ -1514,11 +1624,21 @@ s390_backchain_frame_unwind_cache (struct frame_info *this_frame, struct s390_unwind_cache *info) { struct gdbarch *gdbarch = get_frame_arch (this_frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int word_size = gdbarch_ptr_bit (gdbarch) / 8; enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); CORE_ADDR backchain; ULONGEST reg; LONGEST sp; + int i; + + /* Set up ABI call-saved/call-clobbered registers. */ + for (i = 0; i < S390_NUM_REGS; i++) + if (!s390_register_call_saved (gdbarch, i)) + trad_frame_set_unknown (info->saved_regs, i); + + /* CC is always call-clobbered. */ + trad_frame_set_unknown (info->saved_regs, tdep->cc_regnum); /* Get the backchain. */ reg = get_frame_register_unsigned (this_frame, S390_SP_REGNUM); @@ -1540,7 +1660,8 @@ s390_backchain_frame_unwind_cache (struct frame_info *this_frame, info->saved_regs[S390_RETADDR_REGNUM].addr = backchain + 14*word_size; /* Function return will set PC to %r14. */ - info->saved_regs[S390_PC_REGNUM] = info->saved_regs[S390_RETADDR_REGNUM]; + info->saved_regs[tdep->pc_regnum] + = info->saved_regs[S390_RETADDR_REGNUM]; /* We use the current value of the frame register as local_base, and the top of the register save area as frame_base. */ @@ -1592,8 +1713,28 @@ static struct value * s390_frame_prev_register (struct frame_info *this_frame, void **this_prologue_cache, int regnum) { + struct gdbarch *gdbarch = get_frame_arch (this_frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); struct s390_unwind_cache *info = s390_frame_unwind_cache (this_frame, this_prologue_cache); + + /* Unwind full GPRs to show at least the lower halves (as the + upper halves are undefined). */ + if (tdep->gpr_full_regnum != -1 + && regnum >= tdep->gpr_full_regnum + && regnum < tdep->gpr_full_regnum + 16) + { + int reg = regnum - tdep->gpr_full_regnum + S390_R0_REGNUM; + struct value *val, *newval; + + val = trad_frame_get_prev_register (this_frame, info->saved_regs, reg); + newval = value_cast (register_type (gdbarch, regnum), val); + if (value_optimized_out (val)) + set_value_optimized_out (newval, 1); + + return newval; + } + return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum); } @@ -1621,6 +1762,7 @@ s390_stub_frame_unwind_cache (struct frame_info *this_frame, void **this_prologue_cache) { struct gdbarch *gdbarch = get_frame_arch (this_frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int word_size = gdbarch_ptr_bit (gdbarch) / 8; struct s390_stub_unwind_cache *info; ULONGEST reg; @@ -1633,7 +1775,7 @@ s390_stub_frame_unwind_cache (struct frame_info *this_frame, info->saved_regs = trad_frame_alloc_saved_regs (this_frame); /* The return address is in register %r14. */ - info->saved_regs[S390_PC_REGNUM].realreg = S390_RETADDR_REGNUM; + info->saved_regs[tdep->pc_regnum].realreg = S390_RETADDR_REGNUM; /* Retrieve stack pointer and determine our frame base. */ reg = get_frame_register_unsigned (this_frame, S390_SP_REGNUM); @@ -1700,11 +1842,13 @@ s390_sigtramp_frame_unwind_cache (struct frame_info *this_frame, void **this_prologue_cache) { struct gdbarch *gdbarch = get_frame_arch (this_frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int word_size = gdbarch_ptr_bit (gdbarch) / 8; enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); struct s390_sigtramp_unwind_cache *info; ULONGEST this_sp, prev_sp; - CORE_ADDR next_ra, next_cfa, sigreg_ptr; + CORE_ADDR next_ra, next_cfa, sigreg_ptr, sigreg_high_off; + ULONGEST pswm; int i; if (*this_prologue_cache) @@ -1725,6 +1869,9 @@ s390_sigtramp_frame_unwind_cache (struct frame_info *this_frame, if (next_ra == next_cfa) { sigreg_ptr = next_cfa + 8 + 128 + align_up (5*word_size, 8); + /* sigregs are followed by uc_sigmask (8 bytes), then by the + upper GPR halves if present. */ + sigreg_high_off = 8; } /* Old-style RT frame and all non-RT frames: @@ -1734,6 +1881,9 @@ s390_sigtramp_frame_unwind_cache (struct frame_info *this_frame, { sigreg_ptr = read_memory_unsigned_integer (next_cfa + 8, word_size, byte_order); + /* sigregs are followed by signo (4 bytes), then by the + upper GPR halves if present. */ + sigreg_high_off = 4; } /* The sigregs structure looks like this: @@ -1745,13 +1895,22 @@ s390_sigtramp_frame_unwind_cache (struct frame_info *this_frame, int __pad; double fprs[16]; */ - /* Let's ignore the PSW mask, it will not be restored anyway. */ + /* PSW mask and address. */ + info->saved_regs[S390_PSWM_REGNUM].addr = sigreg_ptr; sigreg_ptr += word_size; - - /* Next comes the PSW address. */ - info->saved_regs[S390_PC_REGNUM].addr = sigreg_ptr; + info->saved_regs[S390_PSWA_REGNUM].addr = sigreg_ptr; sigreg_ptr += word_size; + /* Point PC to PSWA as well. */ + info->saved_regs[tdep->pc_regnum] = info->saved_regs[S390_PSWA_REGNUM]; + + /* Extract CC from PSWM. */ + pswm = read_memory_unsigned_integer ( + info->saved_regs[S390_PSWM_REGNUM].addr, + word_size, byte_order); + trad_frame_set_value (info->saved_regs, tdep->cc_regnum, + (pswm >> (8 * word_size - 20)) & 3); + /* Then the GPRs. */ for (i = 0; i < 16; i++) { @@ -1777,6 +1936,31 @@ s390_sigtramp_frame_unwind_cache (struct frame_info *this_frame, sigreg_ptr += 8; } + /* If we have them, the GPR upper halves are appended at the end. */ + sigreg_ptr += sigreg_high_off; + if (tdep->gpr_full_regnum != -1) + for (i = 0; i < 16; i++) + { + info->saved_regs[S390_R0_UPPER_REGNUM + i].addr = sigreg_ptr; + sigreg_ptr += 4; + } + + /* Provide read-only copies of the full registers. */ + if (tdep->gpr_full_regnum != -1) + for (i = 0; i < 16; i++) + { + ULONGEST low, high; + low = read_memory_unsigned_integer ( + info->saved_regs[S390_R0_REGNUM + i].addr, + 4, byte_order); + high = read_memory_unsigned_integer ( + info->saved_regs[S390_R0_UPPER_REGNUM + i].addr, + 4, byte_order); + + trad_frame_set_value (info->saved_regs, tdep->gpr_full_regnum + i, + (high << 32) | low); + } + /* Restore the previous frame's SP. */ prev_sp = read_memory_unsigned_integer ( info->saved_regs[S390_SP_REGNUM].addr, @@ -1865,8 +2049,9 @@ static const struct frame_base s390_frame_base = { static CORE_ADDR s390_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) { + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ULONGEST pc; - pc = frame_unwind_register_unsigned (next_frame, S390_PC_REGNUM); + pc = frame_unwind_register_unsigned (next_frame, tdep->pc_regnum); return gdbarch_addr_bits_remove (gdbarch, pc); } @@ -1881,6 +2066,23 @@ s390_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) /* DWARF-2 frame support. */ +static struct value * +s390_dwarf2_prev_register (struct frame_info *this_frame, void **this_cache, + int regnum) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int reg = regnum - tdep->gpr_full_regnum; + struct value *val, *newval; + + val = frame_unwind_register_value (this_frame, S390_R0_REGNUM + reg); + newval = value_cast (register_type (gdbarch, regnum), val); + if (value_optimized_out (val)) + set_value_optimized_out (newval, 1); + + return newval; +} + static void s390_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, struct dwarf2_frame_state_reg *reg, @@ -1888,41 +2090,32 @@ s390_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - switch (tdep->abi) + /* Fixed registers are call-saved or call-clobbered + depending on the ABI in use. */ + if (regnum >= 0 && regnum < S390_NUM_REGS) { - case ABI_LINUX_S390: - /* Call-saved registers. */ - if ((regnum >= S390_R6_REGNUM && regnum <= S390_R15_REGNUM) - || regnum == S390_F4_REGNUM - || regnum == S390_F6_REGNUM) + if (s390_register_call_saved (gdbarch, regnum)) reg->how = DWARF2_FRAME_REG_SAME_VALUE; - - /* Call-clobbered registers. */ - else if ((regnum >= S390_R0_REGNUM && regnum <= S390_R5_REGNUM) - || (regnum >= S390_F0_REGNUM && regnum <= S390_F15_REGNUM - && regnum != S390_F4_REGNUM && regnum != S390_F6_REGNUM)) + else reg->how = DWARF2_FRAME_REG_UNDEFINED; + } - /* The return address column. */ - else if (regnum == S390_PC_REGNUM) - reg->how = DWARF2_FRAME_REG_RA; - break; - - case ABI_LINUX_ZSERIES: - /* Call-saved registers. */ - if ((regnum >= S390_R6_REGNUM && regnum <= S390_R15_REGNUM) - || (regnum >= S390_F8_REGNUM && regnum <= S390_F15_REGNUM)) - reg->how = DWARF2_FRAME_REG_SAME_VALUE; + /* The CC pseudo register is call-clobbered. */ + else if (regnum == tdep->cc_regnum) + reg->how = DWARF2_FRAME_REG_UNDEFINED; - /* Call-clobbered registers. */ - else if ((regnum >= S390_R0_REGNUM && regnum <= S390_R5_REGNUM) - || (regnum >= S390_F0_REGNUM && regnum <= S390_F7_REGNUM)) - reg->how = DWARF2_FRAME_REG_UNDEFINED; + /* The PC register unwinds to the return address. */ + else if (regnum == tdep->pc_regnum) + reg->how = DWARF2_FRAME_REG_RA; - /* The return address column. */ - else if (regnum == S390_PC_REGNUM) - reg->how = DWARF2_FRAME_REG_RA; - break; + /* We install a special function to unwind full GPRs to show at + least the lower halves (as the upper halves are undefined). */ + else if (tdep->gpr_full_regnum != -1 + && regnum >= tdep->gpr_full_regnum + && regnum < tdep->gpr_full_regnum + 16) + { + reg->how = DWARF2_FRAME_REG_FN; + reg->loc.fn = s390_dwarf2_prev_register; } } @@ -2484,20 +2677,146 @@ s390_address_class_name_to_type_flags (struct gdbarch *gdbarch, const char *name static struct gdbarch * s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { + const struct target_desc *tdesc = info.target_desc; + struct tdesc_arch_data *tdesc_data = NULL; struct gdbarch *gdbarch; struct gdbarch_tdep *tdep; + int tdep_abi; + int have_upper = 0; + int first_pseudo_reg, last_pseudo_reg; + + /* Default ABI and register size. */ + switch (info.bfd_arch_info->mach) + { + case bfd_mach_s390_31: + tdep_abi = ABI_LINUX_S390; + break; + + case bfd_mach_s390_64: + tdep_abi = ABI_LINUX_ZSERIES; + break; + + default: + return NULL; + } + + /* Use default target description if none provided by the target. */ + if (!tdesc_has_registers (tdesc)) + { + if (tdep_abi == ABI_LINUX_S390) + tdesc = tdesc_s390_linux32; + else + tdesc = tdesc_s390x_linux64; + } + + /* Check any target description for validity. */ + if (tdesc_has_registers (tdesc)) + { + static const char *const gprs[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" + }; + static const char *const fprs[] = { + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", + "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15" + }; + static const char *const acrs[] = { + "acr0", "acr1", "acr2", "acr3", "acr4", "acr5", "acr6", "acr7", + "acr8", "acr9", "acr10", "acr11", "acr12", "acr13", "acr14", "acr15" + }; + static const char *const gprs_lower[] = { + "r0l", "r1l", "r2l", "r3l", "r4l", "r5l", "r6l", "r7l", + "r8l", "r9l", "r10l", "r11l", "r12l", "r13l", "r14l", "r15l" + }; + static const char *const gprs_upper[] = { + "r0h", "r1h", "r2h", "r3h", "r4h", "r5h", "r6h", "r7h", + "r8h", "r9h", "r10h", "r11h", "r12h", "r13h", "r14h", "r15h" + }; + const struct tdesc_feature *feature; + int i, valid_p = 1; + + feature = tdesc_find_feature (tdesc, "org.gnu.gdb.s390.core"); + if (feature == NULL) + return NULL; + + tdesc_data = tdesc_data_alloc (); + + valid_p &= tdesc_numbered_register (feature, tdesc_data, + S390_PSWM_REGNUM, "pswm"); + valid_p &= tdesc_numbered_register (feature, tdesc_data, + S390_PSWA_REGNUM, "pswa"); + + if (tdesc_unnumbered_register (feature, "r0")) + { + for (i = 0; i < 16; i++) + valid_p &= tdesc_numbered_register (feature, tdesc_data, + S390_R0_REGNUM + i, gprs[i]); + } + else + { + have_upper = 1; + + for (i = 0; i < 16; i++) + valid_p &= tdesc_numbered_register (feature, tdesc_data, + S390_R0_REGNUM + i, + gprs_lower[i]); + for (i = 0; i < 16; i++) + valid_p &= tdesc_numbered_register (feature, tdesc_data, + S390_R0_UPPER_REGNUM + i, + gprs_upper[i]); + } + + feature = tdesc_find_feature (tdesc, "org.gnu.gdb.s390.fpr"); + if (feature == NULL) + { + tdesc_data_cleanup (tdesc_data); + return NULL; + } + + valid_p &= tdesc_numbered_register (feature, tdesc_data, + S390_FPC_REGNUM, "fpc"); + for (i = 0; i < 16; i++) + valid_p &= tdesc_numbered_register (feature, tdesc_data, + S390_F0_REGNUM + i, fprs[i]); - /* First see if there is already a gdbarch that can satisfy the request. */ - arches = gdbarch_list_lookup_by_info (arches, &info); - if (arches != NULL) - return arches->gdbarch; + feature = tdesc_find_feature (tdesc, "org.gnu.gdb.s390.acr"); + if (feature == NULL) + { + tdesc_data_cleanup (tdesc_data); + return NULL; + } + + for (i = 0; i < 16; i++) + valid_p &= tdesc_numbered_register (feature, tdesc_data, + S390_A0_REGNUM + i, acrs[i]); + + if (!valid_p) + { + tdesc_data_cleanup (tdesc_data); + return NULL; + } + } - /* None found: is the request for a s390 architecture? */ - if (info.bfd_arch_info->arch != bfd_arch_s390) - return NULL; /* No; then it's not for us. */ + /* Find a candidate among extant architectures. */ + for (arches = gdbarch_list_lookup_by_info (arches, &info); + arches != NULL; + arches = gdbarch_list_lookup_by_info (arches->next, &info)) + { + tdep = gdbarch_tdep (arches->gdbarch); + if (!tdep) + continue; + if (tdep->abi != tdep_abi) + continue; + if ((tdep->gpr_full_regnum != -1) != have_upper) + continue; + if (tdesc_data != NULL) + tdesc_data_cleanup (tdesc_data); + return arches->gdbarch; + } - /* Yes: create a new gdbarch for the specified machine type. */ + /* Otherwise create a new gdbarch for the specified machine type. */ tdep = XCALLOC (1, struct gdbarch_tdep); + tdep->abi = tdep_abi; gdbarch = gdbarch_alloc (&info, tdep); set_gdbarch_believe_pcc_promotion (gdbarch, 0); @@ -2519,19 +2838,38 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_skip_prologue (gdbarch, s390_skip_prologue); set_gdbarch_in_function_epilogue_p (gdbarch, s390_in_function_epilogue_p); - set_gdbarch_pc_regnum (gdbarch, S390_PC_REGNUM); + set_gdbarch_num_regs (gdbarch, S390_NUM_REGS); set_gdbarch_sp_regnum (gdbarch, S390_SP_REGNUM); set_gdbarch_fp0_regnum (gdbarch, S390_F0_REGNUM); - set_gdbarch_num_regs (gdbarch, S390_NUM_REGS); - set_gdbarch_num_pseudo_regs (gdbarch, S390_NUM_PSEUDO_REGS); - set_gdbarch_register_name (gdbarch, s390_register_name); - set_gdbarch_register_type (gdbarch, s390_register_type); set_gdbarch_stab_reg_to_regnum (gdbarch, s390_dwarf_reg_to_regnum); set_gdbarch_dwarf2_reg_to_regnum (gdbarch, s390_dwarf_reg_to_regnum); set_gdbarch_value_from_register (gdbarch, s390_value_from_register); - set_gdbarch_register_reggroup_p (gdbarch, s390_register_reggroup_p); set_gdbarch_regset_from_core_section (gdbarch, s390_regset_from_core_section); + set_gdbarch_core_read_description (gdbarch, s390_core_read_description); + if (have_upper) + set_gdbarch_core_regset_sections (gdbarch, s390_upper_regset_sections); + set_gdbarch_pseudo_register_read (gdbarch, s390_pseudo_register_read); + set_gdbarch_pseudo_register_write (gdbarch, s390_pseudo_register_write); + set_tdesc_pseudo_register_name (gdbarch, s390_pseudo_register_name); + set_tdesc_pseudo_register_type (gdbarch, s390_pseudo_register_type); + set_tdesc_pseudo_register_reggroup_p (gdbarch, + s390_pseudo_register_reggroup_p); + tdesc_use_registers (gdbarch, tdesc, tdesc_data); + + /* Assign pseudo register numbers. */ + first_pseudo_reg = gdbarch_num_regs (gdbarch); + last_pseudo_reg = first_pseudo_reg; + tdep->gpr_full_regnum = -1; + if (have_upper) + { + tdep->gpr_full_regnum = last_pseudo_reg; + last_pseudo_reg += 16; + } + tdep->pc_regnum = last_pseudo_reg++; + tdep->cc_regnum = last_pseudo_reg++; + set_gdbarch_pc_regnum (gdbarch, tdep->pc_regnum); + set_gdbarch_num_pseudo_regs (gdbarch, last_pseudo_reg - first_pseudo_reg); /* Inferior function calls. */ set_gdbarch_push_dummy_call (gdbarch, s390_push_dummy_call); @@ -2541,6 +2879,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Frame handling. */ dwarf2_frame_set_init_reg (gdbarch, s390_dwarf2_frame_init_reg); + dwarf2_frame_set_adjust_regnum (gdbarch, s390_adjust_frame_regnum); dwarf2_append_unwinders (gdbarch); frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer); frame_unwind_append_unwinder (gdbarch, &s390_stub_frame_unwind); @@ -2560,26 +2899,20 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) displaced_step_at_entry_point); set_gdbarch_max_insn_length (gdbarch, S390_MAX_INSTR_SIZE); - switch (info.bfd_arch_info->mach) + switch (tdep->abi) { - case bfd_mach_s390_31: - tdep->abi = ABI_LINUX_S390; - + case ABI_LINUX_S390: tdep->gregset = &s390_gregset; tdep->sizeof_gregset = s390_sizeof_gregset; tdep->fpregset = &s390_fpregset; tdep->sizeof_fpregset = s390_sizeof_fpregset; set_gdbarch_addr_bits_remove (gdbarch, s390_addr_bits_remove); - set_gdbarch_pseudo_register_read (gdbarch, s390_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, s390_pseudo_register_write); set_solib_svr4_fetch_link_map_offsets (gdbarch, svr4_ilp32_fetch_link_map_offsets); - break; - case bfd_mach_s390_64: - tdep->abi = ABI_LINUX_ZSERIES; + case ABI_LINUX_ZSERIES: tdep->gregset = &s390x_gregset; tdep->sizeof_gregset = s390x_sizeof_gregset; tdep->fpregset = &s390_fpregset; @@ -2588,8 +2921,6 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_long_bit (gdbarch, 64); set_gdbarch_long_long_bit (gdbarch, 64); set_gdbarch_ptr_bit (gdbarch, 64); - set_gdbarch_pseudo_register_read (gdbarch, s390x_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, s390x_pseudo_register_write); set_solib_svr4_fetch_link_map_offsets (gdbarch, svr4_lp64_fetch_link_map_offsets); set_gdbarch_address_class_type_flags (gdbarch, @@ -2613,13 +2944,16 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) } - extern initialize_file_ftype _initialize_s390_tdep; /* -Wmissing-prototypes */ void _initialize_s390_tdep (void) { - /* Hook us into the gdbarch mechanism. */ register_gdbarch_init (bfd_arch_s390, s390_gdbarch_init); + + /* Initialize the Linux target descriptions. */ + initialize_tdesc_s390_linux32 (); + initialize_tdesc_s390_linux64 (); + initialize_tdesc_s390x_linux64 (); } diff --git a/gdb/s390-tdep.h b/gdb/s390-tdep.h index 5922b3b..74fc087 100644 --- a/gdb/s390-tdep.h +++ b/gdb/s390-tdep.h @@ -77,14 +77,25 @@ #define S390_F13_REGNUM 48 #define S390_F14_REGNUM 49 #define S390_F15_REGNUM 50 +/* General Purpose Register Upper Halves. */ +#define S390_R0_UPPER_REGNUM 51 +#define S390_R1_UPPER_REGNUM 52 +#define S390_R2_UPPER_REGNUM 53 +#define S390_R3_UPPER_REGNUM 54 +#define S390_R4_UPPER_REGNUM 55 +#define S390_R5_UPPER_REGNUM 56 +#define S390_R6_UPPER_REGNUM 57 +#define S390_R7_UPPER_REGNUM 58 +#define S390_R8_UPPER_REGNUM 59 +#define S390_R9_UPPER_REGNUM 60 +#define S390_R10_UPPER_REGNUM 61 +#define S390_R11_UPPER_REGNUM 62 +#define S390_R12_UPPER_REGNUM 63 +#define S390_R13_UPPER_REGNUM 64 +#define S390_R14_UPPER_REGNUM 65 +#define S390_R15_UPPER_REGNUM 66 /* Total. */ -#define S390_NUM_REGS 51 - -/* Pseudo registers -- PC and condition code. */ -#define S390_PC_REGNUM S390_NUM_REGS -#define S390_CC_REGNUM (S390_NUM_REGS+1) -#define S390_NUM_PSEUDO_REGS 2 -#define S390_NUM_TOTAL_REGS (S390_NUM_REGS+2) +#define S390_NUM_REGS 67 /* Special register usage. */ #define S390_SP_REGNUM S390_R15_REGNUM @@ -99,5 +110,10 @@ extern int s390x_regmap_gregset[S390_NUM_REGS]; #define s390_sizeof_fpregset 0x88 extern int s390_regmap_fpregset[S390_NUM_REGS]; +/* Linux target descriptions. */ +extern struct target_desc *tdesc_s390_linux32; +extern struct target_desc *tdesc_s390_linux64; +extern struct target_desc *tdesc_s390x_linux64; + #endif diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 659f9b8..2d1b834 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2010-01-04 Ulrich Weigand <Ulrich.Weigand@de.ibm.com> + + * gdb.xml/tdesc-regs.exp: Support s390*-*-* targets. + 2010-01-03 Jan Kratochvil <jan.kratochvil@redhat.com> * gdb.mi/var-cmd.c (do_bitfield_tests): Change "V.sharable" type to diff --git a/gdb/testsuite/gdb.xml/tdesc-regs.exp b/gdb/testsuite/gdb.xml/tdesc-regs.exp index 0b84c6d..f11d013 100644 --- a/gdb/testsuite/gdb.xml/tdesc-regs.exp +++ b/gdb/testsuite/gdb.xml/tdesc-regs.exp @@ -42,6 +42,9 @@ switch -glob -- [istarget] { set regdir "rs6000/" set core-regs {power-core.xml} } + "s390*-*-*" { + set core-regs {s390-core32.xml s390-acr.xml s390-fpr.xml} + } "spu*-*-*" { # This may be either the spu-linux-nat target, or the Cell/B.E. # multi-architecture debugger in SPU standalone executable mode. |