This patch contains the merge of 
   - Teemu Torma's patch for thread safe exception handling
   - H.J. Lu's patch to compile egcs-1.0 on Redhat 5.0
   - Sai-Lai Lo's patch to port Teemu's patch to x86 and alpha linux
     on Redhat 5.0
 
   - On x86 and alpha linux, the new compiler flag -pthread enable the
     thread-safe exception handling.

Important Note:
   On x86 and alpha linux, after you have built and installed the compiler, 
   you have to apply the following patch to the resulting spec file:

original:
 %{pg:-lgmon} %{pg:-lc_p} %{!pg:-lc} %{pthread:-lpthread}
---
new:
 %{pg:-lgmon} %{pg:-lc_p} %{!pg:-lc} %{pthread:-rpath /usr/local/lib/pthread -lpthread}

This is to ensure that the thread-safe-eh version of the stdc++ shared
library is picked up when the executable is run.
 
                                                      Sai-Lai Lo
=============================================================================
Teemu Torma (tot@trema.com)
Mon, 08 Dec 1997 09:53:05 +0100

   * Messages sorted by: [ date ][ thread ][ subject ][ author ]
   * Next message: Andrey Slepuhin: "Re: Addition: regression of egcs-1.0 on
     powerpc-ibm-aix4.2.1.0"
   * Previous message: G. Sumner Hayes: "RedHat 5.0 compiled w/ egcs
     [SUCCESS]"
   * Next in thread: Mike Stump: "Re: MT-safe EH diffs against 1.00"

Here are my latest MT-safe exception handling diffs for egcs-1.00.
Some line numbers may not match the release, because I have some
unrelated changes in my version.

Many thanks to Scott Snyder (snyder@d0sgif.fnal.gov) for the initial
patches he posted, and to Andrey Slepuhin (pooh@msu.ru) for testing
sjlj exception part and for supplying patches for AIX.

This version has been tested on the following machines:

     Sparc/Solaris 2.5.1
       - DWARF2 unwinding exceptions / sjlj exceptions
       - Solaris (UI) threads/POSIX threads
     PA/HP-UX 10.20
       - sjlj exceptions
       - DCE threads
     RS6000/AIX 4.1.2
       - sjlj exceptions
       - POSIX threads

I have reworked the ChangeLog entries to describe what is different
against 1.00 and what's left of Scott Snyder's patches.

The major changes since I previously posted these are:
    - New file libgcc-thr.h to encapsulate different thread
      implementations.  The interface is similiar to POSIX threads.
    - Calls to __get_eh_context are inside LIBCALL block and
      effectively __attribute__(const).  At least some calls to it
      will get optimized away.

Teemu
---------------------------------------------------------------------------
ChangeLog:

1997-12-08  Teemu Torma

        From Andrey Slepuhin :
        * config/rs6000/aix41.h (CPP_SPEC): If -mthreads, set
        -D_PTHREADS.
        * config/rs6000/t-newas (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
        Added -mthreads with directory name thread.

1997-12-02  Teemu Torma

        Thread support for pthreads, DCE threads and Solaris threads.

        * config/pa/pa.h (CPP_SPEC): Support for -threads.
        * config/pa/pa-hpux10.h (LIB_SPEC): Ditto.

        * config/pa/t-pa (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
        New multilib for -threads.

        * config/sparc/t-sol2: Added multilibs for -threads and
        made -pthreads alias to it.

        * config/sparc/sol2.h (CPP_SPEC, LIB_SPEC):
        Added -threads and -pthreads options.

        * libgcc-thr.h: New file.

        * libgcc2.c: (__get_cpp_eh_context): Removed.
        (struct cpp_eh_context): Removed.
        (struct eh_context): Replaced cpp_eh_context with generic language
        specific pointer.
        (__get_eh_info): New function.
        (__throw): Check eh_context::info.
        (__sjthrow): Ditto.

        * libgcc2.c: Include libgcc-thr.h.
        (new_eh_context, __get_eh_context,
        eh_pthread_initialize, eh_context_initialize, eh_context_static,
        eh_context_specific, eh_context_free): New functions.
        (get_eh_context, eh_context_key): New variables.

        (__sjthrow, __sjpopnthrow, __eh_pcnthrow, __throw): Use
        get_eh_context to get the context.

        (longjmp): Move the declaration inside
        #ifdef DONT_USE_BUILTIN_SETJMP.

        * frame.c: Include libgcc-thr.h.
        (object_mutex): Mutex to protect the object list.
        (find_fde, __register_frame, __register_frame_table,
        __deregister_frame): Hold the lock while accessing objects.

        * except.h (get_eh_context): Declare.
        * except.c (current_function_ehc): Define.
        (current_function_dhc, current_function_dcc): Removed.
        (get_eh_context): New function.
        (get_dynamic_handler_chain): Use get_eh_context.
        (get_saved_pc_ref): Ditto.
        (get_dynamic_cleanup_chain): Removed references to
        current_function_dcc.
        (save_eh_status, restore_eh_status): Save and restore
        current_function_ehc instead.

        * optabs.c (get_eh_context_libfunc): New variable.
        (init_optabs): Initialize it.
        * expr.h: Declare get_eh_context_libfunc.

        * function.h (struct function): Replaced dhc and dcc with ehc.

        From Scott Snyder :
        * libgcc2.c (__get_saved_pc): New.
        (__eh_type, __eh_pc): Deleted.
        (__eh_pcnthrow): Use __get_saved_pc() instead of __eh_pc.
        (__get_dynamic_handler_chain): Move __dynamic_handler_chain inside
        this fcn.

        * except.c (get_saved_pc_ref): New functions.
        (eh_saved_pc_rtx, eh_saved_pc): Deleted.
        (expand_internal_throw_indirect): Use get_saved_pc_ref() instead
        of eh_saved_pc.
        (end_eh_unwinder): Likewise.
        (init_eh): Remove initialization of eh_saved_pc.
        * optabs.c (get_saved_pc_libfunc): New variable.
        (init_optabs): Initialize it.
        * expr.h: Declare get_saved_pc_libfunc.
        * except.h (eh_saved_pc_rtx): Deleted.
        (get_saved_pc_ref): Declared.

cp/ChangeLog:

1997-12-01  Teemu Torma

        * decl.c (ptr_ptr_type_node): Define.
        (init_decl_processing): Initialize it.
        * cp-tree.h: Declare it.

        * exception.cc (__cp_exception_info): Use __get_eh_info.
        (__cp_push_exception): Ditto.
        (__cp_pop_exception): Ditto.

        From Scott Snyder :
        * except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
        saved_pc.
        (init_exception_processing): Removed saved_pc initialization.
=========================================================================
diff -r -N -c egcs-1.0.orig/gcc/config/alpha/RCS/linux.h,v egcs-1.0/gcc/config/alpha/RCS/linux.h,v
*** egcs-1.0.orig/gcc/config/alpha/RCS/linux.h,v	Thu Jan  1 01:00:00 1970
--- egcs-1.0/gcc/config/alpha/RCS/linux.h,v	Tue Dec 16 19:24:55 1997
***************
*** 0 ****
--- 1,122 ----
+ head	1.1;
+ access;
+ symbols;
+ locks
+ 	sll:1.1; strict;
+ comment	@ * @;
+ 
+ 
+ 1.1
+ date	97.12.16.19.24.49;	author sll;	state Exp;
+ branches;
+ next	;
+ 
+ 
+ desc
+ @@
+ 
+ 
+ 1.1
+ log
+ @Initial revision
+ @
+ text
+ @/* Definitions of target machine for GNU compiler, for Alpha Linux,
+    using ECOFF.
+    Copyright (C) 1996 Free Software Foundation, Inc.
+    Contributed by Bob Manson.
+ 
+ This file is part of GNU CC.
+ 
+ GNU CC 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.
+ 
+ GNU CC 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 GNU CC; see the file COPYING.  If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+ 
+ #undef TARGET_DEFAULT
+ #define TARGET_DEFAULT (3 | MASK_GAS)
+ 
+ #undef TARGET_VERSION
+ #define TARGET_VERSION fprintf (stderr, " (Linux/Alpha)");
+ 
+ #undef CPP_PREDEFINES
+ #define CPP_PREDEFINES "\
+ -D__alpha -D__alpha__ -D__linux__ -D__linux -D_LONGLONG -Dlinux -Dunix \
+ -Asystem(linux) -Acpu(alpha) -Amachine(alpha)"
+ 
+ /* We don't actually need any of these; the MD_ vars are ignored
+    anyway for cross-compilers, and the other specs won't get picked up
+    because the user is supposed to do ld -r (hmm, perhaps that should be
+    the default).  In any case, setting them thus will catch some
+    common user errors. */
+ 
+ #undef MD_EXEC_PREFIX
+ #undef MD_STARTFILE_PREFIX
+ 
+ #undef LIB_SPEC
+ #define LIB_SPEC "%{pg:-lgmon} %{pg:-lc_p} %{!pg:-lc}"
+ 
+ #undef LINK_SPEC
+ #define LINK_SPEC "-G 8 %{O*:-O3} %{!O*:-O1}"
+ 
+ #undef ASM_SPEC
+ #define ASM_SPEC "-nocpp"
+ 
+ /* Can't do stabs */
+ #undef SDB_DEBUGGING_INFO
+ 
+ /* Prefer dbx.  */
+ #undef PREFERRED_DEBUGGING_TYPE
+ #define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+ 
+ #undef FUNCTION_PROFILER
+ #define FUNCTION_PROFILER(FILE, LABELNO)			\
+ 	fputs ("\tjsr $28,_mcount\n", (FILE))
+ 
+ /* Generate calls to memcpy, etc., not bcopy, etc. */
+ #define TARGET_MEM_FUNCTIONS
+ 
+ /* Show that we need a GP when profiling.  */
+ #define TARGET_PROFILING_NEEDS_GP
+ 
+ /* We need that too. */
+ #define HANDLE_SYSV_PRAGMA
+ 
+ #undef ASM_FINAL_SPEC
+ 
+ /* Emit RTL insns to initialize the variable parts of a trampoline.
+    FNADDR is an RTX for the address of the function's pure code.
+    CXT is an RTX for the static chain value for the function. 
+ 
+    This differs from the standard version in that:
+ 
+    We do not initialize the "hint" field because it only has an 8k
+    range and so the target is in range of something on the stack. 
+    Omitting the hint saves a bogus branch-prediction cache line load.
+ 
+    Linux always has an executable stack -- no need for a system call.
+  */
+ 
+ #undef INITIALIZE_TRAMPOLINE
+ #define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT)                       \
+ {                                                                       \
+   rtx _addr;                                             		\
+                                                                         \
+   _addr = memory_address (Pmode, plus_constant ((TRAMP), 16));          \
+   emit_move_insn (gen_rtx (MEM, Pmode, _addr), (FNADDR));               \
+   _addr = memory_address (Pmode, plus_constant ((TRAMP), 24));          \
+   emit_move_insn (gen_rtx (MEM, Pmode, _addr), (CXT));                  \
+                                                                         \
+   emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode,                        \
+                       gen_rtvec (1, const0_rtx), 0));                   \
+ }
+ @
diff -r -N -c egcs-1.0.orig/gcc/config/alpha/RCS/t-linux,v egcs-1.0/gcc/config/alpha/RCS/t-linux,v
*** egcs-1.0.orig/gcc/config/alpha/RCS/t-linux,v	Thu Jan  1 01:00:00 1970
--- egcs-1.0/gcc/config/alpha/RCS/t-linux,v	Tue Dec 16 19:21:43 1997
***************
*** 0 ****
--- 1,29 ----
+ head	1.1;
+ access;
+ symbols;
+ locks
+ 	sll:1.1; strict;
+ comment	@# @;
+ 
+ 
+ 1.1
+ date	97.12.16.19.21.42;	author sll;	state Exp;
+ branches;
+ next	;
+ 
+ 
+ desc
+ @@
+ 
+ 
+ 1.1
+ log
+ @Initial revision
+ @
+ text
+ @# Do not build libgcc1. Let gcc generate those functions. The Linux
+ # C library can handle them.
+ LIBGCC1 = 
+ CROSS_LIBGCC1 =
+ LIBGCC1_TEST =
+ @
diff -r -N -c egcs-1.0.orig/gcc/config/alpha/linux.h egcs-1.0/gcc/config/alpha/linux.h
*** egcs-1.0.orig/gcc/config/alpha/linux.h	Sat Sep 20 03:48:37 1997
--- egcs-1.0/gcc/config/alpha/linux.h	Tue Dec 16 21:47:13 1997
***************
*** 28,34 ****
  #undef CPP_PREDEFINES
  #define CPP_PREDEFINES "\
  -D__alpha -D__alpha__ -D__linux__ -D__linux -D_LONGLONG -Dlinux -Dunix \
