s390-protos.h (s390_emit_tpf_eh_return): Add prototype.
authorP.J. Darcy <darcypj@us.ibm.com>
Wed, 22 Sep 2004 13:57:40 +0000 (13:57 +0000)
committerUlrich Weigand <uweigand@gcc.gnu.org>
Wed, 22 Sep 2004 13:57:40 +0000 (13:57 +0000)
2004-09-22  P.J. Darcy  <darcypj@us.ibm.com>

* config/s390/s390-protos.h (s390_emit_tpf_eh_return): Add prototype.
* config/s390/s390.c (s390_emit_tpf_eh_return): New function.
* config/s390/s390.h (TARGET_TPF): New macro.
* config/s390/s390.md ("eh_return"): New expander.
* config/s390/t-tpf (LIB2ADDEH): Use unwind-dw2-fde.c rather than
unwind-dw2-fde-glibc.c.  Add config/s390/tpf-eh.c.
(LIB2ADDEHDEP): Remove unwind-dw2-fde.c.
* config/s390/tpf.h (TARGET_TPF): Define to 1.
(STACK_POINTER_OFFSET): Increase to 448.
(TARGET_DEFAULT): Set -mtpf-trace on as default.
(TPF_LOC_DIFF_OFFSET): New macro.
(ASM_PREFERRED_EH_DATA_FORMAT): Redefine to always use absolute
encoding.
(__isPATrange): Add prototype.
(MD_FALLBACK_FRAME_STATE_FOR): Define.
* config/s390/tpf-eh.c: New file.

From-SVN: r87857

gcc/ChangeLog
gcc/config/s390/s390-protos.h
gcc/config/s390/s390.c
gcc/config/s390/s390.h
gcc/config/s390/s390.md
gcc/config/s390/t-tpf
gcc/config/s390/tpf-eh.c [new file with mode: 0644]
gcc/config/s390/tpf.h

index 115f39bd7a4c64a0c69c6e33eb13c680a0578756..1a95e0446a3063e064cb9ca7165f8ffc046da6d6 100644 (file)
@@ -1,3 +1,22 @@
+2004-09-22  P.J. Darcy  <darcypj@us.ibm.com>
+
+       * config/s390/s390-protos.h (s390_emit_tpf_eh_return): Add prototype.
+       * config/s390/s390.c (s390_emit_tpf_eh_return): New function.
+       * config/s390/s390.h (TARGET_TPF): New macro.
+       * config/s390/s390.md ("eh_return"): New expander.
+       * config/s390/t-tpf (LIB2ADDEH): Use unwind-dw2-fde.c rather than
+       unwind-dw2-fde-glibc.c.  Add config/s390/tpf-eh.c.
+       (LIB2ADDEHDEP): Remove unwind-dw2-fde.c.
+       * config/s390/tpf.h (TARGET_TPF): Define to 1.
+       (STACK_POINTER_OFFSET): Increase to 448.
+       (TARGET_DEFAULT): Set -mtpf-trace on as default.
+       (TPF_LOC_DIFF_OFFSET): New macro.
+       (ASM_PREFERRED_EH_DATA_FORMAT): Redefine to always use absolute
+       encoding.
+       (__isPATrange): Add prototype.
+       (MD_FALLBACK_FRAME_STATE_FOR): Define.
+       * config/s390/tpf-eh.c: New file.
+
 2004-09-22  Diego Novillo  <dnovillo@redhat.com>
 
        * fold-const.c (fold): Avoid non INTEGER_TYPEs when widening
index 6f05d80d545ba8516144b7a98ea64600923e838c..8b5a263d98bffd67ec707f9879b0d9ce1c0ab970 100644 (file)
@@ -95,6 +95,7 @@ extern rtx s390_gen_rtx_const_DI (int, int);
 extern void s390_output_dwarf_dtprel (FILE*, int, rtx);
 extern int s390_agen_dep_p (rtx, rtx);
 extern rtx s390_load_got (void);
