[parisc-linux] $$remI corner case

John David Anglin dave@hiauly1.hia.nrc.ca
Sat, 30 Mar 2002 13:38:00 -0500 (EST)


I have investigated the failure of gcc.c-torture/execute/arith-rand.c
under hppa-linux.  The failure is caused by $$remI returning an incorrect
signed result when the divisor is 0x80000000 (largest negative integer).
The 32-bit linux port currently uses the millicode routines in milli32.S.
This is older code dating from 1995.

The 64-bit port uses milli64.S.  This code looks like it was originally
written for 32-bit but I it's possible some changes have been made
that would make it incompatible with 32-bit registers.  Paul and Alan,
could you comment on this?

I added $$dyncall to milli64.S and modified t-linux to use milli64.S.
This fixes the arith-rand.c fail and there are no other regressions,
so I think we can use milli64.S on both the 32-bit and 64-bit ports.

Dave
-- 
J. David Anglin                                  dave.anglin@nrc.ca
National Research Council of Canada              (613) 990-0752 (FAX: 952-6605)

2002-03-30  John David Anglin  <dave@hiauly1.hia.nrc.ca>

	* milli64.S ($$dyncall): New function.
	* t-linux (LIB1ASMFUNCS): Revise module list.
	(LIB1ASMSRC): Use pa/milli64.S.

--- milli64.S.orig	Mon Feb  4 15:25:13 2002
+++ milli64.S	Fri Mar 29 19:36:28 2002
@@ -194,6 +194,30 @@
 #define LREF(sym)	 CAT(L$,sym)
 #endif
 
+#ifdef L_dyncall
+	SUBSPA_MILLI
+	ATTR_DATA
+GSYM($$dyncall)
+	.export $$dyncall,millicode
+	.proc
+	.callinfo	millicode
+	.entry
+	bb,>=,n %r22,30,LREF(1)		; branch if not plabel address
+	depi	0,31,2,%r22		; clear the two least significant bits
+	ldw	4(%r22),%r19		; load new LTP value
+	ldw	0(%r22),%r22		; load address of target
+LSYM(1)
+#ifdef LINUX
+	bv	%r0(%r22)		; branch to the real target
+#else
+	ldsid	(%sr0,%r22),%r1		; get the "space ident" selected by r22
+	mtsp	%r1,%sr0		; move that space identifier into sr0
+	be	0(%sr0,%r22)		; branch to the real target
+#endif
+	stw	%r2,-24(%r30)		; save return address into frame marker
+	.exit
+	.procend
+#endif
 
 #ifdef L_divI
 /* ROUTINES:	$$divI, $$divoI
--- t-linux.orig	Thu Mar 28 19:29:46 2002
+++ t-linux	Fri Mar 29 19:40:36 2002
@@ -1,13 +1,9 @@
 #Plug millicode routines into libgcc.a  We want these on both native and
-#cross compiles.
+#cross compiles.  We use the "64-bit" routines because the "32-bit" code
+#is broken for certain corner cases.
 
-LIB1ASMFUNCS =  _divI _divU _remI _remU _multiply \
-	_divI_15 _divI_14 _divI_12 _divI_10 _divI_9 \
-	_divI_7 _divI_6 _divI_5 _divI_3 \
-	_divU_15 _divU_14 _divU_12 _divU_10 _divU_9 \
-	_divU_7 _divU_6 _divU_5 _divU_3 _dyncall
-
-LIB1ASMSRC = pa/milli32.S
+LIB1ASMFUNCS = _divI _divU _remI _remU _div_const _mulI _dyncall
+LIB1ASMSRC = pa/milli64.S
 
 # Compile crtbeginS.o and crtendS.o as PIC.
 CRTSTUFF_T_CFLAGS_S = -fPIC