From: bde@runx.oz.AU (Bruce Evans)
Subject: gcc-2.3.1 -mno-fp-ret-in-387
Organization: RUNX Un*x Timeshare.  Sydney, Australia.
Distribution: gnu
Date: Tue, 10 Nov 1992 06:53:33 GMT

gcc-2.3.1 dumped core while compiling the library function __fixunsdfdi ()
under Minix-386.  This was because the new support for no-fp-ret-in-387
doesn't quite work.

This is a reduced form of the input file showing the bug:
---
fixu.c
---
typedef 	 int SItype;
typedef unsigned int USItype;
typedef		 long long DItype;
typedef unsigned long long UDItype;
typedef		double DFtype;
DItype
__fixunsdfdi (a)
     DFtype a;
{
  DFtype b;
  UDItype v;
  if (a < 0)
    return 0;
  b = (a / (((UDItype) 1) << (sizeof (SItype) * 8 ) ) );
  v = (USItype) b;
  v <<= (sizeof (SItype) * 8 ) ;
  a -= (DFtype)v;
  if (a < 0)
    v -= (USItype) (- a);
  else
    v += (USItype) a;
  return v;
}
---

This is the error output from

    gcc -mno-80387 -mno-ieee-fp -mno-fp-ret-in-387 -O -S -v fixu.c

The -m flags are here to show my nonstandard defaults.
---
Reading specs from /usr/gnu/gcc/lib/gcc-lib/i386-minix/2.3.1/specs
gcc version 2.3.1
 /usr/gnu/gcc/lib/gcc-lib/i386-minix/2.3.1/cpp -lang-c -v -undef -D__GNUC__=2 -D__OPTIMIZE__ fixu.c /usr/tmp/cca07941.i
GNU CPP version 2.3.1 (80386, BSD syntax)
 /usr/gnu/gcc/lib/gcc-lib/i386-minix/2.3.1/cc1 /usr/tmp/cca07941.i -quiet -dumpbase fixu.c -mno-80387 -mno-ieee-fp -mno-fp-ret-in-387 -O -version -o fixu.s
GNU C version 2.3.1 (80386, BSD syntax) compiled by GNU C version 2.3.1.
[Abort]
---

The abort is from this code around line 1172 in reload1.c.
---
		      /* Crash if two dissimilar machine modes both need
			 groups of consecutive regs of the same class.  */

		      if (other_mode != VOIDmode
			  && other_mode != allocate_mode
			  && ! modes_equiv_for_class_p (allocate_mode,
							other_mode,
							class))
			abort ();
		    }
---

gdb says that

	other_mode = DImode
	allocate_mode = DFmode
	class = GENERAL_REGS
---

Here is a possible fix.  I've been using variants of it in gcc-1.38 to
1.40 and gcc-2.2.x.  387 registers are not OK if there are no 387 registers.
However, there's something wrong with either the fix or the documentation.
tm.texi says that it is not necessary for HARD_REGNO_MODE_OK() to check
for the numbers of fixed registers, and the -mno-80387 -mno-fp-ret-in-387
flags are supposed to hide all 387 registers by making them fixed.
---
*** orig/i386.h	Sat Nov  7 22:15:57 1992
--- i386.h	Sun Nov  8 04:20:04 1992
***************
*** 284,287 ****
--- 284,296 ----
     : (MODE) != QImode)
  