! -Asystem(linux) -Acpu(alpha) -Amachine(alpha)"
  
  /* We don't actually need any of these; the MD_ vars are ignored
     anyway for cross-compilers, and the other specs won't get picked up
--- 28,48 ----
  #undef CPP_PREDEFINES
  #define CPP_PREDEFINES "\
  -D__alpha -D__alpha__ -D__linux__ -D__linux -D_LONGLONG -Dlinux -Dunix \
! -Asystem(linux) -Acpu(alpha) -Amachine(alpha) \
! "
! 
! #undef CPP_SPEC
! #define CPP_SPEC "\
! %{!.S:	-D__LANGUAGE_C__ -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C}}  \
! %{.S:	-D__LANGUAGE_ASSEMBLY__ -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
! %{.cc:	-D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \
! %{.cxx:	-D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \
! %{.C:	-D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \
! %{.m:	-D__LANGUAGE_OBJECTIVE_C__ -D__LANGUAGE_OBJECTIVE_C} \
! %{mieee:-D_IEEE_FP} \
! %{mieee-with-inexact:-D_IEEE_FP -D_IEEE_FP_INEXACT} \
! %{pthread:-D_REENTRANT -D_PTHREADS} \
! "
  
  /* We don't actually need any of these; the MD_ vars are ignored
     anyway for cross-compilers, and the other specs won't get picked up
***************
*** 40,46 ****
  #undef MD_STARTFILE_PREFIX
  
  #undef LIB_SPEC
! #define LIB_SPEC "%{pg:-lgmon} %{pg:-lc_p} %{!pg:-lc}"
  
  #undef LINK_SPEC
  #define LINK_SPEC "-G 8 %{O*:-O3} %{!O*:-O1}"
--- 54,60 ----
  #undef MD_STARTFILE_PREFIX
  
  #undef LIB_SPEC
! #define LIB_SPEC "%{pg:-lgmon} %{pg:-lc_p} %{!pg:-lc} %{pthread:-lpthread}"
  
  #undef LINK_SPEC
  #define LINK_SPEC "-G 8 %{O*:-O3} %{!O*:-O1}"
diff -r -N -c egcs-1.0.orig/gcc/config/alpha/t-linux egcs-1.0/gcc/config/alpha/t-linux
*** egcs-1.0.orig/gcc/config/alpha/t-linux	Mon Aug 11 16:57:21 1997
--- egcs-1.0/gcc/config/alpha/t-linux	Tue Dec 16 19:24:16 1997
***************
*** 3,5 ****
--- 3,10 ----
  LIBGCC1 = 
  CROSS_LIBGCC1 =
  LIBGCC1_TEST =
+ 
+ MULTILIB_OPTIONS =  pthread
+ MULTILIB_DIRNAMES = pthread
+ LIBGCC = stmp-multilib
+ INSTALL_LIBGCC = install-multilib
diff -r -N -c egcs-1.0.orig/gcc/config/i386/linux.h egcs-1.0/gcc/config/i386/linux.h
*** egcs-1.0.orig/gcc/config/i386/linux.h	Mon Aug 11 16:57:17 1997
--- egcs-1.0/gcc/config/i386/linux.h	Thu Dec 18 18:13:06 1997
***************
*** 154,160 ****
  #ifdef USE_GNULIBC_1
  #define CPP_SPEC "%(cpp_cpu) %[cpp_cpu] %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}"
  #else
! #define CPP_SPEC "%(cpp_cpu) %[cpp_cpu] %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
  #endif
  
  #undef CC1_SPEC
--- 154,160 ----
  #ifdef USE_GNULIBC_1
  #define CPP_SPEC "%(cpp_cpu) %[cpp_cpu] %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}"
  #else
! #define CPP_SPEC "%(cpp_cpu) %[cpp_cpu] %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT -D_PTHREADS}"
  #endif
  
  #undef CC1_SPEC
diff -r -N -c egcs-1.0.orig/gcc/config/i386/t-pthread egcs-1.0/gcc/config/i386/t-pthread
*** egcs-1.0.orig/gcc/config/i386/t-pthread	Thu Jan  1 01:00:00 1970
--- egcs-1.0/gcc/config/i386/t-pthread	Thu Dec 18 23:23:02 1997
***************
*** 0 ****
--- 1,4 ----
+ MULTILIB_OPTIONS =  pthread
+ MULTILIB_DIRNAMES = pthread
+ LIBGCC = stmp-multilib
+ INSTALL_LIBGCC = install-multilib
diff -r -N -c egcs-1.0.orig/gcc/config/pa/pa-hpux10.h egcs-1.0/gcc/config/pa/pa-hpux10.h
*** egcs-1.0.orig/gcc/config/pa/pa-hpux10.h	Sun Nov 23 01:57:14 1997
--- egcs-1.0/gcc/config/pa/pa-hpux10.h	Tue Dec 16 18:23:33 1997
***************
*** 30,35 ****
--- 30,45 ----
    "-z %{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{shared:-b}"
  #endif
  
+ /* Like the default, except no -lg.  */
+ #undef LIB_SPEC
+ #define LIB_SPEC \
+   "%{!shared:\
+      %{!p:\
+        %{!pg:\
+          %{!threads:-lc}\
+          %{threads:-lcma -lc_r}}\
+        %{p: -L/lib/libp/ -lc}\
+        %{pg: -L/lib/libp/ -lc}}}"
  /* The hpux10 assembler requires a .LEVEL pseudo-op at the start of
     the assembly file.  */
  #undef ASM_FILE_START
