summaryrefslogtreecommitdiff
path: root/target-ppc
diff options
context:
space:
mode:
authorTom Musta <tommusta@gmail.com>2014-11-12 15:46:00 -0600
committerAlexander Graf <agraf@suse.de>2015-01-07 16:16:25 +0100
commit4814f2d116c057d6fdfd57f3b979c77d5668e878 (patch)
tree0db660d9eb28a6416089cc3cd5114b62b060f525 /target-ppc
parentb748863a7f7d2996255dd2cb5a20e49785cc7387 (diff)
target-ppc: Fix Floating Point Move Instructions That Set CR1
The Floating Point Move instructions (fmr., fabs., fnabs., fneg., and fcpsgn.) incorrectly copy FPSCR[FPCC] instead of [FX,FEX,VX,OX]. Furthermore, the current code does this via a call to gen_compute_fprf, which is awkward since these instructions do not actually set FPRF. Change the code to use the gen_set_cr1_from_fpscr utility. Signed-off-by: Tom Musta <tommusta@gmail.com> [agraf: whitespace fixes] Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'target-ppc')
-rw-r--r--target-ppc/translate.c50
1 files changed, 30 insertions, 20 deletions
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index fe36b5816e..35c3a16091 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2077,6 +2077,21 @@ static void gen_srd(DisasContext *ctx)
}
#endif
+#if defined(TARGET_PPC64)
+static void gen_set_cr1_from_fpscr(DisasContext *ctx)
+{
+ TCGv_i32 tmp = tcg_temp_new_i32();
+ tcg_gen_trunc_tl_i32(tmp, cpu_fpscr);
+ tcg_gen_shri_i32(cpu_crf[1], tmp, 28);
+ tcg_temp_free_i32(tmp);
+}
+#else
+static void gen_set_cr1_from_fpscr(DisasContext *ctx)
+{
+ tcg_gen_shri_tl(cpu_crf[1], cpu_fpscr, 28);
+}
+#endif
+
/*** Floating-Point arithmetic ***/
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
static void gen_f##name(DisasContext *ctx) \
@@ -2370,7 +2385,9 @@ static void gen_fabs(DisasContext *ctx)
}
tcg_gen_andi_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
~(1ULL << 63));
- gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
+ if (unlikely(Rc(ctx->opcode))) {
+ gen_set_cr1_from_fpscr(ctx);
+ }
}
/* fmr - fmr. */
@@ -2382,7 +2399,9 @@ static void gen_fmr(DisasContext *ctx)
return;
}
tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
- gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
+ if (unlikely(Rc(ctx->opcode))) {
+ gen_set_cr1_from_fpscr(ctx);
+ }
}
/* fnabs */
@@ -2395,7 +2414,9 @@ static void gen_fnabs(DisasContext *ctx)
}
tcg_gen_ori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
1ULL << 63);
- gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
+ if (unlikely(Rc(ctx->opcode))) {
+ gen_set_cr1_from_fpscr(ctx);
+ }
}
/* fneg */
@@ -2408,7 +2429,9 @@ static void gen_fneg(DisasContext *ctx)
}
tcg_gen_xori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
1ULL << 63);
- gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
+ if (unlikely(Rc(ctx->opcode))) {
+ gen_set_cr1_from_fpscr(ctx);
+ }
}
/* fcpsgn: PowerPC 2.05 specification */
@@ -2421,7 +2444,9 @@ static void gen_fcpsgn(DisasContext *ctx)
}
tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
cpu_fpr[rB(ctx->opcode)], 0, 63);
- gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
+ if (unlikely(Rc(ctx->opcode))) {
+ gen_set_cr1_from_fpscr(ctx);
+ }
}
static void gen_fmrgew(DisasContext *ctx)
@@ -8211,21 +8236,6 @@ static inline TCGv_ptr gen_fprp_ptr(int reg)
return r;
}
-#if defined(TARGET_PPC64)
-static void gen_set_cr1_from_fpscr(DisasContext *ctx)
-{
- TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_trunc_tl_i32(tmp, cpu_fpscr);
- tcg_gen_shri_i32(cpu_crf[1], tmp, 28);
- tcg_temp_free_i32(tmp);
-}
-#else
-static void gen_set_cr1_from_fpscr(DisasContext *ctx)
-{
- tcg_gen_shri_tl(cpu_crf[1], cpu_fpscr, 28);
-}
-#endif
-
#define GEN_DFP_T_A_B_Rc(name) \
static void gen_##name(DisasContext *ctx) \
{ \