+ #undef HARD_REGNO_MODE_OK(REGNO, MODE)
+ #define HARD_REGNO_MODE_OK(REGNO, MODE) \
+   ((REGNO) < 4 ? 1							\
+    : (REGNO) >= 8 ? ((GET_MODE_CLASS (MODE) == MODE_FLOAT		\
+ 		      || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)	\
+ 		     && TARGET_80387					\
+ 		     && GET_MODE_UNIT_SIZE (MODE) <= 8)			\
+    : (MODE) != QImode)
+ 
  /* Value is 1 if it is a good idea to tie two pseudo registers
     when one has mode MODE1 and one has mode MODE2.
---

config/i386sco.h and config/seq386.h contain old no-387 code can now be
done better using by the new 387 target flags.  I don't think the old code
is complete enough to actually work.  It is #ifdef'ed out in i386sco.h.
---

CONST_DOUBLE_OK_FOR_LETTER_P() seems to have the opposite problem to
HARD_REGNO_MODE_OK().  The document doesn't say anything about whether
it should check letters that "can't happen", but the letter never seems
to be a 387-related letter in practice.  I used to use the following
redefinition.
***************
*** 507,510 ****
--- 516,527 ----
  #define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C)  \
    ((C) == 'G' ? standard_80387_constant_p (VALUE) : 0)
+ 
+ #if 0
+ /* Also change above comment.  */
+ #undef CONST_DOUBLE_OK_FOR_LETTER_P
+ #define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C)  \
+   ((C) == 'G' ? (TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387)
+ 		&& standard_80387_constant_p (VALUE) : 0)
+ #endif
  
  /* Place additional restrictions on the register class to use when it
---

Here are my local changes to gcc.  Please put the Minix support in gcc.

Makefile.in:
	enquire needs -lm, and ENQUIRE_LDFLAGS is in the wrong order to
	put it.  Add macro ENQUIRE_LIBS.
c-typeck.c:
	In the format checker, ignoring differences in signedness is not
	done very well.  The difference between integral types was also
	ignored if the types happen to have the same size on the target
	machine.  I would like to have a new -W flag to control error
	reports about type mismatches that only matter on some targets.
	Signedness differences are usually bugs but old code has too many
	of them to warn about them by default.  Many of the signedness
	warnings that my change produced were due to sizeof being unsigned.
	Perhaps the checker could easily ignore the unsignedness for this
	case.
configure:
config/i386minix.h
config/x-i386minix
config/xm-i386min.h
	Support Minix.
	There is nothing special except the change to TARGET_FLAGS to get
	soft-float.  Hard-float works too, but only on my system.

	It's annoying to have to define USG and then take countermeasures
	against it.

---
diff -rc2 orig/Makefile.in ./Makefile.in
*** orig/Makefile.in	Sat Nov  7 22:14:02 1992
--- ./Makefile.in	Sun Nov  8 00:54:09 1992
***************
*** 102,105 ****
--- 102,106 ----
  ENQUIRE_CFLAGS = -DNO_MEM -DNO_STDDEF -DNO_LONG_DOUBLE_IO -O0
  ENQUIRE_LDFLAGS = $(LDFLAGS)
+ ENQUIRE_LIBS =
  
  # Tools to use when building a cross-compiler.
***************
*** 507,511 ****
  # Let's try with GCC.
  enquire: enquire.o $(GCC_PARTS)
! 	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ENQUIRE_LDFLAGS) enquire.o -o $@
  enquire.o: $(srcdir)/enquire.c $(GCC_PASSES)
  #	-if [ "$(srcdir)" != "." ]; then rm -f ./enquire.c; else true; fi
--- 508,513 ----
  # Let's try with GCC.
  enquire: enquire.o $(GCC_PARTS)
! 	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ENQUIRE_LDFLAGS) enquire.o -o $@ \
! 	$(ENQUIRE_LIBS)
  enquire.o: $(srcdir)/enquire.c $(GCC_PASSES)
  #	-if [ "$(srcdir)" != "." ]; then rm -f ./enquire.c; else true; fi
diff -rc2 orig/c-typeck.c ./c-typeck.c
*** orig/c-typeck.c	Sat Nov  7 22:14:19 1992
--- ./c-typeck.c	Mon Nov  9 11:56:50 1992
***************
*** 1729,1732 ****
--- 1729,1733 ----
  	  && ! (wanted_type == void_type_node
  		&& fci->pointer_count > 0)
+ #if 0
  	  /* Don't warn about differences merely in signedness.  */
  	  && !(TREE_CODE (wanted_type) == INTEGER_TYPE
***************
*** 1733,1736 ****
--- 1734,1740 ----
  	       && TREE_CODE (cur_type) == INTEGER_TYPE
  	       && TYPE_PRECISION (wanted_type) == TYPE_PRECISION (cur_type)))