diff -r -N -c egcs-1.0.orig/gcc/config/pa/pa.h egcs-1.0/gcc/config/pa/pa.h
*** egcs-1.0.orig/gcc/config/pa/pa.h	Sun Nov 23 01:57:14 1997
--- egcs-1.0/gcc/config/pa/pa.h	Tue Dec 16 18:23:33 1997
***************
*** 241,249 ****
  #if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 1) == 0
  #define CPP_SPEC "%{msnake:-D__hp9000s700 -D_PA_RISC1_1}\
   %{mpa-risc-1-1:-D__hp9000s700 -D_PA_RISC1_1}\
!  %{!ansi: -D_HPUX_SOURCE -D_HIUX_SOURCE}"
  #else
! #define CPP_SPEC "%{!mpa-risc-1-0:%{!mnosnake:%{!msoft-float:-D__hp9000s700 -D_PA_RISC1_1}}} %{!ansi: -D_HPUX_SOURCE -D_HIUX_SOURCE}"
  #endif
  
  /* Defines for a K&R CC */
--- 241,252 ----
  #if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 1) == 0
  #define CPP_SPEC "%{msnake:-D__hp9000s700 -D_PA_RISC1_1}\
   %{mpa-risc-1-1:-D__hp9000s700 -D_PA_RISC1_1}\
!  %{!ansi: -D_HPUX_SOURCE -D_HIUX_SOURCE}\
!  %{threads:-D_REENTRANT -D_DCE_THREADS}"
  #else
! #define CPP_SPEC "%{!mpa-risc-1-0:%{!mnosnake:%{!msoft-float:-D__hp9000s700 -D_PA_RISC1_1}}} \
!  %{!ansi: -D_HPUX_SOURCE -D_HIUX_SOURCE}\
!  %{threads:-D_REENTRANT -D_DCE_THREADS}"
  #endif
  
  /* Defines for a K&R CC */
diff -r -N -c egcs-1.0.orig/gcc/config/pa/t-pa egcs-1.0/gcc/config/pa/t-pa
*** egcs-1.0.orig/gcc/config/pa/t-pa	Mon Aug 11 16:57:38 1997
--- egcs-1.0/gcc/config/pa/t-pa	Tue Dec 16 18:23:34 1997
***************
*** 16,18 ****
--- 16,22 ----
  	cp $(srcdir)/config/pa/ee_fp.asm .
  
  TARGET_LIBGCC2_CFLAGS = -fPIC
+ MULTILIB_OPTIONS = threads
+ MULTILIB_DIRNAMES = threads
+ LIBGCC = stmp-multilib
+ INSTALL_LIBGCC = install-multilib
diff -r -N -c egcs-1.0.orig/gcc/config/rs6000/aix41.h egcs-1.0/gcc/config/rs6000/aix41.h
*** egcs-1.0.orig/gcc/config/rs6000/aix41.h	Sat Nov 29 19:42:27 1997
--- egcs-1.0/gcc/config/rs6000/aix41.h	Tue Dec 16 18:23:34 1997
***************
*** 74,80 ****
  #undef CPP_SPEC
  #define CPP_SPEC "%{posix: -D_POSIX_SOURCE}\
     %{mpe: -I/usr/lpp/ppe.poe/include}\
!    %{mthreads: -D_THREAD_SAFE}\
     %(cpp_cpu)"
  
  #undef	CPP_DEFAULT_SPEC
--- 74,80 ----
  #undef CPP_SPEC
  #define CPP_SPEC "%{posix: -D_POSIX_SOURCE}\
     %{mpe: -I/usr/lpp/ppe.poe/include}\
!    %{mthreads: -D_THREAD_SAFE -D_PTHREADS}\
     %(cpp_cpu)"
  
  #undef	CPP_DEFAULT_SPEC
diff -r -N -c egcs-1.0.orig/gcc/config/rs6000/t-newas egcs-1.0/gcc/config/rs6000/t-newas
*** egcs-1.0.orig/gcc/config/rs6000/t-newas	Mon Aug 11 16:57:23 1997
--- egcs-1.0/gcc/config/rs6000/t-newas	Tue Dec 16 18:34:01 1997
***************
*** 16,25 ****
  # Build the libraries for both hard and soft floating point and all of the 
  # different processor models
  
! MULTILIB_OPTIONS	= msoft-float \
  			  mcpu=common/mcpu=power/mcpu=powerpc
  
! MULTILIB_DIRNAMES	= soft-float \
  			  common power powerpc
  
  MULTILIB_MATCHES	= msoft-float=mcpu?403 \
--- 16,25 ----
  # Build the libraries for both hard and soft floating point and all of the 
  # different processor models
  
! MULTILIB_OPTIONS	= msoft-float mthreads \
  			  mcpu=common/mcpu=power/mcpu=powerpc
  
! MULTILIB_DIRNAMES	= soft-float thread \
  			  common power powerpc
  
  MULTILIB_MATCHES	= msoft-float=mcpu?403 \
diff -r -N -c egcs-1.0.orig/gcc/config/sparc/sol2.h egcs-1.0/gcc/config/sparc/sol2.h
*** egcs-1.0.orig/gcc/config/sparc/sol2.h	Mon Oct 20 21:49:16 1997
--- egcs-1.0/gcc/config/sparc/sol2.h	Tue Dec 16 18:23:34 1997
***************
*** 30,35 ****
--- 30,37 ----
  
  #undef CPP_SUBTARGET_SPEC
  #define CPP_SUBTARGET_SPEC "\
+ %{pthreads:-D_REENTRANT -D_PTHREADS} \
+ %{!pthreads:%{threads:-D_REENTRANT -D_SOLARIS_THREADS}} \
  %{compat-bsd:-iwithprefixbefore ucbinclude -I/usr/ucbinclude} \
  "
  
***************
*** 131,137 ****
  
  #undef LIB_SPEC
  #define LIB_SPEC \
!   "%{compat-bsd:-lucb -lsocket -lnsl -lelf -laio} %{!shared:%{!symbolic:-lc}}"
  
  #undef  ENDFILE_SPEC
  #define ENDFILE_SPEC "crtend.o%s crtn.o%s"
--- 133,144 ----
  
  #undef LIB_SPEC
  #define LIB_SPEC \
!   "%{compat-bsd:-lucb -lsocket -lnsl -lelf -laio} \
!    %{!shared:\
!      %{!symbolic:\
!        %{pthreads:-lpthread} \
!        %{!pthreads:%{threads:-lthread}} \
!        -lc}}"
  
  #undef  ENDFILE_SPEC
  #define ENDFILE_SPEC "crtend.o%s crtn.o%s"
diff -r -N -c egcs-1.0.orig/gcc/config/sparc/t-sol2 egcs-1.0/gcc/config/sparc/t-sol2
*** egcs-1.0.orig/gcc/config/sparc/t-sol2	Mon Aug 11 16:57:40 1997
--- egcs-1.0/gcc/config/sparc/t-sol2	Tue Dec 16 18:23:34 1997
***************
*** 5,10 ****
--- 5,14 ----
  CROSS_LIBGCC1 =
  LIBGCC1_TEST =
  
+ MULTILIB_OPTIONS = mcpu=v7/mcpu=v8/mcpu=v8plus threads fvtable-thunks
+ MULTILIB_DIRNAMES = sparc-v7 sparc-v8 sparc-v8plus threads vtable-thunks
+ LIBGCC = stmp-multilib
+ INSTALL_LIBGCC = install-multilib
  # gmon build rule:
  gmon.o:	$(srcdir)/config/sparc/gmon-sol2.c $(GCC_PASSES) $(CONFIG_H) stmp-int-hdrs
  	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
diff -r -N -c egcs-1.0.orig/gcc/configure egcs-1.0/gcc/configure
*** egcs-1.0.orig/gcc/configure	Wed Dec  3 16:34:28 1997
--- egcs-1.0/gcc/configure	Thu Dec 18 23:28:07 1997
***************
*** 2394,2400 ****
  		xm_file=i386/xm-linux.h # with ELF format using glibc 2
  		xmake_file=x-linux	# aka Linux C library 6
  		tm_file=i386/linux.h
! 		tmake_file="t-linux i386/t-crtstuff"
  		extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
  		fixincludes=Makefile.in #On Linux, the headers are ok already.
  		gnu_ld=yes
--- 2394,2400 ----
  		xm_file=i386/xm-linux.h # with ELF format using glibc 2
  		xmake_file=x-linux	# aka Linux C library 6
  		tm_file=i386/linux.h
! 		tmake_file="t-linux i386/t-crtstuff i386/t-pthread"
  		extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
  		fixincludes=Makefile.in #On Linux, the headers are ok already.
  		gnu_ld=yes
