OSDN Git Service

* features/Makefile (WHICH): Add s390-linux32, s390-linux64,
authoruweigand <uweigand>
Tue, 5 Jan 2010 00:02:55 +0000 (00:02 +0000)
committeruweigand <uweigand>
Tue, 5 Jan 2010 00:02:55 +0000 (00:02 +0000)
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.

gdb/testsuite/
* gdb.xml/tdesc-regs.exp: Support s390*-*-* targets.

gdbserver/
* 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.

25 files changed:
gdb/ChangeLog
gdb/features/Makefile
gdb/features/s390-acr.xml [new file with mode: 0644]
gdb/features/s390-core32.xml [new file with mode: 0644]
gdb/features/s390-core64.xml [new file with mode: 0644]
gdb/features/s390-fpr.xml [new file with mode: 0644]
gdb/features/s390-linux32.c [new file with mode: 0644]
gdb/features/s390-linux32.xml [new file with mode: 0644]
gdb/features/s390-linux64.c [new file with mode: 0644]
gdb/features/s390-linux64.xml [new file with mode: 0644]
gdb/features/s390x-core64.xml [new file with mode: 0644]
gdb/features/s390x-linux64.c [new file with mode: 0644]
gdb/features/s390x-linux64.xml [new file with mode: 0644]
gdb/gdbserver/ChangeLog
gdb/gdbserver/Makefile.in
gdb/gdbserver/configure.srv
gdb/gdbserver/linux-s390-low.c
gdb/regformats/s390-linux32.dat [moved from gdb/regformats/reg-s390.dat with 80% similarity]
gdb/regformats/s390-linux64.dat [new file with mode: 0644]
gdb/regformats/s390x-linux64.dat [moved from gdb/regformats/reg-s390x.dat with 80% similarity]
gdb/s390-nat.c
gdb/s390-tdep.c
gdb/s390-tdep.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.xml/tdesc-regs.exp

index 3d0de47..dc6a776 100644 (file)
@@ -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.
index 5b1e691..8aa553e 100644 (file)
@@ -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 (file)
index 0000000..9bf3326
--- /dev/null
@@ -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 (file)
index 0000000..5a752e8
--- /dev/null
@@ -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 (file)
index 0000000..43bd9be
--- /dev/null
@@ -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 (file)
index 0000000..8a9599a
--- /dev/null
@@ -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 (file)
index 0000000..0ff3868
--- /dev/null
@@ -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 (file)
index 0000000..45153fd
--- /dev/null
@@ -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 (file)
index 0000000..1e39fc3
--- /dev/null
@@ -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 (file)
index 0000000..10bb036
--- /dev/null
@@ -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 (file)
index 0000000..34659c9
--- /dev/null
@@ -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 (file)
index 0000000..91d2da9
--- /dev/null
@@ -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 (file)
index 0000000..f3700a4
--- /dev/null
@@ -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>
index 53181bd..3ec151c 100644 (file)
@@ -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.
index 079f233..5bf82e2 100644 (file)
@@ -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
index 1814b0e..f6d92b3 100644 (file)
@@ -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
index 0407cad..64b1065 100644 (file)
 #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
 }
similarity index 80%
rename from gdb/regformats/reg-s390.dat
rename to gdb/regformats/s390-linux32.dat
index 79e07b9..d0ac867 100644 (file)
@@ -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 (file)
index 0000000..95265f0
--- /dev/null
@@ -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
similarity index 80%
rename from gdb/regformats/reg-s390x.dat
rename to gdb/regformats/s390x-linux64.dat
index 81ce403..1126940 100644 (file)
@@ -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
index c67777e..3af42ff 100644 (file)
@@ -25,6 +25,7 @@
 #include "inferior.h"
 #include "target.h"
 #include "linux-nat.h"
+#include "auxv.h"
 
 #include "s390-tdep.h"
 
 #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 (&current_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);
index 93bfebf..e7dc48d 100644 (file)
 
 #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 ();
 }
index 5922b3b..74fc087 100644 (file)
 #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
 
index 659f9b8..2d1b834 100644 (file)
@@ -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
index 0b84c6d..f11d013 100644 (file)
@@ -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.