52#ifndef neorv32_zfinx_extension_intrinsics_h
53#define neorv32_zfinx_extension_intrinsics_h
67#if defined __riscv_f || (__riscv_flen == 32)
68 #error Application programs using the Zfinx intrinsic library have to be compiled WITHOUT the <F> MARCH ISA attribute!
94float subnormal_flush(
float tmp) {
99 if (fpclassify(tmp) == FP_SUBNORMAL) {
100 if (signbit(tmp) != 0) {
121uint32_t get_hw_exceptions(
void) {
142inline float __attribute__ ((always_inline)) riscv_intrinsic_fadds(
float rs1,
float rs2) {
160inline float __attribute__ ((always_inline)) riscv_intrinsic_fsubs(
float rs1,
float rs2) {
178inline float __attribute__ ((always_inline)) riscv_intrinsic_fmuls(
float rs1,
float rs2) {
196inline float __attribute__ ((always_inline)) riscv_intrinsic_fmins(
float rs1,
float rs2) {
214inline float __attribute__ ((always_inline)) riscv_intrinsic_fmaxs(
float rs1,
float rs2) {
231inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_fcvt_wus(
float rs1) {
236 return CUSTOM_INSTR_R2_TYPE(0b1100000, 0b00001, opa.
binary_value, 0b000, 0b1010011);
246inline int32_t __attribute__ ((always_inline)) riscv_intrinsic_fcvt_ws(
float rs1) {
251 return (int32_t)CUSTOM_INSTR_R2_TYPE(0b1100000, 0b00000, opa.
binary_value, 0b000, 0b1010011);
261inline float __attribute__ ((always_inline)) riscv_intrinsic_fcvt_swu(uint32_t rs1) {
265 res.
binary_value = CUSTOM_INSTR_R2_TYPE(0b1101000, 0b00001, rs1, 0b000, 0b1010011);
276inline float __attribute__ ((always_inline)) riscv_intrinsic_fcvt_sw(int32_t rs1) {
280 res.
binary_value = CUSTOM_INSTR_R2_TYPE(0b1101000, 0b00000, rs1, 0b000, 0b1010011);
292inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_feqs(
float rs1,
float rs2) {
309inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_flts(
float rs1,
float rs2) {
326inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_fles(
float rs1,
float rs2) {
343inline float __attribute__ ((always_inline)) riscv_intrinsic_fsgnjs(
float rs1,
float rs2) {
361inline float __attribute__ ((always_inline)) riscv_intrinsic_fsgnjns(
float rs1,
float rs2) {
379inline float __attribute__ ((always_inline)) riscv_intrinsic_fsgnjxs(
float rs1,
float rs2) {
396inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_fclasss(
float rs1) {
401 return CUSTOM_INSTR_R2_TYPE(0b1110000, 0b00000, opa.
binary_value, 0b001, 0b1010011);
418inline float __attribute__ ((always_inline)) riscv_intrinsic_fdivs(
float rs1,
float rs2) {
437inline float __attribute__ ((always_inline)) riscv_intrinsic_fsqrts(
float rs1) {
457inline float __attribute__ ((always_inline)) riscv_intrinsic_fmadds(
float rs1,
float rs2,
float rs3) {
479inline float __attribute__ ((always_inline)) riscv_intrinsic_fmsubs(
float rs1,
float rs2,
float rs3) {
501inline float __attribute__ ((always_inline)) riscv_intrinsic_fnmsubs(
float rs1,
float rs2,
float rs3) {
523inline float __attribute__ ((always_inline)) riscv_intrinsic_fnmadds(
float rs1,
float rs2,
float rs3) {
546float __attribute__ ((noinline)) riscv_emulate_fadds(
float rs1,
float rs2) {
548 float opa = subnormal_flush(rs1);
549 float opb = subnormal_flush(rs2);
551 float res = opa + opb;
554 if (fpclassify(res) == FP_NAN) {
558 return subnormal_flush(res);
569float __attribute__ ((noinline)) riscv_emulate_fsubs(
float rs1,
float rs2) {
571 float opa = subnormal_flush(rs1);
572 float opb = subnormal_flush(rs2);
574 float res = opa - opb;
577 if (fpclassify(res) == FP_NAN) {
581 return subnormal_flush(res);
592float __attribute__ ((noinline)) riscv_emulate_fmuls(
float rs1,
float rs2) {
594 float opa = subnormal_flush(rs1);
595 float opb = subnormal_flush(rs2);
597 float res = opa * opb;
598 return subnormal_flush(res);
609float __attribute__ ((noinline)) riscv_emulate_fmins(
float rs1,
float rs2) {
611 float opa = subnormal_flush(rs1);
612 float opb = subnormal_flush(rs2);
615 uint32_t binary_value;
619 if ((fpclassify(opa) == FP_NAN) && (fpclassify(opb) == FP_NAN)) {
623 if (fpclassify(opa) == FP_NAN) {
627 if (fpclassify(opb) == FP_NAN) {
632 tmp_a.float_value = opa;
633 tmp_b.float_value = opb;
634 if (((tmp_a.binary_value == 0x80000000) && (tmp_b.binary_value == 0x00000000)) ||
635 ((tmp_a.binary_value == 0x00000000) && (tmp_b.binary_value == 0x80000000))) {
639 return fmin(opa, opb);
650float __attribute__ ((noinline)) riscv_emulate_fmaxs(
float rs1,
float rs2) {
652 float opa = subnormal_flush(rs1);
653 float opb = subnormal_flush(rs2);
656 uint32_t binary_value;
661 if ((fpclassify(opa) == FP_NAN) && (fpclassify(opb) == FP_NAN)) {
665 if (fpclassify(opa) == FP_NAN) {
669 if (fpclassify(opb) == FP_NAN) {
674 tmp_a.float_value = opa;
675 tmp_b.float_value = opb;
676 if (((tmp_a.binary_value == 0x80000000) && (tmp_b.binary_value == 0x00000000)) ||
677 ((tmp_a.binary_value == 0x00000000) && (tmp_b.binary_value == 0x80000000))) {
681 return fmax(opa, opb);
691uint32_t __attribute__ ((noinline)) riscv_emulate_fcvt_wus(
float rs1) {
693 float opa = subnormal_flush(rs1);
695 return (uint32_t)roundf(opa);
705int32_t __attribute__ ((noinline)) riscv_emulate_fcvt_ws(
float rs1) {
707 float opa = subnormal_flush(rs1);
709 return (int32_t)roundf(opa);
719float __attribute__ ((noinline)) riscv_emulate_fcvt_swu(uint32_t rs1) {
731float __attribute__ ((noinline)) riscv_emulate_fcvt_sw(int32_t rs1) {
744uint32_t __attribute__ ((noinline)) riscv_emulate_feqs(
float rs1,
float rs2) {
746 float opa = subnormal_flush(rs1);
747 float opb = subnormal_flush(rs2);
749 if ((fpclassify(opa) == FP_NAN) || (fpclassify(opb) == FP_NAN)) {
753 if isless(opa, opb) {
756 else if isgreater(opa, opb) {
772uint32_t __attribute__ ((noinline)) riscv_emulate_flts(
float rs1,
float rs2) {
774 float opa = subnormal_flush(rs1);
775 float opb = subnormal_flush(rs2);
777 if ((fpclassify(opa) == FP_NAN) || (fpclassify(opb) == FP_NAN)) {
781 if isless(opa, opb) {
797uint32_t __attribute__ ((noinline)) riscv_emulate_fles(
float rs1,
float rs2) {
799 float opa = subnormal_flush(rs1);
800 float opb = subnormal_flush(rs2);
802 if ((fpclassify(opa) == FP_NAN) || (fpclassify(opb) == FP_NAN)) {
806 if islessequal(opa, opb) {
822float __attribute__ ((noinline)) riscv_emulate_fsgnjs(
float rs1,
float rs2) {
824 float opa = subnormal_flush(rs1);
825 float opb = subnormal_flush(rs2);
827 int sign_1 = (int)signbit(opa);
828 int sign_2 = (int)signbit(opb);
859float __attribute__ ((noinline)) riscv_emulate_fsgnjns(
float rs1,
float rs2) {
861 float opa = subnormal_flush(rs1);
862 float opb = subnormal_flush(rs2);
864 int sign_1 = (int)signbit(opa);
865 int sign_2 = (int)signbit(opb);
896float __attribute__ ((noinline)) riscv_emulate_fsgnjxs(
float rs1,
float rs2) {
898 float opa = subnormal_flush(rs1);
899 float opb = subnormal_flush(rs2);
901 int sign_1 = (int)signbit(opa);
902 int sign_2 = (int)signbit(opb);
905 if (((sign_1 == 0) && (sign_2 != 0)) || ((sign_1 != 0) && (sign_2 == 0))) {
932uint32_t __attribute__ ((noinline)) riscv_emulate_fclasss(
float rs1) {
934 float opa = subnormal_flush(rs1);
937 uint32_t binary_value;
942 const uint32_t CLASS_NEG_INF = 1 << 0;
943 const uint32_t CLASS_NEG_NORM = 1 << 1;
944 const uint32_t CLASS_NEG_DENORM = 1 << 2;
945 const uint32_t CLASS_NEG_ZERO = 1 << 3;
946 const uint32_t CLASS_POS_ZERO = 1 << 4;
947 const uint32_t CLASS_POS_DENORM = 1 << 5;
948 const uint32_t CLASS_POS_NORM = 1 << 6;
949 const uint32_t CLASS_POS_INF = 1 << 7;
950 const uint32_t CLASS_SNAN = 1 << 8;
951 const uint32_t CLASS_QNAN = 1 << 9;
953 int tmp = fpclassify(opa);
954 int sgn = (int)signbit(opa);
959 if (tmp == FP_INFINITE) {
960 if (sgn) { res |= CLASS_NEG_INF; }
961 else { res |= CLASS_POS_INF; }
965 if (tmp == FP_ZERO) {
966 if (sgn) { res |= CLASS_NEG_ZERO; }
967 else { res |= CLASS_POS_ZERO; }
971 if (tmp == FP_NORMAL) {
972 if (sgn) { res |= CLASS_NEG_NORM; }
973 else { res |= CLASS_POS_NORM; }
977 if (tmp == FP_SUBNORMAL) {
978 if (sgn) { res |= CLASS_NEG_DENORM; }
979 else { res |= CLASS_POS_DENORM; }
984 aux.float_value = opa;
985 if ((aux.binary_value >> 22) & 0b1) {
1004float __attribute__ ((noinline)) riscv_emulate_fdivs(
float rs1,
float rs2) {
1006 float opa = subnormal_flush(rs1);
1007 float opb = subnormal_flush(rs2);
1009 float res = opa / opb;
1010 return subnormal_flush(res);
1020float __attribute__ ((noinline)) riscv_emulate_fsqrts(
float rs1) {
1022 float opa = subnormal_flush(rs1);
1024 float res = sqrtf(opa);
1025 return subnormal_flush(res);
1039float __attribute__ ((noinline)) riscv_emulate_fmadds(
float rs1,
float rs2,
float rs3) {
1041 float opa = subnormal_flush(rs1);
1042 float opb = subnormal_flush(rs2);
1043 float opc = subnormal_flush(rs3);
1045 float res = (opa * opb) + opc;
1046 return subnormal_flush(res);
1058float __attribute__ ((noinline)) riscv_emulate_fmsubs(
float rs1,
float rs2,
float rs3) {
1060 float opa = subnormal_flush(rs1);
1061 float opb = subnormal_flush(rs2);
1062 float opc = subnormal_flush(rs3);
1064 float res = (opa * opb) - opc;
1065 return subnormal_flush(res);
1077float __attribute__ ((noinline)) riscv_emulate_fnmsubs(
float rs1,
float rs2,
float rs3) {
1079 float opa = subnormal_flush(rs1);
1080 float opb = subnormal_flush(rs2);
1081 float opc = subnormal_flush(rs3);
1083 float res = -(opa * opb) + opc;
1084 return subnormal_flush(res);
1096float __attribute__ ((noinline)) riscv_emulate_fnmadds(
float rs1,
float rs2,
float rs3) {
1098 float opa = subnormal_flush(rs1);
1099 float opb = subnormal_flush(rs2);
1100 float opc = subnormal_flush(rs3);
1102 float res = -(opa * opb) - opc;
1103 return subnormal_flush(res);
uint32_t neorv32_cpu_csr_read(const int csr_id)
Definition neorv32_cpu.h:172
void neorv32_cpu_csr_write(const int csr_id, uint32_t data)
Definition neorv32_cpu.h:186
@ CSR_FFLAGS
Definition neorv32_cpu_csr.h:25
Definition neorv32_zfinx_extension_intrinsics.h:76
uint32_t binary_value
Definition neorv32_zfinx_extension_intrinsics.h:77
float float_value
Definition neorv32_zfinx_extension_intrinsics.h:78