Module Name: src Committed By: christos Date: Thu Dec 24 14:12:39 UTC 2015
Modified Files: src/sys/arch/m68k/include: Makefile Added Files: src/sys/arch/m68k/include: fenv.h Log Message: fenv for m68k To generate a diff of this commit: cvs rdiff -u -r1.28 -r1.29 src/sys/arch/m68k/include/Makefile cvs rdiff -u -r0 -r1.1 src/sys/arch/m68k/include/fenv.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/m68k/include/Makefile diff -u src/sys/arch/m68k/include/Makefile:1.28 src/sys/arch/m68k/include/Makefile:1.29 --- src/sys/arch/m68k/include/Makefile:1.28 Wed Jul 17 01:42:02 2013 +++ src/sys/arch/m68k/include/Makefile Thu Dec 24 09:12:39 2015 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.28 2013/07/17 05:42:02 matt Exp $ +# $NetBSD: Makefile,v 1.29 2015/12/24 14:12:39 christos Exp $ INCSDIR= /usr/include/m68k @@ -7,7 +7,7 @@ INCS= ansi.h aout_machdep.h asm.h asm_si cacheops.h cacheops_20.h cacheops_30.h cacheops_40.h cacheops_60.h \ cdefs.h cpu.h cpuframe.h \ elf_machdep.h endian.h endian_machdep.h \ - float.h fpreg.h frame.h \ + fenv.h float.h fpreg.h frame.h \ ieee.h ieeefp.h \ int_const.h int_fmtio.h int_limits.h int_mwgwtypes.h int_types.h \ kcore.h \ Added files: Index: src/sys/arch/m68k/include/fenv.h diff -u /dev/null src/sys/arch/m68k/include/fenv.h:1.1 --- /dev/null Thu Dec 24 09:12:39 2015 +++ src/sys/arch/m68k/include/fenv.h Thu Dec 24 09:12:39 2015 @@ -0,0 +1,302 @@ +/* $NetBSD: fenv.h,v 1.1 2015/12/24 14:12:39 christos Exp $ */ + +/*- + * Copyright (c) 2015 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _M68K_FENV_H_ +#define _M68K_FENV_H_ + +#include <sys/stdint.h> +#include <m68k/float.h> +#include <m68k/fpreg.h> + +#ifndef __fenv_static +#define __fenv_static static +#endif + +/* Exception bits, from FPSR */ +#define FE_INEXACT FPSR_AINEX +#define FE_DIVBYZERO FPSR_ADZ +#define FE_UNDERFLOW FPSR_AUNFL +#define FE_OVERFLOW FPSR_AOVFL +#define FE_INVALID FPSR_AIOP + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* Rounding modes, from FPSR */ +#define FE_TONEAREST FPCR_NEAR +#define FE_TOWARDZERO FPCR_ZERO +#define FE_DOWNWARD FPCR_MINF +#define FE_UPWARD FPCR_PINF + +#define _ROUND_MASK \ + (FE_TONEAREST | FE_TOWARDZERO | FE_DOWNWARD | FE_UPWARD) + +typedef uint32_t fexcept_t; + +/* same layout as fmovem */ +typedef struct { + uint32_t fpcr; + uint32_t fpsr; + uint32_t fppc; +} fenv_t; + +#define FE_DFL_ENV ((fenv_t *) -1) + +#define __get_fpcr(__fpcr) \ + __asm__ __volatile__ ("fmove%.l %!,%0" : "=dm" (__fpcr)) +#define __set_fpcr(__fpcr) \ + __asm__ __volatile__ ("fmove%.l %0,%!" : : "dm" (__fpcr)) + +#define __get_fpsr(__fpsr) \ + __asm__ __volatile__ ("fmove%.l %/fpsr,%0" : "=dm" (__fpsr)) +#define __set_fpsr(__fpsr) \ + __asm__ __volatile__ ("fmove%.l %0,%/fpsr" : : "dm" (__fpsr)) + +#define __fmul(__s, __t, __d) \ + do { \ + __t d = __d; \ + __asm__ __volatile__ ("fmul" __s "; fnop" : "=f" (d) : "0" (d)); \ + } while (/*CONSTCOND*/0) + +#define __fdiv(__s, __t, __d) \ + do { \ + __t d = __d; \ + __asm__ __volatile__ ("fdiv" __s "; fnop" : "=f" (d) : "0" (d)); \ + } while (/*CONSTCOND*/0) + +#define __fetox(__s, __t, __d) \ + do { \ + __t d = __d; \ + __asm__ __volatile__ ("fetox" __s "; fnop" : "=f" (d) : "0" (d)); \ + } while (/*CONSTCOND*/0) + +#define __fgetenv(__envp) \ + __asm__ __volatile__ ("fmovem%.l %/fpcr/%/fpsr/%/fpiar,%0" : "=m" (__envp)) + +#define __fsetenv(__envp) \ + __asm__ __volatile__ ("fmovem%.l %0,%/fpcr/%/fpsr/%/fpiar" : : "m" (__envp)) + +__fenv_static inline int +feclearexcept(int __excepts) +{ + fexcept_t __fpsr; + + __excepts &= FE_ALL_EXCEPT; + + __get_fpsr(__fpsr); + __fpsr &= ~__excepts; + __set_fpsr(__fpsr); + + return 0; +} + +__fenv_static inline int +fegetexceptflag(fexcept_t *__flagp, int __excepts) +{ + fexcept_t __fpsr; + + __get_fpsr(__fpsr); + + *__flagp = __fpsr & __excepts & FE_ALL_EXCEPT; + + return 0; +} + +__fenv_static inline int +fesetexceptflag(const fexcept_t *__flagp, int __excepts) +{ + fexcept_t __fpsr; + + __get_fpsr(__fpsr); + + __fpsr &= ~(__excepts & FE_ALL_EXCEPT); + __fpsr |= *__flagp & __excepts & FE_ALL_EXCEPT; + + __set_fpsr(__fpsr); + + return 0; +} + +__fenv_static inline int +feraiseexcept(int __excepts) +{ + if (__excepts & FE_INVALID) /* Inf * 0 */ + __fmul("%.s %#0r0,%0", double, __builtin_huge_val()); + + if (__excepts & FE_DIVBYZERO) /* 1.0 / 0 */ + __fdiv("%.s %#0r0,%0", double, 1.0); + + if (__excepts & FE_OVERFLOW) /* MAX * MAX */ + __fmul("%.x %0,%0", long double, LDBL_MAX); + + if (__excepts & FE_UNDERFLOW) /* e ^ -MAX */ + __fetox("%.x %0", long double, -LDBL_MAX); + + if (__excepts & FE_INEXACT) /* 1 / 3 */ + __fdiv("%.s %#0r3,%0", long double, 1.0); + + return 0; +} + +__fenv_static inline int +fetestexcept(int __excepts) +{ + fexcept_t __fpsr; + + __get_fpsr(__fpsr); + + return __fpsr & __excepts & FE_ALL_EXCEPT; +} + +__fenv_static inline int +fegetround(void) +{ + fexcept_t __fpcr; + + __get_fpcr(__fpcr); + return __fpcr & _ROUND_MASK; +} + +__fenv_static inline int +fesetround(int __round) +{ + fexcept_t __fpcr; + + if (__round & ~_ROUND_MASK) + return -1; + + __get_fpcr(__fpcr); + + __fpcr &= ~_ROUND_MASK; + __fpcr |= __round; + + __set_fpcr(__fpcr); + + return 0; +} + +__fenv_static inline int +fegetenv(fenv_t *__envp) +{ + __fgetenv(__envp); + + return 0; +} + +__fenv_static inline int +feholdexcept(fenv_t *__envp) +{ + fexcept_t __fpcr, __fpsr; + + __fgetenv(__envp); + __fpsr = __envp->fpsr & ~FE_ALL_EXCEPT; + __fset_fpsr(__fpsr); /* clear all */ + __fpcr = __envp->fpcr & ~(FE_ALL_EXCEPT << 6); + __fset_fpcr(__fpcr); /* set non/stop */ + + return 0; +} + +__fenv_static inline int +fesetenv(const fenv_t *__envp) +{ + fenv_t __tenv; + + __fgetenv(__tenv); + + if (__envp == FE_DFL_ENV) { + __tenv.fpcr |= + __envp->fpcr & ((FE_ALL_EXCEPT << 6) | FE_UPWARD); + __tenv.fpsr |= __envp->fpsr & FE_ALL_EXCEPT; + } + + __fsetenv(__tenv); + + return 0; +} + +__fenv_static inline int +feupdateenv(const fenv_t *__envp) +{ + fexcept_t __fpsr; + + __get_fpsr(__fpsr); + __fpsr &= FE_ALL_EXCEPT; + fesetenv(__envp); + feraiseexcept((int)__fpsr); + return 0; +} + +#if defined(_NETBSD_SOURCE) || defined(_GNU_SOURCE) + +/* We currently provide no external definitions of the functions below. */ + +static inline int +feenableexcept(int __mask) +{ + fexcept_t __fpsr, __oldmask; + + __get_fpsr(__fpsr); + __oldmask = __fpsr & FE_ALL_EXCEPT; + __fpsr |= __mask & FE_ALL_EXCEPT; + __set_fpsr(__fpsr); + + return __oldmask; +} + +static inline int +fedisableexcept(int __mask) +{ + fexcept_t __fpsr, __oldmask; + + __get_fpsr(__fpsr); + __oldmask = __fpsr & FE_ALL_EXCEPT; + __fpsr &= ~(__mask & FE_ALL_EXCEPT); + __set_fpsr(__fpsr); + + return __oldmask; +} + +static inline int +fegetexcept(void) +{ + fexcept_t __fpsr; + + __get_fpsr(__fpsr); + + return __fpsr & FE_ALL_EXCEPT; +} + +#endif /* _NETBSD_SOURCE || _GNU_SOURCE */ + +__END_DECLS + +#endif /* _M68K_FENV_H_ */