diff -r -N -c egcs-1.0.orig/gcc/configure.in egcs-1.0/gcc/configure.in
*** egcs-1.0.orig/gcc/configure.in	Fri Nov 28 17:02:43 1997
--- egcs-1.0/gcc/configure.in	Thu Dec 18 23:22:31 1997
***************
*** 874,880 ****
  		xm_file=i386/xm-linux.h # with ELF format using glibc 2
  		xmake_file=x-linux	# aka Linux C library 6
  		tm_file=i386/linux.h
! 		tmake_file="t-linux i386/t-crtstuff"
  		extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
  		fixincludes=Makefile.in #On Linux, the headers are ok already.
  		gnu_ld=yes
--- 874,880 ----
  		xm_file=i386/xm-linux.h # with ELF format using glibc 2
  		xmake_file=x-linux	# aka Linux C library 6
  		tm_file=i386/linux.h
! 		tmake_file="t-linux i386/t-crtstuff i386/t-pthread"
  		extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
  		fixincludes=Makefile.in #On Linux, the headers are ok already.
  		gnu_ld=yes
diff -r -N -c egcs-1.0.orig/gcc/cp/cp-tree.h egcs-1.0/gcc/cp/cp-tree.h
*** egcs-1.0.orig/gcc/cp/cp-tree.h	Sat Nov 15 08:36:06 1997
--- egcs-1.0/gcc/cp/cp-tree.h	Tue Dec 16 18:23:34 1997
***************
*** 1516,1522 ****
  /* A node that is a list (length 1) of error_mark_nodes.  */
  extern tree error_mark_list;
  
! extern tree ptr_type_node;
  extern tree class_type_node, record_type_node, union_type_node, enum_type_node;
  extern tree unknown_type_node;
  extern tree opaque_type_node, signature_type_node;
--- 1516,1522 ----
  /* A node that is a list (length 1) of error_mark_nodes.  */
  extern tree error_mark_list;
  
! extern tree ptr_type_node, ptr_ptr_type_node;
  extern tree class_type_node, record_type_node, union_type_node, enum_type_node;
  extern tree unknown_type_node;
  extern tree opaque_type_node, signature_type_node;
diff -r -N -c egcs-1.0.orig/gcc/cp/decl.c egcs-1.0/gcc/cp/decl.c
*** egcs-1.0.orig/gcc/cp/decl.c	Fri Nov 21 21:04:12 1997
--- egcs-1.0/gcc/cp/decl.c	Tue Dec 16 18:23:34 1997
***************
*** 241,246 ****
--- 241,248 ----
  tree ptr_type_node;
  static tree const_ptr_type_node;
  
+ /* Node for type `void **'. */
+ tree ptr_ptr_type_node;
  /* Nodes for types `char *' and `const char *'.  */
  
  tree string_type_node, const_string_type_node;
***************
*** 5064,5069 ****
--- 5066,5072 ----
    ptr_type_node = build_pointer_type (void_type_node);
    const_ptr_type_node
      = build_pointer_type (build_type_variant (void_type_node, 1, 0));
+   ptr_ptr_type_node = build_pointer_type (ptr_type_node);
  #if 0
    record_builtin_type (RID_MAX, NULL_PTR, ptr_type_node);
  #endif
diff -r -N -c egcs-1.0.orig/gcc/cp/except.c egcs-1.0/gcc/cp/except.c
*** egcs-1.0.orig/gcc/cp/except.c	Fri Nov 28 03:23:04 1997
--- egcs-1.0/gcc/cp/except.c	Tue Dec 16 18:32:53 1997
***************
*** 189,197 ****
  
     ========================================================================= */
  
- /* Holds the pc for doing "throw" */
- static tree saved_pc;
- 
  extern int throw_used;
  extern rtx catch_clauses;
  
--- 189,194 ----
***************
*** 289,301 ****
  
    pop_lang_context ();
  
-   d = build_decl (VAR_DECL, get_identifier ("__eh_pc"), ptr_type_node);
-   TREE_PUBLIC (d) = 1;
-   DECL_EXTERNAL (d) = 1;
-   DECL_ARTIFICIAL (d) = 1;
-   cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
-   saved_pc = d;
- 
    /* If we use setjmp/longjmp EH, arrange for all cleanup actions to
       be protected with __terminate.  */
    protect_cleanup_actions_with_terminate = 1;
--- 286,291 ----
***************
*** 885,893 ****
  
    /* search for an exception handler for the saved_pc */
    handler = do_function_call (FirstExceptionMatch,
! 			      expr_tree_cons (NULL_TREE, saved_pc,
! 					 NULL_TREE),
! 			      ptr_type_node);
    assemble_external (TREE_OPERAND (FirstExceptionMatch, 0));
  
    /* did we find one? */
--- 875,885 ----
  
    /* search for an exception handler for the saved_pc */
    handler = do_function_call (FirstExceptionMatch,
! 			      expr_tree_cons (NULL_TREE,
! 					      make_tree (ptr_ptr_type_node,
! 							 get_saved_pc_ref ()),
! 					      NULL_TREE),
!                               ptr_type_node);
    assemble_external (TREE_OPERAND (FirstExceptionMatch, 0));
  
    /* did we find one? */
***************
*** 966,972 ****
      }
    else
  #endif
!     emit_move_insn (eh_saved_pc_rtx, next_pc);
  
    after_unwind = gen_label_rtx ();
    do_unwind (gen_rtx (LABEL_REF, Pmode, after_unwind));
--- 958,964 ----
      }
    else
  #endif
!     emit_move_insn (get_saved_pc_ref (), next_pc);
  
    after_unwind = gen_label_rtx ();
    do_unwind (gen_rtx (LABEL_REF, Pmode, after_unwind));
diff -r -N -c egcs-1.0.orig/gcc/cp/exception.cc egcs-1.0/gcc/cp/exception.cc
*** egcs-1.0.orig/gcc/cp/exception.cc	Tue Nov 25 19:34:14 1997
--- egcs-1.0/gcc/cp/exception.cc	Tue Dec 16 18:23:34 1997
***************
*** 90,98 ****
    long handlers;
  };
  
! /* Language-specific EH info pointer, defined in libgcc2.  */
  
! extern cp_eh_info *__eh_info;  // actually void*
  
  /* Is P the type_info node for a pointer of some kind?  */
  
--- 90,98 ----
    long handlers;
  };
  
! /* Language-specific EH info pointer, defined in libgcc2. */
  
! extern "C" cp_eh_info **__get_eh_info ();     // actually void **
  
  /* Is P the type_info node for a pointer of some kind?  */
  
***************
*** 104,110 ****
  extern "C" cp_eh_info *
  __cp_exception_info (void)
  {
!   return __eh_info;
  }
  
  /* Compiler hook to push a new exception onto the stack.
--- 104,110 ----
  extern "C" cp_eh_info *
  __cp_exception_info (void)
  {
!   return *__get_eh_info ();
  }
  
  /* Compiler hook to push a new exception onto the stack.
***************
*** 119,126 ****
    p->cleanup = cleanup;
    p->handlers = 0;
    p->caught = false;
!   p->next = __eh_info;
!   __eh_info = p;
  }
  
  /* Compiler hook to pop an exception that has been finalized.  Used by
--- 119,127 ----
    p->cleanup = cleanup;
    p->handlers = 0;
    p->caught = false;
!   cp_eh_info **q = __get_eh_info ();
!   p->next = *q;
!   *q = p;
  }
  
  /* Compiler hook to pop an exception that has been finalized.  Used by
***************
*** 131,137 ****
  extern "C" void
  __cp_pop_exception (cp_eh_info *p, bool handler)
  {
!   cp_eh_info **q = &__eh_info;
  
    --p->handlers;
  
--- 132,138 ----
  extern "C" void
  __cp_pop_exception (cp_eh_info *p, bool handler)
  {
!   cp_eh_info **q = __get_eh_info ();
  
    --p->handlers;
  
diff -r -N -c egcs-1.0.orig/gcc/except.c egcs-1.0/gcc/except.c
*** egcs-1.0.orig/gcc/except.c	Thu Nov 27 16:36:58 1997
--- egcs-1.0/gcc/except.c	Tue Dec 16 18:42:48 1997
***************
*** 431,447 ****
  
  int throw_used;
  
! /* The dynamic handler chain.  Nonzero if the function has already
!    fetched a pointer to the dynamic handler chain for exception
!    handling.  */
  
! rtx current_function_dhc;
! 
! /* The dynamic cleanup chain.  Nonzero if the function has already
!    fetched a pointer to the dynamic cleanup chain for exception
!    handling.  */
! 
! rtx current_function_dcc;
  
  /* A stack used for keeping track of the currectly active exception
     handling region.  As each exception region is started, an entry
--- 431,440 ----
  
  int throw_used;
  
! /* The EH context.  Nonzero if the function has already
!    fetched a pointer to the EH context  for exception handling.  */
  
! rtx current_function_ehc;
  
  /* A stack used for keeping track of the currectly active exception
     handling region.  As each exception region is started, an entry
***************
*** 496,507 ****
  
  struct label_node *false_label_stack = NULL;
  
! /* The rtx and the tree for the saved PC value.  */
! 
! rtx eh_saved_pc_rtx;
! tree eh_saved_pc;
! 
! rtx expand_builtin_return_addr	PROTO((enum built_in_function, int, rtx));
  
  /* Various support routines to manipulate the various data structures
     used by the exception handling code.  */