+extern void s390_emit_tpf_eh_return (rtx);
 
 #endif /* RTX_CODE */
 
index 124f4e54df95166144b3c6e285b59d0096d074cc..5d838ef715c256ae85768c9857d0031af1799b6a 100644 (file)
@@ -8017,5 +8017,25 @@ s390_conditional_register_usage (void)
     }
 }
 
+/* Corresponding function to eh_return expander.  */
+
+static GTY(()) rtx s390_tpf_eh_return_symbol;
+void
+s390_emit_tpf_eh_return (rtx target)
+{
+  rtx insn, reg;
+
+  if (!s390_tpf_eh_return_symbol)
+    s390_tpf_eh_return_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tpf_eh_return");
+
+  reg = gen_rtx_REG (Pmode, 2);
+
+  emit_move_insn (reg, target);
+  insn = s390_emit_call (s390_tpf_eh_return_symbol, NULL_RTX, reg,
+                                     gen_rtx_REG (Pmode, RETURN_REGNUM));
+  use_reg (&CALL_INSN_FUNCTION_USAGE (insn), reg);
+
+  emit_move_insn (EH_RETURN_HANDLER_RTX, reg);
+}
 
 #include "gt-s390.h"
index f361ce4d37409e060f50e341ef865f103bb6af0b..5b083aadbe67c67dcd1d5ea2f8e378040dabea4b 100644 (file)
@@ -80,6 +80,9 @@ extern const char *s390_stack_guard_string;
 
 /* Run-time target specification.  */
 
+/* This will be overridden by OS headers.  */
+#define TARGET_TPF 0
+
 /* Target CPU builtins.  */
 #define TARGET_CPU_CPP_BUILTINS()                      \
   do                                                   \
index 5ca28b5e5c2f5eefc683218fcf3023e94eeb5725..8c65145f41924caa7176025c55c5f79d95a9e234 100644 (file)
                         GEN_INT (0x7fffffff)));
   DONE;
 })
+
+;; Instruction definition to expand eh_return macro to support
+;; swapping in special linkage return addresses.
+
+(define_expand "eh_return"
+  [(use (match_operand 0 "register_operand" ""))]
+  "TARGET_TPF"
+{
+  s390_emit_tpf_eh_return (operands[0]);
+  DONE;
+})
+
index 2a3421c479d28f6db9fc0f1255f8b7be1f6d7368..76d2c23a8b0755837c1650712c8e6422f168f0de 100644 (file)
@@ -7,7 +7,8 @@ TARGET_LIBGCC2_CFLAGS = -fPIC
 # the symbol versions that glibc used.
 SHLIB_MAPFILES += $(srcdir)/config/s390/libgcc-glibc.ver
 
