]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
http://www10.software.ibm.com/developerworks/opensource/linux390/exp_src.html
authorAndrew Cagney <cagney@redhat.com>
Thu, 27 Sep 2001 00:13:30 +0000 (00:13 +0000)
committerAndrew Cagney <cagney@redhat.com>
Thu, 27 Sep 2001 00:13:30 +0000 (00:13 +0000)
Patch:    gdb-5.1pre-050901-s390.tar.gz (09/11/2001)
MD5: 886251f3719a754dd65a69df462ceac1

20 files changed:
config.sub
gdb/config/s390/nm-linux.h [new file with mode: 0644]
gdb/config/s390/s390.mh [new file with mode: 0644]
gdb/config/s390/s390.mt [new file with mode: 0644]
gdb/config/s390/s390x.mt [new file with mode: 0644]
gdb/config/s390/tm-linux.h [new file with mode: 0644]
gdb/config/s390/tm-s390.h [new file with mode: 0644]
gdb/config/s390/xm-linux.h [new file with mode: 0644]
gdb/config/tm-sysv4.h
gdb/configure.host
gdb/defs.h
gdb/gdbarch.c
gdb/gdbarch.sh
gdb/gdbserver/Makefile.in
gdb/gdbserver/low-linux.c
gdb/gdbserver/remote-utils.c
gdb/gdbserver/server.c
gdb/s390-nat.c [new file with mode: 0644]
gdb/s390-tdep.c [new file with mode: 0644]
gdb/signals.c

index 7146a2ffc1c9fa075de242398d1deb696beb336b..c87aebb18f1286da992eab942f3c266f7ab02880 100755 (executable)
@@ -742,6 +742,12 @@ case $basic_machine in
        rtpc | rtpc-*)
                basic_machine=romp-ibm
                ;;
+       s390 | s390-* )
+               basic_machine=s390-ibm
+               ;;
+       s390x | s390x-* )
+               basic_machine=s390x-ibm
+               ;;
        sa29200)
                basic_machine=a29k-amd
                os=-udi
diff --git a/gdb/config/s390/nm-linux.h b/gdb/config/s390/nm-linux.h
new file mode 100644 (file)
index 0000000..2c00e0b
--- /dev/null
@@ -0,0 +1,94 @@
+/* Native support for Linux for S390
+   
+   Copyright 1986, 1987, 1989, 1992, 1996, 1998, 2000
+   Free Software Foundation, Inc.
+   Ported by D.J. Barrow for IBM Deutschland Entwicklung GmbH, IBM Corporation.
+   derived from i390-nmlinux.h
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef NM_LINUX_H
+#define NM_LINUX_H
+
+#include "config/nm-linux.h"
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+       (addr) = s390_register_u_addr((blockend),(regno));
+extern int s390_register_u_addr (int, int);
+
+/* Return sizeof user struct to callers in less machine dependent routines */
+
+#define KERNEL_U_SIZE kernel_u_size()
+extern int kernel_u_size (void);
+
+#define U_REGS_OFFSET 0
+
+
+/* We define this if link.h is available, because with ELF we use SVR4 style
+   shared libraries. */
+
+#ifdef HAVE_LINK_H
+#define SVR4_SHARED_LIBS
+#include "solib.h"             /* Support for shared libraries. */
+#endif
+
+
+/* WATCHPOINT SPECIFIC STUFF */
+
+#define TARGET_HAS_HARDWARE_WATCHPOINTS
+#define HAVE_CONTINUABLE_WATCHPOINT
+#define HAVE_STEPPABLE_WATCHPOINT
+#define target_insert_watchpoint(addr, len, type)  \
+  s390_insert_watchpoint (PIDGET (inferior_ptid), addr, len, type)
+
+#define target_remove_watchpoint(addr, len, type)  \
+  s390_remove_watchpoint (PIDGET (inferior_ptid), addr, len)
+
+extern int watch_area_cnt;
+/* gdb if really stupid & calls this all the time without a
+   watchpoint even being set */
+#define STOPPED_BY_WATCHPOINT(W)  \
+  (watch_area_cnt&&s390_stopped_by_watchpoint (PIDGET(inferior_ptid)))
+
+extern CORE_ADDR s390_stopped_by_watchpoint (int);
+
+/*
+  Type can be 1 for a read_watchpoint or 2 for an access watchpoint.
+ */
+extern int s390_insert_watchpoint (int pid, CORE_ADDR addr, int len, int rw);
+extern int s390_remove_watchpoint (int pid, CORE_ADDR addr, int len);
+#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \
+        (((type) == bp_hardware_watchpoint)|| \
+        ((type) == bp_watchpoint)|| \
+        ((type) == bp_read_watchpoint) || \
+         ((type) == bp_access_watchpoint))
+
+#undef PREPARE_TO_PROCEED
+
+extern void lin_lwp_attach_lwp (ptid_t ptid, int verbose);
+#define ATTACH_LWP(ptid, verbose) lin_lwp_attach_lwp ((ptid), (verbose))
+
+
+#include <signal.h>
+
+extern void lin_thread_get_thread_signals (sigset_t * mask);
+#define GET_THREAD_SIGNALS(mask) lin_thread_get_thread_signals (mask)
+
+/* Needed for s390x */
+#define PTRACE_ARG3_TYPE long
+#define PTRACE_XFER_TYPE long
+#endif /* nm_linux.h */
diff --git a/gdb/config/s390/s390.mh b/gdb/config/s390/s390.mh
new file mode 100644 (file)
index 0000000..fa953b4
--- /dev/null
@@ -0,0 +1,15 @@
+# Host: S390, running Linux
+
+XM_FILE= xm-linux.h
+XDEPFILES= ser-tcp.o
+XM_CLIBS=
+
+NAT_FILE= nm-linux.h
+NATDEPFILES= infptrace.o solib.o inftarg.o fork-child.o corelow.o \
+          s390-nat.o linux-thread.o core-aout.o core-regset.o
+# post 5.0 natdepfiles.
+NATDEPFILES+= thread-db.o lin-lwp.o proc-service.o 
+LOADLIBES = -ldl -rdynamic
+
+
+
diff --git a/gdb/config/s390/s390.mt b/gdb/config/s390/s390.mt
new file mode 100644 (file)
index 0000000..d1dfe9f
--- /dev/null
@@ -0,0 +1,7 @@
+# Target: S390 running Linux
+TM_FILE= tm-linux.h
+TDEPFILES=s390-tdep.o solib.o
+# Post 5.0 tdep-files
+TDEPFILES+=solib-svr4.o solib-legacy.o
+GDB_MULTI_ARCH=2
+GDBSERVER_DEPFILES= low-linux.o s390-tdep.o s390-nat.o
diff --git a/gdb/config/s390/s390x.mt b/gdb/config/s390/s390x.mt
new file mode 100644 (file)
index 0000000..632fa52
--- /dev/null
@@ -0,0 +1,9 @@
+# Target: S390 running Linux
+TM_FILE= tm-linux.h
+TDEPFILES=s390-tdep.o solib.o
+# Post 5.0 tdep-files
+TDEPFILES+=solib-svr4.o solib-legacy.o
+GDB_MULTI_ARCH=2
+GDBSERVER_DEPFILES= low-linux.o s390-tdep.o s390-nat.o
+# needed for gdbserver.
+MT_CFLAGS= -DCONFIG_ARCH_S390X
diff --git a/gdb/config/s390/tm-linux.h b/gdb/config/s390/tm-linux.h
new file mode 100644 (file)
index 0000000..bb1e587
--- /dev/null
@@ -0,0 +1,36 @@
+/* Target definitions for GDB for a s390 running Linux.
+   Copyright (C) 1999-2001 Free Software Foundation, Inc.
+   Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+   for IBM Deutschland Entwicklung GmbH, IBM Corporation.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#ifndef TM_LINUX_H
+#define TM_LINUX_H
+#ifdef GDBSERVER
+#define S390_GNULINUX_TARGET
+#endif /* GDBSERVER */
+#undef  TARGET_ELF64
+#define TARGET_ELF64 (gdbarch_tdep (current_gdbarch)->intreg_size==8)
+
+#include "config/tm-linux.h"
+#include "s390/tm-s390.h"
+
+
+
+#endif /* TM_LINUX_H */
diff --git a/gdb/config/s390/tm-s390.h b/gdb/config/s390/tm-s390.h
new file mode 100644 (file)
index 0000000..3e0c2f2
--- /dev/null
@@ -0,0 +1,115 @@
+/* Macro definitions for GDB on an S390.
+   Copyright (C) 1999-2001 Free Software Foundation, Inc.
+   Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+   for IBM Deutschland Entwicklung GmbH, IBM Corporation.
+
+   This file is part of GDB.
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#if !defined(TM_S390_H)
+#define TM_S390_H 1
+
+#define S390_NUM_GPRS      (16)
+#define S390_GPR_SIZE      REGISTER_SIZE
+#define S390_PSW_MASK_SIZE REGISTER_SIZE
+#define S390_PSW_ADDR_SIZE REGISTER_SIZE
+#define S390_NUM_FPRS      (16)
+#define S390_FPR_SIZE      (8)
+#define S390_FPC_SIZE      (4)
+#define S390_FPC_PAD_SIZE  (4) /* gcc insists on aligning the fpregs */
+#define S390_NUM_CRS       (16)
+#define S390_CR_SIZE       REGISTER_SIZE
+#define S390_NUM_ACRS      (16)
+#define S390_ACR_SIZE      (4)
+
+#define S390_NUM_REGS      (2+S390_NUM_GPRS+S390_NUM_ACRS+S390_NUM_CRS+1+S390_NUM_FPRS)
+#define S390_FIRST_ACR     (2+S390_NUM_GPRS)
+#define S390_LAST_ACR      (S390_FIRST_ACR+S390_NUM_ACRS-1)
+#define S390_FIRST_CR      (S390_FIRST_ACR+S390_NUM_ACRS)
+#define S390_LAST_CR       (S390_FIRST_CR+S390_NUM_CRS-1)
+
+#define S390_PSWM_REGNUM    0
+#define S390_PC_REGNUM      1
+#define        S390_GP0_REGNUM     2   /* GPR register 0 */
+#define S390_GP_LAST_REGNUM (S390_GP0_REGNUM+S390_NUM_GPRS-1)
+/* Usually return address */
+#define S390_RETADDR_REGNUM (S390_GP0_REGNUM+14)
+/* Contains address of top of stack */
+#define S390_SP_REGNUM      (S390_GP0_REGNUM+15)
+/* needed in findvar.c still */
+#define S390_FP_REGNUM     S390_SP_REGNUM
+#define S390_FRAME_REGNUM  (S390_GP0_REGNUM+11)
+#define S390_FPC_REGNUM    (S390_GP0_REGNUM+S390_NUM_GPRS+S390_NUM_ACRS+S390_NUM_CRS)
+/* FPR (Floating point) register 0 */
+#define S390_FP0_REGNUM    (S390_FPC_REGNUM+1)
+/* Last floating point register */
+#define S390_FPLAST_REGNUM (S390_FP0_REGNUM+S390_NUM_FPRS-1)
+#define S390_LAST_REGNUM   S390_FPLAST_REGNUM
+
+
+#define S390_ACR0_OFFSET ((S390_PSW_MASK_SIZE+S390_PSW_ADDR_SIZE)+(S390_GPR_SIZE*S390_NUM_GPRS))
+#define S390_CR0_OFFSET (S390_ACR0_OFFSET+(S390_ACR_SIZE*S390_NUM_ACRS))
+#define S390_FPC_OFFSET (S390_CR0_OFFSET+(S390_CR_SIZE*S390_NUM_CRS))
+#define S390_FP0_OFFSET (S390_FPC_OFFSET+(S390_FPC_SIZE+S390_FPC_PAD_SIZE))
+#define S390_GPR6_STACK_OFFSET (GDB_TARGET_IS_ESAME ? 48:24)
+
+#define S390_REGISTER_BYTES ((4+4)+(4*S390_NUM_GPRS)+(4*S390_NUM_ACRS)+ \
+(4*S390_NUM_CRS)+(S390_FPC_SIZE+S390_FPC_PAD_SIZE)+(S390_FPR_SIZE*S390_NUM_FPRS))
+
+#define S390X_REGISTER_BYTES ((8+8)+(8*S390_NUM_GPRS)+(4*S390_NUM_ACRS)+ \
+(8*S390_NUM_CRS)+(S390_FPC_SIZE+S390_FPC_PAD_SIZE)+(S390_FPR_SIZE*S390_NUM_FPRS))
+
+#ifdef GDBSERVER
+
+int s390_register_byte (int reg_nr);
+#define REGISTER_BYTE(reg_nr) s390_register_byte(reg_nr)
+#define PC_REGNUM S390_PC_REGNUM
+#define NUM_REGS  S390_NUM_REGS
+#define NUM_FREGS S390_NUM_FPRS
+#define FP_REGNUM S390_FP_REGNUM
+#define SP_REGNUM S390_SP_REGNUM
+/* Obviously ptrace for user program tracing cannot be allowed
+  mess with control registers (except per registers for hardware watchpoints),
+  when we add kernel debugging we may need to alter these macros. */
+int s390_cannot_fetch_register (int regno);
+#define CANNOT_FETCH_REGISTER(regno) s390_cannot_fetch_register(regno)
+#define CANNOT_STORE_REGISTER(regno) s390_cannot_fetch_register(regno)
+
+#if CONFIG_ARCH_S390X
+
+int s390x_register_raw_size (int reg_nr);
+#define REGISTER_RAW_SIZE(reg_nr) s390x_register_raw_size(reg_nr)
+#define GDB_TARGET_IS_ESAME (1)
+#define REGISTER_SIZE       (8)
+#define REGISTER_BYTES S390X_REGISTER_BYTES
+
+#else /*  CONFIG_ARCH_S390X */
+
+int s390_register_raw_size (int reg_nr);
+#define REGISTER_RAW_SIZE(reg_nr) s390_register_raw_size(reg_nr)
+#define GDB_TARGET_IS_ESAME (0)
+#define REGISTER_SIZE       (4)
+#define REGISTER_BYTES S390_REGISTER_BYTES
+
+#endif /* CONFIG_ARCH_S390X */
+
+#else /* GDBSERVER */
+
+#define GDB_TARGET_IS_ESAME (TARGET_ARCHITECTURE->mach == bfd_mach_s390_esame)
+
+#endif /* GDBSERVER */
+#endif /* ifndef TM_S390_H */
diff --git a/gdb/config/s390/xm-linux.h b/gdb/config/s390/xm-linux.h
new file mode 100644 (file)
index 0000000..216dc17
--- /dev/null
@@ -0,0 +1,33 @@
+/* Native support for GNU/Linux, for GDB, the GNU debugger.
+   Copyright (C) 1999-2001 Free Software Foundation, Inc.
+   Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+   for IBM Deutschland Entwicklung GmbH, IBM Corporation.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#ifndef XM_LINUX_H
+#define XM_LINUX_H
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+
+/* This is the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values.  */
+#define KERNEL_U_ADDR 0x0
+
+#endif /* #ifndef XM_LINUX_H */
index 35b95eb71f8927285ca3233e6af4a36d7ff24ef2..1ed6bc3c1396d56c5de0943ca855bd612adb5c58 100644 (file)
@@ -33,9 +33,9 @@ extern int in_plt_section (CORE_ADDR, char *);
 
 /* If PC is in a shared library trampoline code, return the PC
    where the function itself actually starts.  If not, return 0.  */