--- 489,495 ----
  
  struct label_node *false_label_stack = NULL;
  
! rtx expand_builtin_return_addr        PROTO((enum built_in_function, int, rtx));
  
  /* Various support routines to manipulate the various data structures
     used by the exception handling code.  */
***************
*** 717,722 ****
--- 705,732 ----
    pop_obstacks ();
  }
  
+ /* This routine is here to facilitate the porting of this code to
+    systems with threads.  One can either replace the routine we emit a
+    call for here in libgcc2.c, or one can modify this routine to work
+    with their thread system.  */
+ rtx
+ get_eh_context ()
+ {
+   rtx ehc;
+   rtx target, insns;
+   start_sequence ();
+   ehc = emit_library_call_value (get_eh_context_libfunc,
+                                NULL_RTX, 1,
+                                Pmode, 0);
+   RTX_UNCHANGING_P (ehc) = 1;
+   insns = get_insns ();
+   end_sequence ();
+   target = gen_reg_rtx (Pmode);
+   emit_libcall_block (insns, target, ehc,
+                     gen_rtx (EXPR_LIST, VOIDmode,
+                              get_eh_context_libfunc, 0));
+   return target;
+ }
  /* Get a reference to the dynamic handler chain.  It points to the
     pointer to the next element in the dynamic handler chain.  It ends
     when there are no more elements in the dynamic handler chain, when
***************
*** 724,766 ****
     pointer, is an area suitable for setjmp/longjmp when
     DONT_USE_BUILTIN_SETJMP is defined, and an area suitable for
     __builtin_setjmp/__builtin_longjmp when DONT_USE_BUILTIN_SETJMP
!    isn't defined.
! 
!    This routine is here to facilitate the porting of this code to
!    systems with threads.  One can either replace the routine we emit a
!    call for here in libgcc2.c, or one can modify this routine to work
!    with their thread system.  */
  
  rtx
  get_dynamic_handler_chain ()
  {
! #if 0
!   /* Do this once we figure out how to get this to the front of the
!      function, and we really only want one per real function, not one
!      per inlined function.  */
!   if (current_function_dhc == 0)
!     {
!       rtx dhc, insns;
!       start_sequence ();
! 
!       dhc = emit_library_call_value (get_dynamic_handler_chain_libfunc,
! 				     NULL_RTX, 1,
! 				     Pmode, 0);
!       current_function_dhc = copy_to_reg (dhc);
!       insns = get_insns ();
!       end_sequence ();
!       emit_insns_before (insns, get_first_nonparm_insn ());
!     }
! #else
!   rtx dhc;
!   dhc = emit_library_call_value (get_dynamic_handler_chain_libfunc,
! 				 NULL_RTX, 1,
! 				 Pmode, 0);
!   current_function_dhc = copy_to_reg (dhc);
! #endif
! 
!   /* We don't want a copy of the dhc, but rather, the single dhc.  */
!   return gen_rtx (MEM, Pmode, current_function_dhc);
  }
  
  /* Get a reference to the dynamic cleanup chain.  It points to the
--- 734,751 ----
     pointer, is an area suitable for setjmp/longjmp when
     DONT_USE_BUILTIN_SETJMP is defined, and an area suitable for
     __builtin_setjmp/__builtin_longjmp when DONT_USE_BUILTIN_SETJMP
!    isn't defined. */
  
  rtx
  get_dynamic_handler_chain ()
  {
!   rtx ehc, dhc, result;
!   ehc = get_eh_context ();
!   dhc = ehc;
!   
!   result = copy_to_reg (dhc);
!   /* We don't want a copy of the dcc, but rather, the single dcc.  */
!   return gen_rtx (MEM, Pmode, result);
  }
  
  /* Get a reference to the dynamic cleanup chain.  It points to the
***************
*** 772,786 ****
  rtx
  get_dynamic_cleanup_chain ()
  {
!   rtx dhc, dcc;
  
    dhc = get_dynamic_handler_chain ();
    dcc = plus_constant (dhc, GET_MODE_SIZE (Pmode));
  
!   current_function_dcc = copy_to_reg (dcc);
  
    /* We don't want a copy of the dcc, but rather, the single dcc.  */
!   return gen_rtx (MEM, Pmode, current_function_dcc);
  }
  
  /* Generate code to evaluate X and jump to LABEL if the value is nonzero.
--- 757,783 ----
  rtx
  get_dynamic_cleanup_chain ()
  {
!   rtx dhc, dcc, result;
  
    dhc = get_dynamic_handler_chain ();
    dcc = plus_constant (dhc, GET_MODE_SIZE (Pmode));
  
!   result = copy_to_reg (dcc);
  
    /* We don't want a copy of the dcc, but rather, the single dcc.  */
!   return gen_rtx (MEM, Pmode, result);
! }
! /* Get a reference to the saved_pc variable. */
! rtx
! get_saved_pc_ref ()
! {
!   rtx ehc, ehpc, result;
!   /* Saved PC is the second word into the returned structure. */
!   ehc = get_eh_context ();
!   ehpc = plus_constant (ehc, GET_MODE_SIZE (Pmode));
!   result = copy_to_reg (ehpc);
!   /* We don't want a copy of the ehpc, but rather, the single ehpc.  */
!   return gen_rtx (MEM, Pmode, result);
  }
  
  /* Generate code to evaluate X and jump to LABEL if the value is nonzero.
***************
*** 1160,1167 ****
  expand_internal_throw_indirect (context)
       rtx context;
  {
!   assemble_external (eh_saved_pc);
!   emit_move_insn (eh_saved_pc_rtx, context);
    emit_throw ();
  }
  
--- 1157,1163 ----
  expand_internal_throw_indirect (context)
       rtx context;
  {
!   emit_move_insn (get_saved_pc_ref (), context);
    emit_throw ();
  }
  
***************
*** 1654,1661 ****
    return;
  #else /* DWARF2_UNWIND_INFO */
  
-   assemble_external (eh_saved_pc);
- 
    expr = make_node (RTL_EXPR);
    TREE_TYPE (expr) = void_type_node;
    RTL_EXPR_RTL (expr) = const0_rtx;
--- 1650,1655 ----
***************
*** 1673,1679 ****
    return_val_rtx = eh_outer_context (return_val_rtx);
    return_val_rtx = expand_binop (Pmode, sub_optab, return_val_rtx, GEN_INT (1),
  				 NULL_RTX, 0, OPTAB_LIB_WIDEN);
!   emit_move_insn (eh_saved_pc_rtx, return_val_rtx);
    
    /* Either set things up so we do a return directly to __throw, or
       we return here instead.  */
--- 1667,1673 ----
    return_val_rtx = eh_outer_context (return_val_rtx);
    return_val_rtx = expand_binop (Pmode, sub_optab, return_val_rtx, GEN_INT (1),
  				 NULL_RTX, 0, OPTAB_LIB_WIDEN);
!   emit_move_insn (get_saved_pc_ref (), return_val_rtx);
    
    /* Either set things up so we do a return directly to __throw, or
       we return here instead.  */
***************
*** 1933,1944 ****
    /* Generate rtl to reference the variable in which the PC of the
       current context is saved.  */
    tree type = build_pointer_type (make_node (VOID_TYPE));
- 
-   eh_saved_pc = build_decl (VAR_DECL, get_identifier ("__eh_pc"), type);
-   DECL_EXTERNAL (eh_saved_pc) = 1;
-   TREE_PUBLIC (eh_saved_pc) = 1;
-   make_decl_rtl (eh_saved_pc, NULL_PTR, 1);
-   eh_saved_pc_rtx = DECL_RTL (eh_saved_pc);
  }
  
  /* Initialize the per-function EH information.  */
--- 1927,1932 ----
***************
*** 1952,1959 ****
    false_label_stack = 0;
    caught_return_label_stack = 0;
    protect_list = NULL_TREE;
