1/* Test x86-specific floating-point environment (bug 16068): SSE part.
2 Copyright (C) 2015-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 <stdint.h>
24#include <stdio.h>
25
26static bool
27have_sse2 (void)
28{
29 unsigned int eax, ebx, ecx, edx;
30
31 if (!__get_cpuid (leaf: 1, eax: &eax, ebx: &ebx, ecx: &ecx, edx: &edx))
32 return false;
33
34 return (edx & bit_SSE2) != 0;
35}
36
37static uint32_t
38get_sse_mxcsr (void)
39{
40 uint32_t temp;
41 __asm__ __volatile__ ("stmxcsr %0" : "=m" (temp));
42 return temp;
43}
44
45static void
46set_sse_mxcsr (uint32_t val)
47{
48 __asm__ __volatile__ ("ldmxcsr %0" : : "m" (val));
49}
50
51static void
52set_sse_mxcsr_bits (uint32_t mask, uint32_t bits)
53{
54 uint32_t mxcsr = get_sse_mxcsr ();
55 mxcsr = (mxcsr & ~mask) | bits;
56 set_sse_mxcsr (mxcsr);
57}
58
59static int
60test_sse_mxcsr_bits (const char *test, uint32_t mask, uint32_t bits)
61{
62 uint32_t mxcsr = get_sse_mxcsr ();
63 printf (format: "Testing %s: mxcsr = %x\n", test, mxcsr);
64 if ((mxcsr & mask) == bits)
65 {
66 printf (format: "PASS: %s\n", test);
67 return 0;
68 }
69 else
70 {
71 printf (format: "FAIL: %s\n", test);
72 return 1;
73 }
74}
75
76#define MXCSR_FZ 0x8000
77#define MXCSR_DAZ 0x40
78#define MXCSR_DE 0x2
79#define MXCSR_DM 0x100
80
81static __attribute__ ((noinline)) int
82sse_tests (void)
83{
84 int result = 0;
85 fenv_t env1, env2;
86 /* Test FZ bit. */
87 fegetenv (envp: &env1);
88 set_sse_mxcsr_bits (MXCSR_FZ, MXCSR_FZ);
89 fegetenv (envp: &env2);
90 fesetenv (envp: &env1);
91 result |= test_sse_mxcsr_bits (test: "fesetenv FZ restoration",
92 MXCSR_FZ, bits: 0);
93 set_sse_mxcsr_bits (MXCSR_FZ, bits: 0);
94 fesetenv (envp: &env2);
95 result |= test_sse_mxcsr_bits (test: "fesetenv FZ restoration 2",
96 MXCSR_FZ, MXCSR_FZ);
97 set_sse_mxcsr_bits (MXCSR_FZ, MXCSR_FZ);
98 fesetenv (FE_NOMASK_ENV);
99 result |= test_sse_mxcsr_bits (test: "fesetenv (FE_NOMASK_ENV) FZ restoration",
100 MXCSR_FZ, bits: 0);
101 set_sse_mxcsr_bits (MXCSR_FZ, MXCSR_FZ);
102 fesetenv (FE_DFL_ENV);
103 result |= test_sse_mxcsr_bits (test: "fesetenv (FE_DFL_ENV) FZ restoration",
104 MXCSR_FZ, bits: 0);
105 /* Test DAZ bit. */
106 set_sse_mxcsr_bits (MXCSR_DAZ, MXCSR_DAZ);
107 fegetenv (envp: &env2);
108 fesetenv (envp: &env1);
109 result |= test_sse_mxcsr_bits (test: "fesetenv DAZ restoration",
110 MXCSR_DAZ, bits: 0);
111 set_sse_mxcsr_bits (MXCSR_DAZ, bits: 0);
112 fesetenv (envp: &env2);
113 result |= test_sse_mxcsr_bits (test: "fesetenv DAZ restoration 2",
114 MXCSR_DAZ, MXCSR_DAZ);
115 set_sse_mxcsr_bits (MXCSR_DAZ, MXCSR_DAZ);
116 fesetenv (FE_NOMASK_ENV);
117 result |= test_sse_mxcsr_bits (test: "fesetenv (FE_NOMASK_ENV) DAZ restoration",
118 MXCSR_DAZ, bits: 0);
119 set_sse_mxcsr_bits (MXCSR_DAZ, MXCSR_DAZ);
120 fesetenv (FE_DFL_ENV);
121 result |= test_sse_mxcsr_bits (test: "fesetenv (FE_DFL_ENV) DAZ restoration",
122 MXCSR_DAZ, bits: 0);
123 /* Test DM bit. */
124 set_sse_mxcsr_bits (MXCSR_DM, bits: 0);
125 fegetenv (envp: &env2);
126 fesetenv (envp: &env1);
127 result |= test_sse_mxcsr_bits (test: "fesetenv DM restoration",
128 MXCSR_DM, MXCSR_DM);
129 set_sse_mxcsr_bits (MXCSR_DM, MXCSR_DM);
130 fesetenv (envp: &env2);
131 result |= test_sse_mxcsr_bits (test: "fesetenv DM restoration 2",
132 MXCSR_DM, bits: 0);
133 set_sse_mxcsr_bits (MXCSR_DM, bits: 0);
134 /* Presume FE_NOMASK_ENV should leave the "denormal operand"
135 exception masked, as not a standard exception. */
136 fesetenv (FE_NOMASK_ENV);
137 result |= test_sse_mxcsr_bits (test: "fesetenv (FE_NOMASK_ENV) DM restoration",
138 MXCSR_DM, MXCSR_DM);
139 set_sse_mxcsr_bits (MXCSR_DM, bits: 0);
140 fesetenv (FE_DFL_ENV);
141 result |= test_sse_mxcsr_bits (test: "fesetenv (FE_DFL_ENV) DM restoration",
142 MXCSR_DM, MXCSR_DM);
143 /* Test DE bit. */
144 set_sse_mxcsr_bits (MXCSR_DE, MXCSR_DE);
145 fegetenv (envp: &env2);
146 fesetenv (envp: &env1);
147 result |= test_sse_mxcsr_bits (test: "fesetenv DE restoration",
148 MXCSR_DE, bits: 0);
149 set_sse_mxcsr_bits (MXCSR_DE, bits: 0);
150 fesetenv (envp: &env2);
151 result |= test_sse_mxcsr_bits (test: "fesetenv DE restoration 2",
152 MXCSR_DE, MXCSR_DE);
153 set_sse_mxcsr_bits (MXCSR_DE, MXCSR_DE);
154 fesetenv (FE_NOMASK_ENV);
155 result |= test_sse_mxcsr_bits (test: "fesetenv (FE_NOMASK_ENV) DE restoration",
156 MXCSR_DE, bits: 0);
157 set_sse_mxcsr_bits (MXCSR_DE, MXCSR_DE);
158 fesetenv (FE_DFL_ENV);
159 result |= test_sse_mxcsr_bits (test: "fesetenv (FE_DFL_ENV) DE restoration",
160 MXCSR_DE, bits: 0);
161 return result;
162}
163
164static int
165do_test (void)
166{
167 if (!have_sse2 ())
168 {
169 puts (s: "CPU does not support SSE2, cannot test");
170 return 0;
171 }
172 return sse_tests ();
173}
174
175#define TEST_FUNCTION do_test ()
176#include <test-skeleton.c>
177

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