diff options
Diffstat (limited to 'lib/libutils/isoc/arch/arm/arm32_aeabi_softfloat.c')
-rw-r--r-- | lib/libutils/isoc/arch/arm/arm32_aeabi_softfloat.c | 317 |
1 files changed, 317 insertions, 0 deletions
diff --git a/lib/libutils/isoc/arch/arm/arm32_aeabi_softfloat.c b/lib/libutils/isoc/arch/arm/arm32_aeabi_softfloat.c new file mode 100644 index 0000000..714dff9 --- /dev/null +++ b/lib/libutils/isoc/arch/arm/arm32_aeabi_softfloat.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + * + * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +#include <compiler.h> +#include "platform.h" +#include <softfloat.h> + +/* + * On ARM32 EABI defines both a soft-float ABI and a hard-float ABI, + * hard-float is basically a super set of soft-float. Hard-float requires + * all the support routines provided for soft-float, but the compiler may + * choose to optimize to not use some of them. + * + * The AEABI functions uses soft-float calling convention even if the + * functions are compiled for hard-float. So where float and double would + * have been expected we use aeabi_float_t and aeabi_double_t respectively + * instead. + */ +typedef unsigned aeabi_float_t; +typedef unsigned long long aeabi_double_t; + +/* + * Helpers to convert between float32 and aeabi_float_t, and float64 and + * aeabi_double_t used by the AEABI functions below. + */ +static aeabi_float_t f32_to_f(float32_t val) +{ + union { + float32_t from; + aeabi_float_t to; + } res = { .from = val }; + + return res.to; +} + +static float32_t f32_from_f(aeabi_float_t val) +{ + union { + aeabi_float_t from; + float32_t to; + } res = { .from = val }; + + return res.to; +} + +static aeabi_double_t f64_to_d(float64_t val) +{ + union { + float64_t from; + aeabi_double_t to; + } res = { .from = val }; + + return res.to; +} + +static float64_t f64_from_d(aeabi_double_t val) +{ + union { + aeabi_double_t from; + float64_t to; + } res = { .from = val }; + + return res.to; +} + +/* + * From ARM Run-time ABI for ARM Architecture + * ARM IHI 0043D, current through ABI release 2.09 + * + * 4.1.2 The floating-point helper functions + */ + +/* + * Table 2, Standard aeabi_double_t precision floating-point arithmetic helper + * functions + */ + +aeabi_double_t __aeabi_dadd(aeabi_double_t a, aeabi_double_t b) +{ + return f64_to_d(f64_add(f64_from_d(a), f64_from_d(b))); +} + +aeabi_double_t __aeabi_ddiv(aeabi_double_t a, aeabi_double_t b) +{ + return f64_to_d(f64_div(f64_from_d(a), f64_from_d(b))); +} + +aeabi_double_t __aeabi_dmul(aeabi_double_t a, aeabi_double_t b) +{ + return f64_to_d(f64_mul(f64_from_d(a), f64_from_d(b))); +} + + +aeabi_double_t __aeabi_drsub(aeabi_double_t a, aeabi_double_t b) +{ + return f64_to_d(f64_sub(f64_from_d(b), f64_from_d(a))); +} + +aeabi_double_t __aeabi_dsub(aeabi_double_t a, aeabi_double_t b) +{ + return f64_to_d(f64_sub(f64_from_d(a), f64_from_d(b))); +} + +/* + * Table 3, double precision floating-point comparison helper functions + */ + +int __aeabi_dcmpeq(aeabi_double_t a, aeabi_double_t b) +{ + return f64_eq(f64_from_d(a), f64_from_d(b)); +} + +int __aeabi_dcmplt(aeabi_double_t a, aeabi_double_t b) +{ + return f64_lt(f64_from_d(a), f64_from_d(b)); +} + +int __aeabi_dcmple(aeabi_double_t a, aeabi_double_t b) +{ + return f64_le(f64_from_d(a), f64_from_d(b)); +} + +int __aeabi_dcmpge(aeabi_double_t a, aeabi_double_t b) +{ + return f64_le(f64_from_d(b), f64_from_d(a)); +} + +int __aeabi_dcmpgt(aeabi_double_t a, aeabi_double_t b) +{ + return f64_lt(f64_from_d(b), f64_from_d(a)); +} + +/* + * Table 4, Standard single precision floating-point arithmetic helper + * functions + */ + +aeabi_float_t __aeabi_fadd(aeabi_float_t a, aeabi_float_t b) +{ + return f32_to_f(f32_add(f32_from_f(a), f32_from_f(b))); +} + +aeabi_float_t __aeabi_fdiv(aeabi_float_t a, aeabi_float_t b) +{ + return f32_to_f(f32_div(f32_from_f(a), f32_from_f(b))); +} + +aeabi_float_t __aeabi_fmul(aeabi_float_t a, aeabi_float_t b) +{ + return f32_to_f(f32_mul(f32_from_f(a), f32_from_f(b))); +} + +aeabi_float_t __aeabi_frsub(aeabi_float_t a, aeabi_float_t b) +{ + return f32_to_f(f32_sub(f32_from_f(b), f32_from_f(a))); +} + +aeabi_float_t __aeabi_fsub(aeabi_float_t a, aeabi_float_t b) +{ + return f32_to_f(f32_sub(f32_from_f(a), f32_from_f(b))); +} + +/* + * Table 5, Standard single precision floating-point comparison helper + * functions + */ + +int __aeabi_fcmpeq(aeabi_float_t a, aeabi_float_t b) +{ + return f32_eq(f32_from_f(a), f32_from_f(b)); +} + +int __aeabi_fcmplt(aeabi_float_t a, aeabi_float_t b) +{ + return f32_lt(f32_from_f(a), f32_from_f(b)); +} + +int __aeabi_fcmple(aeabi_float_t a, aeabi_float_t b) +{ + return f32_le(f32_from_f(a), f32_from_f(b)); +} + +int __aeabi_fcmpge(aeabi_float_t a, aeabi_float_t b) +{ + return f32_le(f32_from_f(b), f32_from_f(a)); +} + +int __aeabi_fcmpgt(aeabi_float_t a, aeabi_float_t b) +{ + return f32_lt(f32_from_f(b), f32_from_f(a)); +} + +/* + * Table 6, Standard floating-point to integer conversions + */ + +int __aeabi_d2iz(aeabi_double_t a) +{ + return f64_to_i32_r_minMag(f64_from_d(a), false); +} + +unsigned __aeabi_d2uiz(aeabi_double_t a) +{ + return f64_to_ui32_r_minMag(f64_from_d(a), false); +} + +long long __aeabi_d2lz(aeabi_double_t a) +{ + return f64_to_i64_r_minMag(f64_from_d(a), false); +} + +unsigned long long __aeabi_d2ulz(aeabi_double_t a) +{ + return f64_to_ui64_r_minMag(f64_from_d(a), false); +} + +int __aeabi_f2iz(aeabi_float_t a) +{ + return f32_to_i32_r_minMag(f32_from_f(a), false); +} + +unsigned __aeabi_f2uiz(aeabi_float_t a) +{ + return f32_to_ui32_r_minMag(f32_from_f(a), false); +} + +long long __aeabi_f2lz(aeabi_float_t a) +{ + return f32_to_i64_r_minMag(f32_from_f(a), false); +} + +unsigned long long __aeabi_f2ulz(aeabi_float_t a) +{ + return f32_to_ui64_r_minMag(f32_from_f(a), false); +} + +/* + * Table 7, Standard conversions between floating types + */ + +aeabi_float_t __aeabi_d2f(aeabi_double_t a) +{ + return f32_to_f(f64_to_f32(f64_from_d(a))); +} + +aeabi_double_t __aeabi_f2d(aeabi_float_t a) +{ + return f64_to_d(f32_to_f64(f32_from_f(a))); +} + +/* + * Table 8, Standard integer to floating-point conversions + */ + +aeabi_double_t __aeabi_i2d(int a) +{ + return f64_to_d(i32_to_f64(a)); +} + +aeabi_double_t __aeabi_ui2d(unsigned a) +{ + return f64_to_d(ui32_to_f64(a)); +} + +aeabi_double_t __aeabi_l2d(long long a) +{ + return f64_to_d(i64_to_f64(a)); +} + +aeabi_double_t __aeabi_ul2d(unsigned long long a) +{ + return f64_to_d(ui64_to_f64(a)); +} + +aeabi_float_t __aeabi_i2f(int a) +{ + return f32_to_f(i32_to_f32(a)); +} + +aeabi_float_t __aeabi_ui2f(unsigned a) +{ + return f32_to_f(ui32_to_f32(a)); +} + +aeabi_float_t __aeabi_l2f(long long a) +{ + return f32_to_f(i64_to_f32(a)); +} + +aeabi_float_t __aeabi_ul2f(unsigned long long a) +{ + return f32_to_f(ui64_to_f32(a)); +} |