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