-
+#if (GDB_MULTI_ARCH <= GDB_MULTI_ARCH_PARTIAL)
 #define SKIP_TRAMPOLINE_CODE(pc)  find_solib_trampoline_target (pc)
-
+#endif
 /* It is unknown which, if any, SVR4 assemblers do not accept dollar signs
    in identifiers.  The default in G++ is to use dots instead, for all SVR4
    systems, so we make that our default also.  FIXME: There should be some
index 403957b70846b942cbf4533998acb28f564183e6..94ea045f8fb8837c5dec344c039c566d3c4dfdb6 100644 (file)
@@ -162,5 +162,10 @@ xscale-*-*)                gdb_host=arm ;;
 vax-*-bsd*)            gdb_host=vaxbsd ;;
 vax-*-ultrix2*)                gdb_host=vaxult2 ;;
 vax-*-ultrix*)         gdb_host=vaxult ;;
-
+s390*-*-*)               gdb_host=s390 ;;
 esac
+
+
+
+
+
index 3fac36e2610941c9925f01650bb7ce10016edebd..bf524c2e826029dd91571761552e3e3d2154cb40 100644 (file)
@@ -1,4 +1,4 @@
-/* *INDENT-OFF* */ /* ATTR_FORMAT confuses indent, avoid running it for now */
+/* *INDENT-OFF* *//* ATTR_FORMAT confuses indent, avoid running it for now */
 /* Basic, host-specific, and target-specific definitions for GDB.
    Copyright 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
    1997, 1998, 1999, 2000, 2001
@@ -25,6 +25,9 @@
 #define DEFS_H
 
 #include "config.h"            /* Generated by configure */
+#if GDBSERVER
+#undef GDB_MULTI_ARCH
+#endif /* GDBSERVER */
 #include <stdio.h>
 #include <errno.h>             /* System call error return status */
 #include <limits.h>
index 40da7a4d22d34b9b9d4f66543079fa387b36769e..d860bedc760073fe832b255631d5302d86bb7142 100644 (file)
@@ -615,7 +615,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
     internal_error (__FILE__, __LINE__,
                     "gdbarch: verify_gdbarch: call_dummy_start_offset invalid");
   if ((GDB_MULTI_ARCH >= 2)
-      && (gdbarch->call_dummy_breakpoint_offset == -1))
+      && (gdbarch->call_dummy_breakpoint_offset_p && gdbarch->call_dummy_breakpoint_offset == -1))
     internal_error (__FILE__, __LINE__,
                     "gdbarch: verify_gdbarch: call_dummy_breakpoint_offset invalid");
   if ((GDB_MULTI_ARCH >= 1)
@@ -3103,7 +3103,7 @@ set_gdbarch_call_dummy_start_offset (struct gdbarch *gdbarch,
 CORE_ADDR
 gdbarch_call_dummy_breakpoint_offset (struct gdbarch *gdbarch)
 {
-  if (gdbarch->call_dummy_breakpoint_offset == -1)
+  if (gdbarch->call_dummy_breakpoint_offset_p && gdbarch->call_dummy_breakpoint_offset == -1)
     internal_error (__FILE__, __LINE__,
                     "gdbarch: gdbarch_call_dummy_breakpoint_offset invalid");
   if (gdbarch_debug >= 2)
index 964e16f25ca32f792031b53f45dfb9429bb53ea8..a9d00af11fd16236d1c7f5b3faf4742cee70231f 100755 (executable)
@@ -436,7 +436,7 @@ v:1:USE_GENERIC_DUMMY_FRAMES:int:use_generic_dummy_frames::::0:-1
 v:2:CALL_DUMMY_LOCATION:int:call_dummy_location::::0:0
 f:2:CALL_DUMMY_ADDRESS:CORE_ADDR:call_dummy_address:void:::0:0::gdbarch->call_dummy_location == AT_ENTRY_POINT && gdbarch->call_dummy_address == 0
 v:2:CALL_DUMMY_START_OFFSET:CORE_ADDR:call_dummy_start_offset::::0:-1:::0x%08lx
-v:2:CALL_DUMMY_BREAKPOINT_OFFSET:CORE_ADDR:call_dummy_breakpoint_offset::::0:-1:::0x%08lx::CALL_DUMMY_BREAKPOINT_OFFSET_P
+v:2:CALL_DUMMY_BREAKPOINT_OFFSET:CORE_ADDR:call_dummy_breakpoint_offset::::0:-1::gdbarch->call_dummy_breakpoint_offset_p && gdbarch->call_dummy_breakpoint_offset == -1:0x%08lx::CALL_DUMMY_BREAKPOINT_OFFSET_P
 v:1:CALL_DUMMY_BREAKPOINT_OFFSET_P:int:call_dummy_breakpoint_offset_p::::0:-1
 v:2:CALL_DUMMY_LENGTH:int:call_dummy_length::::0:-1:::::CALL_DUMMY_LOCATION == BEFORE_TEXT_END || CALL_DUMMY_LOCATION == AFTER_TEXT_END
 f:2:PC_IN_CALL_DUMMY:int:pc_in_call_dummy:CORE_ADDR pc, CORE_ADDR sp, CORE_ADDR frame_address:pc, sp, frame_address::0:0
index 6884b16c02cbbac71db4147977838b38ee6b7cef..5f450468d02b8d34d031fc4493f5d6bdb92dd04b 100644 (file)
@@ -130,18 +130,20 @@ LINTFLAGS= $(BFD_CFLAGS)
 SFILES = $(srcdir)/low-hppabsd.c $(srcdir)/low-linux.c $(srcdir)/low-lynx.c \
         $(srcdir)/low-nbsd.c $(srcdir)/low-sim.c $(srcdir)/low-sparc.c \
         $(srcdir)/low-sun3.c $(srcdir)/utils.c $(srcdir)/server.c \
-        $(srcdir)/remote-utils.c
+        $(srcdir)/remote-utils.c ../signals.c
 
 DEPFILES = $(GDBSERVER_DEPFILES)
 
 SOURCES = $(SFILES) $(ALLDEPFILES)
 TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS} 
 
-OBS = utils.o $(GDBSERVER_DEPFILES) server.o remote-utils.o
+OBS = $(srcdir)/utils.o $(GDBSERVER_DEPFILES) server.o remote-utils.o signals.o
 
 # Prevent Sun make from putting in the machine type.  Setting
 # TARGET_ARCH to nothing works for SunOS 3, 4.0, but not for 4.1.
-.c.o:
+%.o: %.c
+       ${CC} -c ${INTERNAL_CFLAGS} $<
+%.o: ../%.c
        ${CC} -c ${INTERNAL_CFLAGS} $<
 
 all: gdbserver gdbreplay
@@ -246,6 +248,7 @@ low-sim.o : ${srcdir}/low-sim.c ${srcdir}/server.h
 low-sparc.o : $(srcdir)/low-sparc.c $(srcdir)/server.h
 low-sun3.o : $(srcdir)/low-sun3.c $(srcdir)/server.h
 low-hppabsd.o : $(srcdir)/low-hppabsd.c $(srcdir)/server.h
-utils.o : ${srcdir}/utils.c ${srcdir}/server.h
+$(srcdir)/utils.o : ${srcdir}/utils.c ${srcdir}/server.h
+signals.o : ../signals.c ../target.h
 
 # This is the end of "Makefile.in".
index 0c7fce55833e7d058265b125c321b8b07d909d91..62c74653c70c328cd3243dbe5bd3e9eb3fab8d74 100644 (file)
@@ -49,8 +49,9 @@ char *registers = my_registers;
 
 extern int errno;
 
+#ifndef S390_GNULINUX_TARGET
 static void initialize_arch (void);
-
+#endif
 /* Start an inferior process and returns its pid.
    ALLARGS is a vector of program-name and args. */
 
@@ -113,13 +114,15 @@ mywait (char *status)
 
   if (WIFEXITED (w))
     {
-      fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
+      fprintf (stderr, "\nChild exited with retcode = %x \n",
+              WEXITSTATUS (w));
       *status = 'W';
       return ((unsigned char) WEXITSTATUS (w));
     }
   else if (!WIFSTOPPED (w))
     {
-      fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
+      fprintf (stderr, "\nChild terminated with signal = %x \n",
+              WTERMSIG (w));
       *status = 'X';
       return ((unsigned char) WTERMSIG (w));
     }
@@ -178,17 +181,17 @@ int i386_register_byte[MAX_NUM_REGS];
 /* i386_register_raw_size[i] is the number of bytes of storage in
    GDB's register array occupied by register i.  */
 int i386_register_raw_size[MAX_NUM_REGS] = {
-   4,  4,  4,  4,
-   4,  4,  4,  4,
-   4,  4,  4,  4,
-   4,  4,  4,  4,
+  4, 4, 4, 4,
+  4, 4, 4, 4,
+  4, 4, 4, 4,
+  4, 4, 4, 4,
   10, 10, 10, 10,
   10, 10, 10, 10,
-   4,  4,  4,  4,
-   4,  4,  4,  4,
+  4, 4, 4, 4,
+  4, 4, 4, 4,
   16, 16, 16, 16,
   16, 16, 16, 16,
-   4
+  4
 };
 
 static void
@@ -212,8 +215,7 @@ initialize_arch (void)
 
 /* Mapping between the general-purpose registers in `struct user'
    format and GDB's register array layout.  */
-static int regmap[] = 
-{
+static int regmap[] = {
   EAX, ECX, EDX, EBX,
   UESP, EBP, ESI, EDI,
   EIP, EFL, CS, SS,
@@ -236,8 +238,7 @@ initialize_arch (void)
 }
 
 /* This table must line up with REGISTER_NAMES in tm-m68k.h */
-static int regmap[] =
-{
+static int regmap[] = {
 #ifdef PT_D0
   PT_D0, PT_D1, PT_D2, PT_D3, PT_D4, PT_D5, PT_D6, PT_D7,
   PT_A0, PT_A1, PT_A2, PT_A3, PT_A4, PT_A5, PT_A6, PT_USP,
@@ -268,258 +269,257 @@ m68k_linux_register_u_addr (int blockend, int regnum)
 
 #include <asm/ptrace_offsets.h>
 
-static int u_offsets[] =
-  {
-    /* general registers */
-    -1,                /* gr0 not available; i.e, it's always zero */
-    PT_R1,
-    PT_R2,
-    PT_R3,
-    PT_R4,
-    PT_R5,
-    PT_R6,
-    PT_R7,
-    PT_R8,
-    PT_R9,
-    PT_R10,
-    PT_R11,
-    PT_R12,
-    PT_R13,
-    PT_R14,
-    PT_R15,
-    PT_R16,
-    PT_R17,
-    PT_R18,
-    PT_R19,
-    PT_R20,
-    PT_R21,
-    PT_R22,
-    PT_R23,
-    PT_R24,
-    PT_R25,
-    PT_R26,
-    PT_R27,
-    PT_R28,
-    PT_R29,
-    PT_R30,
-    PT_R31,
-    /* gr32 through gr127 not directly available via the ptrace interface */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    /* Floating point registers */
-    -1, -1,    /* f0 and f1 not available (f0 is +0.0 and f1 is +1.0) */
-    PT_F2,
-    PT_F3,
-    PT_F4,
-    PT_F5,
-    PT_F6,
-    PT_F7,
-    PT_F8,
-    PT_F9,
-    PT_F10,
-    PT_F11,
-    PT_F12,
-    PT_F13,
-    PT_F14,
-    PT_F15,
-    PT_F16,
-    PT_F17,
-    PT_F18,
-    PT_F19,
-    PT_F20,
-    PT_F21,
-    PT_F22,
-    PT_F23,
-    PT_F24,
-    PT_F25,
-    PT_F26,
-    PT_F27,
-    PT_F28,
-    PT_F29,
-    PT_F30,
-    PT_F31,
-    PT_F32,
-    PT_F33,
-    PT_F34,
-    PT_F35,
-    PT_F36,
-    PT_F37,
-    PT_F38,
-    PT_F39,
-    PT_F40,
-    PT_F41,
-    PT_F42,
-    PT_F43,
-    PT_F44,
-    PT_F45,
-    PT_F46,
-    PT_F47,
-    PT_F48,
-    PT_F49,
-    PT_F50,
-    PT_F51,
-    PT_F52,
-    PT_F53,
-    PT_F54,
-    PT_F55,
-    PT_F56,
-    PT_F57,
-    PT_F58,
-    PT_F59,
-    PT_F60,
-    PT_F61,
-    PT_F62,
-    PT_F63,
-    PT_F64,
-    PT_F65,
-    PT_F66,
-    PT_F67,
-    PT_F68,
-    PT_F69,
-    PT_F70,
-    PT_F71,
-    PT_F72,
-    PT_F73,
-    PT_F74,
-    PT_F75,
-    PT_F76,
-    PT_F77,
-    PT_F78,
-    PT_F79,
-    PT_F80,
-    PT_F81,
-    PT_F82,
-    PT_F83,
-    PT_F84,
-    PT_F85,
-    PT_F86,
-    PT_F87,
-    PT_F88,
-    PT_F89,
-    PT_F90,
-    PT_F91,
-    PT_F92,
-    PT_F93,
-    PT_F94,
-    PT_F95,
-    PT_F96,
-    PT_F97,
-    PT_F98,
-    PT_F99,
-    PT_F100,
-    PT_F101,
-    PT_F102,
-    PT_F103,
-    PT_F104,
-    PT_F105,
-    PT_F106,
-    PT_F107,
-    PT_F108,
-    PT_F109,
-    PT_F110,
-    PT_F111,
-    PT_F112,
-    PT_F113,
-    PT_F114,
-    PT_F115,
-    PT_F116,
-    PT_F117,
-    PT_F118,
-    PT_F119,
-    PT_F120,
-    PT_F121,
-    PT_F122,
-    PT_F123,
-    PT_F124,
-    PT_F125,
-    PT_F126,
-    PT_F127,
-    /* predicate registers - we don't fetch these individually */
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    /* branch registers */
-    PT_B0,
-    PT_B1,
-    PT_B2,
-    PT_B3,
-    PT_B4,
-    PT_B5,
-    PT_B6,
-    PT_B7,
-    /* virtual frame pointer and virtual return address pointer */
-    -1, -1,
-    /* other registers */
-    PT_PR,
-    PT_CR_IIP, /* ip */
-    PT_CR_IPSR, /* psr */
-    PT_CFM,    /* cfm */
-    /* kernel registers not visible via ptrace interface (?) */
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    /* hole */
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    PT_AR_RSC,
-    PT_AR_BSP,
-    PT_AR_BSPSTORE,
-    PT_AR_RNAT,
-    -1,
-    -1,                /* Not available: FCR, IA32 floating control register */
-    -1, -1,
-    -1,                /* Not available: EFLAG */
-    -1,                /* Not available: CSD */
-    -1,                /* Not available: SSD */
-    -1,                /* Not available: CFLG */
-    -1,                /* Not available: FSR */
-    -1,                /* Not available: FIR */
-    -1,                /* Not available: FDR */
-    -1,
-    PT_AR_CCV,
-    -1, -1, -1,
-    PT_AR_UNAT,
-    -1, -1, -1,
-    PT_AR_FPSR,
-    -1, -1, -1,
-    -1,                /* Not available: ITC */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    PT_AR_PFS,
-    PT_AR_LC,
-    -1,                /* Not available: EC, the Epilog Count register */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1,
-    /* nat bits - not fetched directly; instead we obtain these bits from
-       either rnat or unat or from memory. */
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-  };
+static int u_offsets[] = {
+  /* general registers */
+  -1,                          /* gr0 not available; i.e, it's always zero */
+  PT_R1,
+  PT_R2,
+  PT_R3,
+  PT_R4,
+  PT_R5,
+  PT_R6,
+  PT_R7,
+  PT_R8,
+  PT_R9,
+  PT_R10,
+  PT_R11,
+  PT_R12,
+  PT_R13,
+  PT_R14,
+  PT_R15,
+  PT_R16,
+  PT_R17,
+  PT_R18,
+  PT_R19,
+  PT_R20,
+  PT_R21,
+  PT_R22,
+  PT_R23,
+  PT_R24,
+  PT_R25,
+  PT_R26,
+  PT_R27,
+  PT_R28,
+  PT_R29,
+  PT_R30,
+  PT_R31,
+  /* gr32 through gr127 not directly available via the ptrace interface */
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  /* Floating point registers */
+  -1, -1,                      /* f0 and f1 not available (f0 is +0.0 and f1 is +1.0) */
+  PT_F2,
+  PT_F3,
+  PT_F4,
+  PT_F5,
+  PT_F6,
+  PT_F7,
+  PT_F8,
+  PT_F9,
+  PT_F10,
+  PT_F11,
+  PT_F12,
+  PT_F13,
+  PT_F14,
+  PT_F15,
+  PT_F16,
+  PT_F17,
+  PT_F18,
+  PT_F19,
+  PT_F20,
+  PT_F21,
+  PT_F22,
+  PT_F23,
+  PT_F24,
+  PT_F25,
+  PT_F26,
+  PT_F27,
+  PT_F28,
+  PT_F29,
+  PT_F30,
+  PT_F31,
+  PT_F32,
+  PT_F33,
+  PT_F34,
+  PT_F35,
+  PT_F36,
+  PT_F37,
+  PT_F38,
+  PT_F39,
+  PT_F40,
+  PT_F41,
+  PT_F42,
+  PT_F43,
+  PT_F44,
+  PT_F45,
+  PT_F46,
+  PT_F47,
+  PT_F48,
+  PT_F49,
+  PT_F50,
+  PT_F51,
+  PT_F52,
+  PT_F53,
+  PT_F54,
+  PT_F55,
+  PT_F56,
+  PT_F57,
+  PT_F58,
+  PT_F59,
+  PT_F60,
+  PT_F61,
+  PT_F62,
+  PT_F63,
+  PT_F64,
+  PT_F65,
+  PT_F66,
+  PT_F67,
+  PT_F68,
+  PT_F69,
+  PT_F70,
+  PT_F71,
+  PT_F72,
+  PT_F73,
+  PT_F74,
+  PT_F75,
+  PT_F76,
+  PT_F77,
+  PT_F78,
+  PT_F79,
+  PT_F80,
+  PT_F81,
+  PT_F82,
+  PT_F83,
+  PT_F84,
+  PT_F85,
+  PT_F86,
+  PT_F87,
+  PT_F88,
+  PT_F89,
+  PT_F90,
+  PT_F91,
+  PT_F92,
+  PT_F93,
+  PT_F94,
+  PT_F95,
+  PT_F96,
+  PT_F97,
+  PT_F98,
+  PT_F99,
+  PT_F100,
+  PT_F101,
+  PT_F102,
+  PT_F103,
+  PT_F104,
+  PT_F105,
+  PT_F106,
+  PT_F107,
+  PT_F108,
+  PT_F109,
+  PT_F110,
+  PT_F111,
+  PT_F112,
+  PT_F113,
+  PT_F114,
+  PT_F115,
+  PT_F116,
+  PT_F117,
+  PT_F118,
+  PT_F119,
+  PT_F120,
+  PT_F121,
+  PT_F122,
+  PT_F123,
+  PT_F124,
+  PT_F125,
+  PT_F126,
+  PT_F127,
+  /* predicate registers - we don't fetch these individually */
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  /* branch registers */
+  PT_B0,
+  PT_B1,
+  PT_B2,
+  PT_B3,
+  PT_B4,
+  PT_B5,
+  PT_B6,
+  PT_B7,
+  /* virtual frame pointer and virtual return address pointer */
+  -1, -1,
+  /* other registers */
+  PT_PR,
+  PT_CR_IIP,                   /* ip */
+  PT_CR_IPSR,                  /* psr */
+  PT_CFM,                      /* cfm */
+  /* kernel registers not visible via ptrace interface (?) */
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  /* hole */
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  PT_AR_RSC,
+  PT_AR_BSP,
+  PT_AR_BSPSTORE,
+  PT_AR_RNAT,
+  -1,
+  -1,                          /* Not available: FCR, IA32 floating control register */
+  -1, -1,
+  -1,                          /* Not available: EFLAG */
+  -1,                          /* Not available: CSD */
+  -1,                          /* Not available: SSD */
+  -1,                          /* Not available: CFLG */
+  -1,                          /* Not available: FSR */
+  -1,                          /* Not available: FIR */
+  -1,                          /* Not available: FDR */
+  -1,
+  PT_AR_CCV,
+  -1, -1, -1,
+  PT_AR_UNAT,
+  -1, -1, -1,
+  PT_AR_FPSR,
+  -1, -1, -1,
+  -1,                          /* Not available: ITC */
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  PT_AR_PFS,
+  PT_AR_LC,
+  -1,                          /* Not available: EC, the Epilog Count register */
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1,
+  /* nat bits - not fetched directly; instead we obtain these bits from
+     either rnat or unat or from memory. */
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+};
 
 int
 ia64_register_u_addr (int blockend, int regnum)
@@ -569,22 +569,31 @@ fetch_register (int regno)
 
   offset = U_REGS_OFFSET;
 
-  regaddr = register_addr (regno, offset);
-  for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+#ifdef  S390_GNULINUX_TARGET   /* intel has CANNOT_FETCH_REGISTER defined but not linked */
+  if (CANNOT_FETCH_REGISTER (regno))
+    memset (&registers[REGISTER_BYTE (regno)], 0, REGISTER_RAW_SIZE (regno));
+  else
+#endif
     {
-      errno = 0;
-      *(PTRACE_XFER_TYPE *) &registers[REGISTER_BYTE (regno) + i] =
-       ptrace (PTRACE_PEEKUSER, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, 0);
-      regaddr += sizeof (PTRACE_XFER_TYPE);
-      if (errno != 0)
+      regaddr = register_addr (regno, offset);
+      for (i = 0; i < REGISTER_RAW_SIZE (regno);
+          i += sizeof (PTRACE_XFER_TYPE))
        {
-         /* Warning, not error, in case we are attached; sometimes the
-            kernel doesn't let us at the registers.  */
-         char *err = strerror (errno);
-         char *msg = alloca (strlen (err) + 128);
-         sprintf (msg, "reading register %d: %s", regno, err);
-         error (msg);
-         goto error_exit;
+         errno = 0;
+         *(PTRACE_XFER_TYPE *) & registers[REGISTER_BYTE (regno) + i] =
+           ptrace (PTRACE_PEEKUSER, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+                   0);
+         regaddr += sizeof (PTRACE_XFER_TYPE);
+         if (errno != 0)
+           {
+             /* Warning, not error, in case we are attached; sometimes the
+                kernel doesn't let us at the registers.  */
+             char *err = strerror (errno);
+             char *msg = alloca (strlen (err) + 128);
+             sprintf (msg, "reading register %d: %s", regno, err);
+             error (msg);
+             goto error_exit;
+           }
        }
     }
 error_exit:;
@@ -596,7 +605,11 @@ void
 fetch_inferior_registers (int regno)
 {
   if (regno == -1 || regno == 0)
-    for (regno = 0; regno < NUM_REGS - NUM_FREGS; regno++)
+    for (regno = 0; regno < NUM_REGS
+#ifndef S390_GNULINUX_TARGET
+        - NUM_FREGS
+#endif
+        ; regno++)
       fetch_register (regno);
   else
     fetch_register (regno);
@@ -615,7 +628,7 @@ store_inferior_registers (int regno)
 
   if (regno >= 0)
     {
-#if 0
+#ifdef  S390_GNULINUX_TARGET   /* intel has CANNOT_STORE_REGISTER defined but not implemented */
       if (CANNOT_STORE_REGISTER (regno))
        return;
 #endif
@@ -637,19 +650,20 @@ store_inferior_registers (int regno)
        }
       else
 #endif
-       for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+       for (i = 0; i < REGISTER_RAW_SIZE (regno);
+            i += sizeof (PTRACE_XFER_TYPE))
          {
            errno = 0;
            ptrace (PTRACE_POKEUSER, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
-                   *(int *) &registers[REGISTER_BYTE (regno) + i]);
+                   *(PTRACE_XFER_TYPE *) & registers[REGISTER_BYTE (regno) +
+                                                     i]);
            if (errno != 0)
              {
                /* Warning, not error, in case we are attached; sometimes the
                   kernel doesn't let us at the registers.  */
                char *err = strerror (errno);
                char *msg = alloca (strlen (err) + 128);
-               sprintf (msg, "writing register %d: %s",
-                        regno, err);
+               sprintf (msg, "writing register %d: %s", regno, err);
                error (msg);
                return;
              }
@@ -657,7 +671,11 @@ store_inferior_registers (int regno)
          }
     }
   else
-    for (regno = 0; regno < NUM_REGS - NUM_FREGS; regno++)
+    for (regno = 0; regno < NUM_REGS
+#ifndef S390_GNULINUX_TARGET
+        - NUM_FREGS
+#endif
+        ; regno++)
       store_inferior_registers (regno);
 }
 
@@ -677,11 +695,11 @@ read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
   /* Round starting address down to longword boundary.  */
   register CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE);
   /* Round ending address up; get number of longwords that makes.  */
-  register int count 
-    = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1) 
-      / sizeof (PTRACE_XFER_TYPE);
+  register int count
+    = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1)
+    / sizeof (PTRACE_XFER_TYPE);
   /* Allocate buffer of that many longwords.  */