-# Use unwind-dw2-fde-glibc
-LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-glibc.c \
-  $(srcdir)/unwind-sjlj.c $(srcdir)/gthr-gnat.c $(srcdir)/unwind-c.c
-LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h unwind-dw2-fde.c
+# Use unwind-dw2-fde and extra tpf-eh support routines.
+LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \
+  $(srcdir)/unwind-sjlj.c $(srcdir)/gthr-gnat.c $(srcdir)/unwind-c.c \
+  $(srcdir)/config/s390/tpf-eh.c
+LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h
diff --git a/gcc/config/s390/tpf-eh.c b/gcc/config/s390/tpf-eh.c
new file mode 100644 (file)
index 0000000..1ce01ab
--- /dev/null
@@ -0,0 +1,183 @@
+/* Exception handling routines for TPF.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   Contributed by P.J. Darcy (darcypj@us.ibm.com).
+
+   This file is part of GCC.
+
+   GCC 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, or (at your option)
+   any later version.
+
+   In addition to the permissions in the GNU General Public License, the
+   Free Software Foundation gives you unlimited permission to link the
+   compiled version of this file into combinations with other programs,
+   and to distribute those combinations without any restriction coming
+   from the use of this file.  (The General Public License restrictions
+   do apply in other respects; for example, they cover modification of
+   the file, and distribution when not linked into a combined
+   executable.)
+
+   GCC 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 GCC; see the file COPYING.  If not, write to the Free
+   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#define __USE_GNU 1
+#define _GNU_SOURCE
+#include <dlfcn.h>
+#undef __USE_GNU
+#undef _GNU_SOURCE
+
+#define CURRENT_STACK_PTR() \
+  ({ register unsigned long int *stack_ptr asm ("%r15"); stack_ptr; })
+
+#define PREVIOUS_STACK_PTR() \
+  ((unsigned long int *)(*(CURRENT_STACK_PTR())))
+
+#define RA_OFFSET_FROM_START_OF_STACK_FRAME 112
+#define CURRENT_STACK_PTR_OFFSET 120
+#define TPFRA_OFFSET_FROM_START_OF_STACK_FRAME 168
+#define MIN_PATRANGE 0x10000
+#define MAX_PATRANGE 0x800000
+#define INVALID_RETURN 0
+
+/* Function Name: __isPATrange
+   Parameters passed into it:  address to check
+   Return Value: A 1 if address is in pat code "range", 0 if not
+   Description: This function simply checks to see if the address
+   passed to it is in the CP pat code range.  */
+
+unsigned int __isPATrange(void *addr) 
+{
+  if (addr > (void *)MIN_PATRANGE && addr < (void *)MAX_PATRANGE)
+    return 1;
+  else
+    return 0;
+}
+
+/* Function Name: __tpf_eh_return
+   Parameters passed into it: Destination address to jump to.
+   Return Value: Converted Destination address if a Pat Stub exists.
+   Description: This function swaps the uwinding return address
+      with the cp stub code.  The original target return address is
+      then stored into the tpf return address field.  The cp stub
+      code is searched for by climbing back up the stack and
+      comparing the tpf stored return address object address to
+      that of the targets object address.  */
+
+void *__tpf_eh_return (void *target) 
+{
+  Dl_info targetcodeInfo, currentcodeInfo;
+  int retval;
+  void *current, *stackptr;
+  unsigned long int shifter;
+
+  /* Get code info for target return's address.  */
+  retval = dladdr (target, &targetcodeInfo);
+
+  /* Get the return address of the stack frame to be replaced by
+     the exception unwinder.  So that the __cxa_throw return is
+     replaced by the target return.  */
+  current = (void *) *((unsigned long int *)
+                 ((*((unsigned long int *)*(PREVIOUS_STACK_PTR()))) 
+                             + RA_OFFSET_FROM_START_OF_STACK_FRAME));
+
+  /* Ensure the code info is valid (for target).  */
+  if (retval != INVALID_RETURN) 
+    {
+      /* Now check to see if the current RA is a PAT
+         stub return address.  */
+      if ( __isPATrange(current)) 
+        {
+          /* It was!  Then go into the TPF private stack area and fetch
+             the real address.  */
+          current = (void *) *((unsigned long int *) 
+                           ((unsigned long int)*((unsigned long int *)
+                           *(PREVIOUS_STACK_PTR())) 
+                           +TPFRA_OFFSET_FROM_START_OF_STACK_FRAME));
+        }
+
+      /* Get code info for current return address.  */
+      retval = dladdr (current, &currentcodeInfo);
+
+      /* Ensure the code info is valid (for current frame).  */
+      if (retval != INVALID_RETURN) 
+        {
+          /* Get the stack pointer of the stack frame to be replaced by
+             the exception unwinder.  So that we can begin our climb
+             there.  */
+          stackptr = (void *) (*((unsigned long int *)
+                      (*((unsigned long int *)(*(PREVIOUS_STACK_PTR()))))));
+
+          /* Begin looping through stack frames.  Stop if invalid
+             code information is retrieved or if a match between the
+             current stack frame iteration shared object's address 
+             matches that of the target, calculated above.  */
+          while (retval != INVALID_RETURN
+                 && targetcodeInfo.dli_fbase != currentcodeInfo.dli_fbase)
+            {
+              /* Get return address based on our stackptr iterator.  */
+              current = (void *) *((unsigned long int *) 
+                     (stackptr+RA_OFFSET_FROM_START_OF_STACK_FRAME));
+
+              /* Is it a Pat Stub?  */
+              if (__isPATrange (current)) 
+                {
+                  /* Yes it was, get real return address 
+                     in TPF stack area.  */
+                  current = (void *) *((unsigned long int *) 
+                         (stackptr+TPFRA_OFFSET_FROM_START_OF_STACK_FRAME));
+                }
+
+              /* Get codeinfo on RA so that we can figure out
+                 the module address.  */
+              retval = dladdr (current, &currentcodeInfo);
+
+              /* Check that codeinfo for current stack frame is valid.
+                 Then compare the module address of current stack frame
+                 to target stack frame to determine if we have the pat
+                 stub address we want.  */
+              if (retval != INVALID_RETURN
+                  && targetcodeInfo.dli_fbase == currentcodeInfo.dli_fbase)
+                {
+                  /* Yes!  They are in the same module.  Now store the
+                     real target address into the TPF stack area of
+                     the target frame we are jumping to.  */
+                  *((unsigned long int *)(*((unsigned long int *) 
+                          (*PREVIOUS_STACK_PTR() + CURRENT_STACK_PTR_OFFSET))
+                          + TPFRA_OFFSET_FROM_START_OF_STACK_FRAME)) 
+                          = (unsigned long int) target;
+
+                  /* Before returning the desired pat stub address to
+                     the exception handling unwinder so that it can 
+                     actually do the "leap" shift out the low order 
+                     bit designated to determine if we are in 64BIT mode.
+                     This is nececcary for CTOA stubs.
+                     Otherwise we leap one byte past where we want to 
+                     go to in the TPF pat stub linkage code.  */
+                  shifter = *((unsigned long int *) 
+                       (stackptr + RA_OFFSET_FROM_START_OF_STACK_FRAME));
+
+                  shifter &= ~1ul;
+
+                  return (void *) shifter;
+                }
+
+              /* Desired module pat stub not found ...
+                 Bump stack frame iterator.  */
+              stackptr = (void *) *(unsigned long int *) stackptr;
+            }
+        }
+    }
+
+  /* No pat stub found, could be a problem?  Simply return unmodified
+     target address.  */
+  return target;
+}
+
index ce984e64003a7e4b9057071ae9394acc58c2bc89..587d373d6b745b46d1aa16132d7bb23b4ba0c915 100644 (file)
@@ -1,5 +1,5 @@
 /* Definitions for target OS TPF for GNU compiler, for IBM S/390 hardware
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
    Contributed by P.J. Darcy (darcypj@us.ibm.com),
                   Hartmut Penner (hpenner@de.ibm.com), and
                   Ulrich Weigand (uweigand@de.ibm.com).
@@ -25,6 +25,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define _TPF_H
 
 /* TPF wants the following macros defined/undefined as follows.  */
