Subject: lib/11984: Fix for arm FP comparison wrappers
To: None <gnats-bugs@gnats.netbsd.org>
From: Richard Earnshaw <rearnsha@buzzard.freeserve.co.uk>
List: netbsd-bugs
Date: 01/17/2001 13:57:21
>Number:         11984
>Category:       lib
>Synopsis:       Fix for arm FP comparison wrappers
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Jan 17 13:57:01 PST 2001
>Closed-Date:
>Last-Modified:
>Originator:     Richard Earnshaw
>Release:        NetBSD-current
>Organization:
ARM
	
>Environment:
	
System: NetBSD buzzard.buzzard.freeserve.co.uk 1.5I NetBSD 1.5I (BUZZARD) #216: Sun Nov 19 21:24:48 GMT 2000 rearnsha@buzzard.buzzard.freeserve.co.uk:/usr/src/sys/arch/arm32/compile/BUZZARD arm32


>Description:
	The patch below fixes the regressions reported by the gcc testsuite
	for the ieee comparisons with NaNs.

	A similar patch may also be required for arm26.
	
>How-To-Repeat:
	Run the gcc regression testsuite on arm32.

	
>Fix:
Index: fplib_glue.S
===================================================================
RCS file: /cvsroot/basesrc/lib/libc/arch/arm32/fplib/fplib_glue.S,v
retrieving revision 1.2
diff -p -p -r1.2 fplib_glue.S
*** fplib_glue.S	1999/05/06 13:56:28	1.2
--- fplib_glue.S	2001/01/17 21:51:32
***************
*** 40,75 ****
  
  #define SIGN_BIT_TWIDDLE	0x80000000
  
! /********************************* COMPARISONS ********************************/
! 
! /*
!  * 'Equal' wrapper. This returns 0 if the numbers are equal, or (1 | -1)
!  * otherwise. So we need to invert the output.
   */
- ENTRY(__eqsf2)
- 	stmfd		sp!, {lr}
- 	bl		_C_LABEL(_arm32_float32_eq)
- 	eor		r0, r0, #1
- 	ldmfd		sp!, {pc}
- 
- ENTRY(__eqdf2)
- 	stmfd		sp!, {lr}
- 	bl		_C_LABEL(_arm32_float64_eq)
- 	eor		r0, r0, #1
- 	ldmfd		sp!, {pc}
  
  /*
!  * 'Not Equal' wrapper. This returns -1 or 1 (say, 1!) if the numbers are
!  * not equal, 0 otherwise. However no not equal call is provided, so we have
!  * to use an 'equal' call and invert the result. The result is already
!  * inverted though! Confusing?!
   */
  ENTRY(__nesf2)
  	stmfd		sp!, {lr}
  	bl		_C_LABEL(_arm32_float32_eq)
  	eor		r0, r0, #1
  	ldmfd		sp!, {pc}
  
  ENTRY(__nedf2)
  	stmfd		sp!, {lr}
  	bl		_C_LABEL(_arm32_float64_eq)
--- 40,65 ----
  
  #define SIGN_BIT_TWIDDLE	0x80000000
  
! /********************************* COMPARISONS ********************************
!  * The semantics of the comparison operators of gcc are that
!  *	x <op> y
!  * is replaced by the expression
!  *	f(x,y) <op> 0
!  * where f(x,y) returns an integer (normally 0, 1 or -1)
   */
  
  /*
!  * 'Equal' an 'Not Equal wrappers.  These returns 0 if the numbers are equal,
!  * or (1 | -1) otherwise. So we need to invert the output.
   */
+ ENTRY_NP(__eqsf2)
  ENTRY(__nesf2)
  	stmfd		sp!, {lr}
  	bl		_C_LABEL(_arm32_float32_eq)
  	eor		r0, r0, #1
  	ldmfd		sp!, {pc}
  
+ ENTRY_NP(__eqdf2)
  ENTRY(__nedf2)
  	stmfd		sp!, {lr}
  	bl		_C_LABEL(_arm32_float64_eq)
*************** ENTRY(__nedf2)
*** 80,135 ****
   * 'Greater Than' wrapper. This returns 1 if the number is greater, 0
   * or -1 otherwise. Unfortunately, no such function exists. We have to
   * instead compare the numbers using the 'less than' calls in order to