-  register PTRACE_XFER_TYPE *buffer 
+  register PTRACE_XFER_TYPE *buffer
     = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));
 
   /* Read all the longwords */
@@ -691,7 +709,8 @@ read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
     }
 
   /* Copy appropriate bytes out of the buffer.  */
-  memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)), len);
+  memcpy (myaddr,
+         (char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)), len);
 }
 
 /* Copy LEN bytes of data from debugger memory at MYADDR
@@ -707,9 +726,12 @@ write_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
   register CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE);
   /* Round ending address up; get number of longwords that makes.  */
   register int count
-  = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1) / sizeof (PTRACE_XFER_TYPE);
+    =
+    (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) -
+     1) / sizeof (PTRACE_XFER_TYPE);
   /* Allocate buffer of that many longwords.  */
-  register PTRACE_XFER_TYPE *buffer = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));
+  register PTRACE_XFER_TYPE *buffer =
+    (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));
   extern int errno;
 
   /* Fill start and end extra bytes of buffer with existing memory data.  */
@@ -725,7 +747,8 @@ write_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
 
   /* Copy data to be written over corresponding part of buffer */
 
-  memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)), myaddr, len);
+  memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
+         myaddr, len);
 
   /* Write the entire buffer.  */
 
@@ -743,5 +766,7 @@ write_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
 void
 initialize_low (void)
 {
+#ifndef S390_GNULINUX_TARGET
   initialize_arch ();
+#endif
 }
index cfde0a7dae4c9622cc5fccce138f5485163c3fdf..0e5d5f91d1faec846ba80411645d78e22e2cfa28 100644 (file)
@@ -34,6 +34,7 @@
 #include <fcntl.h>
 #include <sys/time.h>
 #include <unistd.h>
+#include <target.h>
 
 int remote_debug = 0;
 struct ui_file *gdb_stdlog;
@@ -141,7 +142,8 @@ remote_open (char *name)
 
       /* Enable TCP keep alive process. */
       tmp = 1;
-      setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp));
+      setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp,
+                 sizeof (tmp));
 
       /* Tell TCP not to delay small packets.  This greatly speeds up
          interactive response. */
@@ -278,7 +280,7 @@ input_interrupt (void)
     {
       int cc;
       char c;
-      
+
       cc = read (remote_desc, &c, 1);
 
       if (cc != 1 || c != '\003')
@@ -286,7 +288,7 @@ input_interrupt (void)
          fprintf (stderr, "input_interrupt, cc = %d c = %d\n", cc, c);
          return;
        }
-      
+
       kill (inferior_pid, SIGINT);
     }
 }
@@ -463,10 +465,7 @@ prepare_resume_reply (char *buf, char status, unsigned char signo)
 
   *buf++ = status;
 
-  /* FIXME!  Should be converting this signal number (numbered
-     according to the signal numbering of the system we are running on)
-     to the signal numbers used by the gdb protocol (see enum target_signal
-     in gdb/target.h).  */
+  signo = target_signal_from_host (signo);
   nib = ((signo & 0xf0) >> 4);
   *buf++ = tohex (nib);
   nib = signo & 0x0f;
