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 "fp_functions.h"
|
||||||
|
#include "softfloat_types.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "internals.h"
|
#include "internals.h"
|
||||||
@ -194,7 +196,7 @@ uint16_t fclass_h(uint16_t v1) {
|
|||||||
uA.f = a;
|
uA.f = a;
|
||||||
uiA = uA.ui;
|
uiA = uA.ui;
|
||||||
|
|
||||||
bool infOrNaN = expF16UI(uiA) == 0xFF;
|
bool infOrNaN = expF16UI(uiA) == 0x1F;
|
||||||
bool subnormalOrZero = expF16UI(uiA) == 0;
|
bool subnormalOrZero = expF16UI(uiA) == 0;
|
||||||
bool sign = signF16UI(uiA);
|
bool sign = signF16UI(uiA);
|
||||||
bool fracZero = fracF16UI(uiA) == 0;
|
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 && !infOrNaN && !subnormalOrZero) << 6 | (!sign && subnormalOrZero && !fracZero) << 5 |
|
||||||
(!sign && subnormalOrZero && fracZero) << 4 | (isNaN && isSNaN) << 8 | (isNaN && !isSNaN) << 9;
|
(!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) {
|
uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode) {
|
||||||
float32_t v1f{v1}, v2f{v2};
|
float32_t v1f{v1}, v2f{v2};
|
||||||
@ -865,3 +886,84 @@ uint64_t frec7_d(uint64_t v, uint8_t mode) {
|
|||||||
softfloat_exceptionFlags |= (softfloat_flag_inexact | softfloat_flag_overflow);
|
softfloat_exceptionFlags |= (softfloat_flag_inexact | softfloat_flag_overflow);
|
||||||
return ret_val;
|
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" {
|
extern "C" {
|
||||||
uint32_t fget_flags();
|
uint32_t fget_flags();
|
||||||
|
// half precision
|
||||||
uint16_t fadd_h(uint16_t v1, uint16_t v2, uint8_t mode);
|
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 fsub_h(uint16_t v1, uint16_t v2, uint8_t mode);
|
||||||
uint16_t fmul_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 fclass_h(uint16_t v1);
|
||||||
uint16_t frsqrt7_h(uint16_t v);
|
uint16_t frsqrt7_h(uint16_t v);
|
||||||
uint16_t frec7_h(uint16_t v, uint8_t mode);
|
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 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 fsub_s(uint32_t v1, uint32_t v2, uint8_t mode);
|
||||||
uint32_t fmul_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 fclass_s(uint32_t v1);
|
||||||
uint32_t frsqrt7_s(uint32_t v);
|
uint32_t frsqrt7_s(uint32_t v);
|
||||||
uint32_t frec7_s(uint32_t v, uint8_t mode);
|
uint32_t frec7_s(uint32_t v, uint8_t mode);
|
||||||
uint32_t fconv_d2f(uint64_t v1, uint8_t mode);
|
uint32_t unbox_s(uint64_t v);
|
||||||
uint64_t fconv_f2d(uint32_t v1, uint8_t mode);
|
|
||||||
|
// double precision
|
||||||
uint64_t fadd_d(uint64_t v1, uint64_t v2, uint8_t mode);
|
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 fsub_d(uint64_t v1, uint64_t v2, uint8_t mode);
|
||||||
uint64_t fmul_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 fclass_d(uint64_t v1);
|
||||||
uint64_t frsqrt7_d(uint64_t v);
|
uint64_t frsqrt7_d(uint64_t v);
|
||||||
uint64_t frec7_d(uint64_t v, uint8_t mode);
|
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);
|
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 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_ */
|
#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) {
|
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");
|
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) {
|
template <> inline uint32_t fp_f_to_f<uint32_t, uint16_t>(uint8_t rm, uint16_t val) { return f16tof32(val, rm); }
|
||||||
softfloat_exceptionFlags = 0;
|
template <> inline uint64_t fp_f_to_f<uint64_t, uint32_t>(uint8_t rm, uint32_t val) { return f32tof64(val, rm); }
|
||||||
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 <typename dest_elem_t, typename src_elem_t>
|
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) {
|
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) {
|
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");
|
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) {
|
template <> inline uint16_t fp_f_to_f<uint16_t, uint32_t>(uint8_t rm, uint32_t val) { return f32tof16(val, rm); }
|
||||||
softfloat_exceptionFlags = 0;
|
template <> inline uint32_t fp_f_to_f<uint32_t, uint64_t>(uint8_t rm, uint64_t val) { return f64tof32(val, rm); }
|
||||||
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 <typename dest_elem_t, typename src_elem_t>
|
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) {
|
std::function<dest_elem_t(uint8_t, uint8_t&, src_elem_t)> get_fp_narrowing_fn(unsigned unary_op) {
|
||||||
switch(unary_op) {
|
switch(unary_op) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user