+ #else
+ 	 )
+ #endif
  	{
  	  register char *this;
diff -rc2 orig/configure ./configure
*** orig/configure	Sat Nov  7 22:17:14 1992
--- ./configure	Sun Nov  8 00:59:56 1992
***************
*** 375,378 ****
--- 375,385 ----
  		use_collect2=yes
  		;;
+ 	i[3-4]86-*-minix*)		# Intel 80386's running Minix
+ 		cpu_type=i386
+ 		xm_file=xm-i386min.h
+ 		xmake_file=x-i386minix
+ 		tm_file=i386minix.h
+ 		broken_install=yes
+ 		;;
  	i[34]86-*-linux*)               # Intel 80386's running Linux
  		cpu_type=i386
diff -rc2 null/i386minix.h config/i386minix.h
*** null/i386minix.h	Tue Nov 10 15:25:19 1992
--- config/i386minix.h	Mon Nov  9 12:31:37 1992
***************
*** 0 ****
--- 1,28 ----
+ /* Definitions for Intel 386 running Minix
+  * Copyright (C) 1988 Free Software Foundation, Inc.
+  */
+ 
+ /* This is tested by i386gas.h.  */
+ #define YES_UNDERSCORES
+ 
+ #include "i386gstabs.h"
+ 
+ #undef CPP_PREDEFINES
+ #define CPP_PREDEFINES ""	/* no -Dunix -Di386 */
+ 
+ #undef TARGET_DEFAULT
+ #define TARGET_DEFAULT 0	/* no 80387, no ieee-fp, no fp-ret-in-387 */
+ 
+ #define HAVE_ATEXIT
+ 
+ #undef SIZE_TYPE
+ #define SIZE_TYPE "unsigned int"
+ 
+ #undef PTRDIFF_TYPE
+ #define PTRDIFF_TYPE "int"
+ 
+ #undef WCHAR_TYPE
+ #define WCHAR_TYPE "char"
+ 
+ #undef WCHAR_TYPE_SIZE
+ #define WCHAR_TYPE_SIZE BITS_PER_UNIT
diff -rc2 null/x-i386minix config/x-i386minix
*** null/x-i386minix	Tue Nov 10 15:25:19 1992
--- config/x-i386minix	Mon Nov  9 12:35:53 1992
***************
*** 0 ****
--- 1,6 ----
+ CC = gcc
+ CCLIBFLAGS = -O -G
+ CLIB = -lm
+ ENQUIRE_LIBS = -lm
+ LANGUAGES = c proto
+ X_CFLAGS = -O -D_MINIX -D_POSIX_SOURCE -D_POSIX_1_SOURCE=2
diff -rc2 null/xm-i386min.h config/xm-i386min.h
*** null/xm-i386min.h	Tue Nov 10 15:25:19 1992
--- config/xm-i386min.h	Mon Nov  9 12:42:39 1992
***************
*** 0 ****
--- 1,23 ----
+ /* Configuration for GCC for Intel i386 running Minix 1.6.16++.  */
+ 
+ #include "xm-i386.h"
+ 
+ /* Minix isn't USG, but it isn't BSD either, and gcc treats !USG as BSD.  */
+ 
+ #define USG
+ 
+ /* Defining USG causes various braindamage.  Some of it can be avoided:  */
+ 
+ /* Stop cccp.c from providing slow versions of bcopy () etc.  */
+ 
+ #define BSTRING
+ 
+ /* USG forces the use of gstab.h, but prepare for when USG is not defined.  */
+ 
+ #define NO_STAB_H
+ 
+ /* gcc uses the ancient sys_errlist[] and sys_nerr instead of the ANSI
+    strerror().  */
+ 
+ #define sys_errlist	_sys_errlist
+ #define sys_nerr	_sys_nerr
--
-- 
Bruce Evans  (bde@runx.oz.au)

Newsgroups: gnu.gcc.bug