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

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