!  * make up our mind. This means that we can call 'less than or equal' and
!  * invert the result.
!  */
! ENTRY(__gtsf2)
! 	stmfd		sp!, {lr}
! 	bl		_C_LABEL(_arm32_float32_le)
! 	eor		r0, r0, #1
! 	ldmfd		sp!, {pc}
! 
! ENTRY(__gtdf2)
! 	stmfd		sp!, {lr}
! 	bl		_C_LABEL(_arm32_float64_le)
! 	eor		r0, r0, #1
! 	ldmfd		sp!, {pc}
  
  /*
!  * 'Greater Than or Equal' wrapper. We emulate this by inverting the result
!  * of a 'less than' call.
   */
  ENTRY(__gesf2)
  	stmfd		sp!, {lr}
! 	bl		_C_LABEL(_arm32_float32_lt)
! 	eor		r0, r0, #1
! 	cmp		r0, #0
! 	mvneq		r0, #0
  	ldmfd		sp!, {pc}
  
  ENTRY(__gedf2)
  	stmfd		sp!, {lr}
! 	bl		_C_LABEL(_arm32_float64_lt)
! 	eor		r0, r0, #1
! 	cmp		r0, #0
! 	mvneq		r0, #0
  	ldmfd		sp!, {pc}
  
  /*
!  * 'Less Than' wrapper. A 1 from the ARM code needs to be turned into -1.
   */
  ENTRY(__ltsf2)
  	stmfd		sp!, {lr}
  	bl		_C_LABEL(_arm32_float32_lt)
! 	cmp		r0, #1
! 	mvneq		r0, #0
  	ldmfd		sp!, {pc}
  
  ENTRY(__ltdf2)
  	stmfd		sp!, {lr}
  	bl		_C_LABEL(_arm32_float64_lt)
! 	cmp		r0, #1
! 	mvneq		r0, #0
  	ldmfd		sp!, {pc}
  
  /*
--- 70,133 ----
   * 'Greater Than' wrapper. This returns 1 if the number is greater, 0
   * or -1 otherwise. Unfortunately, no such function exists. We have to
   * instead compare the numbers using the 'less than' calls in order to
!  * make up our mind. This means that we must swap the operands and call
!  * 'less than'.  We cannot use 'less than or equal' since that gives
!  * the wrong results for a NaN.
!  * Since the result is correct we simply tail-call.
!  */
! ENTRY_NP(__gtsf2)
! 	mov		r2, r0
! 	mov		r0, r1
! 	mov		r1, r2
! 	b		_C_LABEL(_arm32_float32_lt)
! 
! ENTRY_NP(__gtdf2)
! 	mov		ip, r0
! 	mov		r0, r2
! 	mov		r2, ip
! 	mov		ip, r1
! 	mov		r1, r3
! 	mov		r3, ip
! 	b		_C_LABEL(_arm32_float64_lt)
  
  /*
!  * 'Greater Than or Equal' wrapper.  We swap the inputs and use 'less than
!  * or Equal' - 1.
   */
  ENTRY(__gesf2)
  	stmfd		sp!, {lr}
! 	mov		r2, r0
! 	mov		r0, r1
! 	mov		r1, r2
! 	bl		_C_LABEL(_arm32_float32_le)
! 	sub		r0, r0, #1
  	ldmfd		sp!, {pc}
  
  ENTRY(__gedf2)
  	stmfd		sp!, {lr}
! 	mov		ip, r0
! 	mov		r0, r2
! 	mov		r2, ip
! 	mov		ip, r1
! 	mov		r1, r3
! 	mov		r3, ip
! 	bl		_C_LABEL(_arm32_float64_le)
! 	sub		r0, r0, #1
  	ldmfd		sp!, {pc}
  
  /*
!  * 'Less Than' wrapper.  We negate the result of the lib call.
   */
  ENTRY(__ltsf2)
  	stmfd		sp!, {lr}
  	bl		_C_LABEL(_arm32_float32_lt)
! 	rsb		r0, r0, #0
  	ldmfd		sp!, {pc}
  
  ENTRY(__ltdf2)
  	stmfd		sp!, {lr}
  	bl		_C_LABEL(_arm32_float64_lt)
! 	rsb		r0, r0, #0
  	ldmfd		sp!, {pc}
  
  /*
*************** ENTRY(__ledf2)
*** 153,159 ****
   * position in the registers of arguments, the double precision version can
   * go here too ;-)
   */
! ENTRY(__negsf2)
  ENTRY(__negdf2)
  	eor		r0, r0, #SIGN_BIT_TWIDDLE
  	mov		pc, lr
--- 151,157 ----
   * position in the registers of arguments, the double precision version can
   * go here too ;-)
   */
! ENTRY_NP(__negsf2)
  ENTRY(__negdf2)
  	eor		r0, r0, #SIGN_BIT_TWIDDLE
  	mov		pc, lr

	
>Release-Note:
>Audit-Trail:
>Unformatted: