aboutsummaryrefslogtreecommitdiff
path: root/machine/fp_emulation.c
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2018-07-11 01:16:28 -0700
committerAndrew Waterman <andrew@sifive.com>2018-07-11 01:16:28 -0700
commit5cd8d2b93fad2011fdf8f49a263d77697af35b32 (patch)
treef6fb9cb6d3bef2aa5c9903511b92e5a6e99e9519 /machine/fp_emulation.c
parent8e69141749065ff957383d2112768f95a33429b6 (diff)
downloadriscv-pk-5cd8d2b93fad2011fdf8f49a263d77697af35b32.zip
riscv-pk-5cd8d2b93fad2011fdf8f49a263d77697af35b32.tar.gz
riscv-pk-5cd8d2b93fad2011fdf8f49a263d77697af35b32.tar.bz2
Upgrade to SoftFloat 3e
Diffstat (limited to 'machine/fp_emulation.c')
-rw-r--r--machine/fp_emulation.c63
1 files changed, 34 insertions, 29 deletions
diff --git a/machine/fp_emulation.c b/machine/fp_emulation.c
index 6a0caec..8c40f61 100644
--- a/machine/fp_emulation.c
+++ b/machine/fp_emulation.c
@@ -3,6 +3,7 @@
#include "fp_emulation.h"
#include "unprivileged_memory.h"
#include "softfloat.h"
+#include "internals.h"
#include "config.h"
DECLARE_EMULATION_FUNC(emulate_fp)
@@ -55,16 +56,19 @@ DECLARE_EMULATION_FUNC(emulate_fp)
return f(regs, mcause, mepc, mstatus, insn);
}
+#define f32(x) ((float32_t){ .v = x })
+#define f64(x) ((float64_t){ .v = x })
+
void emulate_any_fadd(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc, uintptr_t mstatus, insn_t insn, int32_t neg_b)
{
if (GET_PRECISION(insn) == PRECISION_S) {
uint32_t rs1 = GET_F32_RS1(insn, regs);
uint32_t rs2 = GET_F32_RS2(insn, regs) ^ neg_b;
- SET_F32_RD(insn, regs, f32_add(rs1, rs2));
+ SET_F32_RD(insn, regs, f32_add(f32(rs1), f32(rs2)).v);
} else if (GET_PRECISION(insn) == PRECISION_D) {
uint64_t rs1 = GET_F64_RS1(insn, regs);
uint64_t rs2 = GET_F64_RS2(insn, regs) ^ ((uint64_t)neg_b << 32);
- SET_F64_RD(insn, regs, f64_add(rs1, rs2));
+ SET_F64_RD(insn, regs, f64_add(f64(rs1), f64(rs2)).v);
} else {
return truly_illegal_insn(regs, mcause, mepc, mstatus, insn);
}
@@ -85,11 +89,11 @@ DECLARE_EMULATION_FUNC(emulate_fmul)
if (GET_PRECISION(insn) == PRECISION_S) {
uint32_t rs1 = GET_F32_RS1(insn, regs);
uint32_t rs2 = GET_F32_RS2(insn, regs);
- SET_F32_RD(insn, regs, f32_mul(rs1, rs2));
+ SET_F32_RD(insn, regs, f32_mul(f32(rs1), f32(rs2)).v);
} else if (GET_PRECISION(insn) == PRECISION_D) {
uint64_t rs1 = GET_F64_RS1(insn, regs);
uint64_t rs2 = GET_F64_RS2(insn, regs);
- SET_F64_RD(insn, regs, f64_mul(rs1, rs2));
+ SET_F64_RD(insn, regs, f64_mul(f64(rs1), f64(rs2)).v);
} else {
return truly_illegal_insn(regs, mcause, mepc, mstatus, insn);
}
@@ -100,11 +104,11 @@ DECLARE_EMULATION_FUNC(emulate_fdiv)
if (GET_PRECISION(insn) == PRECISION_S) {
uint32_t rs1 = GET_F32_RS1(insn, regs);
uint32_t rs2 = GET_F32_RS2(insn, regs);
- SET_F32_RD(insn, regs, f32_div(rs1, rs2));
+ SET_F32_RD(insn, regs, f32_div(f32(rs1), f32(rs2)).v);
} else if (GET_PRECISION(insn) == PRECISION_D) {
uint64_t rs1 = GET_F64_RS1(insn, regs);
uint64_t rs2 = GET_F64_RS2(insn, regs);
- SET_F64_RD(insn, regs, f64_div(rs1, rs2));
+ SET_F64_RD(insn, regs, f64_div(f64(rs1), f64(rs2)).v);
} else {
return truly_illegal_insn(regs, mcause, mepc, mstatus, insn);
}
@@ -116,9 +120,9 @@ DECLARE_EMULATION_FUNC(emulate_fsqrt)
return truly_illegal_insn(regs, mcause, mepc, mstatus, insn);
if (GET_PRECISION(insn) == PRECISION_S) {
- SET_F32_RD(insn, regs, f32_sqrt(GET_F32_RS1(insn, regs)));
+ SET_F32_RD(insn, regs, f32_sqrt(f32(GET_F32_RS1(insn, regs))).v);
} else if (GET_PRECISION(insn) == PRECISION_D) {
- SET_F64_RD(insn, regs, f64_sqrt(GET_F64_RS1(insn, regs)));
+ SET_F64_RD(insn, regs, f64_sqrt(f64(GET_F64_RS1(insn, regs))).v);
} else {
return truly_illegal_insn(regs, mcause, mepc, mstatus, insn);
}
@@ -161,14 +165,14 @@ DECLARE_EMULATION_FUNC(emulate_fmin)
uint32_t rs2 = GET_F32_RS2(insn, regs);
uint32_t arg1 = rm ? rs2 : rs1;
uint32_t arg2 = rm ? rs1 : rs2;
- int use_rs1 = f32_lt_quiet(arg1, arg2) || isNaNF32UI(rs2);
+ int use_rs1 = f32_lt_quiet(f32(arg1), f32(arg2)) || isNaNF32UI(rs2);
SET_F32_RD(insn, regs, use_rs1 ? rs1 : rs2);
} else if (GET_PRECISION(insn) == PRECISION_D) {
uint64_t rs1 = GET_F64_RS1(insn, regs);
uint64_t rs2 = GET_F64_RS2(insn, regs);
uint64_t arg1 = rm ? rs2 : rs1;
uint64_t arg2 = rm ? rs1 : rs2;
- int use_rs1 = f64_lt_quiet(arg1, arg2) || isNaNF64UI(rs2);
+ int use_rs1 = f64_lt_quiet(f64(arg1), f64(arg2)) || isNaNF64UI(rs2);
SET_F64_RD(insn, regs, use_rs1 ? rs1 : rs2);
} else {
return truly_illegal_insn(regs, mcause, mepc, mstatus, insn);
@@ -181,11 +185,11 @@ DECLARE_EMULATION_FUNC(emulate_fcvt_ff)
if (GET_PRECISION(insn) == PRECISION_S) {
if (rs2_num != 1)
return truly_illegal_insn(regs, mcause, mepc, mstatus, insn);
- SET_F32_RD(insn, regs, f64_to_f32(GET_F64_RS1(insn, regs)));
+ SET_F32_RD(insn, regs, f64_to_f32(f64(GET_F64_RS1(insn, regs))).v);
} else if (GET_PRECISION(insn) == PRECISION_D) {
if (rs2_num != 0)
return truly_illegal_insn(regs, mcause, mepc, mstatus, insn);
- SET_F64_RD(insn, regs, f32_to_f64(GET_F32_RS1(insn, regs)));
+ SET_F64_RD(insn, regs, f32_to_f64(f32(GET_F32_RS1(insn, regs))).v);
} else {
return truly_illegal_insn(regs, mcause, mepc, mstatus, insn);
}
@@ -219,12 +223,12 @@ DECLARE_EMULATION_FUNC(emulate_fcvt_fi)
return truly_illegal_insn(regs, mcause, mepc, mstatus, insn);
}
- uint64_t float64 = ui64_to_f64(uint_val);
+ uint64_t float64 = ui64_to_f64(uint_val).v;
if (negative)
float64 ^= INT64_MIN;
if (GET_PRECISION(insn) == PRECISION_S)
- SET_F32_RD(insn, regs, f64_to_f32(float64));
+ SET_F32_RD(insn, regs, f64_to_f32(f64(float64)).v);
else
SET_F64_RD(insn, regs, float64);
}
@@ -242,7 +246,7 @@ DECLARE_EMULATION_FUNC(emulate_fcvt_if)
int64_t float64;
if (GET_PRECISION(insn) == PRECISION_S)
- float64 = f32_to_f64(GET_F32_RS1(insn, regs));
+ float64 = f32_to_f64(f32(GET_F32_RS1(insn, regs))).v;
else if (GET_PRECISION(insn) == PRECISION_D)
float64 = GET_F64_RS1(insn, regs);
else
@@ -253,7 +257,7 @@ DECLARE_EMULATION_FUNC(emulate_fcvt_if)
negative = 1;
float64 ^= INT64_MIN;
}
- uint64_t uint_val = f64_to_ui64(float64, softfloat_roundingMode, true);
+ uint64_t uint_val = f64_to_ui64(f64(float64), softfloat_roundingMode, true);
uint64_t result, limit, limit_result;
switch (rs2_num)
@@ -318,17 +322,17 @@ DECLARE_EMULATION_FUNC(emulate_fcmp)
uint32_t rs1 = GET_F32_RS1(insn, regs);
uint32_t rs2 = GET_F32_RS2(insn, regs);
if (rm != 1)
- result = f32_eq(rs1, rs2);
+ result = f32_eq(f32(rs1), f32(rs2));
if (rm == 1 || (rm == 0 && !result))
- result = f32_lt(rs1, rs2);
+ result = f32_lt(f32(rs1), f32(rs2));
goto success;
} else if (GET_PRECISION(insn) == PRECISION_D) {
uint64_t rs1 = GET_F64_RS1(insn, regs);
uint64_t rs2 = GET_F64_RS2(insn, regs);
if (rm != 1)
- result = f64_eq(rs1, rs2);
+ result = f64_eq(f64(rs1), f64(rs2));
if (rm == 1 || (rm == 0 && !result))
- result = f64_lt(rs1, rs2);
+ result = f64_lt(f64(rs1), f64(rs2));
goto success;
}
return truly_illegal_insn(regs, mcause, mepc, mstatus, insn);
@@ -347,14 +351,14 @@ DECLARE_EMULATION_FUNC(emulate_fmv_if)
result = GET_F32_RS1(insn, regs);
switch (GET_RM(insn)) {
case GET_RM(MATCH_FMV_X_W): break;
- case GET_RM(MATCH_FCLASS_S): result = f32_classify(result); break;
+ case GET_RM(MATCH_FCLASS_S): result = f32_classify(f32(result)); break;
default: return truly_illegal_insn(regs, mcause, mepc, mstatus, insn);
}
} else if (GET_PRECISION(insn) == PRECISION_D) {
result = GET_F64_RS1(insn, regs);
switch (GET_RM(insn)) {
case GET_RM(MATCH_FMV_X_D): break;
- case GET_RM(MATCH_FCLASS_D): result = f64_classify(result); break;
+ case GET_RM(MATCH_FCLASS_D): result = f64_classify(f64(result)); break;
default: return truly_illegal_insn(regs, mcause, mepc, mstatus, insn);
}
} else {
@@ -385,18 +389,19 @@ DECLARE_EMULATION_FUNC(emulate_fmadd)
if (unlikely((mstatus & MSTATUS_FS) == 0))
return truly_illegal_insn(regs, mcause, mepc, mstatus, insn);
- int op = (insn >> 2) & 3;
+ bool negA = (insn >> 3) & 1;
+ bool negC = (insn >> 2) & 1;
SETUP_STATIC_ROUNDING(insn);
if (GET_PRECISION(insn) == PRECISION_S) {
- uint32_t rs1 = GET_F32_RS1(insn, regs);
+ uint32_t rs1 = GET_F32_RS1(insn, regs) ^ (negA ? INT32_MIN : 0);
uint32_t rs2 = GET_F32_RS2(insn, regs);
- uint32_t rs3 = GET_F32_RS3(insn, regs);
- SET_F32_RD(insn, regs, softfloat_mulAddF32(op, rs1, rs2, rs3));
+ uint32_t rs3 = GET_F32_RS3(insn, regs) ^ (negC ? INT32_MIN : 0);
+ SET_F32_RD(insn, regs, softfloat_mulAddF32(rs1, rs2, rs3, 0).v);
} else if (GET_PRECISION(insn) == PRECISION_D) {
- uint64_t rs1 = GET_F64_RS1(insn, regs);
+ uint64_t rs1 = GET_F64_RS1(insn, regs) ^ (negA ? INT64_MIN : 0);
uint64_t rs2 = GET_F64_RS2(insn, regs);
- uint64_t rs3 = GET_F64_RS3(insn, regs);
- SET_F64_RD(insn, regs, softfloat_mulAddF64(op, rs1, rs2, rs3));
+ uint64_t rs3 = GET_F64_RS3(insn, regs) ^ (negC ? INT64_MIN : 0);
+ SET_F64_RD(insn, regs, softfloat_mulAddF64(rs1, rs2, rs3, 0).v);
} else {
return truly_illegal_insn(regs, mcause, mepc, mstatus, insn);
}