+#undef TARGET_TPF
+#define TARGET_TPF 1
 #undef ASM_APP_ON
 #define ASM_APP_ON "#APP\n"
 #undef ASM_APP_OFF
@@ -50,11 +52,20 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 /* TPF OS specific stack-pointer offset.  */
 #undef STACK_POINTER_OFFSET
-#define STACK_POINTER_OFFSET           280
+#define STACK_POINTER_OFFSET           448
+/* TPF stack placeholder offset.  */
+#undef TPF_LOC_DIFF_OFFSET
+#define TPF_LOC_DIFF_OFFSET             168
 
 /* When building for TPF, set a generic default target that is 64 bits.  */
 #undef TARGET_DEFAULT
-#define TARGET_DEFAULT             0x33
+#define TARGET_DEFAULT             0xb3
+
+/* Exception handling.  */
+
+/* Select a format to encode pointers in exception handling data.  */
+#undef ASM_PREFERRED_EH_DATA_FORMAT
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) DW_EH_PE_absptr
 
 /* TPF OS specific compiler settings.  */
 #undef TARGET_OS_CPP_BUILTINS
@@ -108,5 +119,73 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
         %{rdynamic:-export-dynamic} \
         %{!dynamic-linker:-dynamic-linker /lib/ld64.so}}}"
 
