target/ppc: Fix carry flag setting for shift algebraic instructions

For POWER ISA v3.0, the XER bit CA32 needs to be set by the shift
right algebraic instructions whenever the CA bit is to be set. This
change affects the following instructions:
  * Shift Right Algebraic Word (sraw[.])
  * Shift Right Algebraic Word Immediate (srawi[.])
  * Shift Right Algebraic Doubleword (srad[.])
  * Shift Right Algebraic Doubleword Immediate (sradi[.])

Signed-off-by: Sandipan Das <sandipan@linux.vnet.ibm.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
Sandipan Das 2017-10-06 12:12:44 +05:30 committed by David Gibson
parent 1ed9c8af50
commit af1c259f6d
2 changed files with 20 additions and 8 deletions

View File

@ -219,17 +219,17 @@ target_ulong helper_sraw(CPUPPCState *env, target_ulong value,
shift &= 0x1f;
ret = (int32_t)value >> shift;
if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
env->ca = 0;
env->ca32 = env->ca = 0;
} else {
env->ca = 1;
env->ca32 = env->ca = 1;
}
} else {
ret = (int32_t)value;
env->ca = 0;
env->ca32 = env->ca = 0;
}
} else {
ret = (int32_t)value >> 31;
env->ca = (ret != 0);
env->ca32 = env->ca = (ret != 0);
}
return (target_long)ret;
}
@ -245,17 +245,17 @@ target_ulong helper_srad(CPUPPCState *env, target_ulong value,
shift &= 0x3f;
ret = (int64_t)value >> shift;
if (likely(ret >= 0 || (value & ((1ULL << shift) - 1)) == 0)) {
env->ca = 0;
env->ca32 = env->ca = 0;
} else {
env->ca = 1;
env->ca32 = env->ca = 1;
}
} else {
ret = (int64_t)value;
env->ca = 0;
env->ca32 = env->ca = 0;
}
} else {
ret = (int64_t)value >> 63;
env->ca = (ret != 0);
env->ca32 = env->ca = (ret != 0);
}
return ret;
}

View File

@ -2181,6 +2181,9 @@ static void gen_srawi(DisasContext *ctx)
if (sh == 0) {
tcg_gen_ext32s_tl(dst, src);
tcg_gen_movi_tl(cpu_ca, 0);
if (is_isa300(ctx)) {
tcg_gen_movi_tl(cpu_ca32, 0);
}
} else {
TCGv t0;
tcg_gen_ext32s_tl(dst, src);
@ -2190,6 +2193,9 @@ static void gen_srawi(DisasContext *ctx)
tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
tcg_temp_free(t0);
tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
if (is_isa300(ctx)) {
tcg_gen_mov_tl(cpu_ca32, cpu_ca);
}
tcg_gen_sari_tl(dst, dst, sh);
}
if (unlikely(Rc(ctx->opcode) != 0)) {
@ -2259,6 +2265,9 @@ static inline void gen_sradi(DisasContext *ctx, int n)
if (sh == 0) {
tcg_gen_mov_tl(dst, src);
tcg_gen_movi_tl(cpu_ca, 0);
if (is_isa300(ctx)) {
tcg_gen_movi_tl(cpu_ca32, 0);
}
} else {
TCGv t0;
tcg_gen_andi_tl(cpu_ca, src, (1ULL << sh) - 1);
@ -2267,6 +2276,9 @@ static inline void gen_sradi(DisasContext *ctx, int n)
tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
tcg_temp_free(t0);
tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
if (is_isa300(ctx)) {
tcg_gen_mov_tl(cpu_ca32, cpu_ca);
}
tcg_gen_sari_tl(dst, src, sh);
}
if (unlikely(Rc(ctx->opcode) != 0)) {