diff options
Diffstat (limited to 'core/minute-ia/include/fpu.h')
-rw-r--r-- | core/minute-ia/include/fpu.h | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/core/minute-ia/include/fpu.h b/core/minute-ia/include/fpu.h new file mode 100644 index 0000000000..fbcc7ae0f0 --- /dev/null +++ b/core/minute-ia/include/fpu.h @@ -0,0 +1,241 @@ +/* Copyright 2016 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Math utility functions for minute-IA */ + +#ifndef __CROS_EC_FPU_H +#define __CROS_EC_FPU_H + +#include "config.h" + +#ifdef CONFIG_FPU + +#define M_PI 3.14159265358979323846 +#define M_PI_2 1.57079632679489661923 + +static inline float sqrtf(float v) +{ + float root; + + /* root = fsqart (v); */ + asm volatile( + "fsqrt" + : "=t" (root) + : "0" (v) + ); + return root; +} + +/* Absolute value of V. */ +static inline float fabsf(float v) +{ + float root; + + /* root = fabs (v); */ + asm volatile( + "fabs" + : "=t" (root) + : "0" (v) + ); + return root; +} + +/** + * Natural logarithm of V. + * + * @return ln(v) + */ +static inline float logf(float v) +{ + float res; + + asm volatile( + "fldln2\n" + "fxch\n" + "fyl2x\n" + : "=t" (res) + : "0" (v)); + + return res; +} + +/** + * Exponential function of V. + * + * @return e**v + */ +static inline float expf(float v) +{ + float res; + + asm volatile( + "fldl2e\n" + "fmulp\n" + "fld %%st(0)\n" + "frndint\n" + "fsubr %%st(0),%%st(1)\n" /* bug-binutils/19054 */ + "fxch %%st(1)\n" + "f2xm1\n" + "fld1\n" + "faddp\n" + "fscale\n" + "fstp %%st(1)\n" + : "=t" (res) + : "0" (v)); + + return res; +} + +/** + * X to the Y power. + * + * @return x**y + */ +static inline float powf(float x, float y) +{ + float res; + + asm volatile( + "fyl2x\n" + "fld %%st(0)\n" + "frndint\n" + "fsub %%st,%%st(1)\n" + "fxch\n" + "fchs\n" + "f2xm1\n" + "fld1\n" + "faddp\n" + "fxch\n" + "fld1\n" + "fscale\n" + "fstp %%st(1)\n" + "fmulp\n" + : "=t" (res) + : "0" (x), "u" (y) + : "st(1)"); + + return res; +} + +/* Smallest integral value not less than V. */ +static inline float ceilf(float v) +{ + float res; + unsigned short control_word, control_word_tmp; + + asm volatile("fnstcw %0" : "=m" (control_word)); + /* Set Rounding Mode to 10B, round up toward +infinity */ + control_word_tmp = (control_word | 0x0800) & 0xfbff; + asm volatile( + "fld %3\n" + "fldcw %1\n" + "frndint\n" + "fldcw %2" + : "=t" (res) + : "m" (control_word_tmp), "m"(control_word), "m" (v)); + + return res; +} + +/* Arc tangent of Y/X. */ +static inline float atan2f(float y, float x) +{ + float res; + + asm volatile("fpatan" : "=t" (res) : "0" (x), "u" (y) : "st(1)"); + + return res; +} + +/* Arc tangent of V. */ +static inline float atanf(float v) +{ + float res; + + asm volatile( + "fld1\n" + "fpatan\n" + : "=t" (res) + : "0" (v)); + + return res; +} + +/* Sine of V. */ +static inline float sinf(float v) +{ + float res; + + asm volatile("fsin" : "=t" (res) : "0" (v)); + + return res; +} + +/* Cosine of V. */ +static inline float cosf(float v) +{ + float res; + + asm volatile("fcos" : "=t" (res) : "0" (v)); + + return res; +} + +/* Arc cosine of V. */ +static inline float acosf(float v) +{ + return atan2f(sqrtf(1.0 - v * v), v); +} + +#define COND_FP_NAN 0x0100 +#define COND_FP_SIGNBIT 0x0200 +#define COND_FP_NORMAL 0x0400 +#define COND_FP_ZERO 0x4000 +#define COND_FP_INFINITE (COND_FP_NAN | COND_FP_NORMAL) + +/* Check if V is NaN (not-a-number). */ +static inline int __isnanf(float v) +{ + uint16_t stat; + + asm volatile( + "fxam\n" + "fnstsw %0\n" + : "=r" (stat) + : "0" (v)); + + return (stat & (COND_FP_NAN | COND_FP_NORMAL | COND_FP_ZERO)) + == COND_FP_NAN; +} + +/** + * Check if V is infinite. + * + * @return 0 if V is finite or NaN. + * @return +1 if V is +infinite. + * @return -1 if V is -infinite. + */ +static inline int __isinff(float v) +{ + uint16_t stat; + + asm volatile( + "fxam\n" + "fnstsw %0\n" + : "=r" (stat) + : "v" (v)); + + if ((stat & (COND_FP_NAN | COND_FP_NORMAL | COND_FP_ZERO)) == + COND_FP_INFINITE) { + /* Infinite number, check sign */ + return stat & COND_FP_SIGNBIT ? -1 : 1; + } + + /* Finite or NaN */ + return 0; +} + +#endif /* CONFIG_FPU */ +#endif /* __CROS_EC_FPU_H */ |