!   current_function_dhc = NULL_RTX;
!   current_function_dcc = NULL_RTX;
  }
  
  /* Save some of the per-function EH info into the save area denoted by
--- 1940,1946 ----
    false_label_stack = 0;
    caught_return_label_stack = 0;
    protect_list = NULL_TREE;
!   current_function_ehc = NULL_RTX;
  }
  
  /* Save some of the per-function EH info into the save area denoted by
***************
*** 1974,1981 ****
    p->false_label_stack = false_label_stack;
    p->caught_return_label_stack = caught_return_label_stack;
    p->protect_list = protect_list;
!   p->dhc = current_function_dhc;
!   p->dcc = current_function_dcc;
  
    init_eh ();
  }
--- 1961,1967 ----
    p->false_label_stack = false_label_stack;
    p->caught_return_label_stack = caught_return_label_stack;
    p->protect_list = protect_list;
!   p->ehc = current_function_ehc;
  
    init_eh ();
  }
***************
*** 1997,2004 ****
    catch_clauses	= p->catch_clauses;
    ehqueue = p->ehqueue;
    ehstack = p->ehstack;
!   current_function_dhc = p->dhc;
!   current_function_dcc = p->dcc;
  }
  
  /* This section is for the exception handling specific optimization
--- 1983,1989 ----
    catch_clauses	= p->catch_clauses;
    ehqueue = p->ehqueue;
    ehstack = p->ehstack;
!   current_function_ehc = p->ehc;
  }
  
  /* This section is for the exception handling specific optimization
diff -r -N -c egcs-1.0.orig/gcc/except.h egcs-1.0/gcc/except.h
*** egcs-1.0.orig/gcc/except.h	Fri Nov 21 20:21:39 1997
--- egcs-1.0/gcc/except.h	Tue Dec 16 18:33:51 1997
***************
*** 251,270 ****
  
  extern rtx exception_handler_labels;
  
- /* The rtx for the saved PC value.  */
- 
- extern rtx eh_saved_pc_rtx;
- 
  /* Performs optimizations for exception handling, such as removing
     unnecessary exception regions. Invoked from jump_optimize ().  */
  
  extern void exception_optimize			PROTO((void));
  
  /* Get the dynamic handler chain.  */
  extern rtx get_dynamic_handler_chain		PROTO((void));
  
  /* Get the dynamic cleanup chain.  */
  extern rtx get_dynamic_cleanup_chain		PROTO((void));
  
  /* Throw an exception.  */
  
--- 251,272 ----
  
  extern rtx exception_handler_labels;
  
  /* Performs optimizations for exception handling, such as removing
     unnecessary exception regions. Invoked from jump_optimize ().  */
  
  extern void exception_optimize			PROTO((void));
  
+ /* Get the EH contex.  */
+ extern rtx get_eh_context                     PROTO((void));
+ 
  /* Get the dynamic handler chain.  */
  extern rtx get_dynamic_handler_chain		PROTO((void));
  
  /* Get the dynamic cleanup chain.  */
  extern rtx get_dynamic_cleanup_chain		PROTO((void));
+ 
+ /* Get the saved PC variable. */
+ extern rtx get_saved_pc_ref                   PROTO((void));
  
  /* Throw an exception.  */
  
diff -r -N -c egcs-1.0.orig/gcc/expr.h egcs-1.0/gcc/expr.h
*** egcs-1.0.orig/gcc/expr.h	Fri Aug 29 16:02:03 1997
--- egcs-1.0/gcc/expr.h	Tue Dec 16 18:23:33 1997
***************
*** 417,422 ****
--- 417,424 ----
  extern rtx setjmp_libfunc;
  extern rtx longjmp_libfunc;
  extern rtx get_dynamic_handler_chain_libfunc;
+ extern rtx get_saved_pc_libfunc;
+ extern rtx get_eh_context_libfunc;
  
  extern rtx eqhf2_libfunc;
  extern rtx nehf2_libfunc;
diff -r -N -c egcs-1.0.orig/gcc/frame.c egcs-1.0/gcc/frame.c
*** egcs-1.0.orig/gcc/frame.c	Fri Nov  7 18:57:23 1997
--- egcs-1.0/gcc/frame.c	Tue Dec 16 18:33:25 1997
***************
*** 39,44 ****
--- 39,50 ----
  #include "frame.h"
  #include <stddef.h>
  
+ #include "libgcc-thr.h"
+ #ifdef __GTHREAD_MUTEX_INIT
+ static __gthread_mutex_t object_mutex = __GTHREAD_MUTEX_INIT;
+ #else
+ static __gthread_mutex_t object_mutex;
+ #endif
  /* Don't use `fancy_abort' here even if config.h says to use it.  */
  #ifdef abort
  #undef abort
***************
*** 306,311 ****
--- 312,318 ----
    struct object *ob;
    size_t lo, hi;
  
+   __gthread_mutex_lock (&object_mutex);
    for (ob = objects; ob; ob = ob->next)
      {
        if (ob->pc_begin == 0)
***************
*** 314,319 ****
--- 321,327 ----
  	break;
      }
  
+   __gthread_mutex_unlock (&object_mutex);
    if (ob == 0)
      return 0;
  
***************
*** 521,528 ****
--- 529,538 ----
    ob->fde_array = 0;
    ob->count = 0;
  
+   __gthread_mutex_lock (&object_mutex);
    ob->next = objects;
    objects = ob;
+   __gthread_mutex_unlock (&object_mutex);
  }
  
  /* Similar, but BEGIN is actually a pointer to a table of unwind entries
***************
*** 540,547 ****
--- 550,559 ----
    ob->pc_begin = ob->pc_end = 0;
    ob->count = 0;
  
+   __gthread_mutex_lock (&object_mutex);
    ob->next = objects;
    objects = ob;
+   __gthread_mutex_unlock (&object_mutex);
  }
  
  /* Called from crtend.o to deregister the unwind info for an object.  */
