1*8d67ca89SAndroid Build Coastguard Worker /*-
2*8d67ca89SAndroid Build Coastguard Worker * Copyright (c) 2004 David Schultz <[email protected]>
3*8d67ca89SAndroid Build Coastguard Worker * All rights reserved.
4*8d67ca89SAndroid Build Coastguard Worker *
5*8d67ca89SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
6*8d67ca89SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions
7*8d67ca89SAndroid Build Coastguard Worker * are met:
8*8d67ca89SAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright
9*8d67ca89SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
10*8d67ca89SAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright
11*8d67ca89SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the
12*8d67ca89SAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution.
13*8d67ca89SAndroid Build Coastguard Worker *
14*8d67ca89SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*8d67ca89SAndroid Build Coastguard Worker * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*8d67ca89SAndroid Build Coastguard Worker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*8d67ca89SAndroid Build Coastguard Worker * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*8d67ca89SAndroid Build Coastguard Worker * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*8d67ca89SAndroid Build Coastguard Worker * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*8d67ca89SAndroid Build Coastguard Worker * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*8d67ca89SAndroid Build Coastguard Worker * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*8d67ca89SAndroid Build Coastguard Worker * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*8d67ca89SAndroid Build Coastguard Worker * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*8d67ca89SAndroid Build Coastguard Worker * SUCH DAMAGE.
25*8d67ca89SAndroid Build Coastguard Worker *
26*8d67ca89SAndroid Build Coastguard Worker * $FreeBSD: libm/aarch64/fenv.c $
27*8d67ca89SAndroid Build Coastguard Worker */
28*8d67ca89SAndroid Build Coastguard Worker
29*8d67ca89SAndroid Build Coastguard Worker #include <stdint.h>
30*8d67ca89SAndroid Build Coastguard Worker #include <fenv.h>
31*8d67ca89SAndroid Build Coastguard Worker
32*8d67ca89SAndroid Build Coastguard Worker #define FPCR_RMODE_SHIFT 22
33*8d67ca89SAndroid Build Coastguard Worker
34*8d67ca89SAndroid Build Coastguard Worker const fenv_t __fe_dfl_env = { 0 /* control */, 0 /* status */};
35*8d67ca89SAndroid Build Coastguard Worker
36*8d67ca89SAndroid Build Coastguard Worker typedef __uint32_t fpu_control_t; // FPCR, Floating-point Control Register.
37*8d67ca89SAndroid Build Coastguard Worker typedef __uint32_t fpu_status_t; // FPSR, Floating-point Status Register.
38*8d67ca89SAndroid Build Coastguard Worker
39*8d67ca89SAndroid Build Coastguard Worker #define __get(REGISTER, __value) { \
40*8d67ca89SAndroid Build Coastguard Worker uint64_t __value64; \
41*8d67ca89SAndroid Build Coastguard Worker __asm__ __volatile__("mrs %0," REGISTER : "=r" (__value64)); \
42*8d67ca89SAndroid Build Coastguard Worker __value = (__uint32_t) __value64; \
43*8d67ca89SAndroid Build Coastguard Worker }
44*8d67ca89SAndroid Build Coastguard Worker #define __get_fpcr(__fpcr) __get("fpcr", __fpcr)
45*8d67ca89SAndroid Build Coastguard Worker #define __get_fpsr(__fpsr) __get("fpsr", __fpsr)
46*8d67ca89SAndroid Build Coastguard Worker
47*8d67ca89SAndroid Build Coastguard Worker #define __set(REGISTER, __value) { \
48*8d67ca89SAndroid Build Coastguard Worker uint64_t __value64 = __value; \
49*8d67ca89SAndroid Build Coastguard Worker __asm__ __volatile__("msr " REGISTER ",%0" : : "ri" (__value64)); \
50*8d67ca89SAndroid Build Coastguard Worker }
51*8d67ca89SAndroid Build Coastguard Worker #define __set_fpcr(__fpcr) __set("fpcr", __fpcr)
52*8d67ca89SAndroid Build Coastguard Worker #define __set_fpsr(__fpsr) __set("fpsr", __fpsr)
53*8d67ca89SAndroid Build Coastguard Worker
fegetenv(fenv_t * envp)54*8d67ca89SAndroid Build Coastguard Worker int fegetenv(fenv_t* envp) {
55*8d67ca89SAndroid Build Coastguard Worker __get_fpcr(envp->__control);
56*8d67ca89SAndroid Build Coastguard Worker __get_fpsr(envp->__status);
57*8d67ca89SAndroid Build Coastguard Worker return 0;
58*8d67ca89SAndroid Build Coastguard Worker }
59*8d67ca89SAndroid Build Coastguard Worker
fesetenv(const fenv_t * envp)60*8d67ca89SAndroid Build Coastguard Worker int fesetenv(const fenv_t* envp) {
61*8d67ca89SAndroid Build Coastguard Worker fpu_control_t fpcr;
62*8d67ca89SAndroid Build Coastguard Worker __get_fpcr(fpcr);
63*8d67ca89SAndroid Build Coastguard Worker if (envp->__control != fpcr) {
64*8d67ca89SAndroid Build Coastguard Worker __set_fpcr(envp->__control);
65*8d67ca89SAndroid Build Coastguard Worker }
66*8d67ca89SAndroid Build Coastguard Worker __set_fpsr(envp->__status);
67*8d67ca89SAndroid Build Coastguard Worker return 0;
68*8d67ca89SAndroid Build Coastguard Worker }
69*8d67ca89SAndroid Build Coastguard Worker
feclearexcept(int excepts)70*8d67ca89SAndroid Build Coastguard Worker int feclearexcept(int excepts) {
71*8d67ca89SAndroid Build Coastguard Worker fpu_status_t fpsr;
72*8d67ca89SAndroid Build Coastguard Worker __get_fpsr(fpsr);
73*8d67ca89SAndroid Build Coastguard Worker fpsr &= ~(excepts & FE_ALL_EXCEPT);
74*8d67ca89SAndroid Build Coastguard Worker __set_fpsr(fpsr);
75*8d67ca89SAndroid Build Coastguard Worker return 0;
76*8d67ca89SAndroid Build Coastguard Worker }
77*8d67ca89SAndroid Build Coastguard Worker
fegetexceptflag(fexcept_t * flagp,int excepts)78*8d67ca89SAndroid Build Coastguard Worker int fegetexceptflag(fexcept_t* flagp, int excepts) {
79*8d67ca89SAndroid Build Coastguard Worker fpu_status_t fpsr;
80*8d67ca89SAndroid Build Coastguard Worker __get_fpsr(fpsr);
81*8d67ca89SAndroid Build Coastguard Worker *flagp = fpsr & (excepts & FE_ALL_EXCEPT);
82*8d67ca89SAndroid Build Coastguard Worker return 0;
83*8d67ca89SAndroid Build Coastguard Worker }
84*8d67ca89SAndroid Build Coastguard Worker
fesetexceptflag(const fexcept_t * flagp,int excepts)85*8d67ca89SAndroid Build Coastguard Worker int fesetexceptflag(const fexcept_t* flagp, int excepts) {
86*8d67ca89SAndroid Build Coastguard Worker excepts &= FE_ALL_EXCEPT;
87*8d67ca89SAndroid Build Coastguard Worker fpu_status_t fpsr;
88*8d67ca89SAndroid Build Coastguard Worker __get_fpsr(fpsr);
89*8d67ca89SAndroid Build Coastguard Worker fpsr &= ~excepts;
90*8d67ca89SAndroid Build Coastguard Worker fpsr |= *flagp & excepts;
91*8d67ca89SAndroid Build Coastguard Worker __set_fpsr(fpsr);
92*8d67ca89SAndroid Build Coastguard Worker return 0;
93*8d67ca89SAndroid Build Coastguard Worker }
94*8d67ca89SAndroid Build Coastguard Worker
feraiseexcept(int excepts)95*8d67ca89SAndroid Build Coastguard Worker int feraiseexcept(int excepts) {
96*8d67ca89SAndroid Build Coastguard Worker fexcept_t ex = excepts;
97*8d67ca89SAndroid Build Coastguard Worker fesetexceptflag(&ex, excepts);
98*8d67ca89SAndroid Build Coastguard Worker return 0;
99*8d67ca89SAndroid Build Coastguard Worker }
100*8d67ca89SAndroid Build Coastguard Worker
fetestexcept(int excepts)101*8d67ca89SAndroid Build Coastguard Worker int fetestexcept(int excepts) {
102*8d67ca89SAndroid Build Coastguard Worker fpu_status_t fpsr;
103*8d67ca89SAndroid Build Coastguard Worker __get_fpsr(fpsr);
104*8d67ca89SAndroid Build Coastguard Worker return (fpsr & (excepts & FE_ALL_EXCEPT));
105*8d67ca89SAndroid Build Coastguard Worker }
106*8d67ca89SAndroid Build Coastguard Worker
fegetround(void)107*8d67ca89SAndroid Build Coastguard Worker int fegetround(void) {
108*8d67ca89SAndroid Build Coastguard Worker fpu_control_t fpcr;
109*8d67ca89SAndroid Build Coastguard Worker __get_fpcr(fpcr);
110*8d67ca89SAndroid Build Coastguard Worker return ((fpcr >> FPCR_RMODE_SHIFT) & FE_TOWARDZERO);
111*8d67ca89SAndroid Build Coastguard Worker }
112*8d67ca89SAndroid Build Coastguard Worker
fesetround(int round)113*8d67ca89SAndroid Build Coastguard Worker int fesetround(int round) {
114*8d67ca89SAndroid Build Coastguard Worker if (round < FE_TONEAREST || round > FE_TOWARDZERO) return -1;
115*8d67ca89SAndroid Build Coastguard Worker fpu_control_t fpcr;
116*8d67ca89SAndroid Build Coastguard Worker __get_fpcr(fpcr);
117*8d67ca89SAndroid Build Coastguard Worker fpu_control_t new_fpcr = fpcr & ~(FE_TOWARDZERO << FPCR_RMODE_SHIFT);
118*8d67ca89SAndroid Build Coastguard Worker new_fpcr |= (round << FPCR_RMODE_SHIFT);
119*8d67ca89SAndroid Build Coastguard Worker if (new_fpcr != fpcr) {
120*8d67ca89SAndroid Build Coastguard Worker __set_fpcr(new_fpcr);
121*8d67ca89SAndroid Build Coastguard Worker }
122*8d67ca89SAndroid Build Coastguard Worker return 0;
123*8d67ca89SAndroid Build Coastguard Worker }
124*8d67ca89SAndroid Build Coastguard Worker
feholdexcept(fenv_t * envp)125*8d67ca89SAndroid Build Coastguard Worker int feholdexcept(fenv_t* envp) {
126*8d67ca89SAndroid Build Coastguard Worker fegetenv(envp);
127*8d67ca89SAndroid Build Coastguard Worker feclearexcept(FE_ALL_EXCEPT);
128*8d67ca89SAndroid Build Coastguard Worker return 0;
129*8d67ca89SAndroid Build Coastguard Worker }
130*8d67ca89SAndroid Build Coastguard Worker
feupdateenv(const fenv_t * envp)131*8d67ca89SAndroid Build Coastguard Worker int feupdateenv(const fenv_t* envp) {
132*8d67ca89SAndroid Build Coastguard Worker int excepts = fetestexcept(FE_ALL_EXCEPT);
133*8d67ca89SAndroid Build Coastguard Worker fesetenv(envp);
134*8d67ca89SAndroid Build Coastguard Worker feraiseexcept(excepts);
135*8d67ca89SAndroid Build Coastguard Worker return 0;
136*8d67ca89SAndroid Build Coastguard Worker }
137*8d67ca89SAndroid Build Coastguard Worker
feenableexcept(int mask __unused)138*8d67ca89SAndroid Build Coastguard Worker int feenableexcept(int mask __unused) {
139*8d67ca89SAndroid Build Coastguard Worker return -1;
140*8d67ca89SAndroid Build Coastguard Worker }
141*8d67ca89SAndroid Build Coastguard Worker
fedisableexcept(int mask __unused)142*8d67ca89SAndroid Build Coastguard Worker int fedisableexcept(int mask __unused) {
143*8d67ca89SAndroid Build Coastguard Worker return 0;
144*8d67ca89SAndroid Build Coastguard Worker }
145*8d67ca89SAndroid Build Coastguard Worker
fegetexcept(void)146*8d67ca89SAndroid Build Coastguard Worker int fegetexcept(void) {
147*8d67ca89SAndroid Build Coastguard Worker return 0;
148*8d67ca89SAndroid Build Coastguard Worker }
149