@@ -475,12 +474,11 @@ prepare_resume_reply (char *buf, char status, unsigned char signo)
   if (status == 'T')
     {
 #ifdef GDBSERVER_RESUME_REGS
-      static int gdbserver_resume_regs[] = GDBSERVER_RESUME_REGS ;
+      static int gdbserver_resume_regs[] = GDBSERVER_RESUME_REGS;
       int i;
-      for (i = 0; 
-           i < sizeof (gdbserver_resume_regs) 
-               / sizeof (gdbserver_resume_regs[0]);
-          i++)
+      for (i = 0;
+          i < sizeof (gdbserver_resume_regs)
+          / sizeof (gdbserver_resume_regs[0]); i++)
        {
          int regnum = gdbserver_resume_regs[i];
          buf = outreg (regnum, buf);
index ab37b2ef0791db0ba949cc1d08b8836424a05d62..8bb0630f80dffc07fa1d87e9b7241c8d0145a2cd 100644 (file)
@@ -20,6 +20,7 @@
    Boston, MA 02111-1307, USA.  */
 
 #include "server.h"
+#include "target.h"
 
 int cont_thread;
 int general_thread;
@@ -60,7 +61,6 @@ main (int argc, char *argv[])
     error ("Usage: gdbserver tty prog [args ...]");
 
   initialize_low ();
-
   /* Wait till we are at first instruction in program.  */
   signal = start_inferior (&argv[2], &status);
 
@@ -130,12 +130,14 @@ main (int argc, char *argv[])
              break;
            case 'C':
              convert_ascii_to_int (own_buf + 1, &sig, 1);
+             sig = target_signal_to_host (sig);
              myresume (0, sig);
              signal = mywait (&status);
              prepare_resume_reply (own_buf, status, signal);
              break;
            case 'S':
              convert_ascii_to_int (own_buf + 1, &sig, 1);
+             sig = target_signal_to_host (sig);
              myresume (1, sig);
              signal = mywait (&status);
              prepare_resume_reply (own_buf, status, signal);
@@ -210,8 +212,7 @@ main (int argc, char *argv[])
          putpkt (own_buf);
 
          if (status == 'W')
-           fprintf (stderr,
-                    "\nChild exited with status %d\n", sig);
+           fprintf (stderr, "\nChild exited with status %d\n", sig);
          if (status == 'X')
            fprintf (stderr, "\nChild terminated with signal = 0x%x\n", sig);
          if (status == 'W' || status == 'X')
@@ -250,7 +251,8 @@ main (int argc, char *argv[])
        }
       else
        {
-         fprintf (stderr, "Remote side has terminated connection.  GDBserver will reopen the connection.\n");
+         fprintf (stderr,
+                  "Remote side has terminated connection.  GDBserver will reopen the connection.\n");
 
          remote_close ();
        }
diff --git a/gdb/s390-nat.c b/gdb/s390-nat.c
new file mode 100644 (file)
index 0000000..a7ab493
--- /dev/null
@@ -0,0 +1,308 @@
+/* S390 native-dependent code for GDB, the GNU debugger.
+   Copyright 1999-2001 Free Software Foundation, Inc
+   Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+   for IBM Deutschland Entwicklung GmbH, IBM Corporation.
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#include "defs.h"
+#include "tm.h"
+#include <asm/ptrace.h>
+#include <sys/ptrace.h>
+#include <asm/processor.h>
+#include <sys/procfs.h>
+#include <sys/user.h>
+#include <value.h>
+#include <sys/ucontext.h>
+#ifndef offsetof
+#define offsetof(type,member) ((size_t) &((type *)0)->member)
+#endif
+
+
+int
+s390_register_u_addr (int blockend, int regnum)
+{
+  int retval;
+
+  if (regnum >= S390_GP0_REGNUM && regnum <= S390_GP_LAST_REGNUM)
+    retval = PT_GPR0 + ((regnum - S390_GP0_REGNUM) * S390_GPR_SIZE);
+  else if (regnum >= S390_PSWM_REGNUM && regnum <= S390_PC_REGNUM)
+    retval = PT_PSWMASK + ((regnum - S390_PSWM_REGNUM) * S390_PSW_MASK_SIZE);
+  else if (regnum == S390_FPC_REGNUM)
+    retval = PT_FPC;
+  else if (regnum >= S390_FP0_REGNUM && regnum <= S390_FPLAST_REGNUM)
+    retval =
+#if CONFIG_ARCH_S390X
+      PT_FPR0
+#else
+      PT_FPR0_HI
+#endif
+      + ((regnum - S390_FP0_REGNUM) * S390_FPR_SIZE);
+  else if (regnum >= S390_FIRST_ACR && regnum <= S390_LAST_ACR)
+    retval = PT_ACR0 + ((regnum - S390_FIRST_ACR) * S390_ACR_SIZE);
+  else if (regnum >= (S390_FIRST_CR + 9) && regnum <= (S390_FIRST_CR + 11))
+    retval = PT_CR_9 + ((regnum - (S390_FIRST_CR + 9)) * S390_CR_SIZE);
+  else
+    {
+#ifdef GDBSERVER
+      error
+#else
+      internal_error
+#endif
+       ("s390_register_u_addr invalid regnum %s %d regnum=%d", __FILE__,
+        (int) __LINE__, regnum);
+      retval = 0;
+    }
+  return retval + blockend;
+}
+
+#ifndef GDBSERVER
+/* watch_areas are required if you put 2 or more watchpoints on the same 
+   address or overlapping areas gdb will call us to delete the watchpoint 
+   more than once when we try to delete them.
+   attempted reference counting to reduce the number of areas unfortunately
+   they didn't shrink when areas had to be split overlapping occurs. */
+struct watch_area;
+typedef struct watch_area watch_area;
+struct watch_area
+{
+  watch_area *next;
+  CORE_ADDR lo_addr;
+  CORE_ADDR hi_addr;
+};
+
+static watch_area *watch_base = NULL;
+int watch_area_cnt = 0;
+static CORE_ADDR watch_lo_addr = 0, watch_hi_addr = 0;
+
+
+
+CORE_ADDR
+s390_stopped_by_watchpoint (int pid)
+{
+  per_lowcore_bits per_lowcore;
+  ptrace_area parea;
+
+  parea.len = sizeof (per_lowcore);
+  parea.process_addr = (addr_t) & per_lowcore;
+  parea.kernel_addr = offsetof (struct user_regs_struct, per_info.lowcore);
+  ptrace (PTRACE_PEEKUSR_AREA, pid, &parea);
+  return ((per_lowcore.perc_storage_alteration == 1) &&
+         (per_lowcore.perc_store_real_address == 0));
+}
+
+
+void
+s390_fix_watch_points (int pid)
+{
+  per_struct per_info;
+  ptrace_area parea;
+
+  parea.len = sizeof (per_info);
+  parea.process_addr = (addr_t) & per_info;
+  parea.kernel_addr = PT_CR_9;
+  ptrace (PTRACE_PEEKUSR_AREA, pid, &parea);
+  /* The kernel automatically sets the psw for per depending */
+  /* on whether the per control registers are set for event recording */
+  /* & sets cr9 & cr10 appropriately also */
+  if (watch_area_cnt)
+    {
+      per_info.control_regs.bits.em_storage_alteration = 1;
+      per_info.control_regs.bits.storage_alt_space_ctl = 1;
+    }
+  else
+    {
+      per_info.control_regs.bits.em_storage_alteration = 0;
+      per_info.control_regs.bits.storage_alt_space_ctl = 0;
+    }
+  per_info.starting_addr = watch_lo_addr;
+  per_info.ending_addr = watch_hi_addr;
+  ptrace (PTRACE_POKEUSR_AREA, pid, &parea);
+}
+
+int
+s390_insert_watchpoint (int pid, CORE_ADDR addr, int len, int rw)
+{
+  CORE_ADDR hi_addr = addr + len - 1;
+  watch_area *newarea = (watch_area *) malloc (sizeof (watch_area));
+
+
+  if (newarea)
+    {
+      newarea->next = watch_base;
+      watch_base = newarea;
+      watch_lo_addr = min (watch_lo_addr, addr);
+      watch_hi_addr = max (watch_hi_addr, hi_addr);
+      newarea->lo_addr = addr;
+      newarea->hi_addr = hi_addr;
+      if (watch_area_cnt == 0)
+       {
+         watch_lo_addr = newarea->lo_addr;
+         watch_hi_addr = newarea->hi_addr;
+       }
+      watch_area_cnt++;
+      s390_fix_watch_points (pid);
+    }
+  return newarea ? 0 : -1;
+}
+
+
+int
+s390_remove_watchpoint (int pid, CORE_ADDR addr, int len)
+{
+  watch_area *curr = watch_base, *prev, *matchCurr;
+  CORE_ADDR hi_addr = addr + len - 1;
+  CORE_ADDR watch_second_lo_addr = 0xffffffffUL, watch_second_hi_addr = 0;
+  int lo_addr_ref_cnt, hi_addr_ref_cnt;
+  prev = matchCurr = NULL;
+  lo_addr_ref_cnt = (addr == watch_lo_addr);
+  hi_addr_ref_cnt = (addr == watch_hi_addr);
+  while (curr)
+    {
+      if (matchCurr == NULL)
+       {
+         if (curr->lo_addr == addr && curr->hi_addr == hi_addr)
+           {
+             matchCurr = curr;
+             if (prev)
+               prev->next = curr->next;
+             else
+               watch_base = curr->next;
+           }
+         prev = curr;
+       }
+      if (lo_addr_ref_cnt)
+       {
+         if (watch_lo_addr == curr->lo_addr)
+           lo_addr_ref_cnt++;
+         if (curr->lo_addr > watch_lo_addr &&
+             curr->lo_addr < watch_second_lo_addr)
+           watch_second_lo_addr = curr->lo_addr;
+       }
+      if (hi_addr_ref_cnt)
+       {
+         if (watch_hi_addr == curr->hi_addr)
+           hi_addr_ref_cnt++;
+         if (curr->hi_addr < watch_hi_addr &&
+             curr->hi_addr > watch_second_hi_addr)
+           watch_second_hi_addr = curr->hi_addr;
+       }
+      curr = curr->next;
+    }
+  if (matchCurr)
+    {
+      free (matchCurr);
+      watch_area_cnt--;
+      if (watch_area_cnt)
+       {
+         if (lo_addr_ref_cnt == 2)
+           watch_lo_addr = watch_second_lo_addr;
+         if (hi_addr_ref_cnt == 2)
+           watch_hi_addr = watch_second_hi_addr;
+       }
+      else
+       {
+         watch_lo_addr = watch_hi_addr = 0;
+       }
+      s390_fix_watch_points (pid);
+      return 0;
+    }
+  else
+    {
+      fprintf_unfiltered (gdb_stderr,
+                         "Attempt to remove nonexistent watchpoint in s390_remove_watchpoint\n");
+      return -1;
+    }
+}
+
+int
+kernel_u_size (void)
+{
+  return sizeof (struct user);
+}
+
+
+#if  (defined (S390_FP0_REGNUM) && defined (HAVE_FPREGSET_T) && defined(HAVE_SYS_PROCFS_H) && defined (HAVE_GREGSET_T))
+void
+supply_gregset (gregset_t * gregsetp)
+{
+  int regi;
+  greg_t *gregp = (greg_t *) gregsetp;
+
+  supply_register (S390_PSWM_REGNUM, (char *) &gregp[S390_PSWM_REGNUM]);
+  supply_register (S390_PC_REGNUM, (char *) &gregp[S390_PC_REGNUM]);
+  for (regi = 0; regi < S390_NUM_GPRS; regi++)
+    supply_register (S390_GP0_REGNUM + regi,
+                    (char *) &gregp[S390_GP0_REGNUM + regi]);
+  for (regi = 0; regi < S390_NUM_ACRS; regi++)
+    supply_register (S390_FIRST_ACR + regi,
+                    (char *) &gregp[S390_FIRST_ACR + regi]);
+  /* unfortunately this isn't in gregsetp */
+  for (regi = 0; regi < S390_NUM_CRS; regi++)
+    supply_register (S390_FIRST_CR + regi, NULL);
+}
+
+
+void
+supply_fpregset (fpregset_t * fpregsetp)
+{
+  int regi;
+
+  supply_register (S390_FPC_REGNUM, (char *) &fpregsetp->fpc);
+  for (regi = 0; regi < S390_NUM_FPRS; regi++)
+    supply_register (S390_FP0_REGNUM + regi, (char *) &fpregsetp->fprs[regi]);
+
+}
+
+void
+fill_gregset (gregset_t * gregsetp, int regno)
+{
+  greg_t *gregp = (greg_t *) gregsetp;
+
+  if (regno >= S390_FIRST_CR && regno <= S390_LAST_CR)
+    supply_register (regno, NULL);
+  else if (regno != -1)
+    supply_register (regno, (char *) &gregp[regno]);
+  else
+    supply_gregset (gregsetp);
+}
+
+/*  Given a pointer to a floating point register set in /proc format
+   (fpregset_t *), update the register specified by REGNO from gdb's idea
+   of the current floating point register set.  If REGNO is -1, update
+   them all. */
+
+void
+fill_fpregset (fpregset_t * fpregsetp, int regno)
+{
+  if (regno == -1)
+    supply_fpregset (fpregsetp);
+  else
+    supply_register (regno,
+                    &((char *) fpregsetp)[REGISTER_BYTE (regno) -
+                                          REGISTER_BYTE (S390_FPC_REGNUM)]);
+}
+
+
+#else
+#error "There are a few possibilities here"
+#error "1) You aren't compiling for linux & don't need a core dumps to work."
+#error "2) The header files sys/elf.h sys/user.h sys/ptrace.h & sys/procfs.h"
+#error "libc files are inconsistent with linux/include/asm-s390/"
+#error "3) you didn't do a completely clean build & delete config.cache."
+#endif
+#endif /* GDBSERVER */
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
new file mode 100644 (file)
index 0000000..4050607
--- /dev/null
@@ -0,0 +1,1504 @@
+/* Target-dependent code for GDB, the GNU debugger.
+   Copyright 1999 Free Software Foundation, Inc.
+   Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+   for IBM Deutschland Entwicklung GmbH, IBM Corporation.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#define S390_TDEP              /* for special macros in tm-s390.h */
+#include <defs.h>
+#include "arch-utils.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "tm.h"
+#include "../bfd/bfd.h"
+#include "floatformat.h"
+#include "regcache.h"
+
+
+
+
+
+/* Number of bytes of storage in the actual machine representation
+   for register N. 
+   Note that the unsigned cast here forces the result of the
+   subtraction to very high positive values if N < S390_FP0_REGNUM */
+int
+s390_register_raw_size (int reg_nr)
+{
+  return ((unsigned) reg_nr - S390_FP0_REGNUM) <
+    S390_NUM_FPRS ? S390_FPR_SIZE : 4;
+}
+
+int
+s390x_register_raw_size (int reg_nr)
+{
+  return (reg_nr == S390_FPC_REGNUM)
+    || (reg_nr >= S390_FIRST_ACR && reg_nr <= S390_LAST_ACR) ? 4 : 8;
+}
+
+int
+s390_cannot_fetch_register (int regno)
+{
+  return (regno >= S390_FIRST_CR && regno < (S390_FIRST_CR + 9)) ||
+    (regno >= (S390_FIRST_CR + 12) && regno <= S390_LAST_CR);
+}
+
+int
+s390_register_byte (int reg_nr)
+{
+  if (reg_nr <= S390_GP_LAST_REGNUM)
+    return reg_nr * S390_GPR_SIZE;
+  if (reg_nr <= S390_LAST_ACR)
+    return S390_ACR0_OFFSET + (((reg_nr) - S390_FIRST_ACR) * S390_ACR_SIZE);
+  if (reg_nr <= S390_LAST_CR)
+    return S390_CR0_OFFSET + (((reg_nr) - S390_FIRST_CR) * S390_CR_SIZE);
+  if (reg_nr == S390_FPC_REGNUM)
+    return S390_FPC_OFFSET;
+  else
+    return S390_FP0_OFFSET + (((reg_nr) - S390_FP0_REGNUM) * S390_FPR_SIZE);
+}
+
+#ifndef GDBSERVER
+#define S390_MAX_INSTR_SIZE (6)
+#define S390_SYSCALL_OPCODE (0x0a)
+#define S390_SYSCALL_SIZE   (2)
+#define S390_SIGCONTEXT_SREGS_OFFSET (8)
+#define S390X_SIGCONTEXT_SREGS_OFFSET (8)
+#define S390_SIGREGS_FP0_OFFSET       (144)
+#define S390X_SIGREGS_FP0_OFFSET      (216)
+#define S390_UC_MCONTEXT_OFFSET    (256)
+#define S390X_UC_MCONTEXT_OFFSET   (344)
+#define S390_STACK_FRAME_OVERHEAD  (GDB_TARGET_IS_ESAME ? 160:96)
+#define S390_SIGNAL_FRAMESIZE  (GDB_TARGET_IS_ESAME ? 160:96)
+#define s390_NR_sigreturn          119
+#define s390_NR_rt_sigreturn       173
+
+
+
+struct frame_extra_info
+{
+  int initialised;
+  int good_prologue;
+  CORE_ADDR function_start;
+  CORE_ADDR skip_prologue_function_start;
+  CORE_ADDR saved_pc_valid;
+  CORE_ADDR saved_pc;
+  CORE_ADDR sig_fixed_saved_pc_valid;
+  CORE_ADDR sig_fixed_saved_pc;
+  CORE_ADDR frame_pointer_saved_pc;    /* frame pointer needed for alloca */
+  CORE_ADDR stack_bought;      /* amount we decrement the stack pointer by */
+  CORE_ADDR sigcontext;
+};
+
+
+static CORE_ADDR s390_frame_saved_pc_nofix (struct frame_info *fi);
+
+int
+s390_readinstruction (bfd_byte instr[], CORE_ADDR at,
+                     struct disassemble_info *info)
+{
+  int instrlen;
+
+  static int s390_instrlen[] = {
+    2,
+    4,
+    4,
+    6
+  };
+  if ((*info->read_memory_func) (at, &instr[0], 2, info))
+    return -1;
+  instrlen = s390_instrlen[instr[0] >> 6];
+  if ((*info->read_memory_func) (at + 2, &instr[2], instrlen - 2, info))
+    return -1;
+  return instrlen;
+}
+
+static void
+s390_memset_extra_info (struct frame_extra_info *fextra_info)
+{
+  memset (fextra_info, 0, sizeof (struct frame_extra_info));
+}
+
+
+
+char *
+s390_register_name (int reg_nr)
+{
+  static char *register_names[] = {
+    "pswm", "pswa",
+    "gpr0", "gpr1", "gpr2", "gpr3", "gpr4", "gpr5", "gpr6", "gpr7",
+    "gpr8", "gpr9", "gpr10", "gpr11", "gpr12", "gpr13", "gpr14", "gpr15",
+    "acr0", "acr1", "acr2", "acr3", "acr4", "acr5", "acr6", "acr7",
+    "acr8", "acr9", "acr10", "acr11", "acr12", "acr13", "acr14", "acr15",
+    "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
+    "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15",
+    "fpc",
+    "fpr0", "fpr1", "fpr2", "fpr3", "fpr4", "fpr5", "fpr6", "fpr7",
+    "fpr8", "fpr9", "fpr10", "fpr11", "fpr12", "fpr13", "fpr14", "fpr15"
+  };
+
+  if (reg_nr >= S390_LAST_REGNUM)
+    return NULL;
+  return register_names[reg_nr];
+}
+
+
+
+
+int
+s390_stab_reg_to_regnum (int regno)
+{
+  return regno >= 64 ? S390_PSWM_REGNUM - 64 :
+    regno >= 48 ? S390_FIRST_ACR - 48 :
+    regno >= 32 ? S390_FIRST_CR - 32 :
+    regno <= 15 ? (regno + 2) :
+    S390_FP0_REGNUM + ((regno - 16) & 8) + (((regno - 16) & 3) << 1) +
+    (((regno - 16) & 4) >> 2);
+}
+
+
+
+/* s390_get_frame_info based on Hartmuts
+   prologue definition in
+   gcc-2.8.1/config/l390/linux.c 
+
+   It reads one instruction at a time & based on whether
+   it looks like prologue code or not it makes a decision on
+   whether the prologue is over, there are various state machines
+   in the code to determine if the prologue code is possilby valid.
+   
+   This is done to hopefully allow the code survive minor revs of
+   calling conventions.
+
+ */
+
+int
+s390_get_frame_info (CORE_ADDR pc, struct frame_extra_info *fextra_info,
+                    struct frame_info *fi, int init_extra_info)
+{
+#define CONST_POOL_REGIDX 13
+#define GOT_REGIDX        12
+  bfd_byte instr[S390_MAX_INSTR_SIZE];
+  CORE_ADDR test_pc = pc, test_pc2;
+  CORE_ADDR orig_sp = 0, save_reg_addr = 0, *saved_regs = NULL;
+  int valid_prologue, good_prologue = 0;
+  int gprs_saved[S390_NUM_GPRS];
+  int fprs_saved[S390_NUM_FPRS];
+  int regidx, instrlen;
+  int save_link_regidx, subtract_sp_regidx;
+  int const_pool_state, save_link_state, got_state;
+  int frame_pointer_found, varargs_state;
+  int loop_cnt, gdb_gpr_store, gdb_fpr_store;
+  int frame_pointer_regidx = 0xf;
+  int offset, expected_offset;
+  int err = 0;
+  disassemble_info info;
+  const_pool_state = save_link_state = got_state = varargs_state = 0;
+  frame_pointer_found = 0;
+  memset (gprs_saved, 0, sizeof (gprs_saved));
+  memset (fprs_saved, 0, sizeof (fprs_saved));
+  info.read_memory_func = dis_asm_read_memory;
+
+  save_link_regidx = subtract_sp_regidx = 0;
+  if (fextra_info)
+    {
+      if (fi && fi->frame)
+       {
+         orig_sp = fi->frame + fextra_info->stack_bought;
+         saved_regs = fi->saved_regs;
+       }
+      if (init_extra_info || !fextra_info->initialised)
+       {
+         s390_memset_extra_info (fextra_info);
+         fextra_info->function_start = pc;
+         fextra_info->initialised = 1;
+       }
+    }
+  instrlen = 0;
+  do
+    {
+      valid_prologue = 0;
+      test_pc += instrlen;
+      /* add the previous instruction len */
+      instrlen = s390_readinstruction (instr, test_pc, &info);
+      if (instrlen < 0)
+       {
+         good_prologue = 0;
+         err = -1;
+         break;
+       }
+      /* We probably are in a glibc syscall */
+      if (instr[0] == S390_SYSCALL_OPCODE && test_pc == pc)
+       {
+         good_prologue = 1;
+         if (saved_regs && fextra_info && fi->next && fi->next->extra_info
+             && fi->next->extra_info->sigcontext)
+           {
+             /* We are backtracing from a signal handler */
+             save_reg_addr = fi->next->extra_info->sigcontext +
+               REGISTER_BYTE (S390_GP0_REGNUM);
+             for (regidx = 0; regidx < S390_NUM_GPRS; regidx++)
+               {
+                 saved_regs[S390_GP0_REGNUM + regidx] = save_reg_addr;
+                 save_reg_addr += S390_GPR_SIZE;
+               }
+             save_reg_addr = fi->next->extra_info->sigcontext +
+               (GDB_TARGET_IS_ESAME ? S390X_SIGREGS_FP0_OFFSET :
+                S390_SIGREGS_FP0_OFFSET);
+             for (regidx = 0; regidx < S390_NUM_FPRS; regidx++)
+               {
+                 saved_regs[S390_FP0_REGNUM + regidx] = save_reg_addr;
+                 save_reg_addr += S390_FPR_SIZE;
+               }
+           }
+         break;
+       }
+      if (save_link_state == 0)
+       {
+         /* check for a stack relative STMG or STM */
+         if (((GDB_TARGET_IS_ESAME &&
+               ((instr[0] == 0xeb) && (instr[5] == 0x24))) ||
+              (instr[0] == 0x90)) && ((instr[2] >> 4) == 0xf))
+           {
+             regidx = (instr[1] >> 4);
+             if (regidx < 6)
+               varargs_state = 1;
+             offset = ((instr[2] & 0xf) << 8) + instr[3];
+             expected_offset =
+               S390_GPR6_STACK_OFFSET + (S390_GPR_SIZE * (regidx - 6));
+             if (offset != expected_offset)
+               {
+                 good_prologue = 0;
+                 break;
+               }
+             if (saved_regs)
+               save_reg_addr = orig_sp + offset;
+             for (; regidx <= (instr[1] & 0xf); regidx++)
+               {
+                 if (gprs_saved[regidx])
+                   {
+                     good_prologue = 0;
+                     break;
+                   }
+                 good_prologue = 1;
+                 gprs_saved[regidx] = 1;
+                 if (saved_regs)
+                   {
+                     saved_regs[S390_GP0_REGNUM + regidx] = save_reg_addr;
+                     save_reg_addr += S390_GPR_SIZE;
+                   }
+               }
+             valid_prologue = 1;
+             continue;
+           }
+       }
+      /* check for a stack relative STG or ST */
+      if ((save_link_state == 0 || save_link_state == 3) &&
+         ((GDB_TARGET_IS_ESAME &&
+           ((instr[0] == 0xe3) && (instr[5] == 0x24))) ||
+          (instr[0] == 0x50)) && ((instr[2] >> 4) == 0xf))
+       {
+         regidx = instr[1] >> 4;
+         offset = ((instr[2] & 0xf) << 8) + instr[3];
+         if (offset == 0)
+           {
+             if (save_link_state == 3 && regidx == save_link_regidx)
+               {
+                 save_link_state = 4;
+                 valid_prologue = 1;
+                 continue;
+               }
+             else
+               break;
+           }
+         if (regidx < 6)
+           varargs_state = 1;
+         expected_offset =
+           S390_GPR6_STACK_OFFSET + (S390_GPR_SIZE * (regidx - 6));
+         if (offset != expected_offset)
+           {
+             good_prologue = 0;
+             break;
+           }
+         if (gprs_saved[regidx])
+           {
+             good_prologue = 0;
+             break;
+           }
+         good_prologue = 1;
+         gprs_saved[regidx] = 1;
+         if (saved_regs)
+           {
+             save_reg_addr = orig_sp + offset;
+             saved_regs[S390_GP0_REGNUM + regidx] = save_reg_addr;
+           }
+         valid_prologue = 1;
+         continue;
+       }
+
+      /* check for STD */
+      if (instr[0] == 0x60 && (instr[2] >> 4) == 0xf)
+       {
+         regidx = instr[1] >> 4;
+         if (regidx == 0 || regidx == 2)
+           varargs_state = 1;
+         if (fprs_saved[regidx])
+           {
+             good_prologue = 0;
+             break;
+           }
+         fprs_saved[regidx] = 1;
+         if (saved_regs)
+           {
+             save_reg_addr = orig_sp + (((instr[2] & 0xf) << 8) + instr[3]);
+             saved_regs[S390_FP0_REGNUM + regidx] = save_reg_addr;
+           }
+         valid_prologue = 1;
+         continue;
+       }
+
+
+      if (const_pool_state == 0)
+       {
+
+         if (GDB_TARGET_IS_ESAME)
+           {
+             /* Check for larl CONST_POOL_REGIDX,offset on ESAME */
+             if ((instr[0] == 0xc0)
+                 && (instr[1] == (CONST_POOL_REGIDX << 4)))
+               {
+                 const_pool_state = 2;
+                 valid_prologue = 1;
+                 continue;
+               }
+           }
+         else
+           {
+             /* Check for BASR gpr13,gpr0 used to load constant pool pointer to r13 in old compiler */
+             if (instr[0] == 0xd && (instr[1] & 0xf) == 0
+                 && ((instr[1] >> 4) == CONST_POOL_REGIDX))
+               {
+                 const_pool_state = 1;
+                 valid_prologue = 1;
+                 continue;
+               }
+           }
+         /* Check for new fangled bras %r13,newpc to load new constant pool */
+         /* embedded in code, older pre abi compilers also emitted this stuff.  */
+         if ((instr[0] == 0xa7) && ((instr[1] & 0xf) == 0x5) &&
+             ((instr[1] >> 4) == CONST_POOL_REGIDX)
+             && ((instr[2] & 0x80) == 0))
+           {
+             const_pool_state = 2;
+             test_pc +=
+               (((((instr[2] & 0xf) << 8) + instr[3]) << 1) - instrlen);
+             valid_prologue = 1;
+             continue;
+           }
+       }
+      /* Check for AGHI or AHI CONST_POOL_REGIDX,val */
+      if (const_pool_state == 1 && (instr[0] == 0xa7) &&
+         ((GDB_TARGET_IS_ESAME &&
+           (instr[1] == ((CONST_POOL_REGIDX << 4) | 0xb))) ||
+          (instr[1] == ((CONST_POOL_REGIDX << 4) | 0xa))))
+       {
+         const_pool_state = 2;
+         valid_prologue = 1;
+         continue;
+       }
+      /* Check for LGR or LR gprx,15 */
+      if ((GDB_TARGET_IS_ESAME &&
+          instr[0] == 0xb9 && instr[1] == 0x04 && (instr[3] & 0xf) == 0xf) ||
+         (instr[0] == 0x18 && (instr[1] & 0xf) == 0xf))
+       {
+         if (GDB_TARGET_IS_ESAME)
+           regidx = instr[3] >> 4;
+         else
+           regidx = instr[1] >> 4;
+         if (save_link_state == 0 && regidx != 0xb)
+           {
+             /* Almost defintely code for
+                decrementing the stack pointer 
+                ( i.e. a non leaf function 
+                or else leaf with locals ) */
+             save_link_regidx = regidx;
+             save_link_state = 1;
+             valid_prologue = 1;
+             continue;
+           }
+         /* We use this frame pointer for alloca
+            unfortunately we need to assume its gpr11
+            otherwise we would need a smarter prologue
+            walker. */
+         if (!frame_pointer_found && regidx == 0xb)
+           {
+             frame_pointer_regidx = 0xb;
+             frame_pointer_found = 1;
+             if (fextra_info)
+               fextra_info->frame_pointer_saved_pc = test_pc;
+             valid_prologue = 1;
+             continue;
+           }
+       }
+      /* Check for AHI or AGHI gpr15,val */
+      if (save_link_state == 1 && (instr[0] == 0xa7) &&
+         ((GDB_TARGET_IS_ESAME && (instr[1] == 0xfb)) || (instr[1] == 0xfa)))
+       {
+         if (fextra_info)
+           fextra_info->stack_bought =
+             -extract_signed_integer (&instr[2], 2);
+         save_link_state = 3;
+         valid_prologue = 1;
+         continue;
+       }
+      /* Alternatively check for the complex construction for
+         buying more than 32k of stack
+         BRAS gprx,.+8
+         long vals    %r15,0(%gprx)  gprx currently r1 */
+      if ((save_link_state == 1) && (instr[0] == 0xa7)
+         && ((instr[1] & 0xf) == 0x5) && (instr[2] == 0)
+         && (instr[3] == 0x4) && ((instr[1] >> 4) != CONST_POOL_REGIDX))
+       {
+         subtract_sp_regidx = instr[1] >> 4;
+         save_link_state = 2;
+         if (fextra_info)
+           target_read_memory (test_pc + instrlen,
+                               (char *) &fextra_info->stack_bought,
+                               sizeof (fextra_info->stack_bought));
+         test_pc += 4;
+         valid_prologue = 1;
+         continue;
+       }
+      if (save_link_state == 2 && instr[0] == 0x5b
+         && instr[1] == 0xf0 &&
+         instr[2] == (subtract_sp_regidx << 4) && instr[3] == 0)
+       {
+         save_link_state = 3;
+         valid_prologue = 1;
+         continue;
+       }
+      /* check for LA gprx,offset(15) used for varargs */
+      if ((instr[0] == 0x41) && ((instr[2] >> 4) == 0xf) &&
+         ((instr[1] & 0xf) == 0))
+       {
+         /* some code uses gpr7 to point to outgoing args */
+         if (((instr[1] >> 4) == 7) && (save_link_state == 0) &&
+             ((instr[2] & 0xf) == 0)
+             && (instr[3] == S390_STACK_FRAME_OVERHEAD))
+           {
+             valid_prologue = 1;
+             continue;
+           }
+         if (varargs_state == 1)
+           {
+             varargs_state = 2;
+             valid_prologue = 1;
+             continue;
+           }
+       }
+      /* Check for a GOT load */
+
+      if (GDB_TARGET_IS_ESAME)
+       {
+         /* Check for larl  GOT_REGIDX, on ESAME */
+         if ((got_state == 0) && (instr[0] == 0xc0)
+             && (instr[1] == (GOT_REGIDX << 4)))
+           {
+             got_state = 2;
+             valid_prologue = 1;
+             continue;
+           }
+       }
+      else
+       {
+         /* check for l GOT_REGIDX,x(CONST_POOL_REGIDX) */
+         if (got_state == 0 && const_pool_state == 2 && instr[0] == 0x58
+             && (instr[2] == (CONST_POOL_REGIDX << 4))
+             && ((instr[1] >> 4) == GOT_REGIDX))
+           {
+             got_state == 1;
+             valid_prologue = 1;
+             continue;
+           }
+         /* Check for subsequent ar got_regidx,basr_regidx */
+         if (got_state == 1 && instr[0] == 0x1a &&
+             instr[1] == ((GOT_REGIDX << 4) | CONST_POOL_REGIDX))
+           {
+             got_state = 2;
+             valid_prologue = 1;
+             continue;
+           }
+       }
+    }
+  while (valid_prologue && good_prologue);
+  if (good_prologue)
+    {
+      good_prologue = (((got_state == 0) || (got_state == 2)) &&
+                      ((const_pool_state == 0) || (const_pool_state == 2)) &&
+                      ((save_link_state == 0) || (save_link_state == 4)) &&
+                      ((varargs_state == 0) || (varargs_state == 2)));
+    }
+  if (fextra_info)
+    {
+      fextra_info->good_prologue = good_prologue;
+      fextra_info->skip_prologue_function_start =
+       (good_prologue ? test_pc : pc);
+    }
+  return err;
+}
+
+
+int
+s390_check_function_end (CORE_ADDR pc)
+{
+  bfd_byte instr[S390_MAX_INSTR_SIZE];
+  disassemble_info info;
+  int regidx, instrlen;
+
+  info.read_memory_func = dis_asm_read_memory;
+  instrlen = s390_readinstruction (instr, pc, &info);
+  if (instrlen < 0)
+    return -1;
+  /* check for BR */
+  if (instrlen != 2 || instr[0] != 07 || (instr[1] >> 4) != 0xf)
+    return 0;
+  regidx = instr[1] & 0xf;
+  /* Check for LMG or LG */
+  instrlen =
+    s390_readinstruction (instr, pc - (GDB_TARGET_IS_ESAME ? 6 : 4), &info);
+  if (instrlen < 0)
+    return -1;
+  if (GDB_TARGET_IS_ESAME)
+    {
+
+      if (instrlen != 6 || instr[0] != 0xeb || instr[5] != 0x4)
+       return 0;
+    }
+  else if (instrlen != 4 || instr[0] != 0x98)
+    {
+      return 0;
+    }
+  if ((instr[2] >> 4) != 0xf)
+    return 0;
+  if (regidx == 14)
+    return 1;
+  instrlen = s390_readinstruction (instr, pc - (GDB_TARGET_IS_ESAME ? 12 : 8),
+                                  &info);
+  if (instrlen < 0)
+    return -1;
+  if (GDB_TARGET_IS_ESAME)
+    {
+      /* Check for LG */
+      if (instrlen != 6 || instr[0] != 0xe3 || instr[5] != 0x4)
+       return 0;
+    }
+  else
+    {
+      /* Check for L */
+      if (instrlen != 4 || instr[0] != 0x58)
+       return 0;
+    }
+  if (instr[2] >> 4 != 0xf)
+    return 0;
+  if (instr[1] >> 4 != regidx)
+    return 0;
+  return 1;
+}
+
+static CORE_ADDR
+s390_sniff_pc_function_start (CORE_ADDR pc, struct frame_info *fi)
+{
+  CORE_ADDR function_start, test_function_start;
+  int loop_cnt, err, function_end;
+  struct frame_extra_info fextra_info;
+  function_start = get_pc_function_start (pc);
+
+  if (function_start == 0)
+    {
+      test_function_start = pc;
+      if (test_function_start & 1)
+       return 0;               /* This has to be bogus */
+      loop_cnt = 0;
+      do
+       {
+
+         err =
+           s390_get_frame_info (test_function_start, &fextra_info, fi, 1);
+         loop_cnt++;
+         test_function_start -= 2;
+         function_end = s390_check_function_end (test_function_start);
+       }
+      while (!(function_end == 1 || err || loop_cnt >= 4096 ||
+              (fextra_info.good_prologue)));
+      if (fextra_info.good_prologue)
+       function_start = fextra_info.function_start;
+      else if (function_end == 1)
+       function_start = test_function_start;
+    }
+  return function_start;
+}
+
+
+
+CORE_ADDR
+s390_function_start (struct frame_info *fi)
+{
+  CORE_ADDR function_start = 0;
+
+  if (fi->extra_info && fi->extra_info->initialised)
+    function_start = fi->extra_info->function_start;
+  else if (fi->pc)
+    function_start = get_pc_function_start (fi->pc);
+  return function_start;
+}
+
+
+
+
+int
+s390_frameless_function_invocation (struct frame_info *fi)
+{
+  struct frame_extra_info fextra_info, *fextra_info_ptr;
+  int frameless = 0;
+
+  if (fi->next == NULL)                /* no may be frameless */
+    {
+      if (fi->extra_info)
+       fextra_info_ptr = fi->extra_info;
+      else
+       {
+         fextra_info_ptr = &fextra_info;
+         s390_get_frame_info (s390_sniff_pc_function_start (fi->pc, fi),
+                              fextra_info_ptr, fi, 1);
+       }
+      frameless = ((fextra_info_ptr->stack_bought == 0));
+    }
+  return frameless;
+
+}
+
+
+static int
+s390_is_sigreturn (CORE_ADDR pc, struct frame_info *sighandler_fi,
+                  CORE_ADDR *sregs, CORE_ADDR *sigcaller_pc)
+{
+  bfd_byte instr[S390_MAX_INSTR_SIZE];
+  disassemble_info info;
+  int instrlen;
+  CORE_ADDR scontext;
+  int retval = 0;
+  CORE_ADDR orig_sp;
+  CORE_ADDR temp_sregs;
+
+  scontext = temp_sregs = 0;
+
+  info.read_memory_func = dis_asm_read_memory;
+  instrlen = s390_readinstruction (instr, pc, &info);
+  if (sigcaller_pc)
+    *sigcaller_pc = 0;
+  if (((instrlen == S390_SYSCALL_SIZE) &&
+       (instr[0] == S390_SYSCALL_OPCODE)) &&
+      ((instr[1] == s390_NR_sigreturn) || (instr[1] == s390_NR_rt_sigreturn)))
+    {
+      if (sighandler_fi)
+       {
+         if (s390_frameless_function_invocation (sighandler_fi))
+           orig_sp = sighandler_fi->frame;
+         else
+           orig_sp = ADDR_BITS_REMOVE ((CORE_ADDR)
+                                       read_memory_integer (sighandler_fi->
+                                                            frame,
+                                                            S390_GPR_SIZE));
+         if (orig_sp && sigcaller_pc)
+           {
+             scontext = orig_sp + S390_SIGNAL_FRAMESIZE;
+             if (pc == scontext && instr[1] == s390_NR_rt_sigreturn)
+               {
+                 /* We got a new style rt_signal */
+                 /* get address of read ucontext->uc_mcontext */
+                 temp_sregs = orig_sp + (GDB_TARGET_IS_ESAME ?
+                                         S390X_UC_MCONTEXT_OFFSET :
+                                         S390_UC_MCONTEXT_OFFSET);
+               }
+             else
+               {
+                 /* read sigcontext->sregs */
+                 temp_sregs = ADDR_BITS_REMOVE ((CORE_ADDR)
+                                                read_memory_integer (scontext
+                                                                     +
+                                                                     (GDB_TARGET_IS_ESAME
+                                                                      ?
+                                                                      S390X_SIGCONTEXT_SREGS_OFFSET
+                                                                      :
+                                                                      S390_SIGCONTEXT_SREGS_OFFSET),
+                                                                     S390_GPR_SIZE));
+
+               }
+             /* read sigregs->psw.addr */
+             *sigcaller_pc =
+               ADDR_BITS_REMOVE ((CORE_ADDR)
+                                 read_memory_integer (temp_sregs +
+                                                      REGISTER_BYTE
+                                                      (S390_PC_REGNUM),
+                                                      S390_PSW_ADDR_SIZE));
+           }
+       }
+      retval = 1;
+    }
+  if (sregs)
+    *sregs = temp_sregs;
+  return retval;
+}
+
+/*
+  We need to do something better here but this will keep us out of trouble
+  for the moment.
+  For some reason the blockframe.c calls us with fi->next->fromleaf
+  so this seems of little use to us. */
+void
+s390_init_frame_pc_first (int next_fromleaf, struct frame_info *fi)
+{
+  CORE_ADDR sigcaller_pc;
+
+  fi->pc = 0;
+  if (next_fromleaf)
+    {
+      fi->pc = ADDR_BITS_REMOVE (read_register (S390_RETADDR_REGNUM));
+      /* fix signal handlers */
+    }
+  else if (fi->next && fi->next->pc)
+    fi->pc = s390_frame_saved_pc_nofix (fi->next);
+  if (fi->pc && fi->next && fi->next->frame &&
+      s390_is_sigreturn (fi->pc, fi->next, NULL, &sigcaller_pc))
+    {
+      fi->pc = sigcaller_pc;
+    }
+
+}
+
+void
+s390_init_extra_frame_info (int fromleaf, struct frame_info *fi)
+{
+  fi->extra_info = frame_obstack_alloc (sizeof (struct frame_extra_info));
+  if (fi->pc)
+    s390_get_frame_info (s390_sniff_pc_function_start (fi->pc, fi),
+                        fi->extra_info, fi, 1);
+  else
+    s390_memset_extra_info (fi->extra_info);
+}
+
+/* If saved registers of frame FI are not known yet, read and cache them.
+   &FEXTRA_INFOP contains struct frame_extra_info; TDATAP can be NULL,
+   in which case the framedata are read.  */
+
+void
+s390_frame_init_saved_regs (struct frame_info *fi)
+{
+
+  int quick;
+
+  if (fi->saved_regs == NULL)
+    {
+      /* zalloc memsets the saved regs */
+      frame_saved_regs_zalloc (fi);
+      if (fi->pc)
+       {
+         quick = (fi->extra_info && fi->extra_info->initialised
+                  && fi->extra_info->good_prologue);
+         s390_get_frame_info (quick ? fi->extra_info->function_start :
+                              s390_sniff_pc_function_start (fi->pc, fi),
+                              fi->extra_info, fi, !quick);
+       }
+    }
+}
+
+
+
+CORE_ADDR
+s390_frame_args_address (struct frame_info *fi)
+{
+
+  /* Apparently gdb already knows gdb_args_offset itself */
+  return fi->frame;
+}
+
+
+static CORE_ADDR
+s390_frame_saved_pc_nofix (struct frame_info *fi)
+{
+  if (fi->extra_info && fi->extra_info->saved_pc_valid)
+    return fi->extra_info->saved_pc;
+  s390_frame_init_saved_regs (fi);
+  if (fi->extra_info)
+    {
+      fi->extra_info->saved_pc_valid = 1;
+      if (fi->extra_info->good_prologue)
+       {
+         if (fi->saved_regs[S390_RETADDR_REGNUM])
+           {
+             return (fi->extra_info->saved_pc =
+                     ADDR_BITS_REMOVE (read_memory_integer
+                                       (fi->saved_regs[S390_RETADDR_REGNUM],
+                                        S390_GPR_SIZE)));
+           }
+       }
+    }
+  return 0;
+}
+
+CORE_ADDR
+s390_frame_saved_pc (struct frame_info *fi)
+{
+  CORE_ADDR saved_pc = 0, sig_pc;
+
+  if (fi->extra_info && fi->extra_info->sig_fixed_saved_pc_valid)
+    return fi->extra_info->sig_fixed_saved_pc;
+  saved_pc = s390_frame_saved_pc_nofix (fi);
+
+  if (fi->extra_info)
+    {
+      fi->extra_info->sig_fixed_saved_pc_valid = 1;
+      if (saved_pc)
+       {
+         if (s390_is_sigreturn (saved_pc, fi, NULL, &sig_pc))
+           saved_pc = sig_pc;
+       }
+      fi->extra_info->sig_fixed_saved_pc = saved_pc;
+    }
+  return saved_pc;
+}
+
+
+
+
+/* We want backtraces out of signal handlers so we don't
+   set thisframe->signal_handler_caller to 1 */
+
+CORE_ADDR
+s390_frame_chain (struct frame_info *thisframe)
+{
+  CORE_ADDR prev_fp = 0;
+
+  if (thisframe->prev && thisframe->prev->frame)
+    prev_fp = thisframe->prev->frame;
+  else
+    {
+      int sigreturn = 0;
+      CORE_ADDR sregs = 0;
+      struct frame_extra_info prev_fextra_info;
+
+      memset (&prev_fextra_info, 0, sizeof (prev_fextra_info));
+      if (thisframe->pc)
+       {
+         CORE_ADDR saved_pc, sig_pc;
+
+         saved_pc = s390_frame_saved_pc_nofix (thisframe);
+         if (saved_pc)
+           {
+             if ((sigreturn =
+                  s390_is_sigreturn (saved_pc, thisframe, &sregs, &sig_pc)))
+               saved_pc = sig_pc;
+             s390_get_frame_info (s390_sniff_pc_function_start
+                                  (saved_pc, NULL), &prev_fextra_info, NULL,
+                                  1);
+           }
+       }
+      if (sigreturn)
+       {
+         /* read sigregs,regs.gprs[11 or 15] */
+         prev_fp = read_memory_integer (sregs +
+                                        REGISTER_BYTE (S390_GP0_REGNUM +
+                                                       (prev_fextra_info.
+                                                        frame_pointer_saved_pc
+                                                        ? 11 : 15)),
+                                        S390_GPR_SIZE);
+         thisframe->extra_info->sigcontext = sregs;
+       }
+      else
+       {
+         if (thisframe->saved_regs)
+           {
+
+             int regno;
+
+             regno =
+               ((prev_fextra_info.frame_pointer_saved_pc
+                 && thisframe->
+                 saved_regs[S390_FRAME_REGNUM]) ? S390_FRAME_REGNUM :
+                S390_SP_REGNUM);
+             if (thisframe->saved_regs[regno])
+               prev_fp =
+                 read_memory_integer (thisframe->saved_regs[regno],
+                                      S390_GPR_SIZE);
+           }
+       }
+    }
+  return ADDR_BITS_REMOVE (prev_fp);
+}
+
+/*
+  Whether struct frame_extra_info is actually needed I'll have to figure
+  out as our frames are similar to rs6000 there is a possibility
+  i386 dosen't need it. */
+
+
+
+/* a given return value in `regbuf' with a type `valtype', extract and copy its
+   value into `valbuf' */
+void
+s390_extract_return_value (struct type *valtype, char *regbuf, char *valbuf)
+{
+  /* floats and doubles are returned in fpr0. fpr's have a size of 8 bytes.
+     We need to truncate the return value into float size (4 byte) if
+     necessary. */
+  int len = TYPE_LENGTH (valtype);
+
+  if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
+    {
+      if (len > (TARGET_FLOAT_BIT >> 3))
+       memcpy (valbuf, &regbuf[REGISTER_BYTE (S390_FP0_REGNUM)], len);
+      else
+       {
+         /* float */
+         DOUBLEST val;
+
+         floatformat_to_doublest (&floatformat_ieee_double_big,
+                                  &regbuf[REGISTER_BYTE (S390_FP0_REGNUM)],
+                                  &val);
+         store_floating (valbuf, len, val);
+       }
+    }
+  else
+    {
+      int offset = 0;
+      /* return value is copied starting from r2. */
+      if (TYPE_LENGTH (valtype) < S390_GPR_SIZE)
+       offset = S390_GPR_SIZE - TYPE_LENGTH (valtype);
+      memcpy (valbuf,
+             regbuf + REGISTER_BYTE (S390_GP0_REGNUM + 2) + offset,
+             TYPE_LENGTH (valtype));
+    }
+}
+
+
+static char *
+s390_promote_integer_argument (struct type *valtype, char *valbuf,
+                              char *reg_buff, int *arglen)
+{
+  char *value = valbuf;
+  int len = TYPE_LENGTH (valtype);
+
+  if (len < S390_GPR_SIZE)
+    {
+      /* We need to upgrade this value to a register to pass it correctly */
+      int idx, diff = S390_GPR_SIZE - len, negative =
+       (!TYPE_UNSIGNED (valtype) && value[0] & 0x80);
+      for (idx = 0; idx < S390_GPR_SIZE; idx++)
+       {
+         reg_buff[idx] = (idx < diff ? (negative ? 0xff : 0x0) :
+                          value[idx - diff]);
+       }
+      value = reg_buff;
+      *arglen = S390_GPR_SIZE;
+    }
+  else
+    {
+      if (len & (S390_GPR_SIZE - 1))
+       {
+         fprintf_unfiltered (gdb_stderr,
+                             "s390_promote_integer_argument detected an argument not "
+                             "a multiple of S390_GPR_SIZE & greater than S390_GPR_SIZE "
+                             "we might not deal with this correctly.\n");
+       }
+      *arglen = len;
+    }
+
+  return (value);
+}
+
+void
+s390_store_return_value (struct type *valtype, char *valbuf)
+{
+  int arglen;
+  char *reg_buff = alloca (max (S390_FPR_SIZE, REGISTER_SIZE)), *value;
+
+  if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
+    {
+      DOUBLEST tempfloat = extract_floating (valbuf, TYPE_LENGTH (valtype));
+
+      floatformat_from_doublest (&floatformat_ieee_double_big, &tempfloat,
+                                reg_buff);
+      write_register_bytes (REGISTER_BYTE (S390_FP0_REGNUM), reg_buff,
+                           S390_FPR_SIZE);
+    }
+  else
+    {
+      value =
+       s390_promote_integer_argument (valtype, valbuf, reg_buff, &arglen);
+      /* Everything else is returned in GPR2 and up. */
+      write_register_bytes (REGISTER_BYTE (S390_GP0_REGNUM + 2), value,
+                           arglen);
+    }
+}
+static int
+gdb_print_insn_s390 (bfd_vma memaddr, disassemble_info * info)
+{
+  bfd_byte instrbuff[S390_MAX_INSTR_SIZE];
+  int instrlen, cnt;
+
+  instrlen = s390_readinstruction (instrbuff, (CORE_ADDR) memaddr, info);
+  if (instrlen < 0)
+    {
+      (*info->memory_error_func) (instrlen, memaddr, info);
+      return -1;
+    }
+  for (cnt = 0; cnt < instrlen; cnt++)
+    info->fprintf_func (info->stream, "%02X ", instrbuff[cnt]);
+  for (cnt = instrlen; cnt < S390_MAX_INSTR_SIZE; cnt++)
+    info->fprintf_func (info->stream, "   ");
+  instrlen = print_insn_s390 (memaddr, info);
+  return instrlen;
+}
+
+
+
+/* Not the most efficent code in the world */
+int
+s390_fp_regnum ()
+{
+  int regno = S390_SP_REGNUM;
+  struct frame_extra_info fextra_info;
+
+  CORE_ADDR pc = ADDR_BITS_REMOVE (read_register (S390_PC_REGNUM));
+
+  s390_get_frame_info (s390_sniff_pc_function_start (pc, NULL), &fextra_info,
+                      NULL, 1);
+  if (fextra_info.frame_pointer_saved_pc)
+    regno = S390_FRAME_REGNUM;
+  return regno;
+}
+
+CORE_ADDR
+s390_read_fp ()
+{
+  return read_register (s390_fp_regnum ());
+}
+
+
+void
+s390_write_fp (CORE_ADDR val)
+{
+  write_register (s390_fp_regnum (), val);
+}
+
+
+void
+s390_push_dummy_frame ()
+{
+  CORE_ADDR orig_sp = read_register (S390_SP_REGNUM), new_sp;
+  void *saved_regs = alloca (REGISTER_BYTES);
+
+  new_sp = (orig_sp - (REGISTER_BYTES + S390_GPR_SIZE));
+  read_register_bytes (0, (char *) saved_regs, REGISTER_BYTES);
+  /* Use saved copy instead of orig_sp as this will have the correct endianness */
+  write_memory (new_sp, (char *) saved_regs + REGISTER_BYTE (S390_SP_REGNUM),
+               S390_GPR_SIZE);
+  write_memory (new_sp + S390_GPR_SIZE, (char *) &saved_regs, REGISTER_BYTES);
+  write_register (S390_SP_REGNUM, new_sp);
+}
+
+/* pop the innermost frame, go back to the caller.
+    Used in `call_function_by_hand' to remove an artificial stack
+     frame.  */
+void
+s390_pop_frame ()
+{
+  CORE_ADDR new_sp = read_register (S390_SP_REGNUM), orig_sp;
+  void *saved_regs = alloca (REGISTER_BYTES);
+
+
+  read_memory (new_sp + S390_GPR_SIZE, (char *) saved_regs, REGISTER_BYTES);
+  write_register_bytes (0, (char *) &saved_regs, REGISTER_BYTES);
+}
+
+/* used by call function by hand
+  struct_return indicates that this function returns a structure &
+  therefore gpr2 stores a pointer to the structure to be returned as
+  opposed to the first argument.
+  Currently I haven't seen a TYPE_CODE_INT whose size wasn't 2^n or less
+  than S390_GPR_SIZE this is good because I don't seem to have to worry
+  about sign extending pushed arguments (i.e. a signed char currently
+  comes into this code with a size of 4 ). */
+
+CORE_ADDR
+s390_push_arguments (int nargs, value_ptr *args, CORE_ADDR sp,
+                    int struct_return, CORE_ADDR struct_addr)
+{
+  int num_float_args, num_gpr_args, orig_num_gpr_args, argno;
+  int second_pass, len, arglen, gprs_required;
+  CORE_ADDR outgoing_args_ptr, outgoing_args_space;
+  value_ptr arg;
+  struct type *type;
+  int max_num_gpr_args = 5 - (struct_return ? 1 : 0);
+  int arg0_regnum = S390_GP0_REGNUM + 2 + (struct_return ? 1 : 0);
+  char *reg_buff = alloca (max (S390_FPR_SIZE, REGISTER_SIZE)), *value;
+
+  for (second_pass = 0; second_pass <= 1; second_pass++)
+    {
+      if (second_pass)
+       outgoing_args_ptr = sp + S390_STACK_FRAME_OVERHEAD;
+      else
+       outgoing_args_ptr = 0;
+      num_float_args = 0;
+      num_gpr_args = 0;
+      for (argno = 0; argno < nargs; argno++)
+       {
+         arg = args[argno];
+         type = check_typedef (VALUE_TYPE (arg));
+         len = TYPE_LENGTH (type);
+         if (TYPE_CODE (type) == TYPE_CODE_FLT)
+           {
+             int all_float_registers_used =
+               num_float_args > (GDB_TARGET_IS_ESAME ? 3 : 1);
+
+             if (second_pass)
+               {
+                 DOUBLEST tempfloat =
+                   extract_floating (VALUE_CONTENTS (arg), len);
+
+
+                 floatformat_from_doublest (all_float_registers_used &&
+                                            len == (TARGET_FLOAT_BIT >> 3)
+                                            ? &floatformat_ieee_single_big
+                                            : &floatformat_ieee_double_big,
+                                            &tempfloat, reg_buff);
+                 if (all_float_registers_used)
+                   write_memory (outgoing_args_ptr, reg_buff, len);
+                 else
+                   write_register_bytes (REGISTER_BYTE ((S390_FP0_REGNUM)
+                                                        +
+                                                        (2 *
+                                                         num_float_args)),
+                                         reg_buff, S390_FPR_SIZE);
+               }
+             if (all_float_registers_used)
+               outgoing_args_ptr += len;
+             num_float_args++;
+           }
+         else
+           {
+             gprs_required = ((len + (S390_GPR_SIZE - 1)) / S390_GPR_SIZE);
+
+             value =
+               s390_promote_integer_argument (type, VALUE_CONTENTS (arg),
+                                              reg_buff, &arglen);
+
+             orig_num_gpr_args = num_gpr_args;
+             num_gpr_args += gprs_required;
+             if (num_gpr_args > max_num_gpr_args)
+               {
+                 if (second_pass)
+                   write_memory (outgoing_args_ptr, value, arglen);
+                 outgoing_args_ptr += arglen;
+               }
+             else
+               {
+                 if (second_pass)
+                   write_register_bytes (REGISTER_BYTE (arg0_regnum)
+                                         +
+                                         (orig_num_gpr_args * S390_GPR_SIZE),
+                                         value, arglen);
+               }
+           }
+       }
+      if (!second_pass)
+       {
+         outgoing_args_space = outgoing_args_ptr;
+         /* Align to 16 bytes because because I like alignment & 
+            some of the kernel code requires 8 byte stack alignment at least. */
+         sp = (sp - (S390_STACK_FRAME_OVERHEAD + outgoing_args_ptr)) & (-16);
+       }
+
+    }
+  return sp;
+
+}
+
+void
+s390_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
+                    struct value **args, struct type *value_type,
+                    int using_gcc)
+{
+  store_unsigned_integer (dummy + 4, REGISTER_SIZE, fun);
+}
+
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+struct type *
+s390_register_virtual_type (int regno)
+{
+  return ((unsigned) regno - S390_FPC_REGNUM) <
+    S390_NUM_FPRS ? builtin_type_double : builtin_type_int;
+}
+
+
+struct type *
+s390x_register_virtual_type (int regno)
+{
+  return (regno == S390_FPC_REGNUM) ||
+    (regno >= S390_FIRST_ACR && regno <= S390_LAST_ACR) ? builtin_type_int :
+    (regno >= S390_FP0_REGNUM) ? builtin_type_double : builtin_type_long;
+}
+
+
+
+void
+s390_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
+{
+  write_register (S390_GP0_REGNUM + 2, addr);
+}
+
+
+
+static unsigned char *
+s390_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
+{
+  static unsigned char breakpoint[] = { 0x0, 0x1 };
+
+  *lenptr = sizeof (breakpoint);
+  return breakpoint;
+}
+
+/* Advance PC across any function entry prologue instructions to reach some
+   "real" code.  */
+CORE_ADDR
+s390_skip_prologue (CORE_ADDR pc)
+{
+  struct frame_extra_info fextra_info;
+
+  s390_get_frame_info (pc, &fextra_info, NULL, 1);
+  return fextra_info.skip_prologue_function_start;
+}
+
+/* pc_in_call_dummy_on stack may work for us must test this */
+int
+s390_pc_in_call_dummy (CORE_ADDR pc, CORE_ADDR sp, CORE_ADDR frame_address)
+{
+  return pc > sp && pc < (sp + 4096);
+}
+
+/* Immediately after a function call, return the saved pc.
+   Can't go through the frames for this because on some machines
+   the new frame is not set up until the new function executes
+   some instructions.  */
+CORE_ADDR
+s390_saved_pc_after_call (struct frame_info *frame)
+{
+  return ADDR_BITS_REMOVE (read_register (S390_RETADDR_REGNUM));
+}
+
+static CORE_ADDR
+s390_addr_bits_remove (CORE_ADDR addr)
+{
+  return (addr) & 0x7fffffff;
+}
+
+
+static CORE_ADDR
+s390_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
+{
+  return sp;
+}
+
+struct gdbarch *
+s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+
+  /* instruction sequence for s390 call dummy is as follows
+     bras %r1,.+8      ; 0xA7150004   
+     long basraddr     ; 0x00000000
+     l    %r1,0(%r1)   ; 0x58101000
+     basr %r14,%r1     ; 0x0DE1
+     breakpoint        ; 0x0001 */
+  static LONGEST s390_call_dummy_words[] = { 0xA7150004, 0x00000000,
+    0x58101000, 0x0DE10001
+  };
+  /* instruction sequence for esame call dummy is as follows
+     bras %r1,.+12     ; 0xA7150006   
+     long basraddr     ; 0x0000000000000000
+     lg   %r1,0(%r1)   ; 0xE31010000004
+     basr %r14,%r1     ; 0x0DE1
+     breakpoint        ; 0x0001 */
+  static LONGEST s390x_call_dummy_words[] = { 0xA715000600000000,
+    0x00000000E3101000,
+    0x00040DE100010000
+  };
+  struct gdbarch *gdbarch;
+  struct gdbarch_tdep *tdep;
+  int elf_flags;
+
+  /* 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;
+
+  /* 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.  */
+
+  /* Yes: create a new gdbarch for the specified machine type.  */
+  gdbarch = gdbarch_alloc (&info, NULL);
+
+  set_gdbarch_believe_pcc_promotion (gdbarch, 0);
+
+  /* We don't define set_gdbarch_call_dummy_breakpoint_offset 
+     as we already have a breakpoint inserted. */
+  set_gdbarch_use_generic_dummy_frames (gdbarch, 0);
+
+  set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
+  set_gdbarch_call_dummy_start_offset (gdbarch, 0);
+  set_gdbarch_pc_in_call_dummy (gdbarch, s390_pc_in_call_dummy);
+  set_gdbarch_frame_args_skip (gdbarch, 0);
+  set_gdbarch_frame_args_address (gdbarch, s390_frame_args_address);
+  set_gdbarch_frame_chain (gdbarch, s390_frame_chain);
+  set_gdbarch_frame_init_saved_regs (gdbarch, s390_frame_init_saved_regs);
+  set_gdbarch_frame_locals_address (gdbarch, s390_frame_args_address);
+  /* We can't do this */
+  set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
+  set_gdbarch_store_struct_return (gdbarch, s390_store_struct_return);
+  set_gdbarch_extract_return_value (gdbarch, s390_extract_return_value);
+  set_gdbarch_store_return_value (gdbarch, s390_store_return_value);
+  /* Amount PC must be decremented by after a breakpoint.
+     This is often the number of bytes in BREAKPOINT
+     but not always.  */
+  set_gdbarch_decr_pc_after_break (gdbarch, 2);
+  set_gdbarch_pop_frame (gdbarch, s390_pop_frame);
+  set_gdbarch_push_dummy_frame (gdbarch, s390_push_dummy_frame);
+  set_gdbarch_push_arguments (gdbarch, s390_push_arguments);
+  set_gdbarch_ieee_float (gdbarch, 1);
+  /* Stack grows downward.  */
+  set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+  /* Offset from address of function to start of its code.
+     Zero on most machines.  */
+  set_gdbarch_function_start_offset (gdbarch, 0);
+  set_gdbarch_max_register_raw_size (gdbarch, 8);
+  set_gdbarch_max_register_virtual_size (gdbarch, 8);
+  set_gdbarch_breakpoint_from_pc (gdbarch, s390_breakpoint_from_pc);
+  set_gdbarch_skip_prologue (gdbarch, s390_skip_prologue);
+  set_gdbarch_init_extra_frame_info (gdbarch, s390_init_extra_frame_info);
+  set_gdbarch_init_frame_pc_first (gdbarch, s390_init_frame_pc_first);
+  set_gdbarch_read_fp (gdbarch, s390_read_fp);
+  set_gdbarch_write_fp (gdbarch, s390_write_fp);
+  /* This function that tells us whether the function invocation represented
+     by FI does not have a frame on the stack associated with it.  If it
+     does not, FRAMELESS is set to 1, else 0.  */
+  set_gdbarch_frameless_function_invocation (gdbarch,
+                                            s390_frameless_function_invocation);
+  /* Return saved PC from a frame */
+  set_gdbarch_frame_saved_pc (gdbarch, s390_frame_saved_pc);
+  /* FRAME_CHAIN takes a frame's nominal address
+     and produces the frame's chain-pointer. */
+  set_gdbarch_frame_chain (gdbarch, s390_frame_chain);
+  set_gdbarch_saved_pc_after_call (gdbarch, s390_saved_pc_after_call);
+  set_gdbarch_register_byte (gdbarch, s390_register_byte);
+  set_gdbarch_pc_regnum (gdbarch, S390_PC_REGNUM);
+  set_gdbarch_sp_regnum (gdbarch, S390_SP_REGNUM);
+  set_gdbarch_fp_regnum (gdbarch, S390_FP_REGNUM);
+  set_gdbarch_fp0_regnum (gdbarch, S390_FP0_REGNUM);
+  set_gdbarch_num_regs (gdbarch, S390_NUM_REGS);
+  set_gdbarch_cannot_fetch_register (gdbarch, s390_cannot_fetch_register);
+  set_gdbarch_cannot_store_register (gdbarch, s390_cannot_fetch_register);
+  set_gdbarch_get_saved_register (gdbarch, generic_get_saved_register);
+  set_gdbarch_use_struct_convention (gdbarch, generic_use_struct_convention);
+  set_gdbarch_frame_chain_valid (gdbarch, file_frame_chain_valid);
+  set_gdbarch_register_name (gdbarch, s390_register_name);
+  set_gdbarch_stab_reg_to_regnum (gdbarch, s390_stab_reg_to_regnum);
+  set_gdbarch_dwarf_reg_to_regnum (gdbarch, s390_stab_reg_to_regnum);
+  set_gdbarch_dwarf2_reg_to_regnum (gdbarch, s390_stab_reg_to_regnum);
+  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
+
+  /* Stuff below here wouldn't be required if gdbarch.sh was a little */
+  /* more intelligent */
+  set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 0);
+  set_gdbarch_call_dummy_p (gdbarch, 1);
+  set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
+  set_gdbarch_extract_struct_value_address (gdbarch, 0);
+  set_gdbarch_fix_call_dummy (gdbarch, s390_fix_call_dummy);
+#ifdef GDB_NM_FILE
+  set_gdbarch_prepare_to_proceed (gdbarch, linuxthreads_prepare_to_proceed);
+#endif
+  set_gdbarch_push_return_address (gdbarch, s390_push_return_address);
+
+  switch (info.bfd_arch_info->mach)
+    {
+    case bfd_mach_s390_esa:
+      set_gdbarch_register_size (gdbarch, 4);
+      set_gdbarch_call_dummy_length (gdbarch, 16);
+      set_gdbarch_register_raw_size (gdbarch, s390_register_raw_size);
+      set_gdbarch_register_virtual_size (gdbarch, s390_register_raw_size);
+      set_gdbarch_register_virtual_type (gdbarch, s390_register_virtual_type);
+
+      set_gdbarch_addr_bits_remove (gdbarch, s390_addr_bits_remove);
+
+      set_gdbarch_sizeof_call_dummy_words (gdbarch,
+                                          sizeof (s390_call_dummy_words));
+      set_gdbarch_call_dummy_words (gdbarch, s390_call_dummy_words);
+      set_gdbarch_register_bytes (gdbarch, S390_REGISTER_BYTES);
+      break;
+    case bfd_mach_s390_esame:
+      set_gdbarch_register_size (gdbarch, 8);
+      set_gdbarch_call_dummy_length (gdbarch, 22);
+      set_gdbarch_register_raw_size (gdbarch, s390x_register_raw_size);
+      set_gdbarch_register_virtual_size (gdbarch, s390x_register_raw_size);
+      set_gdbarch_register_virtual_type (gdbarch,
+                                        s390x_register_virtual_type);
+
+      set_gdbarch_long_bit (gdbarch, 64);
+      set_gdbarch_long_long_bit (gdbarch, 64);
+      set_gdbarch_ptr_bit (gdbarch, 64);
+      set_gdbarch_sizeof_call_dummy_words (gdbarch,
+                                          sizeof (s390x_call_dummy_words));
+      set_gdbarch_call_dummy_words (gdbarch, s390x_call_dummy_words);
+      set_gdbarch_register_bytes (gdbarch, S390X_REGISTER_BYTES);
+      break;
+    }
+
+  return gdbarch;
+}
+
+
+
+void
+_initialize_s390_tdep ()
+{
+
+  /* Hook us into the gdbarch mechanism.  */
+  register_gdbarch_init (bfd_arch_s390, s390_gdbarch_init);
+  if (!tm_print_insn)          /* Someone may have already set it */
+    tm_print_insn = gdb_print_insn_s390;
+}
+
+#endif /* GDBSERVER */
index abbd7a56c926a0291dcb48a081b4dbd3718c33b6..8a959e5784c1cdaa6e1dbd5de863614a376d40aa 100644 (file)
@@ -24,6 +24,7 @@
 #include "target.h"
 #include <signal.h>
 
