adds complete Zfh support, small rework regarding floating point interface
This commit is contained in:
parent
8220c00a3d
commit
0e35a2a8c9
@ -33,7 +33,9 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "fp_functions.h"
|
||||
#include "softfloat_types.h"
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
extern "C" {
|
||||
#include "internals.h"
|
||||
@ -194,7 +196,7 @@ uint16_t fclass_h(uint16_t v1) {
|
||||
uA.f = a;
|
||||
uiA = uA.ui;
|
||||
|
||||
bool infOrNaN = expF16UI(uiA) == 0xFF;
|
||||
bool infOrNaN = expF16UI(uiA) == 0x1F;
|
||||
bool subnormalOrZero = expF16UI(uiA) == 0;
|
||||
bool sign = signF16UI(uiA);
|
||||
bool fracZero = fracF16UI(uiA) == 0;
|
||||
@ -206,6 +208,25 @@ uint16_t fclass_h(uint16_t v1) {
|
||||
(!sign && !infOrNaN && !subnormalOrZero) << 6 | (!sign && subnormalOrZero && !fracZero) << 5 |
|
||||
(!sign && subnormalOrZero && fracZero) << 4 | (isNaN && isSNaN) << 8 | (isNaN && !isSNaN) << 9;
|
||||
}
|
||||
uint16_t unbox_h(uint8_t FLEN, uint64_t v) {
|
||||
uint64_t mask = 0;
|
||||
switch(FLEN) {
|
||||
case 32: {
|
||||
mask = std::numeric_limits<uint32_t>::max() & ~((uint64_t)std::numeric_limits<uint16_t>::max());
|
||||
break;
|
||||
}
|
||||
case 64: {
|
||||
mask = std::numeric_limits<uint64_t>::max() & ~((uint64_t)std::numeric_limits<uint16_t>::max());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if((v & mask) != mask)
|
||||
return 0x7e00;
|
||||
else
|
||||
return v & std::numeric_limits<uint32_t>::max();
|
||||
}
|
||||
|
||||
uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode) {
|
||||
float32_t v1f{v1}, v2f{v2};
|
||||
@ -864,4 +885,85 @@ uint64_t frec7_d(uint64_t v, uint8_t mode) {
|
||||
if(frec_general(ret_val, s, e, sign, exp, sig, subnormal, mode))
|
||||
softfloat_exceptionFlags |= (softfloat_flag_inexact | softfloat_flag_overflow);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
// conversion: float to float
|
||||
uint32_t f16tof32(uint16_t val, uint8_t rm) {
|
||||
softfloat_exceptionFlags = 0;
|
||||
softfloat_roundingMode = rm;
|
||||
return f16_to_f32(float16_t{val}).v;
|
||||
}
|
||||
uint64_t f16tof64(uint16_t val, uint8_t rm) {
|
||||
softfloat_exceptionFlags = 0;
|
||||
softfloat_roundingMode = rm;
|
||||
return f16_to_f64(float16_t{val}).v;
|
||||
}
|
||||
|
||||
uint16_t f32tof16(uint32_t val, uint8_t rm) {
|
||||
softfloat_exceptionFlags = 0;
|
||||
softfloat_roundingMode = rm;
|
||||
return f32_to_f16(float32_t{val}).v;
|
||||
}
|
||||
uint64_t f32tof64(uint32_t val, uint8_t rm) {
|
||||
softfloat_exceptionFlags = 0;
|
||||
softfloat_roundingMode = rm;
|
||||
return f32_to_f64(float32_t{val}).v;
|
||||
}
|
||||
|
||||
uint16_t f64tof16(uint64_t val, uint8_t rm) {
|
||||
softfloat_exceptionFlags = 0;
|
||||
softfloat_roundingMode = rm;
|
||||
return f64_to_f16(float64_t{val}).v;
|
||||
}
|
||||
uint32_t f64tof32(uint64_t val, uint8_t rm) {
|
||||
softfloat_exceptionFlags = 0;
|
||||
softfloat_roundingMode = rm;
|
||||
return f64_to_f32(float64_t{val}).v;
|
||||
}
|
||||
// conversions: float to unsigned
|
||||
uint32_t f16toui32(uint16_t v, uint8_t rm) {
|
||||
softfloat_exceptionFlags = 0;
|
||||
softfloat_roundingMode = rm;
|
||||
return f16_to_ui32(float16_t{v}, rm, true);
|
||||
}
|
||||
uint64_t f16toui64(uint16_t v, uint8_t rm) {
|
||||
softfloat_exceptionFlags = 0;
|
||||
softfloat_roundingMode = rm;
|
||||
return f16_to_ui64(float16_t{v}, rm, true);
|
||||
}
|
||||
|
||||
// conversions: float to signed
|
||||
uint32_t f16toi32(uint16_t v, uint8_t rm) {
|
||||
softfloat_exceptionFlags = 0;
|
||||
softfloat_roundingMode = rm;
|
||||
return f16_to_i32(float16_t{v}, rm, true);
|
||||
}
|
||||
uint64_t f16toi64(uint16_t v, uint8_t rm) {
|
||||
softfloat_exceptionFlags = 0;
|
||||
softfloat_roundingMode = rm;
|
||||
return f16_to_i64(float16_t{v}, rm, true);
|
||||
}
|
||||
|
||||
// conversions: unsigned to float
|
||||
uint16_t ui32tof16(uint32_t v, uint8_t rm) {
|
||||
softfloat_exceptionFlags = 0;
|
||||
softfloat_roundingMode = rm;
|
||||
return ui32_to_f16(v).v;
|
||||
}
|
||||
uint16_t ui64tof16(uint64_t v, uint8_t rm) {
|
||||
softfloat_exceptionFlags = 0;
|
||||
softfloat_roundingMode = rm;
|
||||
return ui64_to_f16(v).v;
|
||||
}
|
||||
|
||||
// conversions: signed to float
|
||||
uint16_t i32tof16(uint32_t v, uint8_t rm) {
|
||||
softfloat_exceptionFlags = 0;
|
||||
softfloat_roundingMode = rm;
|
||||
return i32_to_f16(v).v;
|
||||
}
|
||||
uint16_t i64tof16(uint64_t v, uint8_t rm) {
|
||||
softfloat_exceptionFlags = 0;
|
||||
softfloat_roundingMode = rm;
|
||||
return i64_to_f16(v).v;
|
||||
}
|
@ -39,6 +39,7 @@
|
||||
|
||||
extern "C" {
|
||||
uint32_t fget_flags();
|
||||
// half precision
|
||||
uint16_t fadd_h(uint16_t v1, uint16_t v2, uint8_t mode);
|
||||
uint16_t fsub_h(uint16_t v1, uint16_t v2, uint8_t mode);
|
||||
uint16_t fmul_h(uint16_t v1, uint16_t v2, uint8_t mode);
|
||||
@ -52,6 +53,9 @@ uint16_t fsqrt_h(uint16_t v1, uint8_t mode);
|
||||
uint16_t fclass_h(uint16_t v1);
|
||||
uint16_t frsqrt7_h(uint16_t v);
|
||||
uint16_t frec7_h(uint16_t v, uint8_t mode);
|
||||
uint16_t unbox_h(uint8_t FLEN, uint64_t v);
|
||||
|
||||
// single precision
|
||||
uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode);
|
||||
uint32_t fsub_s(uint32_t v1, uint32_t v2, uint8_t mode);
|
||||
uint32_t fmul_s(uint32_t v1, uint32_t v2, uint8_t mode);
|
||||
@ -64,8 +68,9 @@ uint32_t fsel_s(uint32_t v1, uint32_t v2, uint32_t op);
|
||||
uint32_t fclass_s(uint32_t v1);
|
||||
uint32_t frsqrt7_s(uint32_t v);
|
||||
uint32_t frec7_s(uint32_t v, uint8_t mode);
|
||||
uint32_t fconv_d2f(uint64_t v1, uint8_t mode);
|
||||
uint64_t fconv_f2d(uint32_t v1, uint8_t mode);
|
||||
uint32_t unbox_s(uint64_t v);
|
||||
|
||||
// double precision
|
||||
uint64_t fadd_d(uint64_t v1, uint64_t v2, uint8_t mode);
|
||||
uint64_t fsub_d(uint64_t v1, uint64_t v2, uint8_t mode);
|
||||
uint64_t fmul_d(uint64_t v1, uint64_t v2, uint8_t mode);
|
||||
@ -78,8 +83,37 @@ uint64_t fsel_d(uint64_t v1, uint64_t v2, uint32_t op);
|
||||
uint64_t fclass_d(uint64_t v1);
|
||||
uint64_t frsqrt7_d(uint64_t v);
|
||||
uint64_t frec7_d(uint64_t v, uint8_t mode);
|
||||
|
||||
// conversions
|
||||
uint32_t fconv_d2f(uint64_t v1, uint8_t mode);
|
||||
uint64_t fconv_f2d(uint32_t v1, uint8_t mode);
|
||||
uint64_t fcvt_32_64(uint32_t v1, uint32_t op, uint8_t mode);
|
||||
uint32_t fcvt_64_32(uint64_t v1, uint32_t op, uint8_t mode);
|
||||
uint32_t unbox_s(uint64_t v);
|
||||
|
||||
// conversion: float to float
|
||||
uint32_t f16tof32(uint16_t val, uint8_t rm);
|
||||
uint64_t f16tof64(uint16_t val, uint8_t rm);
|
||||
|
||||
uint16_t f32tof16(uint32_t val, uint8_t rm);
|
||||
uint64_t f32tof64(uint32_t val, uint8_t rm);
|
||||
|
||||
uint16_t f64tof16(uint64_t val, uint8_t rm);
|
||||
uint32_t f64tof32(uint64_t val, uint8_t rm);
|
||||
|
||||
// conversions: float to unsigned
|
||||
uint32_t f16toui32(uint16_t v, uint8_t rm);
|
||||
uint64_t f16toui64(uint16_t v, uint8_t rm);
|
||||
|
||||
// conversions: float to signed
|
||||
uint32_t f16toi32(uint16_t v, uint8_t rm);
|
||||
uint64_t f16toi64(uint16_t v, uint8_t rm);
|
||||
|
||||
// conversions: unsigned to float
|
||||
uint16_t ui32tof16(uint32_t v, uint8_t rm);
|
||||
uint16_t ui64tof16(uint64_t v, uint8_t rm);
|
||||
|
||||
// conversions: signed to float
|
||||
uint16_t i32tof16(uint32_t v, uint8_t rm);
|
||||
uint16_t i64tof16(uint64_t v, uint8_t rm);
|
||||
}
|
||||
#endif /* _VM_FP_FUNCTIONS_H_ */
|
||||
|
@ -1541,16 +1541,8 @@ template <> inline uint64_t fp_i_to_f<uint64_t, uint32_t>(uint8_t rm, uint32_t v
|
||||
template <> inline uint16_t fp_f_to_f<uint16_t, uint8_t>(uint8_t rm, uint8_t val) {
|
||||
throw new std::runtime_error("Attempting illegal widening conversion");
|
||||
}
|
||||
template <> inline uint32_t fp_f_to_f<uint32_t, uint16_t>(uint8_t rm, uint16_t val) {
|
||||
softfloat_exceptionFlags = 0;
|
||||
softfloat_roundingMode = rm;
|
||||
return f16_to_f32(float16_t{val}).v;
|
||||
}
|
||||
template <> inline uint64_t fp_f_to_f<uint64_t, uint32_t>(uint8_t rm, uint32_t val) {
|
||||
softfloat_exceptionFlags = 0;
|
||||
softfloat_roundingMode = rm;
|
||||
return f32_to_f64(float32_t{val}).v;
|
||||
}
|
||||
template <> inline uint32_t fp_f_to_f<uint32_t, uint16_t>(uint8_t rm, uint16_t val) { return f16tof32(val, rm); }
|
||||
template <> inline uint64_t fp_f_to_f<uint64_t, uint32_t>(uint8_t rm, uint32_t val) { return f32tof64(val, rm); }
|
||||
|
||||
template <typename dest_elem_t, typename src_elem_t>
|
||||
std::function<dest_elem_t(uint8_t, uint8_t&, src_elem_t)> get_fp_widening_fn(unsigned unary_op) {
|
||||
@ -1676,16 +1668,8 @@ template <> inline uint32_t fp_i_to_f<uint32_t, uint64_t>(uint8_t rm, uint64_t v
|
||||
template <> inline uint8_t fp_f_to_f<uint8_t, uint16_t>(uint8_t rm, uint16_t val) {
|
||||
throw new std::runtime_error("Attempting illegal narrowing conversion");
|
||||
}
|
||||
template <> inline uint16_t fp_f_to_f<uint16_t, uint32_t>(uint8_t rm, uint32_t val) {
|
||||
softfloat_exceptionFlags = 0;
|
||||
softfloat_roundingMode = rm;
|
||||
return f32_to_f16(float32_t{val}).v;
|
||||
}
|
||||
template <> inline uint32_t fp_f_to_f<uint32_t, uint64_t>(uint8_t rm, uint64_t val) {
|
||||
softfloat_exceptionFlags = 0;
|
||||
softfloat_roundingMode = rm;
|
||||
return f64_to_f32(float64_t{val}).v;
|
||||
}
|
||||
template <> inline uint16_t fp_f_to_f<uint16_t, uint32_t>(uint8_t rm, uint32_t val) { return f32tof16(val, rm); }
|
||||
template <> inline uint32_t fp_f_to_f<uint32_t, uint64_t>(uint8_t rm, uint64_t val) { return f64tof32(val, rm); }
|
||||
template <typename dest_elem_t, typename src_elem_t>
|
||||
std::function<dest_elem_t(uint8_t, uint8_t&, src_elem_t)> get_fp_narrowing_fn(unsigned unary_op) {
|
||||
switch(unary_op) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user