Home | History | Annotate | Line # | Download | only in alpha
      1 /*	$NetBSD: fenv.c,v 1.3 2017/12/30 17:59:24 martin Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2004-2005 David Schultz <das (at) FreeBSD.ORG>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  *
     28  * $FreeBSD: src/lib/msun/alpha/fenv.c,v 1.2 2005/03/16 19:03:44 das Exp $
     29  */
     30 #include <sys/cdefs.h>
     31 __RCSID("$NetBSD: fenv.c,v 1.3 2017/12/30 17:59:24 martin Exp $");
     32 
     33 #include "namespace.h"
     34 
     35 #include <machine/sysarch.h>
     36 #include <fenv.h>
     37 
     38 #ifdef __weak_alias
     39 __weak_alias(fegetenv,_fegetenv)
     40 __weak_alias(feholdexcept,_feholdexcept)
     41 __weak_alias(fesetenv,_fesetenv)
     42 __weak_alias(feupdateenv,_feupdateenv)
     43 __weak_alias(feenableexcept,_feenableexcept)
     44 __weak_alias(fedisableexcept,_fedisableexcept)
     45 __weak_alias(fegetexcept,_fegetexcept)
     46 #endif
     47 
     48 const fenv_t __fe_dfl_env = 0x680e000000000000ULL;
     49 
     50 /*
     51  * The lower 49 bits of the FPCR are unused by the hardware, so we use
     52  * the lower order bits to store the kernel's idea of the FP mask as
     53  * described in the Alpha Architecture Manual.
     54  */
     55 int
     56 fegetenv(fenv_t *envp)
     57 {
     58 	struct alpha_fp_except_args p;
     59 	union __fpcr r;
     60 
     61 	/*
     62 	 * The syscall acts as an implicit exception barrier, so we
     63 	 * only need to issue an excb after the mf_fpcr to ensure that
     64 	 * the read is executed before any subsequent FP ops.
     65 	 */
     66 	p.mask = sysarch(ALPHA_FPGETMASK, 0);
     67 	__mf_fpcr(&r.__d);
     68 	*envp = r.__bits | p.mask;
     69 	__excb();
     70 	return 0;
     71 }
     72 
     73 int
     74 feholdexcept(fenv_t *envp)
     75 {
     76 	struct alpha_fp_except_args p;
     77 	union __fpcr r;
     78 
     79 	p.mask = sysarch(ALPHA_FPGETMASK, 0);
     80 	__mf_fpcr(&r.__d);
     81 	*envp = r.__bits | p.mask;
     82 	r.__bits &= ~((fenv_t)FE_ALL_EXCEPT << _FPUSW_SHIFT);
     83 	__mt_fpcr(r.__d);
     84 	if (p.mask & FE_ALL_EXCEPT) {
     85 		p.mask = 0;
     86 		sysarch(ALPHA_FPSETMASK, &p);
     87 	}
     88 	__excb();
     89 	return 0;
     90 }
     91 
     92 int
     93 fesetenv(const fenv_t *envp)
     94 {
     95 	struct alpha_fp_except_args p;
     96 	union __fpcr r;
     97 
     98 	p.mask = *envp & FE_ALL_EXCEPT;
     99 	sysarch(ALPHA_FPSETMASK, &p);
    100 	r.__bits = *envp & ~FE_ALL_EXCEPT;
    101 	__mt_fpcr(r.__d);
    102 	__excb();
    103 	return 0;
    104 }
    105 
    106 int
    107 feupdateenv(const fenv_t *envp)
    108 {
    109 	struct alpha_fp_except_args p;
    110 	union __fpcr oldr, newr;
    111 
    112 	p.mask = *envp & FE_ALL_EXCEPT;
    113 	sysarch(ALPHA_FPSETMASK, &p);
    114 	__mf_fpcr(&oldr.__d);
    115 	newr.__bits = *envp & ~FE_ALL_EXCEPT;
    116 	__excb();
    117 	__mt_fpcr(newr.__d);
    118 	feraiseexcept((oldr.__bits >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
    119 	return 0;
    120 }
    121 
    122 int
    123 feenableexcept(int mask)
    124 {
    125 	struct alpha_fp_except_args p;
    126 
    127 	p.mask = sysarch(ALPHA_FPGETMASK, 0);
    128 	p.mask |= (mask & FE_ALL_EXCEPT);
    129 	sysarch(ALPHA_FPSETMASK, &p);
    130 	return p.mask;
    131 }
    132 
    133 int
    134 fedisableexcept(int mask)
    135 {
    136 	struct alpha_fp_except_args p;
    137 
    138 	p.mask = sysarch(ALPHA_FPGETMASK, 0);
    139 	p.mask &= ~(mask & FE_ALL_EXCEPT);
    140 	sysarch(ALPHA_FPSETMASK, &p);
    141 	return p.mask;
    142 }
    143 
    144 int
    145 fegetexcept(void)
    146 {
    147 
    148 	return sysarch(ALPHA_FPGETMASK, 0);
    149 }
    150