aboutsummaryrefslogtreecommitdiff
path: root/target/ppc/cpu.c
diff options
context:
space:
mode:
authorBruno Larsen (billionai) <bruno.larsen@eldorado.org.br>2021-05-27 13:35:22 -0300
committerDavid Gibson <david@gibson.dropbear.id.au>2021-06-03 18:10:31 +1000
commitfe43ba9721f36e47e09779682c3525659c6818f0 (patch)
tree0cad3444bbc0a426961d378e07e0a4c71576b88b /target/ppc/cpu.c
parent1a1c9a00f390e236eab910fdf0ab08df0be08890 (diff)
downloadqemu-fe43ba9721f36e47e09779682c3525659c6818f0.zip
qemu-fe43ba9721f36e47e09779682c3525659c6818f0.tar.gz
qemu-fe43ba9721f36e47e09779682c3525659c6818f0.tar.bz2
target/ppc: overhauled and moved logic of storing fpscr
Followed the suggested overhaul to store_fpscr logic, and moved it to cpu.c where it can be accessed in !TCG builds. The overhaul was suggested because storing a value to fpscr should never raise an exception, so we could remove all the mess that happened with POWERPC_EXCP_FP. We also moved fpscr_set_rounding_mode into cpu.c as it could now be moved there, and it is needed when a value for the fpscr is being stored directly. Suggested-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Bruno Larsen (billionai) <bruno.larsen@eldorado.org.br> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20210527163522.23019-1-bruno.larsen@eldorado.org.br> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'target/ppc/cpu.c')
-rw-r--r--target/ppc/cpu.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/target/ppc/cpu.c b/target/ppc/cpu.c
index c8e87e3..19d67b5 100644
--- a/target/ppc/cpu.c
+++ b/target/ppc/cpu.c
@@ -25,6 +25,7 @@
#include "fpu/softfloat-helpers.h"
#include "mmu-hash64.h"
#include "helper_regs.h"
+#include "sysemu/tcg.h"
target_ulong cpu_read_xer(CPUPPCState *env)
{
@@ -109,3 +110,45 @@ void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val)
/* The gtse bit affects hflags */
hreg_compute_hflags(env);
}
+
+static inline void fpscr_set_rounding_mode(CPUPPCState *env)
+{
+ int rnd_type;
+
+ /* Set rounding mode */
+ switch (fpscr_rn) {
+ case 0:
+ /* Best approximation (round to nearest) */
+ rnd_type = float_round_nearest_even;
+ break;
+ case 1:
+ /* Smaller magnitude (round toward zero) */
+ rnd_type = float_round_to_zero;
+ break;
+ case 2:
+ /* Round toward +infinite */
+ rnd_type = float_round_up;
+ break;
+ default:
+ case 3:
+ /* Round toward -infinite */
+ rnd_type = float_round_down;
+ break;
+ }
+ set_float_rounding_mode(rnd_type, &env->fp_status);
+}
+
+void ppc_store_fpscr(CPUPPCState *env, target_ulong val)
+{
+ val &= ~(FP_VX | FP_FEX);
+ if (val & FPSCR_IX) {
+ val |= FP_VX;
+ }
+ if ((val >> FPSCR_XX) & (val >> FPSCR_XE) & 0x1f) {
+ val |= FP_FEX;
+ }
+ env->fpscr = val;
+ if (tcg_enabled()) {
+ fpscr_set_rounding_mode(env);
+ }
+}