summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorP.J. Darcy <darcypj@us.ibm.com>2004-09-22 13:57:40 +0000
committerUlrich Weigand <uweigand@gcc.gnu.org>2004-09-22 13:57:40 +0000
commit4798630cb0aa99b3497a16b3e1a5ee0e12a1760b (patch)
tree5ea4cb91c0ccfc079c8ba527aecfba6dfff616d2 /gcc
parent6a97296a060b9e053ae598076ffa14c41a5b6f39 (diff)
downloadgcc-4798630cb0aa99b3497a16b3e1a5ee0e12a1760b.tar.gz
s390-protos.h (s390_emit_tpf_eh_return): Add prototype.
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/config/s390/s390-protos.h1
-rw-r--r--gcc/config/s390/s390.c20
-rw-r--r--gcc/config/s390/s390.h3
-rw-r--r--gcc/config/s390/s390.md12
-rw-r--r--gcc/config/s390/t-tpf9
-rw-r--r--gcc/config/s390/tpf-eh.c183
-rw-r--r--gcc/config/s390/tpf.h85
8 files changed, 325 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 115f39bd7a4..1a95e0446a3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index 6f05d80d545..8b5a263d98b 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -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 */
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 124f4e54df9..5d838ef715c 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -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"
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index f361ce4d374..5b083aadbe6 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -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 \
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 5ca28b5e5c2..8c65145f419 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -7504,3 +7504,15 @@
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;
+})
+
diff --git a/gcc/config/s390/t-tpf b/gcc/config/s390/t-tpf
index 2a3421c479d..76d2c23a8b0 100644
--- a/gcc/config/s390/t-tpf
+++ b/gcc/config/s390/t-tpf
@@ -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
index 00000000000..1ce01ab56ea
--- /dev/null
+++ b/gcc/config/s390/tpf-eh.c
@@ -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;
+}
+
diff --git a/gcc/config/s390/tpf.h b/gcc/config/s390/tpf.h
index ce984e64003..587d373d6b7 100644
--- a/gcc/config/s390/tpf.h
+++ b/gcc/config/s390/tpf.h
@@ -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 */