[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 */ \