52#ifndef neorv32_zfinx_extension_intrinsics_h
53#define neorv32_zfinx_extension_intrinsics_h
69#if defined __riscv_f || (__riscv_flen == 32)
70 #error Application programs using the Zfinx intrinsic library have to be compiled WITHOUT the <F> MARCH ISA attribute!
79 uint32_t binary_value;
96float subnormal_flush(
float tmp) {
101 if (fpclassify(tmp) == FP_SUBNORMAL) {
102 if (signbit(tmp) != 0) {
123uint32_t get_hw_exceptions(
void) {
140uint32_t get_sw_exceptions(
void) {
142 const uint32_t FP_EXC_NV_C = 1 << 0;
143 const uint32_t FP_EXC_DZ_C = 1 << 1;
144 const uint32_t FP_EXC_OF_C = 1 << 2;
145 const uint32_t FP_EXC_UF_C = 1 << 3;
146 const uint32_t FP_EXC_NX_C = 1 << 4;
148 int fpeRaised = fetestexcept(FE_ALL_EXCEPT);
152 if (fpeRaised & FE_INVALID) { res |= FP_EXC_NV_C; }
153 if (fpeRaised & FE_DIVBYZERO) { res |= FP_EXC_DZ_C; }
154 if (fpeRaised & FE_OVERFLOW) { res |= FP_EXC_OF_C; }
155 if (fpeRaised & FE_UNDERFLOW) { res |= FP_EXC_UF_C; }
156 if (fpeRaised & FE_INEXACT) { res |= FP_EXC_NX_C; }
158 feclearexcept(FE_ALL_EXCEPT);
175inline float __attribute__ ((always_inline)) riscv_intrinsic_fadds(
float rs1,
float rs2) {
193inline float __attribute__ ((always_inline)) riscv_intrinsic_fsubs(
float rs1,
float rs2) {
211inline float __attribute__ ((always_inline)) riscv_intrinsic_fmuls(
float rs1,
float rs2) {
229inline float __attribute__ ((always_inline)) riscv_intrinsic_fmins(
float rs1,
float rs2) {
247inline float __attribute__ ((always_inline)) riscv_intrinsic_fmaxs(
float rs1,
float rs2) {
264inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_fcvt_wus(
float rs1) {
269 return CUSTOM_INSTR_R2_TYPE(0b1100000, 0b00001, opa.
binary_value, 0b000, 0b1010011);
279inline int32_t __attribute__ ((always_inline)) riscv_intrinsic_fcvt_ws(
float rs1) {
284 return (int32_t)CUSTOM_INSTR_R2_TYPE(0b1100000, 0b00000, opa.
binary_value, 0b000, 0b1010011);
294inline float __attribute__ ((always_inline)) riscv_intrinsic_fcvt_swu(uint32_t rs1) {
298 res.
binary_value = CUSTOM_INSTR_R2_TYPE(0b1101000, 0b00001, rs1, 0b000, 0b1010011);
309inline float __attribute__ ((always_inline)) riscv_intrinsic_fcvt_sw(int32_t rs1) {
313 res.
binary_value = CUSTOM_INSTR_R2_TYPE(0b1101000, 0b00000, rs1, 0b000, 0b1010011);
325inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_feqs(
float rs1,
float rs2) {
342inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_flts(
float rs1,
float rs2) {
359inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_fles(
float rs1,
float rs2) {
376inline float __attribute__ ((always_inline)) riscv_intrinsic_fsgnjs(
float rs1,
float rs2) {
394inline float __attribute__ ((always_inline)) riscv_intrinsic_fsgnjns(
float rs1,
float rs2) {
412inline float __attribute__ ((always_inline)) riscv_intrinsic_fsgnjxs(
float rs1,
float rs2) {
429inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_fclasss(
float rs1) {
434 return CUSTOM_INSTR_R2_TYPE(0b1110000, 0b00000, opa.
binary_value, 0b001, 0b1010011);
451inline float __attribute__ ((always_inline)) riscv_intrinsic_fdivs(
float rs1,
float rs2) {
470inline float __attribute__ ((always_inline)) riscv_intrinsic_fsqrts(
float rs1) {
490inline float __attribute__ ((always_inline)) riscv_intrinsic_fmadds(
float rs1,
float rs2,
float rs3) {
512inline float __attribute__ ((always_inline)) riscv_intrinsic_fmsubs(
float rs1,
float rs2,
float rs3) {
534inline float __attribute__ ((always_inline)) riscv_intrinsic_fnmsubs(
float rs1,
float rs2,
float rs3) {
556inline float __attribute__ ((always_inline)) riscv_intrinsic_fnmadds(
float rs1,
float rs2,
float rs3) {
579float __attribute__ ((noinline)) riscv_emulate_fadds(
float rs1,
float rs2) {
581 float opa = subnormal_flush(rs1);
582 float opb = subnormal_flush(rs2);
584 float res = opa + opb;
587 if (fpclassify(res) == FP_NAN) {
591 return subnormal_flush(res);
602float __attribute__ ((noinline)) riscv_emulate_fsubs(
float rs1,
float rs2) {
604 float opa = subnormal_flush(rs1);
605 float opb = subnormal_flush(rs2);
607 float res = opa - opb;
610 if (fpclassify(res) == FP_NAN) {
614 return subnormal_flush(res);
625float __attribute__ ((noinline)) riscv_emulate_fmuls(
float rs1,
float rs2) {
627 float opa = subnormal_flush(rs1);
628 float opb = subnormal_flush(rs2);
630 float res = opa * opb;
631 return subnormal_flush(res);
642float __attribute__ ((noinline)) riscv_emulate_fmins(
float rs1,
float rs2) {
644 float opa = subnormal_flush(rs1);
645 float opb = subnormal_flush(rs2);
648 uint32_t binary_value;
652 if ((fpclassify(opa) == FP_NAN) && (fpclassify(opb) == FP_NAN)) {
656 if (fpclassify(opa) == FP_NAN) {
660 if (fpclassify(opb) == FP_NAN) {
665 tmp_a.float_value = opa;
666 tmp_b.float_value = opb;
667 if (((tmp_a.binary_value == 0x80000000) && (tmp_b.binary_value == 0x00000000)) ||
668 ((tmp_a.binary_value == 0x00000000) && (tmp_b.binary_value == 0x80000000))) {
672 return fmin(opa, opb);
683float __attribute__ ((noinline)) riscv_emulate_fmaxs(
float rs1,
float rs2) {
685 float opa = subnormal_flush(rs1);
686 float opb = subnormal_flush(rs2);
689 uint32_t binary_value;
694 if ((fpclassify(opa) == FP_NAN) && (fpclassify(opb) == FP_NAN)) {
698 if (fpclassify(opa) == FP_NAN) {
702 if (fpclassify(opb) == FP_NAN) {
707 tmp_a.float_value = opa;
708 tmp_b.float_value = opb;
709 if (((tmp_a.binary_value == 0x80000000) && (tmp_b.binary_value == 0x00000000)) ||
710 ((tmp_a.binary_value == 0x00000000) && (tmp_b.binary_value == 0x80000000))) {
714 return fmax(opa, opb);
724uint32_t __attribute__ ((noinline)) riscv_emulate_fcvt_wus(
float rs1) {
726 float opa = subnormal_flush(rs1);
728 return (uint32_t)roundf(opa);
738int32_t __attribute__ ((noinline)) riscv_emulate_fcvt_ws(
float rs1) {
740 float opa = subnormal_flush(rs1);
742 return (int32_t)roundf(opa);
752float __attribute__ ((noinline)) riscv_emulate_fcvt_swu(uint32_t rs1) {
764float __attribute__ ((noinline)) riscv_emulate_fcvt_sw(int32_t rs1) {
777uint32_t __attribute__ ((noinline)) riscv_emulate_feqs(
float rs1,
float rs2) {
779 float opa = subnormal_flush(rs1);
780 float opb = subnormal_flush(rs2);
782 if ((fpclassify(opa) == FP_NAN) || (fpclassify(opb) == FP_NAN)) {
786 if isless(opa, opb) {
789 else if isgreater(opa, opb) {
805uint32_t __attribute__ ((noinline)) riscv_emulate_flts(
float rs1,
float rs2) {
807 float opa = subnormal_flush(rs1);
808 float opb = subnormal_flush(rs2);
810 if ((fpclassify(opa) == FP_NAN) || (fpclassify(opb) == FP_NAN)) {
814 if isless(opa, opb) {
830uint32_t __attribute__ ((noinline)) riscv_emulate_fles(
float rs1,
float rs2) {
832 float opa = subnormal_flush(rs1);
833 float opb = subnormal_flush(rs2);
835 if ((fpclassify(opa) == FP_NAN) || (fpclassify(opb) == FP_NAN)) {
839 if islessequal(opa, opb) {
855float __attribute__ ((noinline)) riscv_emulate_fsgnjs(
float rs1,
float rs2) {
857 float opa = subnormal_flush(rs1);
858 float opb = subnormal_flush(rs2);
860 int sign_1 = (int)signbit(opa);
861 int sign_2 = (int)signbit(opb);
892float __attribute__ ((noinline)) riscv_emulate_fsgnjns(
float rs1,
float rs2) {
894 float opa = subnormal_flush(rs1);
895 float opb = subnormal_flush(rs2);
897 int sign_1 = (int)signbit(opa);
898 int sign_2 = (int)signbit(opb);
929float __attribute__ ((noinline)) riscv_emulate_fsgnjxs(
float rs1,
float rs2) {
931 float opa = subnormal_flush(rs1);
932 float opb = subnormal_flush(rs2);
934 int sign_1 = (int)signbit(opa);
935 int sign_2 = (int)signbit(opb);
938 if (((sign_1 == 0) && (sign_2 != 0)) || ((sign_1 != 0) && (sign_2 == 0))) {
965uint32_t __attribute__ ((noinline)) riscv_emulate_fclasss(
float rs1) {
967 float opa = subnormal_flush(rs1);
970 uint32_t binary_value;
975 const uint32_t CLASS_NEG_INF = 1 << 0;
976 const uint32_t CLASS_NEG_NORM = 1 << 1;
977 const uint32_t CLASS_NEG_DENORM = 1 << 2;
978 const uint32_t CLASS_NEG_ZERO = 1 << 3;
979 const uint32_t CLASS_POS_ZERO = 1 << 4;
980 const uint32_t CLASS_POS_DENORM = 1 << 5;
981 const uint32_t CLASS_POS_NORM = 1 << 6;
982 const uint32_t CLASS_POS_INF = 1 << 7;
983 const uint32_t CLASS_SNAN = 1 << 8;
984 const uint32_t CLASS_QNAN = 1 << 9;
986 int tmp = fpclassify(opa);
987 int sgn = (int)signbit(opa);
992 if (tmp == FP_INFINITE) {
993 if (sgn) { res |= CLASS_NEG_INF; }
994 else { res |= CLASS_POS_INF; }
998 if (tmp == FP_ZERO) {
999 if (sgn) { res |= CLASS_NEG_ZERO; }
1000 else { res |= CLASS_POS_ZERO; }
1004 if (tmp == FP_NORMAL) {
1005 if (sgn) { res |= CLASS_NEG_NORM; }
1006 else { res |= CLASS_POS_NORM; }
1010 if (tmp == FP_SUBNORMAL) {
1011 if (sgn) { res |= CLASS_NEG_DENORM; }
1012 else { res |= CLASS_POS_DENORM; }
1016 if (tmp == FP_NAN) {
1017 aux.float_value = opa;
1018 if ((aux.binary_value >> 22) & 0b1) {
1037float __attribute__ ((noinline)) riscv_emulate_fdivs(
float rs1,
float rs2) {
1039 float opa = subnormal_flush(rs1);
1040 float opb = subnormal_flush(rs2);
1042 float res = opa / opb;
1043 return subnormal_flush(res);
1053float __attribute__ ((noinline)) riscv_emulate_fsqrts(
float rs1) {
1055 float opa = subnormal_flush(rs1);
1057 float res = sqrtf(opa);
1058 return subnormal_flush(res);
1072float __attribute__ ((noinline)) riscv_emulate_fmadds(
float rs1,
float rs2,
float rs3) {
1074 float opa = subnormal_flush(rs1);
1075 float opb = subnormal_flush(rs2);
1076 float opc = subnormal_flush(rs3);
1078 float res = (opa * opb) + opc;
1079 return subnormal_flush(res);
1091float __attribute__ ((noinline)) riscv_emulate_fmsubs(
float rs1,
float rs2,
float rs3) {
1093 float opa = subnormal_flush(rs1);
1094 float opb = subnormal_flush(rs2);
1095 float opc = subnormal_flush(rs3);
1097 float res = (opa * opb) - opc;
1098 return subnormal_flush(res);
1110float __attribute__ ((noinline)) riscv_emulate_fnmsubs(
float rs1,
float rs2,
float rs3) {
1112 float opa = subnormal_flush(rs1);
1113 float opb = subnormal_flush(rs2);
1114 float opc = subnormal_flush(rs3);
1116 float res = -(opa * opb) + opc;
1117 return subnormal_flush(res);
1129float __attribute__ ((noinline)) riscv_emulate_fnmadds(
float rs1,
float rs2,
float rs3) {
1131 float opa = subnormal_flush(rs1);
1132 float opb = subnormal_flush(rs2);
1133 float opc = subnormal_flush(rs3);
1135 float res = -(opa * opb) - opc;
1136 return subnormal_flush(res);
uint32_t neorv32_cpu_csr_read(const int csr_id)
Definition: neorv32_cpu.h:220
void neorv32_cpu_csr_write(const int csr_id, uint32_t data)
Definition: neorv32_cpu.h:236
@ CSR_FFLAGS
Definition: neorv32_cpu_csr.h:53
Definition: neorv32_zfinx_extension_intrinsics.h:78
uint32_t binary_value
Definition: neorv32_zfinx_extension_intrinsics.h:79
float float_value
Definition: neorv32_zfinx_extension_intrinsics.h:80