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: