Path: blob/main/lib/libc/tests/gen/fpsetmask_test.c
289379 views
/* $NetBSD: t_fpsetmask.c,v 1.16 2016/03/12 11:55:14 martin Exp $ */12/*-3* Copyright (c) 1995 The NetBSD Foundation, Inc.4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS16* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED17* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR18* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS19* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR20* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF21* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS22* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN23* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)24* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE25* POSSIBILITY OF SUCH DAMAGE.26*/2728#include <sys/param.h>2930#include <atf-c.h>3132#include <stdio.h>33#include <signal.h>34#include <float.h>35#include <setjmp.h>36#include <stdlib.h>37#include <string.h>3839#ifndef __i386__4041ATF_TC(no_test);42ATF_TC_HEAD(no_test, tc)43{4445atf_tc_set_md_var(tc, "descr", "Dummy test case");46}4748ATF_TC_BODY(no_test, tc)49{5051atf_tc_skip("Test not available on this architecture.");52}5354#else /* defined(__i386__) */5556#include <ieeefp.h>57#ifndef ___STRING58#define ___STRING(x) #x59#endif60#ifndef __arraycount61#define __arraycount(x) (sizeof(x) / sizeof((x)[0]))62#endif636465#if __arm__ && !__SOFTFP__66/*67* Some NEON fpus do not implement IEEE exception handling,68* skip these tests if running on them and compiled for69* hard float.70*/71#define FPU_PREREQ() \72if (0 == fpsetmask(fpsetmask(FP_X_INV))) \73atf_tc_skip("FPU does not implement exception handling");74#endif7576#ifndef FPU_PREREQ77#define FPU_PREREQ() /* nothing */78#endif7980void sigfpe(int, siginfo_t *, void *);8182volatile sig_atomic_t signal_caught;83volatile int sicode;8485static volatile const float f_one = 1.0;86static volatile const float f_zero = 0.0;87static volatile const double d_one = 1.0;88static volatile const double d_zero = 0.0;89static volatile const long double ld_one = 1.0;90static volatile const long double ld_zero = 0.0;9192static volatile const float f_huge = FLT_MAX;93static volatile const float f_tiny = FLT_MIN;94static volatile const double d_huge = DBL_MAX;95static volatile const double d_tiny = DBL_MIN;96static volatile const long double ld_huge = LDBL_MAX;97static volatile const long double ld_tiny = LDBL_MIN;9899static volatile float f_x;100static volatile double d_x;101static volatile long double ld_x;102103/* trip divide by zero */104static void105f_dz(void)106{107108f_x = f_one / f_zero;109}110111static void112d_dz(void)113{114115d_x = d_one / d_zero;116}117118static void119ld_dz(void)120{121122ld_x = ld_one / ld_zero;123}124125/* trip invalid operation */126static void127d_inv(void)128{129130d_x = d_zero / d_zero;131}132133static void134ld_inv(void)135{136137ld_x = ld_zero / ld_zero;138}139140static void141f_inv(void)142{143144f_x = f_zero / f_zero;145}146147/* trip overflow */148static void149f_ofl(void)150{151f_x = f_huge * f_huge;152printf("%f %f %Lf", f_x, d_x, ld_x); // avoid compiler optimization153}154155static void156d_ofl(void)157{158159d_x = d_huge * d_huge;160printf("%f %f %Lf", f_x, d_x, ld_x); // avoid compiler optimization161}162163static void164ld_ofl(void)165{166167ld_x = ld_huge * ld_huge;168printf("%f %f %Lf", f_x, d_x, ld_x); // avoid compiler optimization169}170171/* trip underflow */172static void173f_ufl(void)174{175f_x = f_tiny * f_tiny;176printf("%f %f %Lf", f_x, d_x, ld_x); // avoid compiler optimization177}178179static void180d_ufl(void)181{182d_x = d_tiny * d_tiny;183printf("%f %f %Lf", f_x, d_x, ld_x); // avoid compiler optimization184}185186static void187ld_ufl(void)188{189ld_x = ld_tiny * ld_tiny;190printf("%f %f %Lf", f_x, d_x, ld_x); // avoid compiler optimization191}192193struct ops {194void (*op)(void);195fp_except_t mask;196int sicode;197};198199static const struct ops float_ops[] = {200{ f_dz, FP_X_DZ, FPE_FLTDIV },201{ f_inv, FP_X_INV, FPE_FLTINV },202{ f_ofl, FP_X_OFL, FPE_FLTOVF },203{ f_ufl, FP_X_UFL, FPE_FLTUND },204{ NULL, 0, 0 }205};206207static const struct ops double_ops[] = {208{ d_dz, FP_X_DZ, FPE_FLTDIV },209{ d_inv, FP_X_INV, FPE_FLTINV },210{ d_ofl, FP_X_OFL, FPE_FLTOVF },211{ d_ufl, FP_X_UFL, FPE_FLTUND },212{ NULL, 0, 0 }213};214215static const struct ops long_double_ops[] = {216{ ld_dz, FP_X_DZ, FPE_FLTDIV },217{ ld_inv, FP_X_INV, FPE_FLTINV },218{ ld_ofl, FP_X_OFL, FPE_FLTOVF },219{ ld_ufl, FP_X_UFL, FPE_FLTUND },220{ NULL, 0, 0 }221};222223static sigjmp_buf b;224225static void226fpsetmask_masked(const struct ops *test_ops)227{228struct sigaction sa;229fp_except_t ex1, ex2;230const struct ops *t;231232/* mask all exceptions, clear history */233fpsetmask(0);234fpresetsticky(~0);235236/* set up signal handler */237sa.sa_sigaction = sigfpe;238sigemptyset(&sa.sa_mask);239sa.sa_flags = SA_SIGINFO;240sigaction(SIGFPE, &sa, 0);241signal_caught = 0;242243/*244* exceptions masked, check whether "sticky" bits are set correctly245*/246for (t = test_ops; t->op != NULL; t++) {247(*t->op)();248ex1 = fpgetsticky();249ATF_CHECK_EQ(ex1 & t->mask, t->mask);250ATF_CHECK_EQ(signal_caught, 0);251252/* check correct fpresetsticky() behaviour */253ex2 = fpresetsticky(~0);254ATF_CHECK_EQ(fpgetsticky(), 0);255ATF_CHECK_EQ(ex1, ex2);256}257}258259/* force delayed exceptions to be delivered */260#define BARRIER() fpsetmask(0); f_x = f_one * f_one261262static void263fpsetmask_unmasked(const struct ops *test_ops)264{265struct sigaction sa;266int r;267const struct ops *volatile t;268269/* mask all exceptions, clear history */270fpsetmask(0);271fpresetsticky(~0);272273/* set up signal handler */274sa.sa_sigaction = sigfpe;275sigemptyset(&sa.sa_mask);276sa.sa_flags = SA_SIGINFO;277sigaction(SIGFPE, &sa, 0);278signal_caught = 0;279280/*281* exception unmasked, check SIGFPE delivery and correct siginfo282*/283for (t = test_ops; t->op != NULL; t++) {284fpsetmask(t->mask);285r = sigsetjmp(b, 1);286printf("r = %d\n", r);287if (!r) {288(*t->op)();289BARRIER();290fpresetsticky(~0);291}292ATF_CHECK_EQ(signal_caught, 1);293ATF_CHECK_EQ(sicode, t->sicode);294signal_caught = 0;295sicode = 0;296}297}298299void300sigfpe(int s, siginfo_t *si, void *c)301{302signal_caught = 1;303sicode = si->si_code;304siglongjmp(b, 1);305}306307#define TEST(m, t) \308ATF_TC(m##_##t); \309\310ATF_TC_HEAD(m##_##t, tc) \311{ \312\313atf_tc_set_md_var(tc, "descr", \314"Test " ___STRING(m) " exceptions for " \315___STRING(t) "values"); \316} \317\318ATF_TC_BODY(m##_##t, tc) \319{ \320\321FPU_PREREQ(); \322\323if (strcmp(MACHINE, "macppc") == 0) \324atf_tc_expect_fail("PR port-macppc/46319"); \325\326\327m(t##_ops); \328}329330TEST(fpsetmask_masked, float)331TEST(fpsetmask_masked, double)332TEST(fpsetmask_masked, long_double)333TEST(fpsetmask_unmasked, float)334TEST(fpsetmask_unmasked, double)335TEST(fpsetmask_unmasked, long_double)336337ATF_TC(fpsetmask_basic);338ATF_TC_HEAD(fpsetmask_basic, tc)339{340atf_tc_set_md_var(tc, "descr", "A basic test of fpsetmask(3)");341}342343ATF_TC_BODY(fpsetmask_basic, tc)344{345size_t i;346fp_except_t msk, lst[] = { FP_X_INV, FP_X_DZ, FP_X_OFL, FP_X_UFL };347348FPU_PREREQ();349350msk = fpgetmask();351for (i = 0; i < __arraycount(lst); i++) {352fpsetmask(msk | lst[i]);353ATF_CHECK((fpgetmask() & lst[i]) != 0);354fpsetmask(msk & ~lst[i]);355ATF_CHECK((fpgetmask() & lst[i]) == 0);356}357358}359360#endif /* defined(__i386__) */361362ATF_TP_ADD_TCS(tp)363{364365#ifndef __i386__366ATF_TP_ADD_TC(tp, no_test);367#else368ATF_TP_ADD_TC(tp, fpsetmask_basic);369ATF_TP_ADD_TC(tp, fpsetmask_masked_float);370ATF_TP_ADD_TC(tp, fpsetmask_masked_double);371ATF_TP_ADD_TC(tp, fpsetmask_masked_long_double);372ATF_TP_ADD_TC(tp, fpsetmask_unmasked_float);373ATF_TP_ADD_TC(tp, fpsetmask_unmasked_double);374ATF_TP_ADD_TC(tp, fpsetmask_unmasked_long_double);375#endif376377return atf_no_error();378}379380381