aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/x86_64/fpu
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/x86_64/fpu')
-rw-r--r--sysdeps/x86_64/fpu/s_fmax.S19
-rw-r--r--sysdeps/x86_64/fpu/s_fmaxf.S19
-rw-r--r--sysdeps/x86_64/fpu/s_fmaxl.S29
-rw-r--r--sysdeps/x86_64/fpu/s_fmin.S19
-rw-r--r--sysdeps/x86_64/fpu/s_fminf.S19
-rw-r--r--sysdeps/x86_64/fpu/s_fminl.S27
6 files changed, 120 insertions, 12 deletions
diff --git a/sysdeps/x86_64/fpu/s_fmax.S b/sysdeps/x86_64/fpu/s_fmax.S
index 02096c0aea..0ff326fb66 100644
--- a/sysdeps/x86_64/fpu/s_fmax.S
+++ b/sysdeps/x86_64/fpu/s_fmax.S
@@ -27,8 +27,25 @@ ENTRY(__fmax)
jmp 2f
1: ucomisd %xmm1, %xmm1 // Is xmm1 a NaN?
- jp 2f // then return xmm0
+ jp 3f
+ // xmm0 is a NaN; xmm1 is not. Test if xmm0 is signaling.
+ movsd %xmm0, -8(%rsp)
+ testb $0x8, -2(%rsp)
+ jz 4f
movsd %xmm1, %xmm0 // otherwise return xmm1
+ ret
+
+3: // xmm1 is a NaN; xmm0 may or may not be.
+ ucomisd %xmm0, %xmm0
+ jp 4f
+ // xmm1 is a NaN; xmm0 is not. Test if xmm1 is signaling.
+ movsd %xmm1, -8(%rsp)
+ testb $0x8, -2(%rsp)
+ jz 4f
+ ret
+
+4: // Both arguments are NaNs, or one is a signaling NaN.
+ addsd %xmm1, %xmm0
2: ret
END(__fmax)
diff --git a/sysdeps/x86_64/fpu/s_fmaxf.S b/sysdeps/x86_64/fpu/s_fmaxf.S
index 28e129701e..0f36ee084c 100644
--- a/sysdeps/x86_64/fpu/s_fmaxf.S
+++ b/sysdeps/x86_64/fpu/s_fmaxf.S
@@ -27,8 +27,25 @@ ENTRY(__fmaxf)
jmp 2f
1: ucomiss %xmm1, %xmm1 // Is xmm1 a NaN?
- jp 2f // then return xmm0
+ jp 3f
+ // xmm0 is a NaN; xmm1 is not. Test if xmm0 is signaling.
+ movss %xmm0, -4(%rsp)
+ testb $0x40, -2(%rsp)
+ jz 4f
movss %xmm1, %xmm0 // otherwise return xmm1
+ ret
+
+3: // xmm1 is a NaN; xmm0 may or may not be.
+ ucomiss %xmm0, %xmm0
+ jp 4f
+ // xmm1 is a NaN; xmm0 is not. Test if xmm1 is signaling.
+ movss %xmm1, -4(%rsp)
+ testb $0x40, -2(%rsp)
+ jz 4f
+ ret
+
+4: // Both arguments are NaNs, or one is a signaling NaN.
+ addss %xmm1, %xmm0
2: ret
END(__fmaxf)
diff --git a/sysdeps/x86_64/fpu/s_fmaxl.S b/sysdeps/x86_64/fpu/s_fmaxl.S
index f0c2bc0d56..5f0b1e0860 100644
--- a/sysdeps/x86_64/fpu/s_fmaxl.S
+++ b/sysdeps/x86_64/fpu/s_fmaxl.S
@@ -24,16 +24,35 @@ ENTRY(__fmaxl)
fldt 8(%rsp) // x
fldt 24(%rsp) // x : y
- fucomi %st(0), %st
- fcmovu %st(1), %st // now %st contains y if not NaN, x otherwise
-
- fxch
-
fucomi %st(1), %st
+ jp 2f
fcmovb %st(1), %st
fstp %st(1)
ret
+
+2: // Unordered.
+ fucomi %st(0), %st
+ jp 3f
+ // st(1) is a NaN; st(0) is not. Test if st(1) is signaling.
+ testb $0x40, 15(%rsp)
+ jz 4f
+ fstp %st(1)
+ ret
+
+3: // st(0) is a NaN; st(1) may or may not be.
+ fxch
+ fucomi %st(0), %st
+ jp 4f
+ // st(1) is a NaN; st(0) is not. Test if st(1) is signaling.
+ testb $0x40, 31(%rsp)
+ jz 4f
+ fstp %st(1)
+ ret
+
+4: // Both arguments are NaNs, or one is a signaling NaN.
+ faddp
+ ret
END(__fmaxl)
weak_alias (__fmaxl, fmaxl)
diff --git a/sysdeps/x86_64/fpu/s_fmin.S b/sysdeps/x86_64/fpu/s_fmin.S
index fb14e2f3ed..db89befb6b 100644
--- a/sysdeps/x86_64/fpu/s_fmin.S
+++ b/sysdeps/x86_64/fpu/s_fmin.S
@@ -27,8 +27,25 @@ ENTRY(__fmin)
jmp 2f
1: ucomisd %xmm1, %xmm1 // Is xmm1 a NaN?
- jp 2f // then return xmm0
+ jp 3f
+ // xmm0 is a NaN; xmm1 is not. Test if xmm0 is signaling.
+ movsd %xmm0, -8(%rsp)
+ testb $0x8, -2(%rsp)
+ jz 4f
movsd %xmm1, %xmm0 // otherwise return xmm1
+ ret
+
+3: // xmm1 is a NaN; xmm0 may or may not be.
+ ucomisd %xmm0, %xmm0
+ jp 4f
+ // xmm1 is a NaN; xmm0 is not. Test if xmm1 is signaling.
+ movsd %xmm1, -8(%rsp)
+ testb $0x8, -2(%rsp)
+ jz 4f
+ ret
+
+4: // Both arguments are NaNs, or one is a signaling NaN.
+ addsd %xmm1, %xmm0
2: ret
END(__fmin)
diff --git a/sysdeps/x86_64/fpu/s_fminf.S b/sysdeps/x86_64/fpu/s_fminf.S
index c8d6d0fd33..41a99787d3 100644
--- a/sysdeps/x86_64/fpu/s_fminf.S
+++ b/sysdeps/x86_64/fpu/s_fminf.S
@@ -27,8 +27,25 @@ ENTRY(__fminf)
jmp 2f
1: ucomiss %xmm1, %xmm1 // Is xmm1 a NaN?
- jp 2f // then return xmm0
+ jp 3f
+ // xmm0 is a NaN; xmm1 is not. Test if xmm0 is signaling.
+ movss %xmm0, -4(%rsp)
+ testb $0x40, -2(%rsp)
+ jz 4f
movss %xmm1, %xmm0 // otherwise return xmm1
+ ret
+
+3: // xmm1 is a NaN; xmm0 may or may not be.
+ ucomiss %xmm0, %xmm0
+ jp 4f
+ // xmm1 is a NaN; xmm0 is not. Test if xmm1 is signaling.
+ movss %xmm1, -4(%rsp)
+ testb $0x40, -2(%rsp)
+ jz 4f
+ ret
+
+4: // Both arguments are NaNs, or one is a signaling NaN.
+ addss %xmm1, %xmm0
2: ret
END(__fminf)
diff --git a/sysdeps/x86_64/fpu/s_fminl.S b/sysdeps/x86_64/fpu/s_fminl.S
index f1a06d29d7..12fc3fb06c 100644
--- a/sysdeps/x86_64/fpu/s_fminl.S
+++ b/sysdeps/x86_64/fpu/s_fminl.S
@@ -24,14 +24,35 @@ ENTRY(__fminl)
fldt 8(%rsp) // x
fldt 24(%rsp) // x : y
- fucomi %st(0), %st
- fcmovu %st(1), %st // now %st contains y if not NaN, x otherwise
-
fucomi %st(1), %st
+ jp 2f
fcmovnb %st(1), %st
fstp %st(1)
ret
+
+2: // Unordered.
+ fucomi %st(0), %st
+ jp 3f
+ // st(1) is a NaN; st(0) is not. Test if st(1) is signaling.
+ testb $0x40, 15(%rsp)
+ jz 4f
+ fstp %st(1)
+ ret
+
+3: // st(0) is a NaN; st(1) may or may not be.
+ fxch
+ fucomi %st(0), %st
+ jp 4f
+ // st(1) is a NaN; st(0) is not. Test if st(1) is signaling.
+ testb $0x40, 31(%rsp)
+ jz 4f
+ fstp %st(1)
+ ret
+
+4: // Both arguments are NaNs, or one is a signaling NaN.
+ faddp
+ ret
END(__fminl)
weak_alias (__fminl, fminl)