summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--target-ppc/cpu.h10
-rw-r--r--target-ppc/machine.c2
-rw-r--r--target-ppc/mem_helper.c5
-rw-r--r--target-ppc/translate.c6
4 files changed, 16 insertions, 7 deletions
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 9d4e43cf1f..5282533b38 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -2415,6 +2415,16 @@ static inline bool msr_is_64bit(CPUPPCState *env, target_ulong msr)
     return msr & (1ULL << MSR_SF);
 }
 
+/**
+ * Check whether register rx is in the range between start and
+ * start + nregs (as needed by the LSWX and LSWI instructions)
+ */
+static inline bool lsw_reg_in_range(int start, int nregs, int rx)
+{
+    return (start + nregs <= 32 && rx >= start && rx < start + nregs) ||
+           (start + nregs > 32 && (rx >= start || rx < start + nregs - 32));
+}
+
 extern void (*cpu_ppc_hypercall)(PowerPCCPU *);
 
 #include "exec/exec-all.h"
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index 692121e983..46684fb933 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -136,7 +136,7 @@ static void cpu_pre_save(void *opaque)
 
     env->spr[SPR_LR] = env->lr;
     env->spr[SPR_CTR] = env->ctr;
-    env->spr[SPR_XER] = env->xer;
+    env->spr[SPR_XER] = cpu_read_xer(env);
 #if defined(TARGET_PPC64)
     env->spr[SPR_CFAR] = env->cfar;
 #endif
diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c
index 581d9faa23..6d584c9126 100644
--- a/target-ppc/mem_helper.c
+++ b/target-ppc/mem_helper.c
@@ -102,8 +102,9 @@ void helper_lswx(CPUPPCState *env, target_ulong addr, uint32_t reg,
 {
     if (likely(xer_bc != 0)) {
         int num_used_regs = (xer_bc + 3) / 4;
-        if (unlikely((ra != 0 && reg < ra && (reg + num_used_regs) > ra) ||
-                     (reg < rb && (reg + num_used_regs) > rb))) {
+        if (unlikely((ra != 0 && lsw_reg_in_range(reg, num_used_regs, ra)) ||
+                     lsw_reg_in_range(reg, num_used_regs, rb))) {
+            env->nip += 4;     /* Compensate the "nip - 4" from gen_lswx() */
             helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
                                        POWERPC_EXCP_INVAL |
                                        POWERPC_EXCP_INVAL_LSWX);
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 6f0e7b4fac..b3860ecdea 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3227,10 +3227,8 @@ static void gen_lswi(DisasContext *ctx)
 
     if (nb == 0)
         nb = 32;
-    nr = nb / 4;
-    if (unlikely(((start + nr) > 32  &&
-                  start <= ra && (start + nr - 32) > ra) ||
-                 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
+    nr = (nb + 3) / 4;
+    if (unlikely(lsw_reg_in_range(start, nr, ra))) {
         gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
         return;
     }