mirror of https://github.com/acidanthera/audk.git
284 lines
5.7 KiB
C
284 lines
5.7 KiB
C
/*
|
|
* Copyright (c) 2015 - 2019, Linaro Limited
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
*/
|
|
|
|
#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 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));
|
|
}
|