Line 88... |
Line 88... |
/**********************************************************************//**
|
/**********************************************************************//**
|
* Flush to zero if denormal number.
|
* Flush to zero if denormal number.
|
*
|
*
|
* @warning Subnormal numbers are not supported yet! Flush them to zero.
|
* @warning Subnormal numbers are not supported yet! Flush them to zero.
|
*
|
*
|
* @param[in] tmp Source operand 1.
|
* @param[in] tmp Source operand.
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float subnormal_flush(float tmp) {
|
float subnormal_flush(float tmp) {
|
|
|
float res = tmp;
|
float res = tmp;
|
Line 165... |
Line 165... |
// ################################################################################################
|
// ################################################################################################
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point addition
|
* Single-precision floating-point addition
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1.
|
|
*
|
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float __attribute__ ((noinline)) riscv_intrinsic_fadds(float rs1, float rs2) {
|
inline float __attribute__ ((always_inline)) riscv_intrinsic_fadds(float rs1, float rs2) {
|
|
|
float_conv_t opa, opb, res;
|
float_conv_t opa, opb, res;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
opb.float_value = rs2;
|
opb.float_value = rs2;
|
|
|
Line 187... |
Line 185... |
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
|
|
// fadd.s a0, a0, a1
|
// fadd.s a0, a0, a1
|
CUSTOM_INSTR_R2_TYPE(0b0000000, a1, a0, 0b000, a0, 0b1010011);
|
CUSTOM_INSTR_R2_TYPE(0b0000000, a1, a0, 0b000, a0, 0b1010011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
res.binary_value = result;
|
res.binary_value = result;
|
return res.float_value;
|
return res.float_value;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point subtraction
|
* Single-precision floating-point subtraction
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1.
|
|
*
|
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float __attribute__ ((noinline)) riscv_intrinsic_fsubs(float rs1, float rs2) {
|
inline float __attribute__ ((always_inline)) riscv_intrinsic_fsubs(float rs1, float rs2) {
|
|
|
float_conv_t opa, opb, res;
|
float_conv_t opa, opb, res;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
opb.float_value = rs2;
|
opb.float_value = rs2;
|
|
|
Line 217... |
Line 216... |
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
|
|
// fsub.s a0, a0, a1
|
// fsub.s a0, a0, a1
|
CUSTOM_INSTR_R2_TYPE(0b0000100, a1, a0, 0b000, a0, 0b1010011);
|
CUSTOM_INSTR_R2_TYPE(0b0000100, a1, a0, 0b000, a0, 0b1010011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
res.binary_value = result;
|
res.binary_value = result;
|
return res.float_value;
|
return res.float_value;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point multiplication
|
* Single-precision floating-point multiplication
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1.
|
|
*
|
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float __attribute__ ((noinline)) riscv_intrinsic_fmuls(float rs1, float rs2) {
|
inline float __attribute__ ((always_inline)) riscv_intrinsic_fmuls(float rs1, float rs2) {
|
|
|
float_conv_t opa, opb, res;
|
float_conv_t opa, opb, res;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
opb.float_value = rs2;
|
opb.float_value = rs2;
|
|
|
Line 247... |
Line 247... |
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
|
|
// fmul.s a0, a0, a1
|
// fmul.s a0, a0, a1
|
CUSTOM_INSTR_R2_TYPE(0b0001000, a1, a0, 0b000, a0, 0b1010011);
|
CUSTOM_INSTR_R2_TYPE(0b0001000, a1, a0, 0b000, a0, 0b1010011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
res.binary_value = result;
|
res.binary_value = result;
|
return res.float_value;
|
return res.float_value;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point minimum
|
* Single-precision floating-point minimum
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1.
|
|
*
|
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float __attribute__ ((noinline)) riscv_intrinsic_fmins(float rs1, float rs2) {
|
inline float __attribute__ ((always_inline)) riscv_intrinsic_fmins(float rs1, float rs2) {
|
|
|
float_conv_t opa, opb, res;
|
float_conv_t opa, opb, res;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
opb.float_value = rs2;
|
opb.float_value = rs2;
|
|
|
Line 277... |
Line 278... |
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
|
|
// fmin.s a0, a0, a1
|
// fmin.s a0, a0, a1
|
CUSTOM_INSTR_R2_TYPE(0b0010100, a1, a0, 0b000, a0, 0b1010011);
|
CUSTOM_INSTR_R2_TYPE(0b0010100, a1, a0, 0b000, a0, 0b1010011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
res.binary_value = result;
|
res.binary_value = result;
|
return res.float_value;
|
return res.float_value;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point maximum
|
* Single-precision floating-point maximum
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1.
|
|
*
|
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float __attribute__ ((noinline)) riscv_intrinsic_fmaxs(float rs1, float rs2) {
|
inline float __attribute__ ((always_inline)) riscv_intrinsic_fmaxs(float rs1, float rs2) {
|
|
|
float_conv_t opa, opb, res;
|
float_conv_t opa, opb, res;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
opb.float_value = rs2;
|
opb.float_value = rs2;
|
|
|
Line 307... |
Line 309... |
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
|
|
// fmax.s a0, a0, a1
|
// fmax.s a0, a0, a1
|
CUSTOM_INSTR_R2_TYPE(0b0010100, a1, a0, 0b001, a0, 0b1010011);
|
CUSTOM_INSTR_R2_TYPE(0b0010100, a1, a0, 0b001, a0, 0b1010011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
res.binary_value = result;
|
res.binary_value = result;
|
return res.float_value;
|
return res.float_value;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point convert float to unsigned integer
|
* Single-precision floating-point convert float to unsigned integer
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1.
|
|
*
|
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs1 Source operand 1 (a0).
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
uint32_t __attribute__ ((noinline)) riscv_intrinsic_fcvt_wus(float rs1) {
|
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_fcvt_wus(float rs1) {
|
|
|
float_conv_t opa;
|
float_conv_t opa;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
|
|
register uint32_t result __asm__ ("a0");
|
register uint32_t result __asm__ ("a0");
|
Line 334... |
Line 337... |
asm volatile ("add x0, %[input_i], x0" : : [input_i] "r" (tmp_a));
|
asm volatile ("add x0, %[input_i], x0" : : [input_i] "r" (tmp_a));
|
|
|
// fcvt.wu.s a0, a0
|
// fcvt.wu.s a0, a0
|
CUSTOM_INSTR_R2_TYPE(0b1100000, x1, a0, 0b000, a0, 0b1010011);
|
CUSTOM_INSTR_R2_TYPE(0b1100000, x1, a0, 0b000, a0, 0b1010011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
return result;
|
return result;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point convert float to signed integer
|
* Single-precision floating-point convert float to signed integer
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1.
|
|
*
|
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs1 Source operand 1 (a0).
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
int32_t __attribute__ ((noinline)) riscv_intrinsic_fcvt_ws(float rs1) {
|
inline int32_t __attribute__ ((always_inline)) riscv_intrinsic_fcvt_ws(float rs1) {
|
|
|
float_conv_t opa;
|
float_conv_t opa;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
|
|
register uint32_t result __asm__ ("a0");
|
register uint32_t result __asm__ ("a0");
|
Line 360... |
Line 364... |
asm volatile ("add x0, %[input_i], x0" : : [input_i] "r" (tmp_a));
|
asm volatile ("add x0, %[input_i], x0" : : [input_i] "r" (tmp_a));
|
|
|
// fcvt.w.s a0, a0
|
// fcvt.w.s a0, a0
|
CUSTOM_INSTR_R2_TYPE(0b1100000, x0, a0, 0b000, a0, 0b1010011);
|
CUSTOM_INSTR_R2_TYPE(0b1100000, x0, a0, 0b000, a0, 0b1010011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
return (int32_t)result;
|
return (int32_t)result;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point convert unsigned integer to float
|
* Single-precision floating-point convert unsigned integer to float
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1.
|
|
*
|
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs1 Source operand 1 (a0).
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float __attribute__ ((noinline)) riscv_intrinsic_fcvt_swu(uint32_t rs1) {
|
inline float __attribute__ ((always_inline)) riscv_intrinsic_fcvt_swu(uint32_t rs1) {
|
|
|
float_conv_t res;
|
float_conv_t res;
|
|
|
register uint32_t result __asm__ ("a0");
|
register uint32_t result __asm__ ("a0");
|
register uint32_t tmp_a __asm__ ("a0") = rs1;
|
register uint32_t tmp_a __asm__ ("a0") = rs1;
|
Line 385... |
Line 390... |
asm volatile ("add x0, %[input_i], x0" : : [input_i] "r" (tmp_a));
|
asm volatile ("add x0, %[input_i], x0" : : [input_i] "r" (tmp_a));
|
|
|
// fcvt.s.wu a0, a0
|
// fcvt.s.wu a0, a0
|
CUSTOM_INSTR_R2_TYPE(0b1101000, x1, a0, 0b000, a0, 0b1010011);
|
CUSTOM_INSTR_R2_TYPE(0b1101000, x1, a0, 0b000, a0, 0b1010011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
res.binary_value = result;
|
res.binary_value = result;
|
return res.float_value;
|
return res.float_value;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point convert signed integer to float
|
* Single-precision floating-point convert signed integer to float
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1.
|
|
*
|
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs1 Source operand 1 (a0).
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float __attribute__ ((noinline)) riscv_intrinsic_fcvt_sw(int32_t rs1) {
|
inline float __attribute__ ((always_inline)) riscv_intrinsic_fcvt_sw(int32_t rs1) {
|
|
|
float_conv_t res;
|
float_conv_t res;
|
|
|
register uint32_t result __asm__ ("a0");
|
register uint32_t result __asm__ ("a0");
|
register uint32_t tmp_a __asm__ ("a0") = (uint32_t)rs1;
|
register uint32_t tmp_a __asm__ ("a0") = (uint32_t)rs1;
|
Line 411... |
Line 417... |
asm volatile ("add x0, %[input_i], x0" : : [input_i] "r" (tmp_a));
|
asm volatile ("add x0, %[input_i], x0" : : [input_i] "r" (tmp_a));
|
|
|
// fcvt.s.w a0, a0
|
// fcvt.s.w a0, a0
|
CUSTOM_INSTR_R2_TYPE(0b1101000, x0, a0, 0b000, a0, 0b1010011);
|
CUSTOM_INSTR_R2_TYPE(0b1101000, x0, a0, 0b000, a0, 0b1010011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
res.binary_value = result;
|
res.binary_value = result;
|
return res.float_value;
|
return res.float_value;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point equal comparison
|
* Single-precision floating-point equal comparison
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1.
|
|
*
|
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
uint32_t __attribute__ ((noinline)) riscv_intrinsic_feqs(float rs1, float rs2) {
|
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_feqs(float rs1, float rs2) {
|
|
|
float_conv_t opa, opb;
|
float_conv_t opa, opb;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
opb.float_value = rs2;
|
opb.float_value = rs2;
|
|
|
Line 441... |
Line 448... |
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
|
|
// feq.s a0, a0, a1
|
// feq.s a0, a0, a1
|
CUSTOM_INSTR_R2_TYPE(0b1010000, a1, a0, 0b010, a0, 0b1010011);
|
CUSTOM_INSTR_R2_TYPE(0b1010000, a1, a0, 0b010, a0, 0b1010011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
return result;
|
return result;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point less-than comparison
|
* Single-precision floating-point less-than comparison
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1.
|
|
*
|
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
uint32_t __attribute__ ((noinline)) riscv_intrinsic_flts(float rs1, float rs2) {
|
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_flts(float rs1, float rs2) {
|
|
|
float_conv_t opa, opb;
|
float_conv_t opa, opb;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
opb.float_value = rs2;
|
opb.float_value = rs2;
|
|
|
Line 470... |
Line 478... |
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
|
|
// flt.s a0, a0, a1
|
// flt.s a0, a0, a1
|
CUSTOM_INSTR_R2_TYPE(0b1010000, a1, a0, 0b001, a0, 0b1010011);
|
CUSTOM_INSTR_R2_TYPE(0b1010000, a1, a0, 0b001, a0, 0b1010011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
return result;
|
return result;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point less-than-or-equal comparison
|
* Single-precision floating-point less-than-or-equal comparison
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1.
|
|
*
|
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
uint32_t __attribute__ ((noinline)) riscv_intrinsic_fles(float rs1, float rs2) {
|
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_fles(float rs1, float rs2) {
|
|
|
float_conv_t opa, opb;
|
float_conv_t opa, opb;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
opb.float_value = rs2;
|
opb.float_value = rs2;
|
|
|
Line 499... |
Line 508... |
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
|
|
// fle.s a0, a0, a1
|
// fle.s a0, a0, a1
|
CUSTOM_INSTR_R2_TYPE(0b1010000, a1, a0, 0b000, a0, 0b1010011);
|
CUSTOM_INSTR_R2_TYPE(0b1010000, a1, a0, 0b000, a0, 0b1010011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
return result;
|
return result;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point sign-injection
|
* Single-precision floating-point sign-injection
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1.
|
|
*
|
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float __attribute__ ((noinline)) riscv_intrinsic_fsgnjs(float rs1, float rs2) {
|
inline float __attribute__ ((always_inline)) riscv_intrinsic_fsgnjs(float rs1, float rs2) {
|
|
|
float_conv_t opa, opb, res;
|
float_conv_t opa, opb, res;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
opb.float_value = rs2;
|
opb.float_value = rs2;
|
|
|
Line 528... |
Line 538... |
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
|
|
// fsgnj.s a0, a0, a1
|
// fsgnj.s a0, a0, a1
|
CUSTOM_INSTR_R2_TYPE(0b0010000, a1, a0, 0b000, a0, 0b1010011);
|
CUSTOM_INSTR_R2_TYPE(0b0010000, a1, a0, 0b000, a0, 0b1010011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
res.binary_value = result;
|
res.binary_value = result;
|
return res.float_value;
|
return res.float_value;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point sign-injection NOT
|
* Single-precision floating-point sign-injection NOT
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1.
|
|
*
|
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float __attribute__ ((noinline)) riscv_intrinsic_fsgnjns(float rs1, float rs2) {
|
inline float __attribute__ ((always_inline)) riscv_intrinsic_fsgnjns(float rs1, float rs2) {
|
|
|
float_conv_t opa, opb, res;
|
float_conv_t opa, opb, res;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
opb.float_value = rs2;
|
opb.float_value = rs2;
|
|
|
Line 558... |
Line 569... |
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
|
|
// fsgnjn.s a0, a0, a1
|
// fsgnjn.s a0, a0, a1
|
CUSTOM_INSTR_R2_TYPE(0b0010000, a1, a0, 0b001, a0, 0b1010011);
|
CUSTOM_INSTR_R2_TYPE(0b0010000, a1, a0, 0b001, a0, 0b1010011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
res.binary_value = result;
|
res.binary_value = result;
|
return res.float_value;
|
return res.float_value;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point sign-injection XOR
|
* Single-precision floating-point sign-injection XOR
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1.
|
|
*
|
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float __attribute__ ((noinline)) riscv_intrinsic_fsgnjxs(float rs1, float rs2) {
|
inline float __attribute__ ((always_inline)) riscv_intrinsic_fsgnjxs(float rs1, float rs2) {
|
|
|
float_conv_t opa, opb, res;
|
float_conv_t opa, opb, res;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
opb.float_value = rs2;
|
opb.float_value = rs2;
|
|
|
Line 588... |
Line 600... |
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
|
|
// fsgnjx.s a0, a0, a1
|
// fsgnjx.s a0, a0, a1
|
CUSTOM_INSTR_R2_TYPE(0b0010000, a1, a0, 0b010, a0, 0b1010011);
|
CUSTOM_INSTR_R2_TYPE(0b0010000, a1, a0, 0b010, a0, 0b1010011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
res.binary_value = result;
|
res.binary_value = result;
|
return res.float_value;
|
return res.float_value;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point number classification
|
* Single-precision floating-point number classification
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1.
|
|
*
|
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs1 Source operand 1 (a0).
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
uint32_t __attribute__ ((noinline)) riscv_intrinsic_fclasss(float rs1) {
|
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_fclasss(float rs1) {
|
|
|
float_conv_t opa;
|
float_conv_t opa;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
|
|
register uint32_t result __asm__ ("a0");
|
register uint32_t result __asm__ ("a0");
|
Line 615... |
Line 628... |
asm volatile ("add x0, %[input_i], x0" : : [input_i] "r" (tmp_a));
|
asm volatile ("add x0, %[input_i], x0" : : [input_i] "r" (tmp_a));
|
|
|
// fclass.s a0, a0
|
// fclass.s a0, a0
|
CUSTOM_INSTR_R2_TYPE(0b1110000, x0, a0, 0b001, a0, 0b1010011);
|
CUSTOM_INSTR_R2_TYPE(0b1110000, x0, a0, 0b001, a0, 0b1010011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
return result;
|
return result;
|
}
|
}
|
|
|
|
|
// ################################################################################################
|
// ################################################################################################
|
Line 626... |
Line 642... |
// ################################################################################################
|
// ################################################################################################
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point division
|
* Single-precision floating-point division
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1.
|
|
*
|
|
* @warning This instruction is not supported and should raise an illegal instruction exception when executed.
|
* @warning This instruction is not supported and should raise an illegal instruction exception when executed.
|
*
|
*
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @param[in] rs2 Source operand 2 (a1).
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float __attribute__ ((noinline)) riscv_intrinsic_fdivs(float rs1, float rs2) {
|
inline float __attribute__ ((always_inline)) riscv_intrinsic_fdivs(float rs1, float rs2) {
|
|
|
float_conv_t opa, opb, res;
|
float_conv_t opa, opb, res;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
opb.float_value = rs2;
|
opb.float_value = rs2;
|
|
|
Line 650... |
Line 664... |
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
|
|
|
// fdiv.s a0, a0, x1
|
// fdiv.s a0, a0, x1
|
CUSTOM_INSTR_R2_TYPE(0b0001100, a1, a0, 0b000, a0, 0b1010011);
|
CUSTOM_INSTR_R2_TYPE(0b0001100, a1, a0, 0b000, a0, 0b1010011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
res.binary_value = result;
|
res.binary_value = result;
|
return res.float_value;
|
return res.float_value;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point square root
|
* Single-precision floating-point square root
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1.
|
|
*
|
|
* @warning This instruction is not supported and should raise an illegal instruction exception when executed.
|
* @warning This instruction is not supported and should raise an illegal instruction exception when executed.
|
*
|
*
|
* @param[in] rs1 Source operand 1 (a0).
|
* @param[in] rs1 Source operand 1 (a0).
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float __attribute__ ((noinline)) riscv_intrinsic_fsqrts(float rs1) {
|
inline float __attribute__ ((always_inline)) riscv_intrinsic_fsqrts(float rs1) {
|
|
|
float_conv_t opa, res;
|
float_conv_t opa, res;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
|
|
register uint32_t result __asm__ ("a0");
|
register uint32_t result __asm__ ("a0");
|
Line 679... |
Line 694... |
asm volatile ("add x0, %[input_i], x0" : : [input_i] "r" (tmp_a));
|
asm volatile ("add x0, %[input_i], x0" : : [input_i] "r" (tmp_a));
|
|
|
// fsqrt.s a0, a0, a1
|
// fsqrt.s a0, a0, a1
|
CUSTOM_INSTR_R2_TYPE(0b0101100, a1, a0, 0b000, a0, 0b1010011);
|
CUSTOM_INSTR_R2_TYPE(0b0101100, a1, a0, 0b000, a0, 0b1010011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
res.binary_value = result;
|
res.binary_value = result;
|
return res.float_value;
|
return res.float_value;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point fused multiply-add
|
* Single-precision floating-point fused multiply-add
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0, a1 and a2.
|
|
*
|
|
* @warning This instruction is not supported and should raise an illegal instruction exception when executed.
|
* @warning This instruction is not supported and should raise an illegal instruction exception when executed.
|
*
|
*
|
* @param[in] rs1 Source operand 1 (a0)
|
* @param[in] rs1 Source operand 1 (a0)
|
* @param[in] rs2 Source operand 2 (a1)
|
* @param[in] rs2 Source operand 2 (a1)
|
* @param[in] rs3 Source operand 3 (a2)
|
* @param[in] rs3 Source operand 3 (a2)
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float __attribute__ ((noinline)) riscv_intrinsic_fmadds(float rs1, float rs2, float rs3) {
|
inline float __attribute__ ((always_inline)) riscv_intrinsic_fmadds(float rs1, float rs2, float rs3) {
|
|
|
float_conv_t opa, opb, opc, res;
|
float_conv_t opa, opb, opc, res;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
opb.float_value = rs2;
|
opb.float_value = rs2;
|
opc.float_value = rs3;
|
opc.float_value = rs3;
|
Line 715... |
Line 731... |
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_b), [input_j] "r" (tmp_c));
|
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_b), [input_j] "r" (tmp_c));
|
|
|
// fmadd.s a0, a0, a1, a2
|
// fmadd.s a0, a0, a1, a2
|
CUSTOM_INSTR_R3_TYPE(a2, a1, a0, 0b000, a0, 0b1000011);
|
CUSTOM_INSTR_R3_TYPE(a2, a1, a0, 0b000, a0, 0b1000011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
res.binary_value = result;
|
res.binary_value = result;
|
return res.float_value;
|
return res.float_value;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point fused multiply-sub
|
* Single-precision floating-point fused multiply-sub
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0, a1 and a2.
|
|
*
|
|
* @warning This instruction is not supported and should raise an illegal instruction exception when executed.
|
* @warning This instruction is not supported and should raise an illegal instruction exception when executed.
|
*
|
*
|
* @param[in] rs1 Source operand 1 (a0)
|
* @param[in] rs1 Source operand 1 (a0)
|
* @param[in] rs2 Source operand 2 (a1)
|
* @param[in] rs2 Source operand 2 (a1)
|
* @param[in] rs3 Source operand 3 (a2)
|
* @param[in] rs3 Source operand 3 (a2)
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float __attribute__ ((noinline)) riscv_intrinsic_fmsubs(float rs1, float rs2, float rs3) {
|
inline float __attribute__ ((always_inline)) riscv_intrinsic_fmsubs(float rs1, float rs2, float rs3) {
|
|
|
float_conv_t opa, opb, opc, res;
|
float_conv_t opa, opb, opc, res;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
opb.float_value = rs2;
|
opb.float_value = rs2;
|
opc.float_value = rs3;
|
opc.float_value = rs3;
|
Line 751... |
Line 768... |
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_b), [input_j] "r" (tmp_c));
|
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_b), [input_j] "r" (tmp_c));
|
|
|
// fmsub.s a0, a0, a1, a2
|
// fmsub.s a0, a0, a1, a2
|
CUSTOM_INSTR_R3_TYPE(a2, a1, a0, 0b000, a0, 0b1000111);
|
CUSTOM_INSTR_R3_TYPE(a2, a1, a0, 0b000, a0, 0b1000111);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
res.binary_value = result;
|
res.binary_value = result;
|
return res.float_value;
|
return res.float_value;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point fused negated multiply-sub
|
* Single-precision floating-point fused negated multiply-sub
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0, a1 and a2.
|
|
*
|
|
* @warning This instruction is not supported and should raise an illegal instruction exception when executed.
|
* @warning This instruction is not supported and should raise an illegal instruction exception when executed.
|
*
|
*
|
* @param[in] rs1 Source operand 1 (a0)
|
* @param[in] rs1 Source operand 1 (a0)
|
* @param[in] rs2 Source operand 2 (a1)
|
* @param[in] rs2 Source operand 2 (a1)
|
* @param[in] rs3 Source operand 3 (a2)
|
* @param[in] rs3 Source operand 3 (a2)
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float __attribute__ ((noinline)) riscv_intrinsic_fnmsubs(float rs1, float rs2, float rs3) {
|
inline float __attribute__ ((always_inline)) riscv_intrinsic_fnmsubs(float rs1, float rs2, float rs3) {
|
|
|
float_conv_t opa, opb, opc, res;
|
float_conv_t opa, opb, opc, res;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
opb.float_value = rs2;
|
opb.float_value = rs2;
|
opc.float_value = rs3;
|
opc.float_value = rs3;
|
Line 787... |
Line 805... |
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_b), [input_j] "r" (tmp_c));
|
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_b), [input_j] "r" (tmp_c));
|
|
|
// fnmsub.s a0, a0, a1, a2
|
// fnmsub.s a0, a0, a1, a2
|
CUSTOM_INSTR_R3_TYPE(a2, a1, a0, 0b000, a0, 0b1001011);
|
CUSTOM_INSTR_R3_TYPE(a2, a1, a0, 0b000, a0, 0b1001011);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
res.binary_value = result;
|
res.binary_value = result;
|
return res.float_value;
|
return res.float_value;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Single-precision floating-point fused negated multiply-add
|
* Single-precision floating-point fused negated multiply-add
|
*
|
*
|
* @note "noinline" attributed to make sure arguments/return values are in a0, a1 and a2.
|
|
*
|
|
* @warning This instruction is not supported and should raise an illegal instruction exception when executed.
|
* @warning This instruction is not supported and should raise an illegal instruction exception when executed.
|
*
|
*
|
* @param[in] rs1 Source operand 1 (a0)
|
* @param[in] rs1 Source operand 1 (a0)
|
* @param[in] rs2 Source operand 2 (a1)
|
* @param[in] rs2 Source operand 2 (a1)
|
* @param[in] rs3 Source operand 3 (a2)
|
* @param[in] rs3 Source operand 3 (a2)
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float __attribute__ ((noinline)) riscv_intrinsic_fnmadds(float rs1, float rs2, float rs3) {
|
inline float __attribute__ ((always_inline)) riscv_intrinsic_fnmadds(float rs1, float rs2, float rs3) {
|
|
|
float_conv_t opa, opb, opc, res;
|
float_conv_t opa, opb, opc, res;
|
opa.float_value = rs1;
|
opa.float_value = rs1;
|
opb.float_value = rs2;
|
opb.float_value = rs2;
|
opc.float_value = rs3;
|
opc.float_value = rs3;
|
Line 823... |
Line 842... |
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_b), [input_j] "r" (tmp_c));
|
asm volatile ("add x0, %[input_i], %[input_j]" : : [input_i] "r" (tmp_b), [input_j] "r" (tmp_c));
|
|
|
// fnmadd.s a0, a0, a1, a2
|
// fnmadd.s a0, a0, a1, a2
|
CUSTOM_INSTR_R3_TYPE(a2, a1, a0, 0b000, a0, 0b1001111);
|
CUSTOM_INSTR_R3_TYPE(a2, a1, a0, 0b000, a0, 0b1001111);
|
|
|
|
// dummy instruction to prevent GCC "constprop" optimization
|
|
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) );
|
|
|
res.binary_value = result;
|
res.binary_value = result;
|
return res.float_value;
|
return res.float_value;
|
}
|
}
|
|
|
|
|
Line 839... |
Line 861... |
*
|
*
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs2 Source operand 2.
|
* @param[in] rs2 Source operand 2.
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float riscv_emulate_fadds(float rs1, float rs2) {
|
float __attribute__ ((noinline)) riscv_emulate_fadds(float rs1, float rs2) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
float opb = subnormal_flush(rs2);
|
float opb = subnormal_flush(rs2);
|
|
|
float res = opa + opb;
|
float res = opa + opb;
|
Line 856... |
Line 878... |
*
|
*
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs2 Source operand 2.
|
* @param[in] rs2 Source operand 2.
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float riscv_emulate_fsubs(float rs1, float rs2) {
|
float __attribute__ ((noinline)) riscv_emulate_fsubs(float rs1, float rs2) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
float opb = subnormal_flush(rs2);
|
float opb = subnormal_flush(rs2);
|
|
|
float res = opa - opb;
|
float res = opa - opb;
|
Line 873... |
Line 895... |
*
|
*
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs2 Source operand 2.
|
* @param[in] rs2 Source operand 2.
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float riscv_emulate_fmuls(float rs1, float rs2) {
|
float __attribute__ ((noinline)) riscv_emulate_fmuls(float rs1, float rs2) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
float opb = subnormal_flush(rs2);
|
float opb = subnormal_flush(rs2);
|
|
|
float res = opa * opb;
|
float res = opa * opb;
|
Line 890... |
Line 912... |
*
|
*
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs2 Source operand 2.
|
* @param[in] rs2 Source operand 2.
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float riscv_emulate_fmins(float rs1, float rs2) {
|
float __attribute__ ((noinline)) riscv_emulate_fmins(float rs1, float rs2) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
float opb = subnormal_flush(rs2);
|
float opb = subnormal_flush(rs2);
|
|
|
union {
|
union {
|
Line 931... |
Line 953... |
*
|
*
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs2 Source operand 2.
|
* @param[in] rs2 Source operand 2.
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float riscv_emulate_fmaxs(float rs1, float rs2) {
|
float __attribute__ ((noinline)) riscv_emulate_fmaxs(float rs1, float rs2) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
float opb = subnormal_flush(rs2);
|
float opb = subnormal_flush(rs2);
|
|
|
union {
|
union {
|
Line 972... |
Line 994... |
* Single-precision floating-point float to unsigned integer
|
* Single-precision floating-point float to unsigned integer
|
*
|
*
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs1 Source operand 1.
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
uint32_t riscv_emulate_fcvt_wus(float rs1) {
|
uint32_t __attribute__ ((noinline)) riscv_emulate_fcvt_wus(float rs1) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
|
|
return (uint32_t)roundf(opa);
|
return (uint32_t)roundf(opa);
|
}
|
}
|
Line 986... |
Line 1008... |
* Single-precision floating-point float to signed integer
|
* Single-precision floating-point float to signed integer
|
*
|
*
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs1 Source operand 1.
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
int32_t riscv_emulate_fcvt_ws(float rs1) {
|
int32_t __attribute__ ((noinline)) riscv_emulate_fcvt_ws(float rs1) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
|
|
return (int32_t)roundf(opa);
|
return (int32_t)roundf(opa);
|
}
|
}
|
Line 1000... |
Line 1022... |
* Single-precision floating-point unsigned integer to float
|
* Single-precision floating-point unsigned integer to float
|
*
|
*
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs1 Source operand 1.
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float riscv_emulate_fcvt_swu(uint32_t rs1) {
|
float __attribute__ ((noinline)) riscv_emulate_fcvt_swu(uint32_t rs1) {
|
|
|
return (float)rs1;
|
return (float)rs1;
|
}
|
}
|
|
|
|
|
Line 1012... |
Line 1034... |
* Single-precision floating-point signed integer to float
|
* Single-precision floating-point signed integer to float
|
*
|
*
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs1 Source operand 1.
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float riscv_emulate_fcvt_sw(int32_t rs1) {
|
float __attribute__ ((noinline)) riscv_emulate_fcvt_sw(int32_t rs1) {
|
|
|
return (float)rs1;
|
return (float)rs1;
|
}
|
}
|
|
|
|
|
Line 1025... |
Line 1047... |
*
|
*
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs2 Source operand 2.
|
* @param[in] rs2 Source operand 2.
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
uint32_t riscv_emulate_feqs(float rs1, float rs2) {
|
uint32_t __attribute__ ((noinline)) riscv_emulate_feqs(float rs1, float rs2) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
float opb = subnormal_flush(rs2);
|
float opb = subnormal_flush(rs2);
|
|
|
if ((fpclassify(opa) == FP_NAN) || (fpclassify(opb) == FP_NAN)) {
|
if ((fpclassify(opa) == FP_NAN) || (fpclassify(opb) == FP_NAN)) {
|
Line 1053... |
Line 1075... |
*
|
*
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs2 Source operand 2.
|
* @param[in] rs2 Source operand 2.
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
uint32_t riscv_emulate_flts(float rs1, float rs2) {
|
uint32_t __attribute__ ((noinline)) riscv_emulate_flts(float rs1, float rs2) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
float opb = subnormal_flush(rs2);
|
float opb = subnormal_flush(rs2);
|
|
|
if ((fpclassify(opa) == FP_NAN) || (fpclassify(opb) == FP_NAN)) {
|
if ((fpclassify(opa) == FP_NAN) || (fpclassify(opb) == FP_NAN)) {
|
Line 1078... |
Line 1100... |
*
|
*
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs2 Source operand 2.
|
* @param[in] rs2 Source operand 2.
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
uint32_t riscv_emulate_fles(float rs1, float rs2) {
|
uint32_t __attribute__ ((noinline)) riscv_emulate_fles(float rs1, float rs2) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
float opb = subnormal_flush(rs2);
|
float opb = subnormal_flush(rs2);
|
|
|
if ((fpclassify(opa) == FP_NAN) || (fpclassify(opb) == FP_NAN)) {
|
if ((fpclassify(opa) == FP_NAN) || (fpclassify(opb) == FP_NAN)) {
|
Line 1103... |
Line 1125... |
*
|
*
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs2 Source operand 2.
|
* @param[in] rs2 Source operand 2.
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float riscv_emulate_fsgnjs(float rs1, float rs2) {
|
float __attribute__ ((noinline)) riscv_emulate_fsgnjs(float rs1, float rs2) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
float opb = subnormal_flush(rs2);
|
float opb = subnormal_flush(rs2);
|
|
|
int sign_1 = (int)signbit(opa);
|
int sign_1 = (int)signbit(opa);
|
Line 1140... |
Line 1162... |
*
|
*
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs2 Source operand 2.
|
* @param[in] rs2 Source operand 2.
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float riscv_emulate_fsgnjns(float rs1, float rs2) {
|
float __attribute__ ((noinline)) riscv_emulate_fsgnjns(float rs1, float rs2) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
float opb = subnormal_flush(rs2);
|
float opb = subnormal_flush(rs2);
|
|
|
int sign_1 = (int)signbit(opa);
|
int sign_1 = (int)signbit(opa);
|
Line 1177... |
Line 1199... |
*
|
*
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs2 Source operand 2.
|
* @param[in] rs2 Source operand 2.
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float riscv_emulate_fsgnjxs(float rs1, float rs2) {
|
float __attribute__ ((noinline)) riscv_emulate_fsgnjxs(float rs1, float rs2) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
float opb = subnormal_flush(rs2);
|
float opb = subnormal_flush(rs2);
|
|
|
int sign_1 = (int)signbit(opa);
|
int sign_1 = (int)signbit(opa);
|
Line 1213... |
Line 1235... |
* Single-precision floating-point number classification
|
* Single-precision floating-point number classification
|
*
|
*
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs1 Source operand 1.
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
uint32_t riscv_emulate_fclasss(float rs1) {
|
uint32_t __attribute__ ((noinline)) riscv_emulate_fclasss(float rs1) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
|
|
union {
|
union {
|
uint32_t binary_value; /**< Access as native float */
|
uint32_t binary_value; /**< Access as native float */
|
Line 1285... |
Line 1307... |
*
|
*
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs2 Source operand 2.
|
* @param[in] rs2 Source operand 2.
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float riscv_emulate_fdivs(float rs1, float rs2) {
|
float __attribute__ ((noinline)) riscv_emulate_fdivs(float rs1, float rs2) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
float opb = subnormal_flush(rs2);
|
float opb = subnormal_flush(rs2);
|
|
|
float res = opa / opb;
|
float res = opa / opb;
|
Line 1301... |
Line 1323... |
* Single-precision floating-point square root
|
* Single-precision floating-point square root
|
*
|
*
|
* @param[in] rs1 Source operand 1.
|
* @param[in] rs1 Source operand 1.
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float riscv_emulate_fsqrts(float rs1) {
|
float __attribute__ ((noinline)) riscv_emulate_fsqrts(float rs1) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
|
|
float res = sqrtf(opa);
|
float res = sqrtf(opa);
|
return subnormal_flush(res);
|
return subnormal_flush(res);
|
Line 1322... |
Line 1344... |
* @param[in] rs1 Source operand 1
|
* @param[in] rs1 Source operand 1
|
* @param[in] rs2 Source operand 2
|
* @param[in] rs2 Source operand 2
|
* @param[in] rs3 Source operand 3
|
* @param[in] rs3 Source operand 3
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float riscv_emulate_fmadds(float rs1, float rs2, float rs3) {
|
float __attribute__ ((noinline)) riscv_emulate_fmadds(float rs1, float rs2, float rs3) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
float opb = subnormal_flush(rs2);
|
float opb = subnormal_flush(rs2);
|
float opc = subnormal_flush(rs3);
|
float opc = subnormal_flush(rs3);
|
|
|
Line 1341... |
Line 1363... |
* @param[in] rs1 Source operand 1
|
* @param[in] rs1 Source operand 1
|
* @param[in] rs2 Source operand 2
|
* @param[in] rs2 Source operand 2
|
* @param[in] rs3 Source operand 3
|
* @param[in] rs3 Source operand 3
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float riscv_emulate_fmsubs(float rs1, float rs2, float rs3) {
|
float __attribute__ ((noinline)) riscv_emulate_fmsubs(float rs1, float rs2, float rs3) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
float opb = subnormal_flush(rs2);
|
float opb = subnormal_flush(rs2);
|
float opc = subnormal_flush(rs3);
|
float opc = subnormal_flush(rs3);
|
|
|
Line 1360... |
Line 1382... |
* @param[in] rs1 Source operand 1
|
* @param[in] rs1 Source operand 1
|
* @param[in] rs2 Source operand 2
|
* @param[in] rs2 Source operand 2
|
* @param[in] rs3 Source operand 3
|
* @param[in] rs3 Source operand 3
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float riscv_emulate_fnmsubs(float rs1, float rs2, float rs3) {
|
float __attribute__ ((noinline)) riscv_emulate_fnmsubs(float rs1, float rs2, float rs3) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
float opb = subnormal_flush(rs2);
|
float opb = subnormal_flush(rs2);
|
float opc = subnormal_flush(rs3);
|
float opc = subnormal_flush(rs3);
|
|
|
Line 1379... |
Line 1401... |
* @param[in] rs1 Source operand 1
|
* @param[in] rs1 Source operand 1
|
* @param[in] rs2 Source operand 2
|
* @param[in] rs2 Source operand 2
|
* @param[in] rs3 Source operand 3
|
* @param[in] rs3 Source operand 3
|
* @return Result.
|
* @return Result.
|
**************************************************************************/
|
**************************************************************************/
|
float riscv_emulate_fnmadds(float rs1, float rs2, float rs3) {
|
float __attribute__ ((noinline)) riscv_emulate_fnmadds(float rs1, float rs2, float rs3) {
|
|
|
float opa = subnormal_flush(rs1);
|
float opa = subnormal_flush(rs1);
|
float opb = subnormal_flush(rs2);
|
float opb = subnormal_flush(rs2);
|
float opc = subnormal_flush(rs3);
|
float opc = subnormal_flush(rs3);
|
|
|