+#ifndef GDBSERVER
 /* This table must match in order and size the signals in enum target_signal
    in target.h.  */
 /* *INDENT-OFF* */
@@ -230,13 +231,13 @@ target_signal_from_name (char *name)
 
   /* This ugly cast brought to you by the native VAX compiler.  */
   for (sig = TARGET_SIGNAL_HUP;
-       signals[sig].name != NULL;
-       sig = (enum target_signal) ((int) sig + 1))
+       signals[sig].name != NULL; sig = (enum target_signal) ((int) sig + 1))
     if (STREQ (name, signals[sig].name))
       return sig;
   return TARGET_SIGNAL_UNKNOWN;
 }
-\f
+#endif /* GDBSERVER */
+
 /* The following functions are to help certain targets deal
    with the signal/waitstatus stuff.  They could just as well be in
    a file called native-utils.c or unixwaitstatus-utils.c or whatever.  */
@@ -480,7 +481,8 @@ target_signal_from_host (int hostsig)
        return (enum target_signal)
          (hostsig - 64 + (int) TARGET_SIGNAL_REALTIME_64);
       else
-       error ("GDB bug: target.c (target_signal_from_host): unrecognized real-time signal");
+       error
+         ("GDB bug: target.c (target_signal_from_host): unrecognized real-time signal");
     }
 #endif
 
