1726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman/*-
2726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
3726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * All rights reserved.
4726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman *
5726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * Redistribution and use in source and binary forms, with or without
6726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * modification, are permitted provided that the following conditions
7726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * are met:
8726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * 1. Redistributions of source code must retain the above copyright
9726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman *    notice, this list of conditions and the following disclaimer.
10726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * 2. Redistributions in binary form must reproduce the above copyright
11726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman *    notice, this list of conditions and the following disclaimer in the
12726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman *    documentation and/or other materials provided with the distribution.
13726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman *
14726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * SUCH DAMAGE.
25726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman *
26726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * $FreeBSD: src/lib/msun/mips/fenv.c,v 1.1 2008/04/26 12:20:29 imp Exp $
27726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman */
28726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman
29726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman#include <fenv.h>
30726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman
3189d61243f2f05748c0198b3c0e4766c2df2f4434Elliott Hughes#define FCSR_CAUSE_SHIFT 10
3289d61243f2f05748c0198b3c0e4766c2df2f4434Elliott Hughes#define FCSR_ENABLE_SHIFT 5
3389d61243f2f05748c0198b3c0e4766c2df2f4434Elliott Hughes#define FCSR_ENABLE_MASK (FE_ALL_EXCEPT << FCSR_ENABLE_SHIFT)
3489d61243f2f05748c0198b3c0e4766c2df2f4434Elliott Hughes
3589d61243f2f05748c0198b3c0e4766c2df2f4434Elliott Hughes#define FCSR_RMASK       0x3
3689d61243f2f05748c0198b3c0e4766c2df2f4434Elliott Hughes
37726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman/*
38726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * Hopefully the system ID byte is immutable, so it's valid to use
39726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman * this as a default environment.
40726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearman */
41726800e8f42f25a1bf7a36b1603ded29266e8ac6Chris Dearmanconst fenv_t __fe_dfl_env = 0;
422d367905a2e1b950f79b408141eea07c222b590bCalin Juravle
432d367905a2e1b950f79b408141eea07c222b590bCalin Juravleint fegetenv(fenv_t* __envp) {
442d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fenv_t _fcsr = 0;
452d367905a2e1b950f79b408141eea07c222b590bCalin Juravle#ifdef  __mips_hard_float
462d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  __asm__ __volatile__("cfc1 %0,$31" : "=r" (_fcsr));
472d367905a2e1b950f79b408141eea07c222b590bCalin Juravle#endif
482d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  *__envp = _fcsr;
492d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  return 0;
502d367905a2e1b950f79b408141eea07c222b590bCalin Juravle}
512d367905a2e1b950f79b408141eea07c222b590bCalin Juravle
522d367905a2e1b950f79b408141eea07c222b590bCalin Juravleint fesetenv(const fenv_t* __envp) {
532d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fenv_t _fcsr = *__envp;
542d367905a2e1b950f79b408141eea07c222b590bCalin Juravle#ifdef  __mips_hard_float
552d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  __asm__ __volatile__("ctc1 %0,$31" : : "r" (_fcsr));
562d367905a2e1b950f79b408141eea07c222b590bCalin Juravle#endif
572d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  return 0;
582d367905a2e1b950f79b408141eea07c222b590bCalin Juravle}
592d367905a2e1b950f79b408141eea07c222b590bCalin Juravle
602d367905a2e1b950f79b408141eea07c222b590bCalin Juravleint feclearexcept(int __excepts) {
612d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fexcept_t __fcsr;
622d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fegetenv(&__fcsr);
632d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  __excepts &= FE_ALL_EXCEPT;
6489d61243f2f05748c0198b3c0e4766c2df2f4434Elliott Hughes  __fcsr &= ~(__excepts | (__excepts << FCSR_CAUSE_SHIFT));
652d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fesetenv(&__fcsr);
662d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  return 0;
672d367905a2e1b950f79b408141eea07c222b590bCalin Juravle}
682d367905a2e1b950f79b408141eea07c222b590bCalin Juravle
692d367905a2e1b950f79b408141eea07c222b590bCalin Juravleint fegetexceptflag(fexcept_t* __flagp, int __excepts) {
702d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fexcept_t __fcsr;
712d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fegetenv(&__fcsr);
722d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  *__flagp = __fcsr & __excepts & FE_ALL_EXCEPT;
732d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  return 0;
742d367905a2e1b950f79b408141eea07c222b590bCalin Juravle}
752d367905a2e1b950f79b408141eea07c222b590bCalin Juravle
762d367905a2e1b950f79b408141eea07c222b590bCalin Juravleint fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
772d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fexcept_t __fcsr;
782d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fegetenv(&__fcsr);
792d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  /* Ensure that flags are all legal */
802d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  __excepts &= FE_ALL_EXCEPT;
812d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  __fcsr &= ~__excepts;
822d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  __fcsr |= *__flagp & __excepts;
832d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fesetenv(&__fcsr);
842d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  return 0;
852d367905a2e1b950f79b408141eea07c222b590bCalin Juravle}
862d367905a2e1b950f79b408141eea07c222b590bCalin Juravle
872d367905a2e1b950f79b408141eea07c222b590bCalin Juravleint feraiseexcept(int __excepts) {
882d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fexcept_t __fcsr;
892d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fegetenv(&__fcsr);
902d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  /* Ensure that flags are all legal */
912d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  __excepts &= FE_ALL_EXCEPT;
922d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  /* Cause bit needs to be set as well for generating the exception*/
9389d61243f2f05748c0198b3c0e4766c2df2f4434Elliott Hughes  __fcsr |= __excepts | (__excepts << FCSR_CAUSE_SHIFT);
942d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fesetenv(&__fcsr);
952d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  return 0;
962d367905a2e1b950f79b408141eea07c222b590bCalin Juravle}
972d367905a2e1b950f79b408141eea07c222b590bCalin Juravle
982d367905a2e1b950f79b408141eea07c222b590bCalin Juravleint fetestexcept(int __excepts) {
992d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fexcept_t __FCSR;
1002d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fegetenv(&__FCSR);
1012d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  return (__FCSR & __excepts & FE_ALL_EXCEPT);
1022d367905a2e1b950f79b408141eea07c222b590bCalin Juravle}
1032d367905a2e1b950f79b408141eea07c222b590bCalin Juravle
1042d367905a2e1b950f79b408141eea07c222b590bCalin Juravleint fegetround(void) {
1052d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fenv_t _fcsr;
1062d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fegetenv(&_fcsr);
10789d61243f2f05748c0198b3c0e4766c2df2f4434Elliott Hughes  return (_fcsr & FCSR_RMASK);
1082d367905a2e1b950f79b408141eea07c222b590bCalin Juravle}
1092d367905a2e1b950f79b408141eea07c222b590bCalin Juravle
1102d367905a2e1b950f79b408141eea07c222b590bCalin Juravleint fesetround(int __round) {
1112d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fenv_t _fcsr;
1122d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fegetenv(&_fcsr);
11389d61243f2f05748c0198b3c0e4766c2df2f4434Elliott Hughes  _fcsr &= ~FCSR_RMASK;
11489d61243f2f05748c0198b3c0e4766c2df2f4434Elliott Hughes  _fcsr |= (__round & FCSR_RMASK);
1152d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fesetenv(&_fcsr);
1162d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  return 0;
1172d367905a2e1b950f79b408141eea07c222b590bCalin Juravle}
1182d367905a2e1b950f79b408141eea07c222b590bCalin Juravle
1192d367905a2e1b950f79b408141eea07c222b590bCalin Juravleint feholdexcept(fenv_t* __envp) {
1202d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fenv_t __env;
1212d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fegetenv(&__env);
1222d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  *__envp = __env;
12389d61243f2f05748c0198b3c0e4766c2df2f4434Elliott Hughes  __env &= ~(FE_ALL_EXCEPT | FCSR_ENABLE_MASK);
1242d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fesetenv(&__env);
1252d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  return 0;
1262d367905a2e1b950f79b408141eea07c222b590bCalin Juravle}
1272d367905a2e1b950f79b408141eea07c222b590bCalin Juravle
1282d367905a2e1b950f79b408141eea07c222b590bCalin Juravleint feupdateenv(const fenv_t* __envp) {
1292d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fexcept_t __fcsr;
1302d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fegetenv(&__fcsr);
1312d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fesetenv(__envp);
1322d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  feraiseexcept(__fcsr & FE_ALL_EXCEPT);
1332d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  return 0;
1342d367905a2e1b950f79b408141eea07c222b590bCalin Juravle}
1352d367905a2e1b950f79b408141eea07c222b590bCalin Juravle
1362d367905a2e1b950f79b408141eea07c222b590bCalin Juravleint feenableexcept(int __mask) {
1372d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fenv_t __old_fcsr, __new_fcsr;
1382d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fegetenv(&__old_fcsr);
13989d61243f2f05748c0198b3c0e4766c2df2f4434Elliott Hughes  __new_fcsr = __old_fcsr | (__mask & FE_ALL_EXCEPT) << FCSR_ENABLE_SHIFT;
1402d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fesetenv(&__new_fcsr);
14189d61243f2f05748c0198b3c0e4766c2df2f4434Elliott Hughes  return ((__old_fcsr >> FCSR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
1422d367905a2e1b950f79b408141eea07c222b590bCalin Juravle}
1432d367905a2e1b950f79b408141eea07c222b590bCalin Juravle
1442d367905a2e1b950f79b408141eea07c222b590bCalin Juravleint fedisableexcept(int __mask) {
1452d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fenv_t __old_fcsr, __new_fcsr;
1462d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fegetenv(&__old_fcsr);
14789d61243f2f05748c0198b3c0e4766c2df2f4434Elliott Hughes  __new_fcsr = __old_fcsr & ~((__mask & FE_ALL_EXCEPT) << FCSR_ENABLE_SHIFT);
1482d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fesetenv(&__new_fcsr);
14989d61243f2f05748c0198b3c0e4766c2df2f4434Elliott Hughes  return ((__old_fcsr >> FCSR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
1502d367905a2e1b950f79b408141eea07c222b590bCalin Juravle}
1512d367905a2e1b950f79b408141eea07c222b590bCalin Juravle
1522d367905a2e1b950f79b408141eea07c222b590bCalin Juravleint fegetexcept(void) {
1532d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fenv_t __fcsr;
1542d367905a2e1b950f79b408141eea07c222b590bCalin Juravle  fegetenv(&__fcsr);
15589d61243f2f05748c0198b3c0e4766c2df2f4434Elliott Hughes  return ((__fcsr & FCSR_ENABLE_MASK) >> FCSR_ENABLE_SHIFT);
1562d367905a2e1b950f79b408141eea07c222b590bCalin Juravle}
157