1*1ec3feb6SAlex Richardson /* $NetBSD: t_fenv.c,v 1.6 2019/04/25 20:48:54 kamil Exp $ */
2640235e2SEnji Cooper
3640235e2SEnji Cooper /*-
4640235e2SEnji Cooper * Copyright (c) 2014 The NetBSD Foundation, Inc.
5640235e2SEnji Cooper * All rights reserved.
6640235e2SEnji Cooper *
7640235e2SEnji Cooper * This code is derived from software contributed to The NetBSD Foundation
8640235e2SEnji Cooper * by Martin Husemann.
9640235e2SEnji Cooper *
10640235e2SEnji Cooper * Redistribution and use in source and binary forms, with or without
11640235e2SEnji Cooper * modification, are permitted provided that the following conditions
12640235e2SEnji Cooper * are met:
13640235e2SEnji Cooper * 1. Redistributions of source code must retain the above copyright
14640235e2SEnji Cooper * notice, this list of conditions and the following disclaimer.
15640235e2SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright
16640235e2SEnji Cooper * notice, this list of conditions and the following disclaimer in the
17640235e2SEnji Cooper * documentation and/or other materials provided with the distribution.
18640235e2SEnji Cooper *
19640235e2SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20640235e2SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21640235e2SEnji Cooper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22640235e2SEnji Cooper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23640235e2SEnji Cooper * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24640235e2SEnji Cooper * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25640235e2SEnji Cooper * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26640235e2SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27640235e2SEnji Cooper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28640235e2SEnji Cooper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29640235e2SEnji Cooper * POSSIBILITY OF SUCH DAMAGE.
30640235e2SEnji Cooper */
31640235e2SEnji Cooper #include <sys/cdefs.h>
32*1ec3feb6SAlex Richardson __RCSID("$NetBSD: t_fenv.c,v 1.6 2019/04/25 20:48:54 kamil Exp $");
33640235e2SEnji Cooper
34640235e2SEnji Cooper #include <atf-c.h>
35640235e2SEnji Cooper
36640235e2SEnji Cooper #include <fenv.h>
37640235e2SEnji Cooper #ifdef __HAVE_FENV
38640235e2SEnji Cooper
39640235e2SEnji Cooper #include <ieeefp.h>
40640235e2SEnji Cooper #include <stdlib.h>
41640235e2SEnji Cooper
42640235e2SEnji Cooper
43*1ec3feb6SAlex Richardson #if (__arm__ && !__SOFTFP__) || __aarch64__
44640235e2SEnji Cooper /*
45*1ec3feb6SAlex Richardson * Some NEON fpus do not trap on IEEE 754 FP exceptions.
46*1ec3feb6SAlex Richardson * Skip these tests if running on them and compiled for
47640235e2SEnji Cooper * hard float.
48640235e2SEnji Cooper */
49640235e2SEnji Cooper #define FPU_EXC_PREREQ() \
50640235e2SEnji Cooper if (0 == fpsetmask(fpsetmask(FP_X_INV))) \
51*1ec3feb6SAlex Richardson atf_tc_skip("FPU does not implement traps on FP exceptions");
52640235e2SEnji Cooper
53640235e2SEnji Cooper /*
54640235e2SEnji Cooper * Same as above: some don't allow configuring the rounding mode.
55640235e2SEnji Cooper */
56640235e2SEnji Cooper #define FPU_RND_PREREQ() \
57640235e2SEnji Cooper if (0 == fpsetround(fpsetround(FP_RZ))) \
58640235e2SEnji Cooper atf_tc_skip("FPU does not implement configurable " \
59640235e2SEnji Cooper "rounding modes");
60640235e2SEnji Cooper #endif
61640235e2SEnji Cooper
62640235e2SEnji Cooper #ifndef FPU_EXC_PREREQ
63640235e2SEnji Cooper #define FPU_EXC_PREREQ() /* nothing */
64640235e2SEnji Cooper #endif
65640235e2SEnji Cooper #ifndef FPU_RND_PREREQ
66640235e2SEnji Cooper #define FPU_RND_PREREQ() /* nothing */
67640235e2SEnji Cooper #endif
68640235e2SEnji Cooper
69640235e2SEnji Cooper
70640235e2SEnji Cooper ATF_TC(fegetround);
71640235e2SEnji Cooper
ATF_TC_HEAD(fegetround,tc)72640235e2SEnji Cooper ATF_TC_HEAD(fegetround, tc)
73640235e2SEnji Cooper {
74640235e2SEnji Cooper atf_tc_set_md_var(tc, "descr",
75640235e2SEnji Cooper "verify the fegetround() function agrees with the legacy "
76640235e2SEnji Cooper "fpsetround");
77640235e2SEnji Cooper }
78640235e2SEnji Cooper
ATF_TC_BODY(fegetround,tc)79640235e2SEnji Cooper ATF_TC_BODY(fegetround, tc)
80640235e2SEnji Cooper {
81640235e2SEnji Cooper FPU_RND_PREREQ();
82640235e2SEnji Cooper
83640235e2SEnji Cooper fpsetround(FP_RZ);
84640235e2SEnji Cooper ATF_CHECK(fegetround() == FE_TOWARDZERO);
85640235e2SEnji Cooper fpsetround(FP_RM);
86640235e2SEnji Cooper ATF_CHECK(fegetround() == FE_DOWNWARD);
87640235e2SEnji Cooper fpsetround(FP_RN);
88640235e2SEnji Cooper ATF_CHECK(fegetround() == FE_TONEAREST);
89640235e2SEnji Cooper fpsetround(FP_RP);
90640235e2SEnji Cooper ATF_CHECK(fegetround() == FE_UPWARD);
91640235e2SEnji Cooper }
92640235e2SEnji Cooper
93640235e2SEnji Cooper ATF_TC(fesetround);
94640235e2SEnji Cooper
ATF_TC_HEAD(fesetround,tc)95640235e2SEnji Cooper ATF_TC_HEAD(fesetround, tc)
96640235e2SEnji Cooper {
97640235e2SEnji Cooper atf_tc_set_md_var(tc, "descr",
98640235e2SEnji Cooper "verify the fesetround() function agrees with the legacy "
99640235e2SEnji Cooper "fpgetround");
100640235e2SEnji Cooper }
101640235e2SEnji Cooper
ATF_TC_BODY(fesetround,tc)102640235e2SEnji Cooper ATF_TC_BODY(fesetround, tc)
103640235e2SEnji Cooper {
104640235e2SEnji Cooper FPU_RND_PREREQ();
105640235e2SEnji Cooper
106640235e2SEnji Cooper fesetround(FE_TOWARDZERO);
107640235e2SEnji Cooper ATF_CHECK(fpgetround() == FP_RZ);
108640235e2SEnji Cooper fesetround(FE_DOWNWARD);
109640235e2SEnji Cooper ATF_CHECK(fpgetround() == FP_RM);
110640235e2SEnji Cooper fesetround(FE_TONEAREST);
111640235e2SEnji Cooper ATF_CHECK(fpgetround() == FP_RN);
112640235e2SEnji Cooper fesetround(FE_UPWARD);
113640235e2SEnji Cooper ATF_CHECK(fpgetround() == FP_RP);
114640235e2SEnji Cooper }
115640235e2SEnji Cooper
116640235e2SEnji Cooper ATF_TC(fegetexcept);
117640235e2SEnji Cooper
ATF_TC_HEAD(fegetexcept,tc)118640235e2SEnji Cooper ATF_TC_HEAD(fegetexcept, tc)
119640235e2SEnji Cooper {
120640235e2SEnji Cooper atf_tc_set_md_var(tc, "descr",
121640235e2SEnji Cooper "verify the fegetexcept() function agrees with the legacy "
122640235e2SEnji Cooper "fpsetmask()");
123640235e2SEnji Cooper }
124640235e2SEnji Cooper
ATF_TC_BODY(fegetexcept,tc)125640235e2SEnji Cooper ATF_TC_BODY(fegetexcept, tc)
126640235e2SEnji Cooper {
127640235e2SEnji Cooper FPU_EXC_PREREQ();
128640235e2SEnji Cooper
129640235e2SEnji Cooper fpsetmask(0);
130640235e2SEnji Cooper ATF_CHECK(fegetexcept() == 0);
131640235e2SEnji Cooper
132640235e2SEnji Cooper fpsetmask(FP_X_INV|FP_X_DZ|FP_X_OFL|FP_X_UFL|FP_X_IMP);
133640235e2SEnji Cooper ATF_CHECK(fegetexcept() == (FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW
134640235e2SEnji Cooper |FE_UNDERFLOW|FE_INEXACT));
135640235e2SEnji Cooper
136640235e2SEnji Cooper fpsetmask(FP_X_INV);
137640235e2SEnji Cooper ATF_CHECK(fegetexcept() == FE_INVALID);
138640235e2SEnji Cooper
139640235e2SEnji Cooper fpsetmask(FP_X_DZ);
140640235e2SEnji Cooper ATF_CHECK(fegetexcept() == FE_DIVBYZERO);
141640235e2SEnji Cooper
142640235e2SEnji Cooper fpsetmask(FP_X_OFL);
143640235e2SEnji Cooper ATF_CHECK(fegetexcept() == FE_OVERFLOW);
144640235e2SEnji Cooper
145640235e2SEnji Cooper fpsetmask(FP_X_UFL);
146640235e2SEnji Cooper ATF_CHECK(fegetexcept() == FE_UNDERFLOW);
147640235e2SEnji Cooper
148640235e2SEnji Cooper fpsetmask(FP_X_IMP);
149640235e2SEnji Cooper ATF_CHECK(fegetexcept() == FE_INEXACT);
150640235e2SEnji Cooper }
151640235e2SEnji Cooper
152640235e2SEnji Cooper ATF_TC(feenableexcept);
153640235e2SEnji Cooper
ATF_TC_HEAD(feenableexcept,tc)154640235e2SEnji Cooper ATF_TC_HEAD(feenableexcept, tc)
155640235e2SEnji Cooper {
156640235e2SEnji Cooper atf_tc_set_md_var(tc, "descr",
157640235e2SEnji Cooper "verify the feenableexcept() function agrees with the legacy "
158640235e2SEnji Cooper "fpgetmask()");
159640235e2SEnji Cooper }
160640235e2SEnji Cooper
ATF_TC_BODY(feenableexcept,tc)161640235e2SEnji Cooper ATF_TC_BODY(feenableexcept, tc)
162640235e2SEnji Cooper {
163640235e2SEnji Cooper FPU_EXC_PREREQ();
164640235e2SEnji Cooper
165640235e2SEnji Cooper fedisableexcept(FE_ALL_EXCEPT);
166640235e2SEnji Cooper ATF_CHECK(fpgetmask() == 0);
167640235e2SEnji Cooper
168640235e2SEnji Cooper feenableexcept(FE_UNDERFLOW);
169640235e2SEnji Cooper ATF_CHECK(fpgetmask() == FP_X_UFL);
170640235e2SEnji Cooper
171640235e2SEnji Cooper fedisableexcept(FE_ALL_EXCEPT);
172640235e2SEnji Cooper feenableexcept(FE_OVERFLOW);
173640235e2SEnji Cooper ATF_CHECK(fpgetmask() == FP_X_OFL);
174640235e2SEnji Cooper
175640235e2SEnji Cooper fedisableexcept(FE_ALL_EXCEPT);
176640235e2SEnji Cooper feenableexcept(FE_DIVBYZERO);
177640235e2SEnji Cooper ATF_CHECK(fpgetmask() == FP_X_DZ);
178640235e2SEnji Cooper
179640235e2SEnji Cooper fedisableexcept(FE_ALL_EXCEPT);
180640235e2SEnji Cooper feenableexcept(FE_INEXACT);
181640235e2SEnji Cooper ATF_CHECK(fpgetmask() == FP_X_IMP);
182640235e2SEnji Cooper
183640235e2SEnji Cooper fedisableexcept(FE_ALL_EXCEPT);
184640235e2SEnji Cooper feenableexcept(FE_INVALID);
185640235e2SEnji Cooper ATF_CHECK(fpgetmask() == FP_X_INV);
186640235e2SEnji Cooper }
187640235e2SEnji Cooper
ATF_TP_ADD_TCS(tp)188640235e2SEnji Cooper ATF_TP_ADD_TCS(tp)
189640235e2SEnji Cooper {
190640235e2SEnji Cooper ATF_TP_ADD_TC(tp, fegetround);
191640235e2SEnji Cooper ATF_TP_ADD_TC(tp, fesetround);
192640235e2SEnji Cooper ATF_TP_ADD_TC(tp, fegetexcept);
193640235e2SEnji Cooper ATF_TP_ADD_TC(tp, feenableexcept);
194640235e2SEnji Cooper
195640235e2SEnji Cooper return atf_no_error();
196640235e2SEnji Cooper }
197640235e2SEnji Cooper
198640235e2SEnji Cooper #else /* no fenv.h support */
199640235e2SEnji Cooper
200640235e2SEnji Cooper ATF_TC(t_nofenv);
201640235e2SEnji Cooper
ATF_TC_HEAD(t_nofenv,tc)202640235e2SEnji Cooper ATF_TC_HEAD(t_nofenv, tc)
203640235e2SEnji Cooper {
204640235e2SEnji Cooper atf_tc_set_md_var(tc, "descr",
205640235e2SEnji Cooper "dummy test case - no fenv.h support");
206640235e2SEnji Cooper }
207640235e2SEnji Cooper
208640235e2SEnji Cooper
ATF_TC_BODY(t_nofenv,tc)209640235e2SEnji Cooper ATF_TC_BODY(t_nofenv, tc)
210640235e2SEnji Cooper {
211640235e2SEnji Cooper atf_tc_skip("no fenv.h support on this architecture");
212640235e2SEnji Cooper }
213640235e2SEnji Cooper
ATF_TP_ADD_TCS(tp)214640235e2SEnji Cooper ATF_TP_ADD_TCS(tp)
215640235e2SEnji Cooper {
216640235e2SEnji Cooper ATF_TP_ADD_TC(tp, t_nofenv);
217640235e2SEnji Cooper return atf_no_error();
218640235e2SEnji Cooper }
219640235e2SEnji Cooper
220640235e2SEnji Cooper #endif
221