1/* Test floating-point environment includes SSE state (bug 16064).
2 Copyright (C) 2014-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#include <cpuid.h>
20#include <fenv.h>
21#include <float.h>
22#include <stdbool.h>
23#include <stdio.h>
24
25static bool
26have_sse2 (void)
27{
28 unsigned int eax, ebx, ecx, edx;
29
30 if (!__get_cpuid (leaf: 1, eax: &eax, ebx: &ebx, ecx: &ecx, edx: &edx))
31 return false;
32
33 return (edx & bit_SSE2) != 0;
34}
35
36static __attribute__ ((noinline)) int
37sse_tests (void)
38{
39 int ret = 0;
40 fenv_t base_env;
41 if (fegetenv (envp: &base_env) != 0)
42 {
43 puts (s: "fegetenv (&base_env) failed");
44 return 1;
45 }
46 if (fesetround (FE_UPWARD) != 0)
47 {
48 puts (s: "fesetround (FE_UPWARD) failed");
49 return 1;
50 }
51 if (fesetenv (envp: &base_env) != 0)
52 {
53 puts (s: "fesetenv (&base_env) failed");
54 return 1;
55 }
56 volatile float a = 1.0f, b = FLT_MIN, c;
57 c = a + b;
58 if (c != 1.0f)
59 {
60 puts (s: "fesetenv did not restore rounding mode");
61 ret = 1;
62 }
63 if (fesetround (FE_DOWNWARD) != 0)
64 {
65 puts (s: "fesetround (FE_DOWNWARD) failed");
66 return 1;
67 }
68 if (feupdateenv (envp: &base_env) != 0)
69 {
70 puts (s: "feupdateenv (&base_env) failed");
71 return 1;
72 }
73 volatile float d = -FLT_MIN, e;
74 e = a + d;
75 if (e != 1.0f)
76 {
77 puts (s: "feupdateenv did not restore rounding mode");
78 ret = 1;
79 }
80 if (fesetround (FE_UPWARD) != 0)
81 {
82 puts (s: "fesetround (FE_UPWARD) failed");
83 return 1;
84 }
85 fenv_t upward_env;
86 if (feholdexcept (envp: &upward_env) != 0)
87 {
88 puts (s: "feholdexcept (&upward_env) failed");
89 return 1;
90 }
91 if (fesetround (FE_DOWNWARD) != 0)
92 {
93 puts (s: "fesetround (FE_DOWNWARD) failed");
94 return 1;
95 }
96 if (fesetenv (envp: &upward_env) != 0)
97 {
98 puts (s: "fesetenv (&upward_env) failed");
99 return 1;
100 }
101 e = a + d;
102 if (e != 1.0f)
103 {
104 puts (s: "fesetenv did not restore rounding mode from feholdexcept");
105 ret = 1;
106 }
107 if (fesetround (FE_UPWARD) != 0)
108 {
109 puts (s: "fesetround (FE_UPWARD) failed");
110 return 1;
111 }
112 if (fesetenv (FE_DFL_ENV) != 0)
113 {
114 puts (s: "fesetenv (FE_DFL_ENV) failed");
115 return 1;
116 }
117 c = a + b;
118 if (c != 1.0f)
119 {
120 puts (s: "fesetenv (FE_DFL_ENV) did not restore rounding mode");
121 ret = 1;
122 }
123 return ret;
124}
125
126static int
127do_test (void)
128{
129 if (!have_sse2 ())
130 {
131 puts (s: "CPU does not support SSE2, cannot test");
132 return 0;
133 }
134 return sse_tests ();
135}
136
137#define TEST_FUNCTION do_test ()
138#include <test-skeleton.c>
139

source code of glibc/sysdeps/x86/fpu/test-fenv-sse.c