+extern unsigned int __isPATrange (void *);
+
+/* Exceptions macro defined for TPF so that functions without 
+   dwarf frame information can be used with exceptions.  */
+#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS)               \
+  do                                                                    \
+    {                                                                   \
+      unsigned long int regs_;                                          \
+      unsigned long int new_cfa_;                                       \
+      int i_;                                                           \
+                                                                        \
+      if ((CONTEXT)->cfa == NULL)                                       \
+        goto SUCCESS;                                                   \
+                                                                        \
+      /* Are we going through special linkage code?  */                 \
+      if (__isPATrange((CONTEXT)->ra))                                  \
+        {                                                               \
+          /* No stack frame.   */                                       \
+          (FS)->cfa_how = CFA_REG_OFFSET;                               \
+          (FS)->cfa_reg = 15;                                           \
+          (FS)->cfa_offset = STACK_POINTER_OFFSET;                      \
+                                                                        \
+          /* All registers remain unchanged ...  */                     \
+          for (i_ = 0; i_ < 32; i_++)                                   \
+            {                                                           \
+              (FS)->regs.reg[i_].how = REG_SAVED_REG;                   \
+              (FS)->regs.reg[i_].loc.reg = i_;                          \
+            }                                                           \
+                                                                        \
+          /* ... except for %r14, which is stored at CFA-112            \
+             and used as return address.  */                            \
+          (FS)->regs.reg[14].how = REG_SAVED_OFFSET;                    \
+          (FS)->regs.reg[14].loc.offset =                               \
+            TPF_LOC_DIFF_OFFSET - STACK_POINTER_OFFSET;                 \
+          (FS)->retaddr_column = 14;                                    \
+                                                                        \
+          goto SUCCESS;                                                 \
+                                                                        \
+        }                                                               \
+                                                                        \
+      regs_ = *((unsigned long int *)                                   \
+        (((unsigned long int) (CONTEXT)->cfa) - STACK_POINTER_OFFSET)); \
+      new_cfa_ = regs_ + STACK_POINTER_OFFSET;                          \
+      (FS)->cfa_how = CFA_REG_OFFSET;                                   \
+      (FS)->cfa_reg = 15;                                               \
+      (FS)->cfa_offset = new_cfa_ -                                     \
+        (unsigned long int) (CONTEXT)->cfa + STACK_POINTER_OFFSET;      \
+                                                                        \
+      for (i_ = 0; i_ < 16; i_++)                                       \
+        {                                                               \
+          (FS)->regs.reg[i_].how = REG_SAVED_OFFSET;                    \
+          (FS)->regs.reg[i_].loc.offset =                               \
+            (regs_+(i_*8)) - new_cfa_;                                  \
+        }                                                               \
+                                                                        \
+      for (i_ = 0; i_ < 4; i_++)                                        \
+        {                                                               \
+          (FS)->regs.reg[16+i_].how = REG_SAVED_OFFSET;                 \
+          (FS)->regs.reg[16+i_].loc.offset =                            \
+            (regs_+(16*8)+(i_*8)) - new_cfa_;                           \
+        }                                                               \
+                                                                        \
+      (FS)->retaddr_column = 14;                                        \
+                                                                        \
+      goto SUCCESS;                                                     \
+                                                                        \
+    } while (0)
+
 #endif /* ! _TPF_H */