Home | History | Annotate | Line # | Download | only in gen
t_fpsetmask.c revision 1.16.16.1
      1  1.16.16.1  christos /*	$NetBSD: t_fpsetmask.c,v 1.16.16.1 2019/06/10 22:10:03 christos Exp $ */
      2        1.1    jruoho 
      3        1.1    jruoho /*-
      4        1.1    jruoho  * Copyright (c) 1995 The NetBSD Foundation, Inc.
      5        1.1    jruoho  * All rights reserved.
      6        1.1    jruoho  *
      7        1.1    jruoho  * Redistribution and use in source and binary forms, with or without
      8        1.1    jruoho  * modification, are permitted provided that the following conditions
      9        1.1    jruoho  * are met:
     10        1.1    jruoho  * 1. Redistributions of source code must retain the above copyright
     11        1.1    jruoho  *    notice, this list of conditions and the following disclaimer.
     12        1.1    jruoho  * 2. Redistributions in binary form must reproduce the above copyright
     13        1.1    jruoho  *    notice, this list of conditions and the following disclaimer in the
     14        1.1    jruoho  *    documentation and/or other materials provided with the distribution.
     15        1.1    jruoho  *
     16        1.1    jruoho  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17        1.1    jruoho  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18        1.1    jruoho  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19        1.1    jruoho  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20        1.1    jruoho  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21        1.1    jruoho  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22        1.1    jruoho  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23        1.1    jruoho  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24        1.1    jruoho  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25        1.1    jruoho  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26        1.1    jruoho  * POSSIBILITY OF SUCH DAMAGE.
     27        1.1    jruoho  */
     28        1.1    jruoho 
     29       1.13      jmmv #include <sys/param.h>
     30       1.13      jmmv 
     31        1.1    jruoho #include <atf-c.h>
     32        1.1    jruoho 
     33        1.1    jruoho #include <stdio.h>
     34        1.1    jruoho #include <signal.h>
     35        1.1    jruoho #include <float.h>
     36        1.1    jruoho #include <setjmp.h>
     37        1.1    jruoho #include <stdlib.h>
     38        1.1    jruoho #include <string.h>
     39        1.1    jruoho 
     40       1.10  christos #include "isqemu.h"
     41       1.10  christos 
     42        1.2  christos #ifndef _FLOAT_IEEE754
     43        1.1    jruoho 
     44        1.1    jruoho ATF_TC(no_test);
     45        1.1    jruoho ATF_TC_HEAD(no_test, tc)
     46        1.1    jruoho {
     47        1.1    jruoho 
     48        1.1    jruoho 	atf_tc_set_md_var(tc, "descr", "Dummy test case");
     49        1.1    jruoho }
     50        1.1    jruoho 
     51        1.1    jruoho ATF_TC_BODY(no_test, tc)
     52        1.1    jruoho {
     53        1.1    jruoho 
     54        1.1    jruoho 	atf_tc_skip("Test not available on this architecture.");
     55        1.1    jruoho }
     56        1.1    jruoho 
     57        1.2  christos #else /* defined(_FLOAT_IEEE754) */
     58        1.1    jruoho 
     59        1.1    jruoho #include <ieeefp.h>
     60        1.1    jruoho 
     61  1.16.16.1  christos #if (__arm__ && !__SOFTFP__) || __aarch64__
     62       1.15    martin 	/*
     63  1.16.16.1  christos 	 * Some NEON fpus do not trap on IEEE 754 FP exceptions.
     64       1.15    martin 	 * skip these tests if running on them and compiled for
     65       1.15    martin 	 * hard float.
     66       1.15    martin 	 */
     67       1.15    martin #define	FPU_PREREQ()							\
     68       1.15    martin 	if (0 == fpsetmask(fpsetmask(FP_X_INV)))			\
     69  1.16.16.1  christos 		atf_tc_skip("FPU does not implement traps on FP exceptions");
     70       1.15    martin #endif
     71       1.15    martin 
     72       1.15    martin #ifndef FPU_PREREQ
     73       1.15    martin #define	FPU_PREREQ()	/* nothing */
     74       1.15    martin #endif
     75        1.1    jruoho 
     76        1.1    jruoho void		sigfpe(int, siginfo_t *, void *);
     77        1.1    jruoho 
     78        1.1    jruoho volatile sig_atomic_t signal_caught;
     79        1.1    jruoho volatile int sicode;
     80        1.1    jruoho 
     81        1.1    jruoho static volatile const float	f_one   = 1.0;
     82        1.1    jruoho static volatile const float	f_zero  = 0.0;
     83        1.1    jruoho static volatile const double	d_one   = 1.0;
     84        1.1    jruoho static volatile const double	d_zero  = 0.0;
     85        1.1    jruoho static volatile const long double ld_one  = 1.0;
     86        1.1    jruoho static volatile const long double ld_zero = 0.0;
     87        1.1    jruoho 
     88        1.1    jruoho static volatile const float	f_huge = FLT_MAX;
     89        1.1    jruoho static volatile const float	f_tiny = FLT_MIN;
     90        1.1    jruoho static volatile const double	d_huge = DBL_MAX;
     91        1.1    jruoho static volatile const double	d_tiny = DBL_MIN;
     92        1.1    jruoho static volatile const long double ld_huge = LDBL_MAX;
     93        1.1    jruoho static volatile const long double ld_tiny = LDBL_MIN;
     94        1.1    jruoho 
     95        1.1    jruoho static volatile float f_x;
     96        1.1    jruoho static volatile double d_x;
     97        1.1    jruoho static volatile long double ld_x;
     98        1.1    jruoho 
     99        1.1    jruoho /* trip divide by zero */
    100        1.1    jruoho static void
    101        1.1    jruoho f_dz(void)
    102        1.1    jruoho {
    103        1.1    jruoho 
    104        1.1    jruoho 	f_x = f_one / f_zero;
    105        1.1    jruoho }
    106        1.1    jruoho 
    107        1.1    jruoho static void
    108        1.1    jruoho d_dz(void)
    109        1.1    jruoho {
    110        1.1    jruoho 
    111        1.1    jruoho 	d_x = d_one / d_zero;
    112        1.1    jruoho }
    113        1.1    jruoho 
    114        1.1    jruoho static void
    115        1.1    jruoho ld_dz(void)
    116        1.1    jruoho {
    117        1.1    jruoho 
    118        1.1    jruoho 	ld_x = ld_one / ld_zero;
    119        1.1    jruoho }
    120        1.1    jruoho 
    121        1.1    jruoho /* trip invalid operation */
    122        1.1    jruoho static void
    123        1.1    jruoho d_inv(void)
    124        1.1    jruoho {
    125        1.1    jruoho 
    126        1.1    jruoho 	d_x = d_zero / d_zero;
    127        1.1    jruoho }
    128        1.1    jruoho 
    129        1.1    jruoho static void
    130        1.1    jruoho ld_inv(void)
    131        1.1    jruoho {
    132        1.1    jruoho 
    133        1.1    jruoho 	ld_x = ld_zero / ld_zero;
    134        1.1    jruoho }
    135        1.1    jruoho 
    136        1.1    jruoho static void
    137        1.1    jruoho f_inv(void)
    138        1.1    jruoho {
    139        1.1    jruoho 
    140        1.1    jruoho 	f_x = f_zero / f_zero;
    141        1.1    jruoho }
    142        1.1    jruoho 
    143        1.1    jruoho /* trip overflow */
    144        1.1    jruoho static void
    145        1.1    jruoho f_ofl(void)
    146        1.1    jruoho {
    147        1.1    jruoho 
    148        1.1    jruoho 	f_x = f_huge * f_huge;
    149        1.1    jruoho }
    150        1.1    jruoho 
    151        1.1    jruoho static void
    152        1.1    jruoho d_ofl(void)
    153        1.1    jruoho {
    154        1.1    jruoho 
    155        1.1    jruoho 	d_x = d_huge * d_huge;
    156        1.1    jruoho }
    157        1.1    jruoho 
    158        1.1    jruoho static void
    159        1.1    jruoho ld_ofl(void)
    160        1.1    jruoho {
    161        1.1    jruoho 
    162        1.1    jruoho 	ld_x = ld_huge * ld_huge;
    163        1.1    jruoho }
    164        1.1    jruoho 
    165        1.1    jruoho /* trip underflow */
    166        1.1    jruoho static void
    167        1.1    jruoho f_ufl(void)
    168        1.1    jruoho {
    169        1.1    jruoho 
    170        1.1    jruoho 	f_x = f_tiny * f_tiny;
    171        1.1    jruoho }
    172        1.1    jruoho 
    173        1.1    jruoho static void
    174        1.1    jruoho d_ufl(void)
    175        1.1    jruoho {
    176        1.1    jruoho 
    177        1.1    jruoho 	d_x = d_tiny * d_tiny;
    178        1.1    jruoho }
    179        1.1    jruoho 
    180        1.1    jruoho static void
    181        1.1    jruoho ld_ufl(void)
    182        1.1    jruoho {
    183        1.1    jruoho 
    184        1.1    jruoho 	ld_x = ld_tiny * ld_tiny;
    185        1.1    jruoho }
    186        1.1    jruoho 
    187        1.1    jruoho struct ops {
    188        1.1    jruoho 	void (*op)(void);
    189        1.1    jruoho 	fp_except mask;
    190        1.1    jruoho 	int sicode;
    191        1.1    jruoho };
    192        1.1    jruoho 
    193        1.1    jruoho static const struct ops float_ops[] = {
    194        1.1    jruoho 	{ f_dz, FP_X_DZ, FPE_FLTDIV },
    195        1.1    jruoho 	{ f_inv, FP_X_INV, FPE_FLTINV },
    196        1.1    jruoho 	{ f_ofl, FP_X_OFL, FPE_FLTOVF },
    197        1.1    jruoho 	{ f_ufl, FP_X_UFL, FPE_FLTUND },
    198        1.1    jruoho 	{ NULL, 0, 0 }
    199        1.1    jruoho };
    200        1.1    jruoho 
    201        1.1    jruoho static const struct ops double_ops[] = {
    202        1.1    jruoho 	{ d_dz, FP_X_DZ, FPE_FLTDIV },
    203        1.1    jruoho 	{ d_inv, FP_X_INV, FPE_FLTINV },
    204        1.1    jruoho 	{ d_ofl, FP_X_OFL, FPE_FLTOVF },
    205        1.1    jruoho 	{ d_ufl, FP_X_UFL, FPE_FLTUND },
    206        1.1    jruoho 	{ NULL, 0, 0 }
    207        1.1    jruoho };
    208        1.1    jruoho 
    209        1.1    jruoho static const struct ops long_double_ops[] = {
    210        1.1    jruoho 	{ ld_dz, FP_X_DZ, FPE_FLTDIV },
    211        1.1    jruoho 	{ ld_inv, FP_X_INV, FPE_FLTINV },
    212        1.1    jruoho 	{ ld_ofl, FP_X_OFL, FPE_FLTOVF },
    213        1.1    jruoho 	{ ld_ufl, FP_X_UFL, FPE_FLTUND },
    214        1.1    jruoho 	{ NULL, 0, 0 }
    215        1.1    jruoho };
    216        1.1    jruoho 
    217        1.1    jruoho static sigjmp_buf b;
    218        1.1    jruoho 
    219        1.1    jruoho static void
    220        1.1    jruoho fpsetmask_masked(const struct ops *test_ops)
    221        1.1    jruoho {
    222        1.1    jruoho 	struct sigaction sa;
    223        1.1    jruoho 	fp_except ex1, ex2;
    224        1.1    jruoho 	const struct ops *t;
    225        1.1    jruoho 
    226        1.1    jruoho 	/* mask all exceptions, clear history */
    227        1.1    jruoho 	fpsetmask(0);
    228        1.1    jruoho 	fpsetsticky(0);
    229        1.1    jruoho 
    230        1.1    jruoho 	/* set up signal handler */
    231        1.1    jruoho 	sa.sa_sigaction = sigfpe;
    232        1.1    jruoho 	sigemptyset(&sa.sa_mask);
    233        1.1    jruoho 	sa.sa_flags = SA_SIGINFO;
    234        1.1    jruoho 	sigaction(SIGFPE, &sa, 0);
    235        1.1    jruoho 	signal_caught = 0;
    236        1.1    jruoho 
    237        1.1    jruoho 	/*
    238        1.1    jruoho 	 * exceptions masked, check whether "sticky" bits are set correctly
    239        1.1    jruoho 	 */
    240        1.1    jruoho 	for (t = test_ops; t->op != NULL; t++) {
    241        1.1    jruoho 		(*t->op)();
    242        1.1    jruoho 		ex1 = fpgetsticky();
    243        1.1    jruoho 		ATF_CHECK_EQ(ex1 & t->mask, t->mask);
    244        1.1    jruoho 		ATF_CHECK_EQ(signal_caught, 0);
    245        1.1    jruoho 
    246        1.1    jruoho 		/* check correct fpsetsticky() behaviour */
    247        1.1    jruoho 		ex2 = fpsetsticky(0);
    248        1.1    jruoho 		ATF_CHECK_EQ(fpgetsticky(), 0);
    249        1.1    jruoho 		ATF_CHECK_EQ(ex1, ex2);
    250        1.1    jruoho 	}
    251        1.1    jruoho }
    252        1.1    jruoho 
    253        1.1    jruoho /* force delayed exceptions to be delivered */
    254        1.1    jruoho #define BARRIER() fpsetmask(0); f_x = f_one * f_one
    255        1.1    jruoho 
    256        1.1    jruoho static void
    257        1.1    jruoho fpsetmask_unmasked(const struct ops *test_ops)
    258        1.1    jruoho {
    259        1.1    jruoho 	struct sigaction sa;
    260        1.1    jruoho 	int r;
    261        1.1    jruoho 	const struct ops *volatile t;
    262        1.1    jruoho 
    263        1.1    jruoho 	/* mask all exceptions, clear history */
    264        1.1    jruoho 	fpsetmask(0);
    265        1.1    jruoho 	fpsetsticky(0);
    266        1.1    jruoho 
    267        1.1    jruoho 	/* set up signal handler */
    268        1.1    jruoho 	sa.sa_sigaction = sigfpe;
    269        1.1    jruoho 	sigemptyset(&sa.sa_mask);
    270        1.1    jruoho 	sa.sa_flags = SA_SIGINFO;
    271        1.1    jruoho 	sigaction(SIGFPE, &sa, 0);
    272        1.1    jruoho 	signal_caught = 0;
    273        1.1    jruoho 
    274        1.1    jruoho 	/*
    275        1.1    jruoho 	 * exception unmasked, check SIGFPE delivery and correct siginfo
    276        1.1    jruoho 	 */
    277        1.1    jruoho 	for (t = test_ops; t->op != NULL; t++) {
    278        1.1    jruoho 		fpsetmask(t->mask);
    279        1.1    jruoho 		r = sigsetjmp(b, 1);
    280        1.1    jruoho 		if (!r) {
    281        1.1    jruoho 			(*t->op)();
    282        1.1    jruoho 			BARRIER();
    283        1.1    jruoho 		}
    284        1.1    jruoho 		ATF_CHECK_EQ(signal_caught, 1);
    285        1.1    jruoho 		ATF_CHECK_EQ(sicode, t->sicode);
    286        1.1    jruoho 		signal_caught = 0;
    287        1.1    jruoho 	}
    288        1.1    jruoho }
    289        1.1    jruoho 
    290        1.1    jruoho void
    291        1.1    jruoho sigfpe(int s, siginfo_t *si, void *c)
    292        1.1    jruoho {
    293        1.1    jruoho 	signal_caught = 1;
    294        1.1    jruoho 	sicode = si->si_code;
    295        1.1    jruoho 	siglongjmp(b, 1);
    296        1.1    jruoho }
    297        1.1    jruoho 
    298        1.1    jruoho #define TEST(m, t)							\
    299        1.1    jruoho 	ATF_TC(m##_##t);						\
    300        1.1    jruoho 									\
    301        1.1    jruoho 	ATF_TC_HEAD(m##_##t, tc)					\
    302        1.1    jruoho 	{								\
    303        1.1    jruoho 									\
    304        1.1    jruoho 		atf_tc_set_md_var(tc, "descr",				\
    305        1.1    jruoho 		    "Test " ___STRING(m) " exceptions for "		\
    306        1.1    jruoho 		    ___STRING(t) "values");				\
    307        1.1    jruoho 	}								\
    308        1.1    jruoho 									\
    309        1.1    jruoho 	ATF_TC_BODY(m##_##t, tc)					\
    310        1.1    jruoho 	{								\
    311       1.15    martin 									\
    312       1.15    martin 		FPU_PREREQ();						\
    313       1.15    martin 									\
    314       1.10  christos 		if (isQEMU())						\
    315        1.7    jruoho 			atf_tc_expect_fail("PR misc/44767");		\
    316        1.7    jruoho 									\
    317        1.1    jruoho 		m(t##_ops);						\
    318        1.1    jruoho 	}
    319        1.1    jruoho 
    320        1.1    jruoho TEST(fpsetmask_masked, float)
    321        1.1    jruoho TEST(fpsetmask_masked, double)
    322        1.1    jruoho TEST(fpsetmask_masked, long_double)
    323        1.1    jruoho TEST(fpsetmask_unmasked, float)
    324        1.1    jruoho TEST(fpsetmask_unmasked, double)
    325        1.1    jruoho TEST(fpsetmask_unmasked, long_double)
    326        1.1    jruoho 
    327        1.3     njoly ATF_TC(fpsetmask_basic);
    328        1.3     njoly ATF_TC_HEAD(fpsetmask_basic, tc)
    329        1.3     njoly {
    330        1.3     njoly 	atf_tc_set_md_var(tc, "descr", "A basic test of fpsetmask(3)");
    331        1.3     njoly }
    332        1.3     njoly 
    333        1.3     njoly ATF_TC_BODY(fpsetmask_basic, tc)
    334        1.3     njoly {
    335        1.3     njoly 	size_t i;
    336        1.3     njoly 	fp_except_t msk, lst[] = { FP_X_INV, FP_X_DZ, FP_X_OFL, FP_X_UFL };
    337        1.3     njoly 
    338       1.15    martin 	FPU_PREREQ();
    339       1.15    martin 
    340        1.3     njoly 	msk = fpgetmask();
    341        1.3     njoly 	for (i = 0; i < __arraycount(lst); i++) {
    342        1.3     njoly 		fpsetmask(msk | lst[i]);
    343        1.3     njoly 		ATF_CHECK((fpgetmask() & lst[i]) != 0);
    344       1.16    martin 		fpsetmask(msk & ~lst[i]);
    345        1.3     njoly 		ATF_CHECK((fpgetmask() & lst[i]) == 0);
    346        1.3     njoly 	}
    347        1.3     njoly 
    348        1.3     njoly }
    349        1.3     njoly 
    350        1.2  christos #endif /* defined(_FLOAT_IEEE754) */
    351        1.1    jruoho 
    352        1.1    jruoho ATF_TP_ADD_TCS(tp)
    353        1.1    jruoho {
    354        1.1    jruoho 
    355        1.2  christos #ifndef _FLOAT_IEEE754
    356        1.1    jruoho 	ATF_TP_ADD_TC(tp, no_test);
    357        1.1    jruoho #else
    358        1.3     njoly 	ATF_TP_ADD_TC(tp, fpsetmask_basic);
    359        1.1    jruoho 	ATF_TP_ADD_TC(tp, fpsetmask_masked_float);
    360        1.1    jruoho 	ATF_TP_ADD_TC(tp, fpsetmask_masked_double);
    361        1.1    jruoho 	ATF_TP_ADD_TC(tp, fpsetmask_masked_long_double);
    362        1.1    jruoho 	ATF_TP_ADD_TC(tp, fpsetmask_unmasked_float);
    363        1.1    jruoho 	ATF_TP_ADD_TC(tp, fpsetmask_unmasked_double);
    364        1.1    jruoho 	ATF_TP_ADD_TC(tp, fpsetmask_unmasked_long_double);
    365        1.1    jruoho #endif
    366        1.1    jruoho 
    367        1.1    jruoho 	return atf_no_error();
    368        1.1    jruoho }
    369