***************
*** 549,556 ****
  void
  __deregister_frame (void *begin)
  {
!   struct object **p = &objects;
  
    while (*p)
      {
        if ((*p)->fde_begin == begin)
--- 561,570 ----
  void
  __deregister_frame (void *begin)
  {
!   struct object **p;
  
+   __gthread_mutex_lock (&object_mutex);
+   p = &objects;
    while (*p)
      {
        if ((*p)->fde_begin == begin)
***************
*** 563,572 ****
--- 577,588 ----
  	    free (ob->fde_array);
  	  free (ob);
  
+ 	  __gthread_mutex_unlock (&object_mutex);
  	  return;
  	}
        p = &((*p)->next);
      }
+   __gthread_mutex_unlock (&object_mutex);
    abort ();
  }
  
diff -r -N -c egcs-1.0.orig/gcc/function.h egcs-1.0/gcc/function.h
*** egcs-1.0.orig/gcc/function.h	Mon Aug 11 16:57:07 1997
--- egcs-1.0/gcc/function.h	Tue Dec 16 18:23:33 1997
***************
*** 136,143 ****
    struct label_node *false_label_stack;
    struct label_node *caught_return_label_stack;
    tree protect_list;
!   rtx dhc;
!   rtx dcc;
  
    /* For expr.c.  */
    int pending_stack_adjust;
--- 136,142 ----
    struct label_node *false_label_stack;
    struct label_node *caught_return_label_stack;
    tree protect_list;
!   rtx ehc;
  
    /* For expr.c.  */
    int pending_stack_adjust;
diff -r -N -c egcs-1.0.orig/gcc/libgcc-thr.h egcs-1.0/gcc/libgcc-thr.h
*** egcs-1.0.orig/gcc/libgcc-thr.h	Thu Jan  1 01:00:00 1970
--- egcs-1.0/gcc/libgcc-thr.h	Wed Dec 17 22:15:02 1997
***************
*** 0 ****
--- 1,256 ----
+ /* Threads compatibily routines for libgcc2.  */
+ /* Compile this one with gcc.  */
+ /* Copyright (C) 1997 Free Software Foundation, Inc.
+ This file is part of GNU CC.
+ GNU CC 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.
+ GNU CC 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 GNU CC; see the file COPYING.  If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.  */
+ /* As a special exception, if you link this library with other files,
+    some of which are compiled with GCC, to produce an executable,
+    this library does not by itself cause the resulting executable
+    to be covered by the GNU General Public License.
+    This exception does not however invalidate any other reasons why
+    the executable file might be covered by the GNU General Public License.  */
+ #ifndef __libgcc_thr_h
+ #define __libgcc_thr_h
+ /* If this file is compiled with threads support, it must
+        #define __GTHREADS 1
+    to indicate that threads support is present.
+    The threads interface must define the following types:
+      __gthread_key_t
+      __gthread_once_t
+      __gthread_mutex_t
+    The threads interface must define the following macros:
+      __GTHREAD_ONCE_INIT
+               to initialize __gthread_once_t
+      __GTHREAD_MUTEX_INIT
+               to initialize __gthread_mutex_t to get a fast
+               non-recursive mutex.
+    The threads interface must define the following static functions:
+      int __gthread_once (__gthread_once_t *once, void (*func) ())
+      int __gthread_key_create (__gthread_key_t *keyp, void (*dtor) (void *))
+      int __gthread_key_delete (__gthread_key_t key)
+      void *__gthread_getspecific (__gthread_key_t key)
+      int __gthread_setspecific (__gthread_key_t key, const void *ptr)
+      int __gthread_mutex_lock (__gthread_mutex_t *mutex);
+      int __gthread_mutex_trylock (__gthread_mutex_t *mutex);
+      int __gthread_mutex_unlock (__gthread_mutex_t *mutex);
+    All functions returning int should return 0 on success, -1 on error.
+    Currently supported threads packages are
+      POSIX threads with -D_PTHREADS
+      DCE threads with -D_DCE_THREADS
+      Solaris/UI threads with -D_SOLARIS_THREADS
+ */
+ #if _PTHREADS
+ /* POSIX threads specific definitions.
+    Easy, since the interface is just one-to-one mapping. */
+ #define __GTHREADS 1
+ #include <pthread.h>
+ typedef pthread_key_t __gthread_key_t;
+ typedef pthread_once_t __gthread_once_t;
+ typedef pthread_mutex_t __gthread_mutex_t;
+ #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
+ #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
+ static inline int
+ __gthread_once (__gthread_once_t *once, void (*func) ())
+ {
+   return pthread_once (once, func);
+ }
+ static inline int
+ __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
+ {
+   return pthread_key_create (key, dtor);
+ }
+ static inline int
+ __gthread_key_delete (__gthread_key_t key)
+ {
+   return pthread_key_delete (key);
+ }
+ static inline void *
+ __gthread_getspecific (__gthread_key_t key)
+ {
+   return pthread_getspecific (key);
+ }
+ static inline int
+ __gthread_setspecific (__gthread_key_t key, const void *ptr)
+ {
+   return pthread_setspecific (key, ptr);
+ }
+ static inline int
+ __gthread_mutex_lock (__gthread_mutex_t *mutex)
+ {
+   return pthread_mutex_lock (mutex);
+ }
+ static inline int
+ __gthread_mutex_trylock (__gthread_mutex_t *mutex)
+ {
+   return pthread_mutex_trylock (mutex);
+ }
+ static inline int
+ __gthread_mutex_unlock (__gthread_mutex_t *mutex)
+ {
+   return pthread_mutex_unlock (mutex);
+ }
+ #elif _DCE_THREADS
+ /* DCE threads interface.
+    DCE threads are based on POSIX threads draft 4, and many things
+    have changed since then. */
+ #define __GTHREADS 1
+ #include <pthread.h>
+ typedef pthread_key_t __gthread_key_t;
+ typedef pthread_once_t __gthread_once_t;
+ typedef pthread_mutex_t __gthread_mutex_t;
+ #define __GTHREAD_ONCE_INIT pthread_once_init
+ /* Howto define __GTHREAD_MUTEX_INIT? */
+ static inline int
+ __gthread_once (__gthread_once_t *once, void (*func) ())
+ {
+   return pthread_once (once, func);
+ }
+ static inline int
+ __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
+ {
+   return pthread_keycreate (key, dtor);
+ }
+ static inline int
+ __gthread_key_delete (__gthread_key_t key)
+ {
+   return pthread_key_delete (key);
+ }
+ static inline void *
+ __gthread_getspecific (__gthread_key_t key)
+ {
+   void *ptr;
+   if (pthread_getspecific (key, &ptr) == 0)
+     return ptr;
+   else
+     return 0;
+ }
+ static inline int
+ __gthread_setspecific (__gthread_key_t key, const void *ptr)
+ {
+   return pthread_setspecific (key, (void *) ptr);
+ }
+ static inline int
+ __gthread_mutex_lock (__gthread_mutex_t *mutex)
+ {
+   return pthread_mutex_lock (mutex);
+ }
+ static inline int
+ __gthread_mutex_trylock (__gthread_mutex_t *mutex)
+ {
+   return pthread_mutex_trylock (mutex);
+ }
+ static inline int
+ __gthread_mutex_unlock (__gthread_mutex_t *mutex)
+ {
+   return pthread_mutex_unlock (mutex);
+ }
+ #elif _SOLARIS_THREADS
+ /* Solaris threads as found in Solaris 2.[456].
+    Actually these are Unix International (UI) threads, but I don't
+    know if anyone else implements these. */
+ #define __GTHREADS 1
+ #include <thread.h>
+ #include <sched.h>
+ #include <errno.h>
+ typedef thread_key_t __gthread_key_t;
+ typedef struct
+ {
+   mutex_t mutex;
+   int once;
+ } __gthread_once_t;
+ typedef mutex_t __gthread_mutex_t;
+ #define __GTHREAD_ONCE_INIT { DEFAULTMUTEX, 0 }
+ #define __GTHREAD_MUTEX_INIT DEFAULTMUTEX
+ static inline int
+ __gthread_once (__gthread_once_t *once, void (*func) ())
+ {
+   if (once == 0 || func == 0)
+     {
+       errno = EINVAL;
+       return -1;
+     }
+   if (once->once == 0)
+     {
+       if (mutex_lock (&once->mutex) != 0)
+       return -1;
+       if (once->once == 0)
+       {
+         (*func) ();
+         once->once ++;
+       }
+       mutex_unlock (&once->mutex);
+     }
+   return 0;
+ }
+ static inline int
+ __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
+ {
+   return thr_keycreate (key, dtor);
+ }
+ static inline int
+ __gthread_key_delete (__gthread_key_t key)
+ {
+   /* Not possible. */
+   return -1;
+ }
+ static inline void *
+ __gthread_getspecific (__gthread_key_t key)
+ {
+   void *ptr;
+   if (thr_getspecific (key, &ptr) == 0)
+     return ptr;
+   else
+     return 0;
+ }
+ static inline int
+ __gthread_setspecific (__gthread_key_t key, const void *ptr)
+ {
+   return thr_setspecific (key, (void *) ptr);
+ }
+ static inline int
+ __gthread_mutex_lock (__gthread_mutex_t *mutex)
+ {
+   return mutex_lock (mutex);
+ }
+ static inline int
+ __gthread_mutex_trylock (__gthread_mutex_t *mutex)
+ {
+   return mutex_trylock (mutex);
+ }
+ static inline int
+ __gthread_mutex_unlock (__gthread_mutex_t *mutex)
+ {
+   return mutex_unlock (mutex);
+ }
+ #else /* no threads */
+ /* Just provide compatibility for mutex handling. */
+ typedef int __gthread_mutex_t;
+ #define __GTHREAD_MUTEX_INIT 0
+ static inline int
+ __gthread_mutex_lock (__gthread_mutex_t *mutex)
+ {
+   return 0;
+ }
+ static inline int
+ __gthread_mutex_trylock (__gthread_mutex_t *mutex)
+ {
+   return 0;
+ }
+ static inline int
+ __gthread_mutex_unlock (__gthread_mutex_t *mutex)
+ {
+   return 0;
+ }
+ #endif /* no threads */
+ #endif /* not __libgcc_thr_h */
diff -r -N -c egcs-1.0.orig/gcc/libgcc2.c egcs-1.0/gcc/libgcc2.c
*** egcs-1.0.orig/gcc/libgcc2.c	Wed Nov 26 07:40:30 1997
--- egcs-1.0/gcc/libgcc2.c	Wed Dec 17 21:22:17 1997
***************
*** 3107,3117 ****
  
  #ifdef L_eh
  
! /* Shared exception handling support routines.  */
  
! /* Language-specific information about the active exception(s).  If there
!    are no active exceptions, it is set to 0.  */
! void *__eh_info;
  
  void
  __default_terminate ()
--- 3107,3115 ----
  
  #ifdef L_eh
  
! #include "libgcc-thr.h"
  
! /* Shared exception handling support routines.  */
  
  void
  __default_terminate ()
***************
*** 3144,3184 ****
  {
  }
  
  /* Support routines for setjmp/longjmp exception handling.  */
  
  /* Calls to __sjthrow are generated by the compiler when an exception
     is raised when using the setjmp/longjmp exception handling codegen
     method.  */
  
  extern void longjmp (void *, int);
! 
! static void *top_elt[2];
! void **__dynamic_handler_chain = top_elt;
  
  /* Routine to get the head of the current thread's dynamic handler chain
     use for exception handling.
! 
!    TODO: make thread safe.  */
  
  void ***
  __get_dynamic_handler_chain ()
  {
!   return &__dynamic_handler_chain;
  }
  
  /* This is used to throw an exception when the setjmp/longjmp codegen
     method is used for exception handling.
  
!    We call __terminate if there are no handlers left (we know this
!    when the dynamic handler chain is top_elt).  Otherwise we run the
!    cleanup actions off the dynamic cleanup stack, and pop the top of
!    the dynamic handler chain, and use longjmp to transfer back to the
!    associated handler.  */
  
  void
  __sjthrow ()
  {
!   void ***dhc = __get_dynamic_handler_chain ();
    void *jmpbuf;
    void (*func)(void *, int);
    void *arg;
--- 3142,3302 ----
  {
  }
  
+ /* EH context structure. */
+ struct eh_context
+ {
+   void **dynamic_handler_chain;
+   void *saved_pc;
+ #ifndef DWARF2_UNWIND_INFO
+   void *buf[2];
+ #endif
+   /* This is language dependent part of the eh context. */
+   void *info;
+ };
+ /* This is a safeguard for dynamic handler chain. */
+ static void *top_elt[2];
+ /* Allocate and return a new EH context structure. */
+ extern void __throw ();
+ static void *
+ new_eh_context ()
+ {
+   struct eh_context *eh = (struct eh_context *) malloc (sizeof *eh);
+   if (! eh)
+     __terminate ();
+   memset (eh, 0, sizeof *eh);
+   eh->dynamic_handler_chain = top_elt;
+ #ifndef DWARF2_UNWIND_INFO
+   eh->buf[0] = &eh->saved_pc;
+   eh->buf[1] = &__throw;
+ #endif
+   return eh;
+ }
+ #if __GTHREADS
+ static __gthread_key_t eh_context_key;
+ /* Destructor for struct eh_context. */
+ static void
+ eh_context_free (void *ptr)
+ {
+   if (__gthread_setspecific (eh_context_key,NULL) != 0)
+     __terminate ();
+   if (ptr)
+     free (ptr);
+ }
+ #endif
+ /* Pointer to function to return EH context. */
+ static struct eh_context *eh_context_initialize ();
+ static struct eh_context *eh_context_static ();
+ #if __GTHREADS
+ static struct eh_context *eh_context_specific ();
+ #endif
+ static struct eh_context *(*get_eh_context) () = &eh_context_initialize;
+ /* Routine to get EH context.
+    This one will simply call the function pointer. */
+ void *
+ __get_eh_context ()
+ {
+   return (void *) (*get_eh_context) ();
+ }
+ /* Get and set the language specific info pointer. */
+ void **
+ __get_eh_info ()
+ {
+   struct eh_context *eh = (*get_eh_context) ();
+   return (void **) &eh->info;
+ }
+ #if __GTHREADS
+ static void
+ eh_threads_initialize ()
+ {
+   /* Try to create the key.  If it fails, revert to static method,
+      otherwise start using thread specific EH contexts. */
+   if (__gthread_key_create (&eh_context_key, &eh_context_free) == 0)
+     get_eh_context = &eh_context_specific;
+   else
+     get_eh_context = &eh_context_static;
+ }
+ #endif /* no __GTHREADS */
+ /* Initialize EH context.
+    This will be called only once, since we change GET_EH_CONTEXT
+    pointer to another routine. */
+ static struct eh_context *
+ eh_context_initialize ()
+ {
+ #if __GTHREADS
+   static __gthread_once_t once = __GTHREAD_ONCE_INIT;
+   __gthread_once (&once, eh_threads_initialize);
+ #else /* no __GTHREADS */
+   /* Use static version of EH context. */
+   get_eh_context = &eh_context_static;
+ #endif /* no __GTHREADS */
+   return (*get_eh_context) ();
+ }
+ /* Return a static EH context. */
+ static struct eh_context *
+ eh_context_static ()
+ {
+   static struct eh_context *eh;
+   if (! eh)
+     eh = new_eh_context ();
+   return eh;
+ }
+ #if __GTHREADS
+ /* Return a thread specific EH context. */
+ static struct eh_context *
+ eh_context_specific ()
+ {
+   struct eh_context *eh;
+   eh = (struct eh_context *) __gthread_getspecific (eh_context_key);
+   if (! eh)
+     {
+       eh = new_eh_context ();
+       if (__gthread_setspecific (eh_context_key, (void *) eh) != 0)
+       __terminate ();
+     }
+   return eh;
+ }
+ #endif __GTHREADS
+ 
  /* Support routines for setjmp/longjmp exception handling.  */
  
  /* Calls to __sjthrow are generated by the compiler when an exception
     is raised when using the setjmp/longjmp exception handling codegen
     method.  */
  
+ #ifdef DONT_USE_BUILTIN_SETJMP
  extern void longjmp (void *, int);
! #endif
  
  /* Routine to get the head of the current thread's dynamic handler chain
     use for exception handling.
!  */
  
  void ***
  __get_dynamic_handler_chain ()
  {
!   struct eh_context *eh = (*get_eh_context) ();
!   return (void ***) &eh->dynamic_handler_chain;
! }
! void **
! __get_saved_pc ()
! {
!   struct eh_context *eh = (*get_eh_context) ();
!   return (void **) &eh->saved_pc;
  }
  
  /* This is used to throw an exception when the setjmp/longjmp codegen
     method is used for exception handling.
  
!    We call __terminate if there are no handlers left.  Otherwise we run the
!    cleanup actions off the dynamic cleanup stack, and pop the top of the
!    dynamic handler chain, and use longjmp to transfer back to the associated
!    handler.  */
  
  void
  __sjthrow ()
  {
!   struct eh_context *eh = (*get_eh_context) ();
!   void ***dhc = &eh->dynamic_handler_chain;
    void *jmpbuf;
    void (*func)(void *, int);
    void *arg;
***************
*** 3226,3232 ****
    /* We must call terminate if we try and rethrow an exception, when
       there is no exception currently active and when there are no
       handlers left.  */
!   if (! __eh_info || (*dhc) == top_elt)
      __terminate ();
      
    /* Find the jmpbuf associated with the top element of the dynamic
--- 3344,3350 ----
    /* We must call terminate if we try and rethrow an exception, when
       there is no exception currently active and when there are no
       handlers left.  */
!   if (! eh->info || (*dhc) == top_elt)
      __terminate ();
      
    /* Find the jmpbuf associated with the top element of the dynamic
***************
*** 3253,3259 ****
  void
  __sjpopnthrow ()
  {
!   void ***dhc = __get_dynamic_handler_chain ();
    void *jmpbuf;
    void (*func)(void *, int);
    void *arg;
--- 3371,3378 ----
  void
  __sjpopnthrow ()
  {
!   struct eh_context *eh = (*get_eh_context) ();
!   void ***dhc = &eh->dynamic_handler_chain;
    void *jmpbuf;
    void (*func)(void *, int);
    void *arg;
***************
*** 3309,3316 ****
  /* This value identifies the place from which an exception is being
     thrown.  */
  
- void *__eh_pc;
- 
  #ifdef EH_TABLE_LOOKUP
  
  EH_TABLE_LOOKUP
--- 3428,3433 ----
***************
*** 3433,3443 ****
  /* See expand_builtin_throw for details.  */
  
  void **__eh_pcnthrow () {
!   static void *buf[2] = {
!     &__eh_pc,
!     &__throw
!   };
!   return buf;
  }
  
  #if #machine(i386)
--- 3550,3557 ----
  /* See expand_builtin_throw for details.  */
  
  void **__eh_pcnthrow () {
!   struct eh_context *eh = (*get_eh_context) ();
!   return &eh->buf[0];
  }
  
  #if #machine(i386)
***************
*** 3644,3649 ****
--- 3758,3764 ----
  void
  __throw ()
  {
+   struct eh_context *eh = (*get_eh_context) ();
    void *pc, *handler, *retaddr;
    frame_state ustruct, ustruct2;
    frame_state *udata = &ustruct;
***************
*** 3654,3660 ****
    /* This is required for C++ semantics.  We must call terminate if we
       try and rethrow an exception, when there is no exception currently
       active.  */
!   if (! __eh_info)
      __terminate ();
      
    /* Start at our stack frame.  */
--- 3769,3775 ----
    /* This is required for C++ semantics.  We must call terminate if we
       try and rethrow an exception, when there is no exception currently
       active.  */
!   if (! eh->info)
      __terminate ();
      
    /* Start at our stack frame.  */
***************
*** 3679,3685 ****
    __builtin_unwind_init ();
  
    /* Now reset pc to the right throw point.  */
!   pc = __eh_pc;
  
    handler = 0;
    for (;;)
--- 3794,3800 ----
    __builtin_unwind_init ();
  
    /* Now reset pc to the right throw point.  */
!   pc = eh->saved_pc;
  
    handler = 0;
    for (;;)
***************
*** 3711,3717 ****
    if (! handler)
      __terminate ();
  
!   if (pc == __eh_pc)
      /* We found a handler in the throw context, no need to unwind.  */
      udata = my_udata;
    else
--- 3826,3832 ----
    if (! handler)
      __terminate ();
  
!   if (pc == eh->saved_pc)
      /* We found a handler in the throw context, no need to unwind.  */
      udata = my_udata;
    else
***************
*** 3726,3732 ****
        void *handler_pc = pc;
  
        /* Start from the throw context again.  */
!       pc = __eh_pc;
        memcpy (udata, my_udata, sizeof (*udata));
  
        while (pc != handler_pc)
--- 3841,3847 ----
        void *handler_pc = pc;
  
        /* Start from the throw context again.  */
!       pc = eh->saved_pc;
        memcpy (udata, my_udata, sizeof (*udata));
  
        while (pc != handler_pc)
diff -r -N -c egcs-1.0.orig/gcc/optabs.c egcs-1.0/gcc/optabs.c
*** egcs-1.0.orig/gcc/optabs.c	Mon Aug 11 16:57:11 1997
--- egcs-1.0/gcc/optabs.c	Tue Dec 16 18:23:33 1997
***************
*** 125,130 ****
--- 125,132 ----
  rtx setjmp_libfunc;
  rtx longjmp_libfunc;
  rtx get_dynamic_handler_chain_libfunc;
+ rtx get_saved_pc_libfunc;
+ rtx get_eh_context_libfunc;
  
  rtx eqhf2_libfunc;
  rtx nehf2_libfunc;
***************
*** 4290,4295 ****
--- 4292,4299 ----
    longjmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "longjmp");
  #endif
    get_dynamic_handler_chain_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__get_dynamic_handler_chain");
+   get_saved_pc_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__get_saved_pc");
+   get_eh_context_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__get_eh_context");
  
    eqhf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqhf2");
    nehf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nehf2");
