1// Copyright 2017 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <fenv.h> 6 7#include <zircon/compiler.h> 8#include <stdint.h> 9 10#define ROUND_MASK (FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO) 11 12static inline uint32_t get_fpcr(void) { 13 uint64_t value; 14 __asm__("mrs %0, fpcr" : "=r"(value)); 15 return value; 16} 17 18static inline void set_fpcr(uint32_t value) { 19 __asm__("msr fpcr, %0" :: "r"((uint64_t)value)); 20} 21 22static inline uint32_t get_fpsr(void) { 23 uint64_t value; 24 __asm__("mrs %0, fpsr" : "=r"(value)); 25 return value; 26} 27 28static inline void set_fpsr(uint32_t value) { 29 __asm__("msr fpsr, %0" :: "r"((uint64_t)value)); 30} 31 32int fegetround(void) { 33 return get_fpcr() & ROUND_MASK; 34} 35 36__LOCAL int __fesetround(int round) { 37 uint64_t fpcr = get_fpcr(); 38 set_fpcr((fpcr & ~ROUND_MASK) | round); 39 return 0; 40} 41 42int feclearexcept(int mask) { 43 set_fpsr(get_fpsr() & ~(mask & FE_ALL_EXCEPT)); 44 return 0; 45} 46 47int feraiseexcept(int mask) { 48 set_fpsr(get_fpsr() | (mask & FE_ALL_EXCEPT)); 49 return 0; 50} 51 52int fetestexcept(int mask) { 53 return get_fpsr() & mask & FE_ALL_EXCEPT; 54} 55 56int fegetenv(fenv_t* env) { 57 *env = (fenv_t){.__fpcr = get_fpcr(), .__fpsr = get_fpsr()}; 58 return 0; 59} 60 61int fesetenv(const fenv_t* env) { 62 uint32_t fpcr = 0, fpsr = 0; 63 if (likely(env != FE_DFL_ENV)) { 64 fpcr = env->__fpcr; 65 fpsr = env->__fpsr; 66 } 67 set_fpcr(fpcr); 68 set_fpsr(fpsr); 69 return 0; 70} 71