/* * Copyright (c) 2015 - 2019, Linaro Limited * * SPDX-License-Identifier: BSD-2-Clause-Patent */ #include "platform.h" #include /* * 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 uint32_t aeabi_float_t; typedef uint64_t 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 ) { return val.v; } static float32_t f32_from_f ( aeabi_float_t val ) { float32_t res; res.v = val; return res; } static aeabi_double_t f64_to_d ( float64_t val ) { return val.v; } static float64_t f64_from_d ( aeabi_double_t val ) { float64_t res; res.v = val; return res; } /* * 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)); }