@@ -494,7 +496,8 @@ target_signal_from_host (int hostsig)
       else if (hostsig == 64)
        return TARGET_SIGNAL_REALTIME_64;
       else
-       error ("GDB bug: target.c (target_signal_from_host): unrecognized real-time signal");
+       error
+         ("GDB bug: target.c (target_signal_from_host): unrecognized real-time signal");
     }
 #endif
   return TARGET_SIGNAL_UNKNOWN;
@@ -506,8 +509,7 @@ target_signal_from_host (int hostsig)
    accordingly. */
 
 static int
-do_target_signal_to_host (enum target_signal oursig,
-                         int *oursig_ok)
+do_target_signal_to_host (enum target_signal oursig, int *oursig_ok)
 {
   *oursig_ok = 1;
   switch (oursig)
@@ -737,9 +739,8 @@ do_target_signal_to_host (enum target_signal oursig,
          && oursig <= TARGET_SIGNAL_REALTIME_63)
        {
          /* This block of signals is continuous, and
-             TARGET_SIGNAL_REALTIME_33 is 33 by definition.  */
-         int retsig =
-           (int) oursig - (int) TARGET_SIGNAL_REALTIME_33 + 33;
+            TARGET_SIGNAL_REALTIME_33 is 33 by definition.  */
+         int retsig = (int) oursig - (int) TARGET_SIGNAL_REALTIME_33 + 33;
          if (retsig >= REALTIME_LO && retsig < REALTIME_HI)
            return retsig;
        }
@@ -747,7 +748,7 @@ do_target_signal_to_host (enum target_signal oursig,
       else if (oursig == TARGET_SIGNAL_REALTIME_32)
        {
          /* TARGET_SIGNAL_REALTIME_32 isn't contiguous with
-             TARGET_SIGNAL_REALTIME_33.  It is 32 by definition.  */
+            TARGET_SIGNAL_REALTIME_33.  It is 32 by definition.  */
          return 32;
        }
 #endif
@@ -756,13 +757,12 @@ do_target_signal_to_host (enum target_signal oursig,
          && oursig <= TARGET_SIGNAL_REALTIME_127)
        {
          /* This block of signals is continuous, and
-             TARGET_SIGNAL_REALTIME_64 is 64 by definition.  */
-         int retsig =
-           (int) oursig - (int) TARGET_SIGNAL_REALTIME_64 + 64;
+            TARGET_SIGNAL_REALTIME_64 is 64 by definition.  */
+         int retsig = (int) oursig - (int) TARGET_SIGNAL_REALTIME_64 + 64;
          if (retsig >= REALTIME_LO && retsig < REALTIME_HI)
            return retsig;
        }
-      
+
 #endif
 #endif
 
@@ -771,9 +771,8 @@ do_target_signal_to_host (enum target_signal oursig,
          && oursig <= TARGET_SIGNAL_REALTIME_63)
        {
          /* This block of signals is continuous, and
-             TARGET_SIGNAL_REALTIME_33 is 33 by definition.  */
-         int retsig =
-           (int) oursig - (int) TARGET_SIGNAL_REALTIME_33 + 33;
+            TARGET_SIGNAL_REALTIME_33 is 33 by definition.  */
+         int retsig = (int) oursig - (int) TARGET_SIGNAL_REALTIME_33 + 33;
          if (retsig >= SIGRTMIN && retsig <= SIGRTMAX)
            return retsig;
        }
@@ -785,6 +784,7 @@ do_target_signal_to_host (enum target_signal oursig,
     }
 }
 
+#ifndef GDBSERVER
 int
 target_signal_to_host_p (enum target_signal oursig)
 {
@@ -792,6 +792,7 @@ target_signal_to_host_p (enum target_signal oursig)
   do_target_signal_to_host (oursig, &oursig_ok);
   return oursig_ok;
 }
+#endif /* GDBSERVER */
 
 int
 target_signal_to_host (enum target_signal oursig)
@@ -802,14 +803,21 @@ target_signal_to_host (enum target_signal oursig)
     {
       /* The user might be trying to do "signal SIGSAK" where this system
          doesn't have SIGSAK.  */
+#ifdef GDBSERVER
+      fprintf (stderr, "Target signal %d does not exist on this system.\n",
+              oursig);
+#else
       warning ("Signal %s does not exist on this system.\n",
               target_signal_to_name (oursig));
+#endif
+
       return 0;
     }
   else
     return targ_signo;
 }
 
+#ifndef GDBSERVER
 /* In some circumstances we allow a command to specify a numeric
    signal.  The idea is to keep these circumstances limited so that
    users (and scripts) develop portable habits.  For comparison,
@@ -833,3 +841,4 @@ _initialize_signals (void)
   if (!STREQ (signals[TARGET_SIGNAL_LAST].string, "TARGET_SIGNAL_MAGIC"))
     internal_error (__FILE__, __LINE__, "failed internal consistency check");
 }
+#endif /* GDBSERVER */