[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

MiNTlib: updates for gcc 2.6



There are some changes needed in the MiNTlib to support gcc 2.6:

- libgcc2.c has new modules (_op_vnew.o _op_vdel.o _eh.o _pure.o), and
there are a few bug fixes and cleanups.
- in <linea.h> the macro linea0() has to be changed so that it
compiles with -mbaserel, otherwise gcc dies with "fixed or forbidden
register has been spilled".  This is probably a bug in gcc since
similar problems occured with the Linux/x86 kernel, where they had to
change some asm statements to work around this, too.


--- orig/libgcc2.c	Tue Feb 15 20:23:48 1994
+++ libgcc2.c	Thu Nov 10 18:55:16 1994
@@ -1,6 +1,6 @@
 /* More subroutines needed by GCC output code on some machines.  */
 /* Compile this one with gcc.  */
-/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1992, 1993, 1994 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -18,9 +18,10 @@
 along with GNU CC; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
-/* As a special exception, if you link this library with files
-   compiled with GCC to produce an executable, this does not cause
-   the resulting executable to be covered by the GNU General Public License.
+/* 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.  */
 
@@ -33,7 +34,7 @@
 #include "tconfig.h"
 #include "machmode.h"
 #ifndef L_trampoline
-#include "gstddef.h"
+#include <stddef.h>
 #endif
 
 /* Don't use `fancy_abort' here even if config.h says to use it.  */
@@ -779,7 +780,7 @@
 __umoddi3 (u, v)
      UDItype u, v;
 {
-  DItype w;
+  UDItype w;
 
   (void) __udivmoddi4 (u, v, &w);
 
@@ -1093,6 +1094,9 @@
 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
+#define DI_SIZE (sizeof (DItype) * BITS_PER_UNIT)
+#define DF_SIZE 53
+#define SF_SIZE 24
 
 SFtype
 __floatdisf (u)
@@ -1107,6 +1111,22 @@
   if (u < 0)
     u = -u, negate = 1;
 
+  /* Protect against double-rounding error.
+     Represent any low-order bits, that might be truncated in DFmode,
+     by a bit that won't be lost.  The bit can go in anywhere below the
+     rounding position of the SFmode.  A fixed mask and bit position
+     handles all usual configurations.  It doesn't handle the case
+     of 128-bit DImode, however.  */
+  if (DF_SIZE < DI_SIZE
+      && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
+    {
+#define REP_BIT ((USItype) 1 << (DI_SIZE - DF_SIZE))
+      if (u >= ((UDItype) 1 << DF_SIZE))
+	{
+	  if ((USItype) u & (REP_BIT - 1))
+	    u |= REP_BIT;
+	}
+    }
   f = (USItype) (u >> WORD_SIZE);
   f *= HIGH_HALFWORD_COEFF;
   f *= HIGH_HALFWORD_COEFF;
@@ -1171,16 +1191,18 @@
 #undef float
 #undef double
 
-/* frills for C++ */
+/* Default free-store management functions for C++, per sections 12.5 and
+   17.3.3 of the Working Paper. */
 
 #ifdef L_op_new
+/* operator new (size_t), described in 17.3.3.5.  This function is used by
+   C++ programs to allocate a block of memory to hold a single object. */
+
 #include <memory.h>
 
 typedef void (*vfp)(void);
-
 extern vfp __new_handler;
 
-/* void * operator new (size_t sz) */
 void *
 __builtin_new (size_t sz)
 {
@@ -1190,53 +1212,63 @@
   if (sz == 0)
     sz = 1;
   p = (void *) malloc (sz);
-  if (p == 0)
-    (*__new_handler) ();
+  while (p == 0)
+    {
+      (*__new_handler) ();
+      p = (void *) malloc (sz);
+    }
+  
   return p;
 }
 #endif /* L_op_new */
 
+#ifdef L_op_vnew
+/* void * operator new [] (size_t), described in 17.3.3.6.  This function
+   is used by C++ programs to allocate a block of memory for an array.  */
+
+extern void * __builtin_new (size_t);
+
+void *
+__builtin_vec_new (size_t sz)
+{
+  return __builtin_new (sz);
+}
+#endif /* L_op_vnew */
+
 #ifdef L_new_handler
+/* set_new_handler (fvoid_t *) and the default new handler, described in
+   17.3.3.2 and 17.3.3.5.  These functions define the result of a failure
+   to allocate the amount of memory requested from operator new or new []. */
 
   /* Avoid forcing the library's meaning of `write' on the user program
      by using the "internal" name (for use within the library)  */
 #define write(fd, buf, n)	_write((fd), (buf), (n))
 
 typedef void (*vfp)(void);
+void __default_new_handler (void);
 
-extern void *__builtin_new (size_t);
-static void default_new_handler (void);
-
-vfp __new_handler = default_new_handler;
+vfp __new_handler = __default_new_handler;
 
 vfp
-__set_new_handler (handler)
-     vfp handler;
+set_new_handler (vfp handler)
 {
   vfp prev_handler;
 
   prev_handler = __new_handler;
-  if (handler == 0) handler = default_new_handler;
+  if (handler == 0) handler = __default_new_handler;
   __new_handler = handler;
   return prev_handler;
 }
 
-vfp
-set_new_handler (handler)
-     vfp handler;
-{
-  return __set_new_handler (handler);
-}
-
 #define MESSAGE "Virtual memory exceeded in `new'\n"
 
-static void
-default_new_handler ()
+void
+__default_new_handler ()
 {
   /* don't use fprintf (stderr, ...) because it may need to call malloc.  */
   /* This should really print the name of the program, but that is hard to
      do.  We need a standard, clean way to get at the name.  */
-  write (2, MESSAGE, sizeof (MESSAGE));
+  write (2, MESSAGE, sizeof (MESSAGE) - 1);
   /* don't call exit () because that may call global destructors which
      may cause a loop.  */
   _exit (-1);
@@ -1244,7 +1276,10 @@
 #endif
 
 #ifdef L_op_delete
-/* void operator delete (void *ptr) */
+/* operator delete (void *), described in 17.3.3.3.  This function is used
+   by C++ programs to return to the free store a block of memory allocated
+   as a single object. */
+
 void
 __builtin_delete (void *ptr)
 {
@@ -1252,6 +1287,22 @@
     free (ptr);
 }
 #endif
+
+#ifdef L_op_vdel
+/* operator delete [] (void *), described in 17.3.3.4.  This function is
+   used by C++ programs to return to the free store a block of memory
+   allocated as an array. */
+
+extern void __builtin_delete (void *);
+
+void
+__builtin_vec_delete (void *ptr)
+{
+  __builtin_delete (ptr);
+}
+#endif
+
+/* End of C++ free-store management functions */
 
 #ifdef L_trampoline
 
@@ -1271,21 +1322,13 @@
 void
 __do_global_dtors ()
 {
-  unsigned nptrs = (unsigned long) __DTOR_LIST__[0];
-  unsigned i;
-
-  /* Some systems place the number of pointers
-     in the first word of the table.
-     On other systems, that word is -1.
-     In all cases, the table is null-terminated.  */
-
-  /* If the length is not recorded, count up to the null.  */
-  if (nptrs == -1)
-    for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++);
-
-  /* GNU LD format.  */
-  for (i = nptrs; i >= 1; i--)
-    __DTOR_LIST__[i] ();
+#ifdef DO_GLOBAL_DTORS_BODY
+  DO_GLOBAL_DTORS_BODY;
+#else
+  func_ptr *p;
+  for (p = __DTOR_LIST__ + 1; *p; )
+    (*p++) ();
+#endif
 }
 
 /* Run all the global constructors on entry to the program.  */
@@ -1327,3 +1370,167 @@
 #include "gbl-ctors.h"
 const func_ptr __DTOR_LIST__[2] = {0, 0};
 #endif /* L_ctor_list */
+
+#ifdef L_eh
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct {
+  void *start;
+  void *end;
+  void *exception_handler;
+} exception_table;
+
+struct exception_table_node {
+  exception_table *table;
+  void *start;
+  void *end;
+  struct exception_table_node *next;
+};
+
+static int except_table_pos = 0;
+static void *except_pc = (void *)0;
+static struct exception_table_node *exception_table_list = 0;
+
+static exception_table *
+find_exception_table (pc)
+     void* pc;
+{
+  register struct exception_table_node *table = exception_table_list;
+  for ( ; table != 0; table = table->next)
+    {
+      if (table->start <= pc && table->end > pc)
+	return table->table;
+    }
+  return 0;
+}
+
+/* this routine takes a pc, and the address of the exception handler associated
+   with the closest exception table handler entry associated with that PC,
+   or 0 if there are no table entries the PC fits in.  The algorithm works
+   something like this:
+
+    while(current_entry exists) {
+        if(current_entry.start < pc )
+            current_entry = next_entry;
+        else {
+            if(prev_entry.start <= pc && prev_entry.end > pc) {
+                save pointer to prev_entry;
+                return prev_entry.exception_handler;
+             }
+            else return 0;
+         }
+     }
+    return 0;
+
+   Assuming a correctly sorted table (ascending order) this routine should
+   return the tighest match...
+
+   In the advent of a tie, we have to give the last entry, as it represents
+   an inner block.
+ */
+
+
+void *
+__find_first_exception_table_match(pc)
+void *pc;
+{
+  exception_table *table = find_exception_table (pc);
+  int pos = 0;
+  int best = 0;
+  if (table == 0)
+    return (void*)0;
+#if 0
+  printf("find_first_exception_table_match(): pc = %x!\n",pc);
+#endif
+
+  except_pc = pc;
+
+#if 0
+  /* We can't do this yet, as we don't know that the table is sorted.  */
+  do {
+    ++pos;
+    if (table[pos].start > except_pc)
+      /* found the first table[pos].start > except_pc, so the previous
+	 entry better be the one we want! */
+      break;
+  } while(table[pos].exception_handler != (void*)-1);
+
+  --pos;
+  if (table[pos].start <= except_pc && table[pos].end > except_pc)
+    {
+      except_table_pos = pos;
+#if 0
+      printf("find_first_eh_table_match(): found match: %x\n",table[pos].exception_handler);
+#endif
+      return table[pos].exception_handler;
+    }
+#else
+  while (table[++pos].exception_handler != (void*)-1) {
+    if (table[pos].start <= except_pc && table[pos].end > except_pc)
+      {
+	/* This can apply.  Make sure it is better or as good as the previous
+	   best.  */
+	/* The best one ends first. */
+	if (best == 0 || (table[pos].end <= table[best].end
+			  /* The best one starts last.  */
+			  && table[pos].start >= table[best].start))
+	  best = pos;
+      }
+  }
+  if (best != 0)
+    return table[best].exception_handler;
+#endif
+
+#if 0
+  printf("find_first_eh_table_match(): else: returning NULL!\n");
+#endif
+  return (void*)0;
+}
+
+int
+__throw_type_match (const char *catch_type, const char *throw_type)
+{
+#if 0
+ printf("__throw_type_match (): catch_type = %s, throw_type = %s\n",
+	catch_type, throw_type);
+#endif
+ return strcmp (catch_type, throw_type);
+}
+
+void
+__register_exceptions (exception_table *table)
+{
+  struct exception_table_node *node = (struct exception_table_node*)
+      malloc (sizeof (struct exception_table_node));
+  exception_table *range = table + 1;
+  node->table = table;
+
+  /* This look can be optimized away either if the table
+     is sorted, or if we pass in extra parameters. */
+  node->start = range->start;
+  node->end = range->end;
+  for (range++ ; range->start != (void*)(-1); range++)
+    {
+      if (range->start < node->start)
+	node->start = range->start;
+      if (range->end < node->end)
+	node->end = range->end;
+    }
+
+  node->next = exception_table_list;
+  exception_table_list = node;
+}
+#endif /* L_eh */
+
+#ifdef L_pure
+#include <unistd.h>
+#define MESSAGE "pure virtual method called\n"
+#define write(fd, buf, n)	_write((fd), (buf), (n))
+void
+__pure_virtual ()
+{
+  write (2, MESSAGE, sizeof (MESSAGE) - 1);
+  _exit (-1);
+}
+#endif
--- orig/mincl	Tue Jul 19 18:53:30 1994
+++ mincl	Thu Nov 10 18:16:16 1994
@@ -13,7 +13,7 @@
 	_ucmpdi2.o _floatdidf.o _floatdisf.o _fixunsdfsi.o _fixunssfsi.o \
 	_fixunsdfdi.o _fixdfdi.o _fixunssfdi.o _fixsfdi.o _op_new.o \
 	_new_handler.o _op_delete.o _trampoline.o __main.o _ctor_list.o \
-	_dtor_list.o _ffsdi2.o
+	_dtor_list.o _ffsdi2.o _op_vnew.o _op_vdel.o _eh.o _pure.o
 
 GCC= 	crtinit.o stksiz.o inistack.o heapbase.o binmode.o \
 	$(GLIB1) $(GLIB2) $(FCOMPD) $(FCOMPS) \
------------------------------ cut here ------------------------------
--- orig/linea.h	Sun May 23 15:31:08 1993
+++ linea.h	Sun Nov  6 00:52:50 1994
@@ -800,17 +800,20 @@
 
 #define linea0() 							\
 ({									\
-	    								\
+	register __LINEA *__xaline __asm__ ("a0");			\
+	register __FONT **__xfonts __asm__ ("a1");			\
+	register short (**__xfuncs) (void) __asm__ ("a2");		\
+									\
 	__asm__ volatile						\
 	("\
-		.word   0xA000; \
-		movl    a0,%0;	\
-		movl    a1,%1;	\
-		movl    a2,%2"						\
-	: "=g"(__aline), "=g"(__fonts), "=g"(__funcs)     /* outputs */	\
+		.word   0xA000"						\
+	: "=g"(__xaline), "=g"(__xfonts), "=g"(__xfuncs)  /* outputs */	\
 	: 						  /* inputs  */	\
 	: "d0", "d1", "d2", "a0", "a1", "a2"       /* clobbered regs */	\
 	);								\
+	__aline = __xaline;						\
+	__fonts = __xfonts;						\
+	__funcs = __xfuncs;						\
 })
 
 #define linea1() 							\
@@ -827,11 +830,10 @@
 
 #define linea2() 							\
 ({									\
-	short retvalue;							\
+	register short retvalue __asm__ ("d0");				\
 	__asm__ volatile						\
 	("\
-		.word   0xA002;  \
- 		movew	d0,%0"   \
+		.word   0xA002"   \
 	: "=g"(retvalue)				  /* outputs */	\
 	: 						  /* inputs  */	\
 	: "d0", "d1", "d2", "a0", "a1", "a2"       /* clobbered regs */	\