Skip to content

Commit 04ce561

Browse files
authored
Use interger shortcut in floating point routines (#109)
This commit makes sure that we don't use memcpy but instead the F_int shortcut. FEQ.S/FLT.S/FLE.S are now working properly.
1 parent ca4c361 commit 04ce561

File tree

1 file changed

+51
-47
lines changed

1 file changed

+51
-47
lines changed

src/emulate.c

Lines changed: 51 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -821,14 +821,13 @@ RVOP(amomaxuw, {
821821
RVOP(flw, {
822822
/* copy into the float register */
823823
const uint32_t data = rv->io.mem_read_w(rv, rv->X[ir->rs1] + ir->imm);
824-
memcpy(rv->F + ir->rd, &data, 4);
824+
rv->F_int[ir->rd] = data;
825825
})
826826

827827
/* FSW */
828828
RVOP(fsw, {
829829
/* copy from float registers */
830-
uint32_t data;
831-
memcpy(&data, (const void *) (rv->F + ir->rs2), 4);
830+
uint32_t data = rv->F_int[ir->rs2];
832831
rv->io.mem_write_w(rv, rv->X[ir->rs1] + ir->imm, data);
833832
})
834833

@@ -884,35 +883,29 @@ RVOP(fsqrts, { rv->F[ir->rd] = sqrtf(rv->F[ir->rs1]); })
884883

885884
/* FSGNJ.S */
886885
RVOP(fsgnjs, {
887-
uint32_t f1;
888-
uint32_t f2;
886+
uint32_t f1 = rv->F_int[ir->rs1];
887+
uint32_t f2 = rv->F_int[ir->rs2];
889888
uint32_t res;
890-
memcpy(&f1, rv->F + ir->rs1, 4);
891-
memcpy(&f2, rv->F + ir->rs2, 4);
892889
res = (f1 & ~FMASK_SIGN) | (f2 & FMASK_SIGN);
893-
memcpy(rv->F + ir->rd, &res, 4);
890+
rv->F_int[ir->rd] = res;
894891
})
895892

896893
/* FSGNJN.S */
897894
RVOP(fsgnjns, {
898-
uint32_t f1;
899-
uint32_t f2;
895+
uint32_t f1 = rv->F_int[ir->rs1];
896+
uint32_t f2 = rv->F_int[ir->rs2];
900897
uint32_t res;
901-
memcpy(&f1, rv->F + ir->rs1, 4);
902-
memcpy(&f2, rv->F + ir->rs2, 4);
903898
res = (f1 & ~FMASK_SIGN) | (~f2 & FMASK_SIGN);
904-
memcpy(rv->F + ir->rd, &res, 4);
899+
rv->F_int[ir->rd] = res;
905900
})
906901

907902
/* FSGNJX.S */
908903
RVOP(fsgnjxs, {
909-
uint32_t f1;
910-
uint32_t f2;
904+
uint32_t f1 = rv->F_int[ir->rs1];
905+
uint32_t f2 = rv->F_int[ir->rs2];
911906
uint32_t res;
912-
memcpy(&f1, rv->F + ir->rs1, 4);
913-
memcpy(&f2, rv->F + ir->rs2, 4);
914907
res = f1 ^ (f2 & FMASK_SIGN);
915-
memcpy(rv->F + ir->rd, &res, 4);
908+
rv->F_int[ir->rd] = res;
916909
})
917910

918911
/* FMIN.S
@@ -923,25 +916,23 @@ RVOP(fsgnjxs, {
923916
* When input is signaling NaN, raise invalid operation
924917
*/
925918
RVOP(fmins, {
926-
uint32_t x;
927-
uint32_t y;
928-
memcpy(&x, rv->F + ir->rs1, 4);
929-
memcpy(&y, rv->F + ir->rs2, 4);
930-
if (is_nan(x) || is_nan(y)) {
931-
if (is_snan(x) || is_snan(y))
919+
uint32_t a = rv->F_int[ir->rs1];
920+
uint32_t b = rv->F_int[ir->rs2];
921+
if (is_nan(a) || is_nan(b)) {
922+
if (is_snan(a) || is_snan(b))
932923
rv->csr_fcsr |= FFLAG_INVALID_OP;
933-
if (is_nan(x) && !is_nan(y)) {
924+
if (is_nan(a) && !is_nan(b)) {
934925
rv->F[ir->rd] = rv->F[ir->rs2];
935-
} else if (!is_nan(x) && is_nan(y)) {
926+
} else if (!is_nan(a) && is_nan(b)) {
936927
rv->F[ir->rd] = rv->F[ir->rs1];
937928
} else {
938929
rv->F_int[ir->rd] = RV_NAN;
939930
}
940931
} else {
941932
uint32_t a_sign;
942933
uint32_t b_sign;
943-
a_sign = x & FMASK_SIGN;
944-
b_sign = y & FMASK_SIGN;
934+
a_sign = a & FMASK_SIGN;
935+
b_sign = b & FMASK_SIGN;
945936
if (a_sign != b_sign) {
946937
rv->F[ir->rd] = a_sign ? rv->F[ir->rs1] : rv->F[ir->rs2];
947938
} else {
@@ -953,25 +944,23 @@ RVOP(fmins, {
953944

954945
/* FMAX.S */
955946
RVOP(fmaxs, {
956-
uint32_t x;
957-
uint32_t y;
958-
memcpy(&x, rv->F + ir->rs1, 4);
959-
memcpy(&y, rv->F + ir->rs2, 4);
960-
if (is_nan(x) || is_nan(y)) {
961-
if (is_snan(x) || is_snan(y))
947+
uint32_t a = rv->F_int[ir->rs1];
948+
uint32_t b = rv->F_int[ir->rs2];
949+
if (is_nan(a) || is_nan(b)) {
950+
if (is_snan(a) || is_snan(b))
962951
rv->csr_fcsr |= FFLAG_INVALID_OP;
963-
if (is_nan(x) && !is_nan(y)) {
952+
if (is_nan(a) && !is_nan(b)) {
964953
rv->F[ir->rd] = rv->F[ir->rs2];
965-
} else if (!is_nan(x) && is_nan(y)) {
954+
} else if (!is_nan(a) && is_nan(b)) {
966955
rv->F[ir->rd] = rv->F[ir->rs1];
967956
} else {
968957
rv->F_int[ir->rd] = RV_NAN;
969958
}
970959
} else {
971960
uint32_t a_sign;
972961
uint32_t b_sign;
973-
a_sign = x & FMASK_SIGN;
974-
b_sign = y & FMASK_SIGN;
962+
a_sign = a & FMASK_SIGN;
963+
b_sign = b & FMASK_SIGN;
975964
if (a_sign != b_sign) {
976965
rv->F[ir->rd] = a_sign ? rv->F[ir->rs2] : rv->F[ir->rs1];
977966
} else {
@@ -981,43 +970,58 @@ RVOP(fmaxs, {
981970
}
982971
})
983972

973+
/* FCVT.W.S and FCVT.WU.S convert a floating point number
974+
* to an integer, the rounding mode is specified in rm field.
975+
*/
976+
984977
/* FCVT.W.S */
985978
RVOP(fcvtws, { rv->X[ir->rd] = (int32_t) rv->F[ir->rs1]; })
986979

987980
/* FCVT.WU.S */
988981
RVOP(fcvtwus, { rv->X[ir->rd] = (uint32_t) rv->F[ir->rs1]; })
989982

990983
/* FMV.X.W */
991-
RVOP(fmvxw, { memcpy(rv->X + ir->rd, rv->F + ir->rs1, 4); })
984+
RVOP(fmvxw, { rv->X[ir->rd] = rv->F_int[ir->rs1]; })
992985

993986
/* FEQ.S performs a quiet comparison: it only sets the invalid
994987
* operation exception flag if either input is a signaling NaN.
995988
*/
996-
RVOP(feqs, { rv->X[ir->rd] = (rv->F[ir->rs1] == rv->F[ir->rs2]) ? 1 : 0; })
989+
RVOP(feqs, {
990+
rv->X[ir->rd] = (rv->F[ir->rs1] == rv->F[ir->rs2]) ? 1 : 0;
991+
if (is_snan(rv->F_int[ir->rs1]) || is_snan(rv->F_int[ir->rs2]))
992+
rv->csr_fcsr |= FFLAG_INVALID_OP;
993+
})
997994

998995
/* FLT.S and FLE.S perform what the IEEE 754-2008 standard refers
999996
* to as signaling comparisons: that is, they set the invalid
1000997
* operation exception flag if either input is NaN.
1001998
*/
1002-
RVOP(flts, { rv->X[ir->rd] = (rv->F[ir->rs1] < rv->F[ir->rs2]) ? 1 : 0; })
999+
RVOP(flts, {
1000+
rv->X[ir->rd] = (rv->F[ir->rs1] < rv->F[ir->rs2]) ? 1 : 0;
1001+
if (is_nan(rv->F_int[ir->rs1]) || is_nan(rv->F_int[ir->rs2]))
1002+
rv->csr_fcsr |= FFLAG_INVALID_OP;
1003+
})
10031004

1004-
RVOP(fles, { rv->X[ir->rd] = (rv->F[ir->rs1] <= rv->F[ir->rs2]) ? 1 : 0; })
1005+
RVOP(fles, {
1006+
rv->X[ir->rd] = (rv->F[ir->rs1] <= rv->F[ir->rs2]) ? 1 : 0;
1007+
if (is_nan(rv->F_int[ir->rs1]) || is_nan(rv->F_int[ir->rs2]))
1008+
rv->csr_fcsr |= FFLAG_INVALID_OP;
1009+
})
10051010

10061011
/* FCLASS.S */
10071012
RVOP(fclasss, {
1008-
uint32_t bits;
1009-
memcpy(&bits, rv->F + ir->rs1, 4);
1013+
uint32_t bits = rv->F_int[ir->rs1];
10101014
rv->X[ir->rd] = calc_fclass(bits);
10111015
})
10121016

10131017
/* FCVT.S.W */
1014-
RVOP(fcvtsw, { rv->F[ir->rd] = (float) (int32_t) rv->X[ir->rs1]; })
1018+
RVOP(fcvtsw, { rv->F_int[ir->rd] = rv->X[ir->rs1]; })
10151019

10161020
/* FCVT.S.WU */
1017-
RVOP(fcvtswu, { rv->F[ir->rd] = (float) (uint32_t) rv->X[ir->rs1]; })
1021+
RVOP(fcvtswu, { rv->F_int[ir->rd] = rv->X[ir->rs1]; })
10181022

10191023
/* FMV.W.X */
1020-
RVOP(fmvwx, { memcpy(rv->F + ir->rd, rv->X + ir->rs1, 4); })
1024+
RVOP(fmvwx, { rv->F_int[ir->rd] = rv->X[ir->rs1]; })
10211025
#endif
10221026

10231027
#if RV32_HAS(EXT_C) /* RV32C Standard Extension */

0 commit comments

Comments
 (0)