diff mbox series

[v8,30/62] target/riscv: Update fp_status when float rounding mode changes

Message ID 20200521094413.10425-31-zhiwei_liu@c-sky.com
State New
Headers show
Series target/riscv: support vector extension v0.7.1 | expand

Commit Message

LIU Zhiwei May 21, 2020, 9:43 a.m. UTC
For scalar float instruction, round mode is encoded in instruction,
so fp_status is updating dynamiclly.

For vector float instruction, round mode is always frm, so
update fp_status when frm changes is enough.

Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
---
 target/riscv/csr.c        |  7 +++++++
 target/riscv/fpu_helper.c | 19 ++++++++++++++-----
 target/riscv/internals.h  |  3 +++
 3 files changed, 24 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index d71c49dfff..438093152b 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -22,6 +22,7 @@ 
 #include "cpu.h"
 #include "qemu/main-loop.h"
 #include "exec/exec-all.h"
+#include "internals.h"
 
 /* CSR function table */
 static riscv_csr_operations csr_ops[];
@@ -174,6 +175,9 @@  static int write_frm(CPURISCVState *env, int csrno, target_ulong val)
     env->mstatus |= MSTATUS_FS;
 #endif
     env->frm = val & (FSR_RD >> FSR_RD_SHIFT);
+    if (!riscv_cpu_set_rounding_mode(env, env->frm)) {
+        return -1;
+    }
     return 0;
 }
 
@@ -207,6 +211,9 @@  static int write_fcsr(CPURISCVState *env, int csrno, target_ulong val)
         env->vxsat = (val & FSR_VXSAT) >> FSR_VXSAT_SHIFT;
     }
     riscv_cpu_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
+    if (!riscv_cpu_set_rounding_mode(env, env->frm)) {
+        return -1;
+    }
     return 0;
 }
 
diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c
index 0b79562a69..262610e837 100644
--- a/target/riscv/fpu_helper.c
+++ b/target/riscv/fpu_helper.c
@@ -50,13 +50,10 @@  void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong hard)
     set_float_exception_flags(soft, &env->fp_status);
 }
 
-void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm)
+bool riscv_cpu_set_rounding_mode(CPURISCVState *env, uint32_t rm)
 {
     int softrm;
 
-    if (rm == 7) {
-        rm = env->frm;
-    }
     switch (rm) {
     case 0:
         softrm = float_round_nearest_even;
@@ -74,10 +71,22 @@  void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm)
         softrm = float_round_ties_away;
         break;
     default:
-        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+        return false;
     }
 
     set_float_rounding_mode(softrm, &env->fp_status);
+    return true;
+}
+
+void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm)
+{
+    if (rm == 7) {
+        rm = env->frm;
+    }
+
+    if (!riscv_cpu_set_rounding_mode(env, rm)) {
+        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+    }
 }
 
 uint64_t helper_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
diff --git a/target/riscv/internals.h b/target/riscv/internals.h
index f699d80c41..52f6af2513 100644
--- a/target/riscv/internals.h
+++ b/target/riscv/internals.h
@@ -27,4 +27,7 @@  FIELD(VDATA, VM, 8, 1)
 FIELD(VDATA, LMUL, 9, 2)
 FIELD(VDATA, NF, 11, 4)
 FIELD(VDATA, WD, 11, 1)
+
+/* set float rounding mode */
+bool riscv_cpu_set_rounding_mode(CPURISCVState *env, uint32_t rm);
 #endif