These helpers allow us to move FP register values to/from the specified TCGv_i64
argument.
To prevent FP helpers accessing the cpu_fpr array directly, add extra TCG
temporaries as required.
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
---
target/ppc/translate.c | 10 +
target/ppc/translate/fp-impl.inc.c | 492 ++++++++++++++++++++++++++++---------
2 files changed, 392 insertions(+), 110 deletions(-)
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 2b37910248..1d4bf624a3 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -6694,6 +6694,16 @@ static inline void gen_##name(DisasContext *ctx) \
GEN_TM_PRIV_NOOP(treclaim);
GEN_TM_PRIV_NOOP(trechkpt);
+static inline void get_fpr(TCGv_i64 dst, int regno)
+{
+ tcg_gen_mov_i64(dst, cpu_fpr[regno]);
+}
+
+static inline void set_fpr(int regno, TCGv_i64 src)
+{
+ tcg_gen_mov_i64(cpu_fpr[regno], src);
+}
+
#include "translate/fp-impl.inc.c"
#include "translate/vmx-impl.inc.c"
diff --git a/target/ppc/translate/fp-impl.inc.c b/target/ppc/translate/fp-impl.inc.c
index 08770ba9f5..923fb7550f 100644
--- a/target/ppc/translate/fp-impl.inc.c
+++ b/target/ppc/translate/fp-impl.inc.c
@@ -34,24 +34,39 @@ static void gen_set_cr1_from_fpscr(DisasContext *ctx)
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
static void gen_f##name(DisasContext *ctx) \
{ \
+ TCGv_i64 t0; \
+ TCGv_i64 t1; \
+ TCGv_i64 t2; \
+ TCGv_i64 t3; \
if (unlikely(!ctx->fpu_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_FPU); \
return; \
} \
+ t0 = tcg_temp_new_i64(); \
+ t1 = tcg_temp_new_i64(); \
+ t2 = tcg_temp_new_i64(); \
+ t3 = tcg_temp_new_i64(); \
gen_reset_fpstatus(); \
- gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env, \
- cpu_fpr[rA(ctx->opcode)], \
- cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \
+ get_fpr(t0, rA(ctx->opcode)); \
+ get_fpr(t1, rC(ctx->opcode)); \
+ get_fpr(t2, rB(ctx->opcode)); \
+ gen_helper_f##op(t3, cpu_env, t0, t1, t2); \
+ set_fpr(rD(ctx->opcode), t3); \
if (isfloat) { \
- gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env, \
- cpu_fpr[rD(ctx->opcode)]); \
+ get_fpr(t0, rD(ctx->opcode)); \
+ gen_helper_frsp(t3, cpu_env, t0); \
+ set_fpr(rD(ctx->opcode), t3); \
} \
if (set_fprf) { \
- gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]); \
+ gen_compute_fprf_float64(t3); \
} \
if (unlikely(Rc(ctx->opcode) != 0)) { \
gen_set_cr1_from_fpscr(ctx); \
} \
+ tcg_temp_free_i64(t0); \
+ tcg_temp_free_i64(t1); \
+ tcg_temp_free_i64(t2); \
+ tcg_temp_free_i64(t3); \
}
#define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
@@ -61,24 +76,35 @@ _GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
static void gen_f##name(DisasContext *ctx) \
{ \
+ TCGv_i64 t0; \
+ TCGv_i64 t1; \
+ TCGv_i64 t2; \
if (unlikely(!ctx->fpu_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_FPU); \
return; \
} \
+ t0 = tcg_temp_new_i64(); \
+ t1 = tcg_temp_new_i64(); \
+ t2 = tcg_temp_new_i64(); \
gen_reset_fpstatus(); \
- gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env, \
- cpu_fpr[rA(ctx->opcode)], \
- cpu_fpr[rB(ctx->opcode)]); \
+ get_fpr(t0, rA(ctx->opcode)); \
+ get_fpr(t1, rB(ctx->opcode)); \
+ gen_helper_f##op(t2, cpu_env, t0, t1); \
+ set_fpr(rD(ctx->opcode), t2); \
if (isfloat) { \
- gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env, \
- cpu_fpr[rD(ctx->opcode)]); \
+ get_fpr(t0, rD(ctx->opcode)); \
+ gen_helper_frsp(t2, cpu_env, t0); \
+ set_fpr(rD(ctx->opcode), t2); \
} \
if (set_fprf) { \
- gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]); \
+ gen_compute_fprf_float64(t2); \
} \
if (unlikely(Rc(ctx->opcode) != 0)) { \
gen_set_cr1_from_fpscr(ctx); \
} \
+ tcg_temp_free_i64(t0); \
+ tcg_temp_free_i64(t1); \
+ tcg_temp_free_i64(t2); \
}
#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
@@ -87,24 +113,35 @@ _GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
static void gen_f##name(DisasContext *ctx) \
{ \
+ TCGv_i64 t0; \
+ TCGv_i64 t1; \
+ TCGv_i64 t2; \
if (unlikely(!ctx->fpu_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_FPU); \
return; \
} \
+ t0 = tcg_temp_new_i64(); \
+ t1 = tcg_temp_new_i64(); \
+ t2 = tcg_temp_new_i64(); \
gen_reset_fpstatus(); \
- gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env, \
- cpu_fpr[rA(ctx->opcode)], \
- cpu_fpr[rC(ctx->opcode)]); \
+ get_fpr(t0, rA(ctx->opcode)); \
+ get_fpr(t1, rC(ctx->opcode)); \
+ gen_helper_f##op(t2, cpu_env, t0, t1); \
+ set_fpr(rD(ctx->opcode), t2); \
if (isfloat) { \
- gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env, \
- cpu_fpr[rD(ctx->opcode)]); \
+ get_fpr(t0, rD(ctx->opcode)); \
+ gen_helper_frsp(t2, cpu_env, t0); \
+ set_fpr(rD(ctx->opcode), t2); \
} \
if (set_fprf) { \
- gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]); \
+ gen_compute_fprf_float64(t2); \
} \
if (unlikely(Rc(ctx->opcode) != 0)) { \
gen_set_cr1_from_fpscr(ctx); \
} \
+ tcg_temp_free_i64(t0); \
+ tcg_temp_free_i64(t1); \
+ tcg_temp_free_i64(t2); \
}
#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
@@ -113,37 +150,51 @@ _GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
static void gen_f##name(DisasContext *ctx) \
{ \
+ TCGv_i64 t0; \
+ TCGv_i64 t1; \
if (unlikely(!ctx->fpu_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_FPU); \
return; \
} \
+ t0 = tcg_temp_new_i64(); \
+ t1 = tcg_temp_new_i64(); \
gen_reset_fpstatus(); \
- gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env, \
- cpu_fpr[rB(ctx->opcode)]); \
+ get_fpr(t0, rB(ctx->opcode)); \
+ gen_helper_f##name(t1, cpu_env, t0); \
+ set_fpr(rD(ctx->opcode), t1); \
if (set_fprf) { \
- gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]); \
+ gen_compute_fprf_float64(t1); \
} \
if (unlikely(Rc(ctx->opcode) != 0)) { \
gen_set_cr1_from_fpscr(ctx); \
} \
+ tcg_temp_free_i64(t0); \
+ tcg_temp_free_i64(t1); \
}
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
static void gen_f##name(DisasContext *ctx) \
{ \
+ TCGv_i64 t0; \
+ TCGv_i64 t1; \
if (unlikely(!ctx->fpu_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_FPU); \
return; \
} \
+ t0 = tcg_temp_new_i64(); \
+ t1 = tcg_temp_new_i64(); \
gen_reset_fpstatus(); \
- gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env, \
- cpu_fpr[rB(ctx->opcode)]); \
+ get_fpr(t0, rB(ctx->opcode)); \
+ gen_helper_f##name(t1, cpu_env, t0); \
+ set_fpr(rD(ctx->opcode), t1); \
if (set_fprf) { \
- gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]); \
+ gen_compute_fprf_float64(t1); \
} \
if (unlikely(Rc(ctx->opcode) != 0)) { \
gen_set_cr1_from_fpscr(ctx); \
} \
+ tcg_temp_free_i64(t0); \
+ tcg_temp_free_i64(t1); \
}
/* fadd - fadds */
@@ -165,19 +216,25 @@ GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
/* frsqrtes */
static void gen_frsqrtes(DisasContext *ctx)
{
+ TCGv_i64 t0;
+ TCGv_i64 t1;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
gen_reset_fpstatus();
- gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_env,
- cpu_fpr[rB(ctx->opcode)]);
- gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,
- cpu_fpr[rD(ctx->opcode)]);
- gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]);
+ get_fpr(t0, rB(ctx->opcode));
+ gen_helper_frsqrte(t1, cpu_env, t0);
+ set_fpr(rD(ctx->opcode), t1);
+ gen_helper_frsp(t1, cpu_env, t1);
+ gen_compute_fprf_float64(t1);
if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_cr1_from_fpscr(ctx);
}
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
}
/* fsel */
@@ -189,34 +246,47 @@ GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
/* fsqrt */
static void gen_fsqrt(DisasContext *ctx)
{
+ TCGv_i64 t0;
+ TCGv_i64 t1;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
gen_reset_fpstatus();
- gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
- cpu_fpr[rB(ctx->opcode)]);
- gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]);
+ get_fpr(t0, rB(ctx->opcode));
+ gen_helper_fsqrt(t1, cpu_env, t0);
+ set_fpr(rD(ctx->opcode), t1);
+ gen_compute_fprf_float64(t1);
if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_cr1_from_fpscr(ctx);
}
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
}
static void gen_fsqrts(DisasContext *ctx)
{
+ TCGv_i64 t0;
+ TCGv_i64 t1;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
gen_reset_fpstatus();
- gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
- cpu_fpr[rB(ctx->opcode)]);
- gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,
- cpu_fpr[rD(ctx->opcode)]);
- gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]);
+ get_fpr(t0, rB(ctx->opcode));
+ gen_helper_fsqrt(t1, cpu_env, t0);
+ set_fpr(rD(ctx->opcode), t1);
+ gen_helper_frsp(t1, cpu_env, t1);
+ gen_compute_fprf_float64(t1);
if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_cr1_from_fpscr(ctx);
}
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
}
/*** Floating-Point multiply-and-add ***/
@@ -268,21 +338,32 @@ GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
static void gen_ftdiv(DisasContext *ctx)
{
+ TCGv_i64 t0;
+ TCGv_i64 t1;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
- gen_helper_ftdiv(cpu_crf[crfD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
- cpu_fpr[rB(ctx->opcode)]);
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+ get_fpr(t0, rA(ctx->opcode));
+ get_fpr(t1, rB(ctx->opcode));
+ gen_helper_ftdiv(cpu_crf[crfD(ctx->opcode)], t0, t1);
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
}
static void gen_ftsqrt(DisasContext *ctx)
{
+ TCGv_i64 t0;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
- gen_helper_ftsqrt(cpu_crf[crfD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
+ t0 = tcg_temp_new_i64();
+ get_fpr(t0, rB(ctx->opcode));
+ gen_helper_ftsqrt(cpu_crf[crfD(ctx->opcode)], t0);
+ tcg_temp_free_i64(t0);
}
@@ -293,32 +374,46 @@ static void gen_ftsqrt(DisasContext *ctx)
static void gen_fcmpo(DisasContext *ctx)
{
TCGv_i32 crf;
+ TCGv_i64 t0;
+ TCGv_i64 t1;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
gen_reset_fpstatus();
crf = tcg_const_i32(crfD(ctx->opcode));
- gen_helper_fcmpo(cpu_env, cpu_fpr[rA(ctx->opcode)],
- cpu_fpr[rB(ctx->opcode)], crf);
+ get_fpr(t0, rA(ctx->opcode));
+ get_fpr(t1, rB(ctx->opcode));
+ gen_helper_fcmpo(cpu_env, t0, t1, crf);
tcg_temp_free_i32(crf);
gen_helper_float_check_status(cpu_env);
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
}
/* fcmpu */
static void gen_fcmpu(DisasContext *ctx)
{
TCGv_i32 crf;
+ TCGv_i64 t0;
+ TCGv_i64 t1;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
gen_reset_fpstatus();
crf = tcg_const_i32(crfD(ctx->opcode));
- gen_helper_fcmpu(cpu_env, cpu_fpr[rA(ctx->opcode)],
- cpu_fpr[rB(ctx->opcode)], crf);
+ get_fpr(t0, rA(ctx->opcode));
+ get_fpr(t1, rB(ctx->opcode));
+ gen_helper_fcmpu(cpu_env, t0, t1, crf);
tcg_temp_free_i32(crf);
gen_helper_float_check_status(cpu_env);
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
}
/*** Floating-point move ***/
@@ -326,100 +421,153 @@ static void gen_fcmpu(DisasContext *ctx)
/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
static void gen_fabs(DisasContext *ctx)
{
+ TCGv_i64 t0;
+ TCGv_i64 t1;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
- tcg_gen_andi_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
- ~(1ULL << 63));
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+ get_fpr(t0, rB(ctx->opcode));
+ tcg_gen_andi_i64(t1, t0, ~(1ULL << 63));
+ set_fpr(rD(ctx->opcode), t1);
if (unlikely(Rc(ctx->opcode))) {
gen_set_cr1_from_fpscr(ctx);
}
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
}
/* fmr - fmr. */
/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
static void gen_fmr(DisasContext *ctx)
{
+ TCGv_i64 t0;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
- tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
+ t0 = tcg_temp_new_i64();
+ get_fpr(t0, rB(ctx->opcode));
+ set_fpr(rD(ctx->opcode), t0);
if (unlikely(Rc(ctx->opcode))) {
gen_set_cr1_from_fpscr(ctx);
}
+ tcg_temp_free_i64(t0);
}
/* fnabs */
/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
static void gen_fnabs(DisasContext *ctx)
{
+ TCGv_i64 t0;
+ TCGv_i64 t1;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
- tcg_gen_ori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
- 1ULL << 63);
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+ get_fpr(t0, rB(ctx->opcode));
+ tcg_gen_ori_i64(t1, t0, 1ULL << 63);
+ set_fpr(rD(ctx->opcode), t1);
if (unlikely(Rc(ctx->opcode))) {
gen_set_cr1_from_fpscr(ctx);
}
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
}
/* fneg */
/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
static void gen_fneg(DisasContext *ctx)
{
+ TCGv_i64 t0;
+ TCGv_i64 t1;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
- tcg_gen_xori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
- 1ULL << 63);
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+ get_fpr(t0, rB(ctx->opcode));
+ tcg_gen_xori_i64(t1, t0, 1ULL << 63);
+ set_fpr(rD(ctx->opcode), t1);
if (unlikely(Rc(ctx->opcode))) {
gen_set_cr1_from_fpscr(ctx);
}
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
}
/* fcpsgn: PowerPC 2.05 specification */
/* XXX: beware that fcpsgn never checks for NaNs nor update FPSCR */
static void gen_fcpsgn(DisasContext *ctx)
{
+ TCGv_i64 t0;
+ TCGv_i64 t1;
+ TCGv_i64 t2;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
- tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
- cpu_fpr[rB(ctx->opcode)], 0, 63);
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+ t2 = tcg_temp_new_i64();
+ get_fpr(t0, rA(ctx->opcode));
+ get_fpr(t1, rB(ctx->opcode));
+ tcg_gen_deposit_i64(t2, t0, t1, 0, 63);
+ set_fpr(rD(ctx->opcode), t2);
if (unlikely(Rc(ctx->opcode))) {
gen_set_cr1_from_fpscr(ctx);
}
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
+ tcg_temp_free_i64(t2);
}
static void gen_fmrgew(DisasContext *ctx)
{
TCGv_i64 b0;
+ TCGv_i64 t0;
+ TCGv_i64 t1;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
b0 = tcg_temp_new_i64();
- tcg_gen_shri_i64(b0, cpu_fpr[rB(ctx->opcode)], 32);
- tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
- b0, 0, 32);
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+ get_fpr(t0, rB(ctx->opcode));
+ tcg_gen_shri_i64(b0, t0, 32);
+ get_fpr(t0, rA(ctx->opcode));
+ tcg_gen_deposit_i64(t1, t0, b0, 0, 32);
+ set_fpr(rD(ctx->opcode), t1);
tcg_temp_free_i64(b0);
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
}
static void gen_fmrgow(DisasContext *ctx)
{
+ TCGv_i64 t0;
+ TCGv_i64 t1;
+ TCGv_i64 t2;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
- tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)],
- cpu_fpr[rB(ctx->opcode)],
- cpu_fpr[rA(ctx->opcode)],
- 32, 32);
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+ t2 = tcg_temp_new_i64();
+ get_fpr(t0, rB(ctx->opcode));
+ get_fpr(t1, rA(ctx->opcode));
+ tcg_gen_deposit_i64(t2, t0, t1, 32, 32);
+ set_fpr(rD(ctx->opcode), t2);
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
+ tcg_temp_free_i64(t2);
}
/*** Floating-Point status & ctrl register ***/
@@ -458,15 +606,19 @@ static void gen_mcrfs(DisasContext *ctx)
/* mffs */
static void gen_mffs(DisasContext *ctx)
{
+ TCGv_i64 t0;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
+ t0 = tcg_temp_new_i64();
gen_reset_fpstatus();
- tcg_gen_extu_tl_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
+ tcg_gen_extu_tl_i64(t0, cpu_fpscr);
+ set_fpr(rD(ctx->opcode), t0);
if (unlikely(Rc(ctx->opcode))) {
gen_set_cr1_from_fpscr(ctx);
}
+ tcg_temp_free_i64(t0);
}
/* mtfsb0 */
@@ -522,6 +674,7 @@ static void gen_mtfsb1(DisasContext *ctx)
static void gen_mtfsf(DisasContext *ctx)
{
TCGv_i32 t0;
+ TCGv_i64 t1;
int flm, l, w;
if (unlikely(!ctx->fpu_enabled)) {
@@ -541,7 +694,9 @@ static void gen_mtfsf(DisasContext *ctx)
} else {
t0 = tcg_const_i32(flm << (w * 8));
}
- gen_helper_store_fpscr(cpu_env, cpu_fpr[rB(ctx->opcode)], t0);
+ t1 = tcg_temp_new_i64();
+ get_fpr(t1, rB(ctx->opcode));
+ gen_helper_store_fpscr(cpu_env, t1, t0);
tcg_temp_free_i32(t0);
if (unlikely(Rc(ctx->opcode) != 0)) {
tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
@@ -549,6 +704,7 @@ static void gen_mtfsf(DisasContext *ctx)
}
/* We can raise a differed exception */
gen_helper_float_check_status(cpu_env);
+ tcg_temp_free_i64(t1);
}
/* mtfsfi */
@@ -588,21 +744,26 @@ static void gen_mtfsfi(DisasContext *ctx)
static void glue(gen_, name)(DisasContext *ctx) \
{ \
TCGv EA; \
+ TCGv_i64 t0; \
if (unlikely(!ctx->fpu_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_FPU); \
return; \
} \
gen_set_access_type(ctx, ACCESS_FLOAT); \
EA = tcg_temp_new(); \
+ t0 = tcg_temp_new_i64(); \
gen_addr_imm_index(ctx, EA, 0); \
- gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
+ gen_qemu_##ldop(ctx, t0, EA); \
+ set_fpr(rD(ctx->opcode), t0); \
tcg_temp_free(EA); \
+ tcg_temp_free_i64(t0); \
}
#define GEN_LDUF(name, ldop, opc, type) \
static void glue(gen_, name##u)(DisasContext *ctx) \
{ \
TCGv EA; \
+ TCGv_i64 t0; \
if (unlikely(!ctx->fpu_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_FPU); \
return; \
@@ -613,20 +774,25 @@ static void glue(gen_, name##u)(DisasContext *ctx)
} \
gen_set_access_type(ctx, ACCESS_FLOAT); \
EA = tcg_temp_new(); \
+ t0 = tcg_temp_new_i64(); \
gen_addr_imm_index(ctx, EA, 0); \
- gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
+ gen_qemu_##ldop(ctx, t0, EA); \
+ set_fpr(rD(ctx->opcode), t0); \
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
tcg_temp_free(EA); \
+ tcg_temp_free_i64(t0); \
}
#define GEN_LDUXF(name, ldop, opc, type) \
static void glue(gen_, name##ux)(DisasContext *ctx) \
{ \
TCGv EA; \
+ TCGv_i64 t0; \
if (unlikely(!ctx->fpu_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_FPU); \
return; \
} \
+ t0 = tcg_temp_new_i64(); \
if (unlikely(rA(ctx->opcode) == 0)) { \
gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
return; \
@@ -634,24 +800,30 @@ static void glue(gen_, name##ux)(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_FLOAT); \
EA = tcg_temp_new(); \
gen_addr_reg_index(ctx, EA); \
- gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
+ gen_qemu_##ldop(ctx, t0, EA); \
+ set_fpr(rD(ctx->opcode), t0); \
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
tcg_temp_free(EA); \
+ tcg_temp_free_i64(t0); \
}
#define GEN_LDXF(name, ldop, opc2, opc3, type) \
static void glue(gen_, name##x)(DisasContext *ctx) \
{ \
TCGv EA; \
+ TCGv_i64 t0; \
if (unlikely(!ctx->fpu_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_FPU); \
return; \
} \
gen_set_access_type(ctx, ACCESS_FLOAT); \
EA = tcg_temp_new(); \
+ t0 = tcg_temp_new_i64(); \
gen_addr_reg_index(ctx, EA); \
- gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
+ gen_qemu_##ldop(ctx, t0, EA); \
+ set_fpr(rD(ctx->opcode), t0); \
tcg_temp_free(EA); \
+ tcg_temp_free_i64(t0); \
}
#define GEN_LDFS(name, ldop, op, type) \
@@ -677,6 +849,7 @@ GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
static void gen_lfdepx(DisasContext *ctx)
{
TCGv EA;
+ TCGv_i64 t0;
CHK_SV;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
@@ -684,16 +857,19 @@ static void gen_lfdepx(DisasContext *ctx)
}
gen_set_access_type(ctx, ACCESS_FLOAT);
EA = tcg_temp_new();
+ t0 = tcg_temp_new_i64();
gen_addr_reg_index(ctx, EA);
- tcg_gen_qemu_ld_i64(cpu_fpr[rD(ctx->opcode)], EA, PPC_TLB_EPID_LOAD,
- DEF_MEMOP(MO_Q));
+ tcg_gen_qemu_ld_i64(t0, EA, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_Q));
+ set_fpr(rD(ctx->opcode), t0);
tcg_temp_free(EA);
+ tcg_temp_free_i64(t0);
}
/* lfdp */
static void gen_lfdp(DisasContext *ctx)
{
TCGv EA;
+ TCGv_i64 t0;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
@@ -701,24 +877,31 @@ static void gen_lfdp(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_FLOAT);
EA = tcg_temp_new();
gen_addr_imm_index(ctx, EA, 0);
+ t0 = tcg_temp_new_i64();
/* We only need to swap high and low halves. gen_qemu_ld64_i64 does
necessary 64-bit byteswap already. */
if (unlikely(ctx->le_mode)) {
- gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+ gen_qemu_ld64_i64(ctx, t0, EA);
+ set_fpr(rD(ctx->opcode) + 1, t0);
tcg_gen_addi_tl(EA, EA, 8);
- gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+ gen_qemu_ld64_i64(ctx, t0, EA);
+ set_fpr(rD(ctx->opcode), t0);
} else {
- gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+ gen_qemu_ld64_i64(ctx, t0, EA);
+ set_fpr(rD(ctx->opcode), t0);
tcg_gen_addi_tl(EA, EA, 8);
- gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+ gen_qemu_ld64_i64(ctx, t0, EA);
+ set_fpr(rD(ctx->opcode) + 1, t0);
}
tcg_temp_free(EA);
+ tcg_temp_free_i64(t0);
}
/* lfdpx */
static void gen_lfdpx(DisasContext *ctx)
{
TCGv EA;
+ TCGv_i64 t0;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
@@ -726,18 +909,24 @@ static void gen_lfdpx(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_FLOAT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
+ t0 = tcg_temp_new_i64();
/* We only need to swap high and low halves. gen_qemu_ld64_i64 does
necessary 64-bit byteswap already. */
if (unlikely(ctx->le_mode)) {
- gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+ gen_qemu_ld64_i64(ctx, t0, EA);
+ set_fpr(rD(ctx->opcode) + 1, t0);
tcg_gen_addi_tl(EA, EA, 8);
- gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+ gen_qemu_ld64_i64(ctx, t0, EA);
+ set_fpr(rD(ctx->opcode), t0);
} else {
- gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+ gen_qemu_ld64_i64(ctx, t0, EA);
+ set_fpr(rD(ctx->opcode), t0);
tcg_gen_addi_tl(EA, EA, 8);
- gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+ gen_qemu_ld64_i64(ctx, t0, EA);
+ set_fpr(rD(ctx->opcode) + 1, t0);
}
tcg_temp_free(EA);
+ tcg_temp_free_i64(t0);
}
/* lfiwax */
@@ -745,6 +934,7 @@ static void gen_lfiwax(DisasContext *ctx)
{
TCGv EA;
TCGv t0;
+ TCGv_i64 t1;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
@@ -752,47 +942,59 @@ static void gen_lfiwax(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_FLOAT);
EA = tcg_temp_new();
t0 = tcg_temp_new();
+ t1 = tcg_temp_new_i64();
gen_addr_reg_index(ctx, EA);
gen_qemu_ld32s(ctx, t0, EA);
- tcg_gen_ext_tl_i64(cpu_fpr[rD(ctx->opcode)], t0);
+ tcg_gen_ext_tl_i64(t1, t0);
+ set_fpr(rD(ctx->opcode), t1);
tcg_temp_free(EA);
tcg_temp_free(t0);
+ tcg_temp_free_i64(t1);
}
/* lfiwzx */
static void gen_lfiwzx(DisasContext *ctx)
{
TCGv EA;
+ TCGv_i64 t0;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
gen_set_access_type(ctx, ACCESS_FLOAT);
EA = tcg_temp_new();
+ t0 = tcg_temp_new_i64();
gen_addr_reg_index(ctx, EA);
- gen_qemu_ld32u_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+ gen_qemu_ld32u_i64(ctx, t0, EA);
+ set_fpr(rD(ctx->opcode), t0);
tcg_temp_free(EA);
+ tcg_temp_free_i64(t0);
}
/*** Floating-point store ***/
#define GEN_STF(name, stop, opc, type) \
static void glue(gen_, name)(DisasContext *ctx) \
{ \
TCGv EA; \
+ TCGv_i64 t0; \
if (unlikely(!ctx->fpu_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_FPU); \
return; \
} \
gen_set_access_type(ctx, ACCESS_FLOAT); \
EA = tcg_temp_new(); \
+ t0 = tcg_temp_new_i64(); \
gen_addr_imm_index(ctx, EA, 0); \
- gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
+ get_fpr(t0, rS(ctx->opcode)); \
+ gen_qemu_##stop(ctx, t0, EA); \
tcg_temp_free(EA); \
+ tcg_temp_free_i64(t0); \
}
#define GEN_STUF(name, stop, opc, type) \
static void glue(gen_, name##u)(DisasContext *ctx) \
{ \
TCGv EA; \
+ TCGv_i64 t0; \
if (unlikely(!ctx->fpu_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_FPU); \
return; \
@@ -803,16 +1005,20 @@ static void glue(gen_, name##u)(DisasContext *ctx)
} \
gen_set_access_type(ctx, ACCESS_FLOAT); \
EA = tcg_temp_new(); \
+ t0 = tcg_temp_new_i64(); \
gen_addr_imm_index(ctx, EA, 0); \
- gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
+ get_fpr(t0, rS(ctx->opcode)); \
+ gen_qemu_##stop(ctx, t0, EA); \
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
tcg_temp_free(EA); \
+ tcg_temp_free_i64(t0); \
}
#define GEN_STUXF(name, stop, opc, type) \
static void glue(gen_, name##ux)(DisasContext *ctx) \
{ \
TCGv EA; \
+ TCGv_i64 t0; \
if (unlikely(!ctx->fpu_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_FPU); \
return; \
@@ -823,25 +1029,32 @@ static void glue(gen_, name##ux)(DisasContext *ctx)
} \
gen_set_access_type(ctx, ACCESS_FLOAT); \
EA = tcg_temp_new(); \
+ t0 = tcg_temp_new_i64(); \
gen_addr_reg_index(ctx, EA); \
- gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
+ get_fpr(t0, rS(ctx->opcode)); \
+ gen_qemu_##stop(ctx, t0, EA); \
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
tcg_temp_free(EA); \
+ tcg_temp_free_i64(t0); \
}
#define GEN_STXF(name, stop, opc2, opc3, type) \
static void glue(gen_, name##x)(DisasContext *ctx) \
{ \
TCGv EA; \
+ TCGv_i64 t0; \
if (unlikely(!ctx->fpu_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_FPU); \
return; \
} \
gen_set_access_type(ctx, ACCESS_FLOAT); \
EA = tcg_temp_new(); \
+ t0 = tcg_temp_new_i64(); \
gen_addr_reg_index(ctx, EA); \
- gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
+ get_fpr(t0, rS(ctx->opcode)); \
+ gen_qemu_##stop(ctx, t0, EA); \
tcg_temp_free(EA); \
+ tcg_temp_free_i64(t0); \
}
#define GEN_STFS(name, stop, op, type) \
@@ -867,6 +1080,7 @@ GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
static void gen_stfdepx(DisasContext *ctx)
{
TCGv EA;
+ TCGv_i64 t0;
CHK_SV;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
@@ -874,60 +1088,76 @@ static void gen_stfdepx(DisasContext *ctx)
}
gen_set_access_type(ctx, ACCESS_FLOAT);
EA = tcg_temp_new();
+ t0 = tcg_temp_new_i64();
gen_addr_reg_index(ctx, EA);
- tcg_gen_qemu_st_i64(cpu_fpr[rD(ctx->opcode)], EA, PPC_TLB_EPID_STORE,
- DEF_MEMOP(MO_Q));
+ get_fpr(t0, rD(ctx->opcode));
+ tcg_gen_qemu_st_i64(t0, EA, PPC_TLB_EPID_STORE, DEF_MEMOP(MO_Q));
tcg_temp_free(EA);
+ tcg_temp_free_i64(t0);
}
/* stfdp */
static void gen_stfdp(DisasContext *ctx)
{
TCGv EA;
+ TCGv_i64 t0;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
gen_set_access_type(ctx, ACCESS_FLOAT);
EA = tcg_temp_new();
+ t0 = tcg_temp_new_i64();
gen_addr_imm_index(ctx, EA, 0);
/* We only need to swap high and low halves. gen_qemu_st64_i64 does
necessary 64-bit byteswap already. */
if (unlikely(ctx->le_mode)) {
- gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+ get_fpr(t0, rD(ctx->opcode) + 1);
+ gen_qemu_st64_i64(ctx, t0, EA);
tcg_gen_addi_tl(EA, EA, 8);
- gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+ get_fpr(t0, rD(ctx->opcode));
+ gen_qemu_st64_i64(ctx, t0, EA);
} else {
- gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+ get_fpr(t0, rD(ctx->opcode));
+ gen_qemu_st64_i64(ctx, t0, EA);
tcg_gen_addi_tl(EA, EA, 8);
- gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+ get_fpr(t0, rD(ctx->opcode) + 1);
+ gen_qemu_st64_i64(ctx, t0, EA);
}
tcg_temp_free(EA);
+ tcg_temp_free_i64(t0);
}
/* stfdpx */
static void gen_stfdpx(DisasContext *ctx)
{
TCGv EA;
+ TCGv_i64 t0;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
gen_set_access_type(ctx, ACCESS_FLOAT);
EA = tcg_temp_new();
+ t0 = tcg_temp_new_i64();
gen_addr_reg_index(ctx, EA);
/* We only need to swap high and low halves. gen_qemu_st64_i64 does
necessary 64-bit byteswap already. */
if (unlikely(ctx->le_mode)) {
- gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+ get_fpr(t0, rD(ctx->opcode) + 1);
+ gen_qemu_st64_i64(ctx, t0, EA);
tcg_gen_addi_tl(EA, EA, 8);
- gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+ get_fpr(t0, rD(ctx->opcode));
+ gen_qemu_st64_i64(ctx, t0, EA);
} else {
- gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+ get_fpr(t0, rD(ctx->opcode));
+ gen_qemu_st64_i64(ctx, t0, EA);
tcg_gen_addi_tl(EA, EA, 8);
- gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+ get_fpr(t0, rD(ctx->opcode) + 1);
+ gen_qemu_st64_i64(ctx, t0, EA);
}
tcg_temp_free(EA);
+ tcg_temp_free_i64(t0);
}
/* Optional: */
@@ -949,13 +1179,18 @@ static void gen_lfq(DisasContext *ctx)
{
int rd = rD(ctx->opcode);
TCGv t0;
+ TCGv_i64 t1;
gen_set_access_type(ctx, ACCESS_FLOAT);
t0 = tcg_temp_new();
+ t1 = tcg_temp_new_i64();
gen_addr_imm_index(ctx, t0, 0);
- gen_qemu_ld64_i64(ctx, cpu_fpr[rd], t0);
+ gen_qemu_ld64_i64(ctx, t1, t0);
+ set_fpr(rd, t1);
gen_addr_add(ctx, t0, t0, 8);
- gen_qemu_ld64_i64(ctx, cpu_fpr[(rd + 1) % 32], t0);
+ gen_qemu_ld64_i64(ctx, t1, t0);
+ set_fpr((rd + 1) % 32, t1);
tcg_temp_free(t0);
+ tcg_temp_free_i64(t1);
}
/* lfqu */
@@ -964,17 +1199,22 @@ static void gen_lfqu(DisasContext *ctx)
int ra = rA(ctx->opcode);
int rd = rD(ctx->opcode);
TCGv t0, t1;
+ TCGv_i64 t2;
gen_set_access_type(ctx, ACCESS_FLOAT);
t0 = tcg_temp_new();
t1 = tcg_temp_new();
+ t2 = tcg_temp_new_i64();
gen_addr_imm_index(ctx, t0, 0);
- gen_qemu_ld64_i64(ctx, cpu_fpr[rd], t0);
+ gen_qemu_ld64_i64(ctx, t2, t0);
+ set_fpr(rd, t2);
gen_addr_add(ctx, t1, t0, 8);
- gen_qemu_ld64_i64(ctx, cpu_fpr[(rd + 1) % 32], t1);
+ gen_qemu_ld64_i64(ctx, t2, t1);
+ set_fpr((rd + 1) % 32, t2);
if (ra != 0)
tcg_gen_mov_tl(cpu_gpr[ra], t0);
tcg_temp_free(t0);
tcg_temp_free(t1);
+ tcg_temp_free_i64(t2);
}
/* lfqux */
@@ -984,16 +1224,21 @@ static void gen_lfqux(DisasContext *ctx)
int rd = rD(ctx->opcode);
gen_set_access_type(ctx, ACCESS_FLOAT);
TCGv t0, t1;
+ TCGv_i64 t2;
+ t2 = tcg_temp_new_i64();
t0 = tcg_temp_new();
gen_addr_reg_index(ctx, t0);
- gen_qemu_ld64_i64(ctx, cpu_fpr[rd], t0);
+ gen_qemu_ld64_i64(ctx, t2, t0);
+ set_fpr(rd, t2);
t1 = tcg_temp_new();
gen_addr_add(ctx, t1, t0, 8);
- gen_qemu_ld64_i64(ctx, cpu_fpr[(rd + 1) % 32], t1);
+ gen_qemu_ld64_i64(ctx, t2, t1);
+ set_fpr((rd + 1) % 32, t2);
tcg_temp_free(t1);
if (ra != 0)
tcg_gen_mov_tl(cpu_gpr[ra], t0);
tcg_temp_free(t0);
+ tcg_temp_free_i64(t2);
}
/* lfqx */
@@ -1001,13 +1246,18 @@ static void gen_lfqx(DisasContext *ctx)
{
int rd = rD(ctx->opcode);
TCGv t0;
+ TCGv_i64 t1;
gen_set_access_type(ctx, ACCESS_FLOAT);
t0 = tcg_temp_new();
+ t1 = tcg_temp_new_i64();
gen_addr_reg_index(ctx, t0);
- gen_qemu_ld64_i64(ctx, cpu_fpr[rd], t0);
+ gen_qemu_ld64_i64(ctx, t1, t0);
+ set_fpr(rd, t1);
gen_addr_add(ctx, t0, t0, 8);
- gen_qemu_ld64_i64(ctx, cpu_fpr[(rd + 1) % 32], t0);
+ gen_qemu_ld64_i64(ctx, t1, t0);
+ set_fpr((rd + 1) % 32, t1);
tcg_temp_free(t0);
+ tcg_temp_free_i64(t1);
}
/* stfq */
@@ -1015,13 +1265,18 @@ static void gen_stfq(DisasContext *ctx)
{
int rd = rD(ctx->opcode);
TCGv t0;
+ TCGv_i64 t1;
gen_set_access_type(ctx, ACCESS_FLOAT);
t0 = tcg_temp_new();
+ t1 = tcg_temp_new_i64();
gen_addr_imm_index(ctx, t0, 0);
- gen_qemu_st64_i64(ctx, cpu_fpr[rd], t0);
+ get_fpr(t1, rd);
+ gen_qemu_st64_i64(ctx, t1, t0);
gen_addr_add(ctx, t0, t0, 8);
- gen_qemu_st64_i64(ctx, cpu_fpr[(rd + 1) % 32], t0);
+ get_fpr(t1, (rd + 1) % 32);
+ gen_qemu_st64_i64(ctx, t1, t0);
tcg_temp_free(t0);
+ tcg_temp_free_i64(t1);
}
/* stfqu */
@@ -1030,17 +1285,23 @@ static void gen_stfqu(DisasContext *ctx)
int ra = rA(ctx->opcode);
int rd = rD(ctx->opcode);
TCGv t0, t1;
+ TCGv_i64 t2;
gen_set_access_type(ctx, ACCESS_FLOAT);
+ t2 = tcg_temp_new_i64();
t0 = tcg_temp_new();
gen_addr_imm_index(ctx, t0, 0);
- gen_qemu_st64_i64(ctx, cpu_fpr[rd], t0);
+ get_fpr(t2, rd);
+ gen_qemu_st64_i64(ctx, t2, t0);
t1 = tcg_temp_new();
gen_addr_add(ctx, t1, t0, 8);
- gen_qemu_st64_i64(ctx, cpu_fpr[(rd + 1) % 32], t1);
+ get_fpr(t2, (rd + 1) % 32);
+ gen_qemu_st64_i64(ctx, t2, t1);
tcg_temp_free(t1);
- if (ra != 0)
+ if (ra != 0) {
tcg_gen_mov_tl(cpu_gpr[ra], t0);
+ }
tcg_temp_free(t0);
+ tcg_temp_free_i64(t2);
}
/* stfqux */
@@ -1049,17 +1310,23 @@ static void gen_stfqux(DisasContext *ctx)
int ra = rA(ctx->opcode);
int rd = rD(ctx->opcode);
TCGv t0, t1;
+ TCGv_i64 t2;
gen_set_access_type(ctx, ACCESS_FLOAT);
+ t2 = tcg_temp_new_i64();
t0 = tcg_temp_new();
gen_addr_reg_index(ctx, t0);
- gen_qemu_st64_i64(ctx, cpu_fpr[rd], t0);
+ get_fpr(t2, rd);
+ gen_qemu_st64_i64(ctx, t2, t0);
t1 = tcg_temp_new();
gen_addr_add(ctx, t1, t0, 8);
- gen_qemu_st64_i64(ctx, cpu_fpr[(rd + 1) % 32], t1);
+ get_fpr(t2, (rd + 1) % 32);
+ gen_qemu_st64_i64(ctx, t2, t1);
tcg_temp_free(t1);
- if (ra != 0)
+ if (ra != 0) {
tcg_gen_mov_tl(cpu_gpr[ra], t0);
+ }
tcg_temp_free(t0);
+ tcg_temp_free_i64(t2);
}
/* stfqx */
@@ -1067,13 +1334,18 @@ static void gen_stfqx(DisasContext *ctx)
{
int rd = rD(ctx->opcode);
TCGv t0;
+ TCGv_i64 t1;
gen_set_access_type(ctx, ACCESS_FLOAT);
+ t1 = tcg_temp_new_i64();
t0 = tcg_temp_new();
gen_addr_reg_index(ctx, t0);
- gen_qemu_st64_i64(ctx, cpu_fpr[rd], t0);
+ get_fpr(t1, rd);
+ gen_qemu_st64_i64(ctx, t1, t0);
gen_addr_add(ctx, t0, t0, 8);
- gen_qemu_st64_i64(ctx, cpu_fpr[(rd + 1) % 32], t0);
+ get_fpr(t1, (rd + 1) % 32);
+ gen_qemu_st64_i64(ctx, t1, t0);
tcg_temp_free(t0);
+ tcg_temp_free_i64(t1);
}
#undef _GEN_FLOAT_ACB
--
2.11.0
On Fri, Dec 07, 2018 at 08:56:30AM +0000, Mark Cave-Ayland wrote:
> These helpers allow us to move FP register values to/from the specified TCGv_i64
> argument.
>
> To prevent FP helpers accessing the cpu_fpr array directly, add extra TCG
> temporaries as required.
It's not obvious to me why that's a desirable thing. I'm assuming
it's somehow necessary for the stuff later in the series, but I think
we need a brief rationale here to explain why this isn't just adding
extra reg copies for the sake of it.
>
> Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
> ---
> target/ppc/translate.c | 10 +
> target/ppc/translate/fp-impl.inc.c | 492 ++++++++++++++++++++++++++++---------
> 2 files changed, 392 insertions(+), 110 deletions(-)
>
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index 2b37910248..1d4bf624a3 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -6694,6 +6694,16 @@ static inline void gen_##name(DisasContext *ctx) \
> GEN_TM_PRIV_NOOP(treclaim);
> GEN_TM_PRIV_NOOP(trechkpt);
>
> +static inline void get_fpr(TCGv_i64 dst, int regno)
> +{
> + tcg_gen_mov_i64(dst, cpu_fpr[regno]);
> +}
> +
> +static inline void set_fpr(int regno, TCGv_i64 src)
> +{
> + tcg_gen_mov_i64(cpu_fpr[regno], src);
> +}
> +
> #include "translate/fp-impl.inc.c"
>
> #include "translate/vmx-impl.inc.c"
> diff --git a/target/ppc/translate/fp-impl.inc.c b/target/ppc/translate/fp-impl.inc.c
> index 08770ba9f5..923fb7550f 100644
> --- a/target/ppc/translate/fp-impl.inc.c
> +++ b/target/ppc/translate/fp-impl.inc.c
> @@ -34,24 +34,39 @@ static void gen_set_cr1_from_fpscr(DisasContext *ctx)
> #define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
> static void gen_f##name(DisasContext *ctx) \
> { \
> + TCGv_i64 t0; \
> + TCGv_i64 t1; \
> + TCGv_i64 t2; \
> + TCGv_i64 t3; \
> if (unlikely(!ctx->fpu_enabled)) { \
> gen_exception(ctx, POWERPC_EXCP_FPU); \
> return; \
> } \
> + t0 = tcg_temp_new_i64(); \
> + t1 = tcg_temp_new_i64(); \
> + t2 = tcg_temp_new_i64(); \
> + t3 = tcg_temp_new_i64(); \
> gen_reset_fpstatus(); \
> - gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env, \
> - cpu_fpr[rA(ctx->opcode)], \
> - cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \
> + get_fpr(t0, rA(ctx->opcode)); \
> + get_fpr(t1, rC(ctx->opcode)); \
> + get_fpr(t2, rB(ctx->opcode)); \
> + gen_helper_f##op(t3, cpu_env, t0, t1, t2); \
> + set_fpr(rD(ctx->opcode), t3); \
> if (isfloat) { \
> - gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env, \
> - cpu_fpr[rD(ctx->opcode)]); \
> + get_fpr(t0, rD(ctx->opcode)); \
> + gen_helper_frsp(t3, cpu_env, t0); \
> + set_fpr(rD(ctx->opcode), t3); \
> } \
> if (set_fprf) { \
> - gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]); \
> + gen_compute_fprf_float64(t3); \
> } \
> if (unlikely(Rc(ctx->opcode) != 0)) { \
> gen_set_cr1_from_fpscr(ctx); \
> } \
> + tcg_temp_free_i64(t0); \
> + tcg_temp_free_i64(t1); \
> + tcg_temp_free_i64(t2); \
> + tcg_temp_free_i64(t3); \
> }
>
> #define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
> @@ -61,24 +76,35 @@ _GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
> #define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
> static void gen_f##name(DisasContext *ctx) \
> { \
> + TCGv_i64 t0; \
> + TCGv_i64 t1; \
> + TCGv_i64 t2; \
> if (unlikely(!ctx->fpu_enabled)) { \
> gen_exception(ctx, POWERPC_EXCP_FPU); \
> return; \
> } \
> + t0 = tcg_temp_new_i64(); \
> + t1 = tcg_temp_new_i64(); \
> + t2 = tcg_temp_new_i64(); \
> gen_reset_fpstatus(); \
> - gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env, \
> - cpu_fpr[rA(ctx->opcode)], \
> - cpu_fpr[rB(ctx->opcode)]); \
> + get_fpr(t0, rA(ctx->opcode)); \
> + get_fpr(t1, rB(ctx->opcode)); \
> + gen_helper_f##op(t2, cpu_env, t0, t1); \
> + set_fpr(rD(ctx->opcode), t2); \
> if (isfloat) { \
> - gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env, \
> - cpu_fpr[rD(ctx->opcode)]); \
> + get_fpr(t0, rD(ctx->opcode)); \
> + gen_helper_frsp(t2, cpu_env, t0); \
> + set_fpr(rD(ctx->opcode), t2); \
> } \
> if (set_fprf) { \
> - gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]); \
> + gen_compute_fprf_float64(t2); \
> } \
> if (unlikely(Rc(ctx->opcode) != 0)) { \
> gen_set_cr1_from_fpscr(ctx); \
> } \
> + tcg_temp_free_i64(t0); \
> + tcg_temp_free_i64(t1); \
> + tcg_temp_free_i64(t2); \
> }
> #define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
> _GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
> @@ -87,24 +113,35 @@ _GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
> #define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
> static void gen_f##name(DisasContext *ctx) \
> { \
> + TCGv_i64 t0; \
> + TCGv_i64 t1; \
> + TCGv_i64 t2; \
> if (unlikely(!ctx->fpu_enabled)) { \
> gen_exception(ctx, POWERPC_EXCP_FPU); \
> return; \
> } \
> + t0 = tcg_temp_new_i64(); \
> + t1 = tcg_temp_new_i64(); \
> + t2 = tcg_temp_new_i64(); \
> gen_reset_fpstatus(); \
> - gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env, \
> - cpu_fpr[rA(ctx->opcode)], \
> - cpu_fpr[rC(ctx->opcode)]); \
> + get_fpr(t0, rA(ctx->opcode)); \
> + get_fpr(t1, rC(ctx->opcode)); \
> + gen_helper_f##op(t2, cpu_env, t0, t1); \
> + set_fpr(rD(ctx->opcode), t2); \
> if (isfloat) { \
> - gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env, \
> - cpu_fpr[rD(ctx->opcode)]); \
> + get_fpr(t0, rD(ctx->opcode)); \
> + gen_helper_frsp(t2, cpu_env, t0); \
> + set_fpr(rD(ctx->opcode), t2); \
> } \
> if (set_fprf) { \
> - gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]); \
> + gen_compute_fprf_float64(t2); \
> } \
> if (unlikely(Rc(ctx->opcode) != 0)) { \
> gen_set_cr1_from_fpscr(ctx); \
> } \
> + tcg_temp_free_i64(t0); \
> + tcg_temp_free_i64(t1); \
> + tcg_temp_free_i64(t2); \
> }
> #define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
> _GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
> @@ -113,37 +150,51 @@ _GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
> #define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
> static void gen_f##name(DisasContext *ctx) \
> { \
> + TCGv_i64 t0; \
> + TCGv_i64 t1; \
> if (unlikely(!ctx->fpu_enabled)) { \
> gen_exception(ctx, POWERPC_EXCP_FPU); \
> return; \
> } \
> + t0 = tcg_temp_new_i64(); \
> + t1 = tcg_temp_new_i64(); \
> gen_reset_fpstatus(); \
> - gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env, \
> - cpu_fpr[rB(ctx->opcode)]); \
> + get_fpr(t0, rB(ctx->opcode)); \
> + gen_helper_f##name(t1, cpu_env, t0); \
> + set_fpr(rD(ctx->opcode), t1); \
> if (set_fprf) { \
> - gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]); \
> + gen_compute_fprf_float64(t1); \
> } \
> if (unlikely(Rc(ctx->opcode) != 0)) { \
> gen_set_cr1_from_fpscr(ctx); \
> } \
> + tcg_temp_free_i64(t0); \
> + tcg_temp_free_i64(t1); \
> }
>
> #define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
> static void gen_f##name(DisasContext *ctx) \
> { \
> + TCGv_i64 t0; \
> + TCGv_i64 t1; \
> if (unlikely(!ctx->fpu_enabled)) { \
> gen_exception(ctx, POWERPC_EXCP_FPU); \
> return; \
> } \
> + t0 = tcg_temp_new_i64(); \
> + t1 = tcg_temp_new_i64(); \
> gen_reset_fpstatus(); \
> - gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env, \
> - cpu_fpr[rB(ctx->opcode)]); \
> + get_fpr(t0, rB(ctx->opcode)); \
> + gen_helper_f##name(t1, cpu_env, t0); \
> + set_fpr(rD(ctx->opcode), t1); \
> if (set_fprf) { \
> - gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]); \
> + gen_compute_fprf_float64(t1); \
> } \
> if (unlikely(Rc(ctx->opcode) != 0)) { \
> gen_set_cr1_from_fpscr(ctx); \
> } \
> + tcg_temp_free_i64(t0); \
> + tcg_temp_free_i64(t1); \
> }
>
> /* fadd - fadds */
> @@ -165,19 +216,25 @@ GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
> /* frsqrtes */
> static void gen_frsqrtes(DisasContext *ctx)
> {
> + TCGv_i64 t0;
> + TCGv_i64 t1;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> }
> + t0 = tcg_temp_new_i64();
> + t1 = tcg_temp_new_i64();
> gen_reset_fpstatus();
> - gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_env,
> - cpu_fpr[rB(ctx->opcode)]);
> - gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,
> - cpu_fpr[rD(ctx->opcode)]);
> - gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]);
> + get_fpr(t0, rB(ctx->opcode));
> + gen_helper_frsqrte(t1, cpu_env, t0);
> + set_fpr(rD(ctx->opcode), t1);
> + gen_helper_frsp(t1, cpu_env, t1);
> + gen_compute_fprf_float64(t1);
> if (unlikely(Rc(ctx->opcode) != 0)) {
> gen_set_cr1_from_fpscr(ctx);
> }
> + tcg_temp_free_i64(t0);
> + tcg_temp_free_i64(t1);
> }
>
> /* fsel */
> @@ -189,34 +246,47 @@ GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
> /* fsqrt */
> static void gen_fsqrt(DisasContext *ctx)
> {
> + TCGv_i64 t0;
> + TCGv_i64 t1;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> }
> + t0 = tcg_temp_new_i64();
> + t1 = tcg_temp_new_i64();
> gen_reset_fpstatus();
> - gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
> - cpu_fpr[rB(ctx->opcode)]);
> - gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]);
> + get_fpr(t0, rB(ctx->opcode));
> + gen_helper_fsqrt(t1, cpu_env, t0);
> + set_fpr(rD(ctx->opcode), t1);
> + gen_compute_fprf_float64(t1);
> if (unlikely(Rc(ctx->opcode) != 0)) {
> gen_set_cr1_from_fpscr(ctx);
> }
> + tcg_temp_free_i64(t0);
> + tcg_temp_free_i64(t1);
> }
>
> static void gen_fsqrts(DisasContext *ctx)
> {
> + TCGv_i64 t0;
> + TCGv_i64 t1;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> }
> + t0 = tcg_temp_new_i64();
> + t1 = tcg_temp_new_i64();
> gen_reset_fpstatus();
> - gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
> - cpu_fpr[rB(ctx->opcode)]);
> - gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,
> - cpu_fpr[rD(ctx->opcode)]);
> - gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]);
> + get_fpr(t0, rB(ctx->opcode));
> + gen_helper_fsqrt(t1, cpu_env, t0);
> + set_fpr(rD(ctx->opcode), t1);
> + gen_helper_frsp(t1, cpu_env, t1);
> + gen_compute_fprf_float64(t1);
> if (unlikely(Rc(ctx->opcode) != 0)) {
> gen_set_cr1_from_fpscr(ctx);
> }
> + tcg_temp_free_i64(t0);
> + tcg_temp_free_i64(t1);
> }
>
> /*** Floating-Point multiply-and-add ***/
> @@ -268,21 +338,32 @@ GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
>
> static void gen_ftdiv(DisasContext *ctx)
> {
> + TCGv_i64 t0;
> + TCGv_i64 t1;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> }
> - gen_helper_ftdiv(cpu_crf[crfD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
> - cpu_fpr[rB(ctx->opcode)]);
> + t0 = tcg_temp_new_i64();
> + t1 = tcg_temp_new_i64();
> + get_fpr(t0, rA(ctx->opcode));
> + get_fpr(t1, rB(ctx->opcode));
> + gen_helper_ftdiv(cpu_crf[crfD(ctx->opcode)], t0, t1);
> + tcg_temp_free_i64(t0);
> + tcg_temp_free_i64(t1);
> }
>
> static void gen_ftsqrt(DisasContext *ctx)
> {
> + TCGv_i64 t0;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> }
> - gen_helper_ftsqrt(cpu_crf[crfD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
> + t0 = tcg_temp_new_i64();
> + get_fpr(t0, rB(ctx->opcode));
> + gen_helper_ftsqrt(cpu_crf[crfD(ctx->opcode)], t0);
> + tcg_temp_free_i64(t0);
> }
>
>
> @@ -293,32 +374,46 @@ static void gen_ftsqrt(DisasContext *ctx)
> static void gen_fcmpo(DisasContext *ctx)
> {
> TCGv_i32 crf;
> + TCGv_i64 t0;
> + TCGv_i64 t1;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> }
> + t0 = tcg_temp_new_i64();
> + t1 = tcg_temp_new_i64();
> gen_reset_fpstatus();
> crf = tcg_const_i32(crfD(ctx->opcode));
> - gen_helper_fcmpo(cpu_env, cpu_fpr[rA(ctx->opcode)],
> - cpu_fpr[rB(ctx->opcode)], crf);
> + get_fpr(t0, rA(ctx->opcode));
> + get_fpr(t1, rB(ctx->opcode));
> + gen_helper_fcmpo(cpu_env, t0, t1, crf);
> tcg_temp_free_i32(crf);
> gen_helper_float_check_status(cpu_env);
> + tcg_temp_free_i64(t0);
> + tcg_temp_free_i64(t1);
> }
>
> /* fcmpu */
> static void gen_fcmpu(DisasContext *ctx)
> {
> TCGv_i32 crf;
> + TCGv_i64 t0;
> + TCGv_i64 t1;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> }
> + t0 = tcg_temp_new_i64();
> + t1 = tcg_temp_new_i64();
> gen_reset_fpstatus();
> crf = tcg_const_i32(crfD(ctx->opcode));
> - gen_helper_fcmpu(cpu_env, cpu_fpr[rA(ctx->opcode)],
> - cpu_fpr[rB(ctx->opcode)], crf);
> + get_fpr(t0, rA(ctx->opcode));
> + get_fpr(t1, rB(ctx->opcode));
> + gen_helper_fcmpu(cpu_env, t0, t1, crf);
> tcg_temp_free_i32(crf);
> gen_helper_float_check_status(cpu_env);
> + tcg_temp_free_i64(t0);
> + tcg_temp_free_i64(t1);
> }
>
> /*** Floating-point move ***/
> @@ -326,100 +421,153 @@ static void gen_fcmpu(DisasContext *ctx)
> /* XXX: beware that fabs never checks for NaNs nor update FPSCR */
> static void gen_fabs(DisasContext *ctx)
> {
> + TCGv_i64 t0;
> + TCGv_i64 t1;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> }
> - tcg_gen_andi_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
> - ~(1ULL << 63));
> + t0 = tcg_temp_new_i64();
> + t1 = tcg_temp_new_i64();
> + get_fpr(t0, rB(ctx->opcode));
> + tcg_gen_andi_i64(t1, t0, ~(1ULL << 63));
> + set_fpr(rD(ctx->opcode), t1);
> if (unlikely(Rc(ctx->opcode))) {
> gen_set_cr1_from_fpscr(ctx);
> }
> + tcg_temp_free_i64(t0);
> + tcg_temp_free_i64(t1);
> }
>
> /* fmr - fmr. */
> /* XXX: beware that fmr never checks for NaNs nor update FPSCR */
> static void gen_fmr(DisasContext *ctx)
> {
> + TCGv_i64 t0;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> }
> - tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
> + t0 = tcg_temp_new_i64();
> + get_fpr(t0, rB(ctx->opcode));
> + set_fpr(rD(ctx->opcode), t0);
> if (unlikely(Rc(ctx->opcode))) {
> gen_set_cr1_from_fpscr(ctx);
> }
> + tcg_temp_free_i64(t0);
> }
>
> /* fnabs */
> /* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
> static void gen_fnabs(DisasContext *ctx)
> {
> + TCGv_i64 t0;
> + TCGv_i64 t1;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> }
> - tcg_gen_ori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
> - 1ULL << 63);
> + t0 = tcg_temp_new_i64();
> + t1 = tcg_temp_new_i64();
> + get_fpr(t0, rB(ctx->opcode));
> + tcg_gen_ori_i64(t1, t0, 1ULL << 63);
> + set_fpr(rD(ctx->opcode), t1);
> if (unlikely(Rc(ctx->opcode))) {
> gen_set_cr1_from_fpscr(ctx);
> }
> + tcg_temp_free_i64(t0);
> + tcg_temp_free_i64(t1);
> }
>
> /* fneg */
> /* XXX: beware that fneg never checks for NaNs nor update FPSCR */
> static void gen_fneg(DisasContext *ctx)
> {
> + TCGv_i64 t0;
> + TCGv_i64 t1;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> }
> - tcg_gen_xori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
> - 1ULL << 63);
> + t0 = tcg_temp_new_i64();
> + t1 = tcg_temp_new_i64();
> + get_fpr(t0, rB(ctx->opcode));
> + tcg_gen_xori_i64(t1, t0, 1ULL << 63);
> + set_fpr(rD(ctx->opcode), t1);
> if (unlikely(Rc(ctx->opcode))) {
> gen_set_cr1_from_fpscr(ctx);
> }
> + tcg_temp_free_i64(t0);
> + tcg_temp_free_i64(t1);
> }
>
> /* fcpsgn: PowerPC 2.05 specification */
> /* XXX: beware that fcpsgn never checks for NaNs nor update FPSCR */
> static void gen_fcpsgn(DisasContext *ctx)
> {
> + TCGv_i64 t0;
> + TCGv_i64 t1;
> + TCGv_i64 t2;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> }
> - tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
> - cpu_fpr[rB(ctx->opcode)], 0, 63);
> + t0 = tcg_temp_new_i64();
> + t1 = tcg_temp_new_i64();
> + t2 = tcg_temp_new_i64();
> + get_fpr(t0, rA(ctx->opcode));
> + get_fpr(t1, rB(ctx->opcode));
> + tcg_gen_deposit_i64(t2, t0, t1, 0, 63);
> + set_fpr(rD(ctx->opcode), t2);
> if (unlikely(Rc(ctx->opcode))) {
> gen_set_cr1_from_fpscr(ctx);
> }
> + tcg_temp_free_i64(t0);
> + tcg_temp_free_i64(t1);
> + tcg_temp_free_i64(t2);
> }
>
> static void gen_fmrgew(DisasContext *ctx)
> {
> TCGv_i64 b0;
> + TCGv_i64 t0;
> + TCGv_i64 t1;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> }
> b0 = tcg_temp_new_i64();
> - tcg_gen_shri_i64(b0, cpu_fpr[rB(ctx->opcode)], 32);
> - tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
> - b0, 0, 32);
> + t0 = tcg_temp_new_i64();
> + t1 = tcg_temp_new_i64();
> + get_fpr(t0, rB(ctx->opcode));
> + tcg_gen_shri_i64(b0, t0, 32);
> + get_fpr(t0, rA(ctx->opcode));
> + tcg_gen_deposit_i64(t1, t0, b0, 0, 32);
> + set_fpr(rD(ctx->opcode), t1);
> tcg_temp_free_i64(b0);
> + tcg_temp_free_i64(t0);
> + tcg_temp_free_i64(t1);
> }
>
> static void gen_fmrgow(DisasContext *ctx)
> {
> + TCGv_i64 t0;
> + TCGv_i64 t1;
> + TCGv_i64 t2;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> }
> - tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)],
> - cpu_fpr[rB(ctx->opcode)],
> - cpu_fpr[rA(ctx->opcode)],
> - 32, 32);
> + t0 = tcg_temp_new_i64();
> + t1 = tcg_temp_new_i64();
> + t2 = tcg_temp_new_i64();
> + get_fpr(t0, rB(ctx->opcode));
> + get_fpr(t1, rA(ctx->opcode));
> + tcg_gen_deposit_i64(t2, t0, t1, 32, 32);
> + set_fpr(rD(ctx->opcode), t2);
> + tcg_temp_free_i64(t0);
> + tcg_temp_free_i64(t1);
> + tcg_temp_free_i64(t2);
> }
>
> /*** Floating-Point status & ctrl register ***/
> @@ -458,15 +606,19 @@ static void gen_mcrfs(DisasContext *ctx)
> /* mffs */
> static void gen_mffs(DisasContext *ctx)
> {
> + TCGv_i64 t0;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> }
> + t0 = tcg_temp_new_i64();
> gen_reset_fpstatus();
> - tcg_gen_extu_tl_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
> + tcg_gen_extu_tl_i64(t0, cpu_fpscr);
> + set_fpr(rD(ctx->opcode), t0);
> if (unlikely(Rc(ctx->opcode))) {
> gen_set_cr1_from_fpscr(ctx);
> }
> + tcg_temp_free_i64(t0);
> }
>
> /* mtfsb0 */
> @@ -522,6 +674,7 @@ static void gen_mtfsb1(DisasContext *ctx)
> static void gen_mtfsf(DisasContext *ctx)
> {
> TCGv_i32 t0;
> + TCGv_i64 t1;
> int flm, l, w;
>
> if (unlikely(!ctx->fpu_enabled)) {
> @@ -541,7 +694,9 @@ static void gen_mtfsf(DisasContext *ctx)
> } else {
> t0 = tcg_const_i32(flm << (w * 8));
> }
> - gen_helper_store_fpscr(cpu_env, cpu_fpr[rB(ctx->opcode)], t0);
> + t1 = tcg_temp_new_i64();
> + get_fpr(t1, rB(ctx->opcode));
> + gen_helper_store_fpscr(cpu_env, t1, t0);
> tcg_temp_free_i32(t0);
> if (unlikely(Rc(ctx->opcode) != 0)) {
> tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
> @@ -549,6 +704,7 @@ static void gen_mtfsf(DisasContext *ctx)
> }
> /* We can raise a differed exception */
> gen_helper_float_check_status(cpu_env);
> + tcg_temp_free_i64(t1);
> }
>
> /* mtfsfi */
> @@ -588,21 +744,26 @@ static void gen_mtfsfi(DisasContext *ctx)
> static void glue(gen_, name)(DisasContext *ctx) \
> { \
> TCGv EA; \
> + TCGv_i64 t0; \
> if (unlikely(!ctx->fpu_enabled)) { \
> gen_exception(ctx, POWERPC_EXCP_FPU); \
> return; \
> } \
> gen_set_access_type(ctx, ACCESS_FLOAT); \
> EA = tcg_temp_new(); \
> + t0 = tcg_temp_new_i64(); \
> gen_addr_imm_index(ctx, EA, 0); \
> - gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
> + gen_qemu_##ldop(ctx, t0, EA); \
> + set_fpr(rD(ctx->opcode), t0); \
> tcg_temp_free(EA); \
> + tcg_temp_free_i64(t0); \
> }
>
> #define GEN_LDUF(name, ldop, opc, type) \
> static void glue(gen_, name##u)(DisasContext *ctx) \
> { \
> TCGv EA; \
> + TCGv_i64 t0; \
> if (unlikely(!ctx->fpu_enabled)) { \
> gen_exception(ctx, POWERPC_EXCP_FPU); \
> return; \
> @@ -613,20 +774,25 @@ static void glue(gen_, name##u)(DisasContext *ctx)
> } \
> gen_set_access_type(ctx, ACCESS_FLOAT); \
> EA = tcg_temp_new(); \
> + t0 = tcg_temp_new_i64(); \
> gen_addr_imm_index(ctx, EA, 0); \
> - gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
> + gen_qemu_##ldop(ctx, t0, EA); \
> + set_fpr(rD(ctx->opcode), t0); \
> tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
> tcg_temp_free(EA); \
> + tcg_temp_free_i64(t0); \
> }
>
> #define GEN_LDUXF(name, ldop, opc, type) \
> static void glue(gen_, name##ux)(DisasContext *ctx) \
> { \
> TCGv EA; \
> + TCGv_i64 t0; \
> if (unlikely(!ctx->fpu_enabled)) { \
> gen_exception(ctx, POWERPC_EXCP_FPU); \
> return; \
> } \
> + t0 = tcg_temp_new_i64(); \
> if (unlikely(rA(ctx->opcode) == 0)) { \
> gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
> return; \
> @@ -634,24 +800,30 @@ static void glue(gen_, name##ux)(DisasContext *ctx)
> gen_set_access_type(ctx, ACCESS_FLOAT); \
> EA = tcg_temp_new(); \
> gen_addr_reg_index(ctx, EA); \
> - gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
> + gen_qemu_##ldop(ctx, t0, EA); \
> + set_fpr(rD(ctx->opcode), t0); \
> tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
> tcg_temp_free(EA); \
> + tcg_temp_free_i64(t0); \
> }
>
> #define GEN_LDXF(name, ldop, opc2, opc3, type) \
> static void glue(gen_, name##x)(DisasContext *ctx) \
> { \
> TCGv EA; \
> + TCGv_i64 t0; \
> if (unlikely(!ctx->fpu_enabled)) { \
> gen_exception(ctx, POWERPC_EXCP_FPU); \
> return; \
> } \
> gen_set_access_type(ctx, ACCESS_FLOAT); \
> EA = tcg_temp_new(); \
> + t0 = tcg_temp_new_i64(); \
> gen_addr_reg_index(ctx, EA); \
> - gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
> + gen_qemu_##ldop(ctx, t0, EA); \
> + set_fpr(rD(ctx->opcode), t0); \
> tcg_temp_free(EA); \
> + tcg_temp_free_i64(t0); \
> }
>
> #define GEN_LDFS(name, ldop, op, type) \
> @@ -677,6 +849,7 @@ GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
> static void gen_lfdepx(DisasContext *ctx)
> {
> TCGv EA;
> + TCGv_i64 t0;
> CHK_SV;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> @@ -684,16 +857,19 @@ static void gen_lfdepx(DisasContext *ctx)
> }
> gen_set_access_type(ctx, ACCESS_FLOAT);
> EA = tcg_temp_new();
> + t0 = tcg_temp_new_i64();
> gen_addr_reg_index(ctx, EA);
> - tcg_gen_qemu_ld_i64(cpu_fpr[rD(ctx->opcode)], EA, PPC_TLB_EPID_LOAD,
> - DEF_MEMOP(MO_Q));
> + tcg_gen_qemu_ld_i64(t0, EA, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_Q));
> + set_fpr(rD(ctx->opcode), t0);
> tcg_temp_free(EA);
> + tcg_temp_free_i64(t0);
> }
>
> /* lfdp */
> static void gen_lfdp(DisasContext *ctx)
> {
> TCGv EA;
> + TCGv_i64 t0;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> @@ -701,24 +877,31 @@ static void gen_lfdp(DisasContext *ctx)
> gen_set_access_type(ctx, ACCESS_FLOAT);
> EA = tcg_temp_new();
> gen_addr_imm_index(ctx, EA, 0);
> + t0 = tcg_temp_new_i64();
> /* We only need to swap high and low halves. gen_qemu_ld64_i64 does
> necessary 64-bit byteswap already. */
> if (unlikely(ctx->le_mode)) {
> - gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
> + gen_qemu_ld64_i64(ctx, t0, EA);
> + set_fpr(rD(ctx->opcode) + 1, t0);
> tcg_gen_addi_tl(EA, EA, 8);
> - gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
> + gen_qemu_ld64_i64(ctx, t0, EA);
> + set_fpr(rD(ctx->opcode), t0);
> } else {
> - gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
> + gen_qemu_ld64_i64(ctx, t0, EA);
> + set_fpr(rD(ctx->opcode), t0);
> tcg_gen_addi_tl(EA, EA, 8);
> - gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
> + gen_qemu_ld64_i64(ctx, t0, EA);
> + set_fpr(rD(ctx->opcode) + 1, t0);
> }
> tcg_temp_free(EA);
> + tcg_temp_free_i64(t0);
> }
>
> /* lfdpx */
> static void gen_lfdpx(DisasContext *ctx)
> {
> TCGv EA;
> + TCGv_i64 t0;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> @@ -726,18 +909,24 @@ static void gen_lfdpx(DisasContext *ctx)
> gen_set_access_type(ctx, ACCESS_FLOAT);
> EA = tcg_temp_new();
> gen_addr_reg_index(ctx, EA);
> + t0 = tcg_temp_new_i64();
> /* We only need to swap high and low halves. gen_qemu_ld64_i64 does
> necessary 64-bit byteswap already. */
> if (unlikely(ctx->le_mode)) {
> - gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
> + gen_qemu_ld64_i64(ctx, t0, EA);
> + set_fpr(rD(ctx->opcode) + 1, t0);
> tcg_gen_addi_tl(EA, EA, 8);
> - gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
> + gen_qemu_ld64_i64(ctx, t0, EA);
> + set_fpr(rD(ctx->opcode), t0);
> } else {
> - gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
> + gen_qemu_ld64_i64(ctx, t0, EA);
> + set_fpr(rD(ctx->opcode), t0);
> tcg_gen_addi_tl(EA, EA, 8);
> - gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
> + gen_qemu_ld64_i64(ctx, t0, EA);
> + set_fpr(rD(ctx->opcode) + 1, t0);
> }
> tcg_temp_free(EA);
> + tcg_temp_free_i64(t0);
> }
>
> /* lfiwax */
> @@ -745,6 +934,7 @@ static void gen_lfiwax(DisasContext *ctx)
> {
> TCGv EA;
> TCGv t0;
> + TCGv_i64 t1;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> @@ -752,47 +942,59 @@ static void gen_lfiwax(DisasContext *ctx)
> gen_set_access_type(ctx, ACCESS_FLOAT);
> EA = tcg_temp_new();
> t0 = tcg_temp_new();
> + t1 = tcg_temp_new_i64();
> gen_addr_reg_index(ctx, EA);
> gen_qemu_ld32s(ctx, t0, EA);
> - tcg_gen_ext_tl_i64(cpu_fpr[rD(ctx->opcode)], t0);
> + tcg_gen_ext_tl_i64(t1, t0);
> + set_fpr(rD(ctx->opcode), t1);
> tcg_temp_free(EA);
> tcg_temp_free(t0);
> + tcg_temp_free_i64(t1);
> }
>
> /* lfiwzx */
> static void gen_lfiwzx(DisasContext *ctx)
> {
> TCGv EA;
> + TCGv_i64 t0;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> }
> gen_set_access_type(ctx, ACCESS_FLOAT);
> EA = tcg_temp_new();
> + t0 = tcg_temp_new_i64();
> gen_addr_reg_index(ctx, EA);
> - gen_qemu_ld32u_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
> + gen_qemu_ld32u_i64(ctx, t0, EA);
> + set_fpr(rD(ctx->opcode), t0);
> tcg_temp_free(EA);
> + tcg_temp_free_i64(t0);
> }
> /*** Floating-point store ***/
> #define GEN_STF(name, stop, opc, type) \
> static void glue(gen_, name)(DisasContext *ctx) \
> { \
> TCGv EA; \
> + TCGv_i64 t0; \
> if (unlikely(!ctx->fpu_enabled)) { \
> gen_exception(ctx, POWERPC_EXCP_FPU); \
> return; \
> } \
> gen_set_access_type(ctx, ACCESS_FLOAT); \
> EA = tcg_temp_new(); \
> + t0 = tcg_temp_new_i64(); \
> gen_addr_imm_index(ctx, EA, 0); \
> - gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
> + get_fpr(t0, rS(ctx->opcode)); \
> + gen_qemu_##stop(ctx, t0, EA); \
> tcg_temp_free(EA); \
> + tcg_temp_free_i64(t0); \
> }
>
> #define GEN_STUF(name, stop, opc, type) \
> static void glue(gen_, name##u)(DisasContext *ctx) \
> { \
> TCGv EA; \
> + TCGv_i64 t0; \
> if (unlikely(!ctx->fpu_enabled)) { \
> gen_exception(ctx, POWERPC_EXCP_FPU); \
> return; \
> @@ -803,16 +1005,20 @@ static void glue(gen_, name##u)(DisasContext *ctx)
> } \
> gen_set_access_type(ctx, ACCESS_FLOAT); \
> EA = tcg_temp_new(); \
> + t0 = tcg_temp_new_i64(); \
> gen_addr_imm_index(ctx, EA, 0); \
> - gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
> + get_fpr(t0, rS(ctx->opcode)); \
> + gen_qemu_##stop(ctx, t0, EA); \
> tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
> tcg_temp_free(EA); \
> + tcg_temp_free_i64(t0); \
> }
>
> #define GEN_STUXF(name, stop, opc, type) \
> static void glue(gen_, name##ux)(DisasContext *ctx) \
> { \
> TCGv EA; \
> + TCGv_i64 t0; \
> if (unlikely(!ctx->fpu_enabled)) { \
> gen_exception(ctx, POWERPC_EXCP_FPU); \
> return; \
> @@ -823,25 +1029,32 @@ static void glue(gen_, name##ux)(DisasContext *ctx)
> } \
> gen_set_access_type(ctx, ACCESS_FLOAT); \
> EA = tcg_temp_new(); \
> + t0 = tcg_temp_new_i64(); \
> gen_addr_reg_index(ctx, EA); \
> - gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
> + get_fpr(t0, rS(ctx->opcode)); \
> + gen_qemu_##stop(ctx, t0, EA); \
> tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
> tcg_temp_free(EA); \
> + tcg_temp_free_i64(t0); \
> }
>
> #define GEN_STXF(name, stop, opc2, opc3, type) \
> static void glue(gen_, name##x)(DisasContext *ctx) \
> { \
> TCGv EA; \
> + TCGv_i64 t0; \
> if (unlikely(!ctx->fpu_enabled)) { \
> gen_exception(ctx, POWERPC_EXCP_FPU); \
> return; \
> } \
> gen_set_access_type(ctx, ACCESS_FLOAT); \
> EA = tcg_temp_new(); \
> + t0 = tcg_temp_new_i64(); \
> gen_addr_reg_index(ctx, EA); \
> - gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
> + get_fpr(t0, rS(ctx->opcode)); \
> + gen_qemu_##stop(ctx, t0, EA); \
> tcg_temp_free(EA); \
> + tcg_temp_free_i64(t0); \
> }
>
> #define GEN_STFS(name, stop, op, type) \
> @@ -867,6 +1080,7 @@ GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
> static void gen_stfdepx(DisasContext *ctx)
> {
> TCGv EA;
> + TCGv_i64 t0;
> CHK_SV;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> @@ -874,60 +1088,76 @@ static void gen_stfdepx(DisasContext *ctx)
> }
> gen_set_access_type(ctx, ACCESS_FLOAT);
> EA = tcg_temp_new();
> + t0 = tcg_temp_new_i64();
> gen_addr_reg_index(ctx, EA);
> - tcg_gen_qemu_st_i64(cpu_fpr[rD(ctx->opcode)], EA, PPC_TLB_EPID_STORE,
> - DEF_MEMOP(MO_Q));
> + get_fpr(t0, rD(ctx->opcode));
> + tcg_gen_qemu_st_i64(t0, EA, PPC_TLB_EPID_STORE, DEF_MEMOP(MO_Q));
> tcg_temp_free(EA);
> + tcg_temp_free_i64(t0);
> }
>
> /* stfdp */
> static void gen_stfdp(DisasContext *ctx)
> {
> TCGv EA;
> + TCGv_i64 t0;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> }
> gen_set_access_type(ctx, ACCESS_FLOAT);
> EA = tcg_temp_new();
> + t0 = tcg_temp_new_i64();
> gen_addr_imm_index(ctx, EA, 0);
> /* We only need to swap high and low halves. gen_qemu_st64_i64 does
> necessary 64-bit byteswap already. */
> if (unlikely(ctx->le_mode)) {
> - gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
> + get_fpr(t0, rD(ctx->opcode) + 1);
> + gen_qemu_st64_i64(ctx, t0, EA);
> tcg_gen_addi_tl(EA, EA, 8);
> - gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
> + get_fpr(t0, rD(ctx->opcode));
> + gen_qemu_st64_i64(ctx, t0, EA);
> } else {
> - gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
> + get_fpr(t0, rD(ctx->opcode));
> + gen_qemu_st64_i64(ctx, t0, EA);
> tcg_gen_addi_tl(EA, EA, 8);
> - gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
> + get_fpr(t0, rD(ctx->opcode) + 1);
> + gen_qemu_st64_i64(ctx, t0, EA);
> }
> tcg_temp_free(EA);
> + tcg_temp_free_i64(t0);
> }
>
> /* stfdpx */
> static void gen_stfdpx(DisasContext *ctx)
> {
> TCGv EA;
> + TCGv_i64 t0;
> if (unlikely(!ctx->fpu_enabled)) {
> gen_exception(ctx, POWERPC_EXCP_FPU);
> return;
> }
> gen_set_access_type(ctx, ACCESS_FLOAT);
> EA = tcg_temp_new();
> + t0 = tcg_temp_new_i64();
> gen_addr_reg_index(ctx, EA);
> /* We only need to swap high and low halves. gen_qemu_st64_i64 does
> necessary 64-bit byteswap already. */
> if (unlikely(ctx->le_mode)) {
> - gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
> + get_fpr(t0, rD(ctx->opcode) + 1);
> + gen_qemu_st64_i64(ctx, t0, EA);
> tcg_gen_addi_tl(EA, EA, 8);
> - gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
> + get_fpr(t0, rD(ctx->opcode));
> + gen_qemu_st64_i64(ctx, t0, EA);
> } else {
> - gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
> + get_fpr(t0, rD(ctx->opcode));
> + gen_qemu_st64_i64(ctx, t0, EA);
> tcg_gen_addi_tl(EA, EA, 8);
> - gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
> + get_fpr(t0, rD(ctx->opcode) + 1);
> + gen_qemu_st64_i64(ctx, t0, EA);
> }
> tcg_temp_free(EA);
> + tcg_temp_free_i64(t0);
> }
>
> /* Optional: */
> @@ -949,13 +1179,18 @@ static void gen_lfq(DisasContext *ctx)
> {
> int rd = rD(ctx->opcode);
> TCGv t0;
> + TCGv_i64 t1;
> gen_set_access_type(ctx, ACCESS_FLOAT);
> t0 = tcg_temp_new();
> + t1 = tcg_temp_new_i64();
> gen_addr_imm_index(ctx, t0, 0);
> - gen_qemu_ld64_i64(ctx, cpu_fpr[rd], t0);
> + gen_qemu_ld64_i64(ctx, t1, t0);
> + set_fpr(rd, t1);
> gen_addr_add(ctx, t0, t0, 8);
> - gen_qemu_ld64_i64(ctx, cpu_fpr[(rd + 1) % 32], t0);
> + gen_qemu_ld64_i64(ctx, t1, t0);
> + set_fpr((rd + 1) % 32, t1);
> tcg_temp_free(t0);
> + tcg_temp_free_i64(t1);
> }
>
> /* lfqu */
> @@ -964,17 +1199,22 @@ static void gen_lfqu(DisasContext *ctx)
> int ra = rA(ctx->opcode);
> int rd = rD(ctx->opcode);
> TCGv t0, t1;
> + TCGv_i64 t2;
> gen_set_access_type(ctx, ACCESS_FLOAT);
> t0 = tcg_temp_new();
> t1 = tcg_temp_new();
> + t2 = tcg_temp_new_i64();
> gen_addr_imm_index(ctx, t0, 0);
> - gen_qemu_ld64_i64(ctx, cpu_fpr[rd], t0);
> + gen_qemu_ld64_i64(ctx, t2, t0);
> + set_fpr(rd, t2);
> gen_addr_add(ctx, t1, t0, 8);
> - gen_qemu_ld64_i64(ctx, cpu_fpr[(rd + 1) % 32], t1);
> + gen_qemu_ld64_i64(ctx, t2, t1);
> + set_fpr((rd + 1) % 32, t2);
> if (ra != 0)
> tcg_gen_mov_tl(cpu_gpr[ra], t0);
> tcg_temp_free(t0);
> tcg_temp_free(t1);
> + tcg_temp_free_i64(t2);
> }
>
> /* lfqux */
> @@ -984,16 +1224,21 @@ static void gen_lfqux(DisasContext *ctx)
> int rd = rD(ctx->opcode);
> gen_set_access_type(ctx, ACCESS_FLOAT);
> TCGv t0, t1;
> + TCGv_i64 t2;
> + t2 = tcg_temp_new_i64();
> t0 = tcg_temp_new();
> gen_addr_reg_index(ctx, t0);
> - gen_qemu_ld64_i64(ctx, cpu_fpr[rd], t0);
> + gen_qemu_ld64_i64(ctx, t2, t0);
> + set_fpr(rd, t2);
> t1 = tcg_temp_new();
> gen_addr_add(ctx, t1, t0, 8);
> - gen_qemu_ld64_i64(ctx, cpu_fpr[(rd + 1) % 32], t1);
> + gen_qemu_ld64_i64(ctx, t2, t1);
> + set_fpr((rd + 1) % 32, t2);
> tcg_temp_free(t1);
> if (ra != 0)
> tcg_gen_mov_tl(cpu_gpr[ra], t0);
> tcg_temp_free(t0);
> + tcg_temp_free_i64(t2);
> }
>
> /* lfqx */
> @@ -1001,13 +1246,18 @@ static void gen_lfqx(DisasContext *ctx)
> {
> int rd = rD(ctx->opcode);
> TCGv t0;
> + TCGv_i64 t1;
> gen_set_access_type(ctx, ACCESS_FLOAT);
> t0 = tcg_temp_new();
> + t1 = tcg_temp_new_i64();
> gen_addr_reg_index(ctx, t0);
> - gen_qemu_ld64_i64(ctx, cpu_fpr[rd], t0);
> + gen_qemu_ld64_i64(ctx, t1, t0);
> + set_fpr(rd, t1);
> gen_addr_add(ctx, t0, t0, 8);
> - gen_qemu_ld64_i64(ctx, cpu_fpr[(rd + 1) % 32], t0);
> + gen_qemu_ld64_i64(ctx, t1, t0);
> + set_fpr((rd + 1) % 32, t1);
> tcg_temp_free(t0);
> + tcg_temp_free_i64(t1);
> }
>
> /* stfq */
> @@ -1015,13 +1265,18 @@ static void gen_stfq(DisasContext *ctx)
> {
> int rd = rD(ctx->opcode);
> TCGv t0;
> + TCGv_i64 t1;
> gen_set_access_type(ctx, ACCESS_FLOAT);
> t0 = tcg_temp_new();
> + t1 = tcg_temp_new_i64();
> gen_addr_imm_index(ctx, t0, 0);
> - gen_qemu_st64_i64(ctx, cpu_fpr[rd], t0);
> + get_fpr(t1, rd);
> + gen_qemu_st64_i64(ctx, t1, t0);
> gen_addr_add(ctx, t0, t0, 8);
> - gen_qemu_st64_i64(ctx, cpu_fpr[(rd + 1) % 32], t0);
> + get_fpr(t1, (rd + 1) % 32);
> + gen_qemu_st64_i64(ctx, t1, t0);
> tcg_temp_free(t0);
> + tcg_temp_free_i64(t1);
> }
>
> /* stfqu */
> @@ -1030,17 +1285,23 @@ static void gen_stfqu(DisasContext *ctx)
> int ra = rA(ctx->opcode);
> int rd = rD(ctx->opcode);
> TCGv t0, t1;
> + TCGv_i64 t2;
> gen_set_access_type(ctx, ACCESS_FLOAT);
> + t2 = tcg_temp_new_i64();
> t0 = tcg_temp_new();
> gen_addr_imm_index(ctx, t0, 0);
> - gen_qemu_st64_i64(ctx, cpu_fpr[rd], t0);
> + get_fpr(t2, rd);
> + gen_qemu_st64_i64(ctx, t2, t0);
> t1 = tcg_temp_new();
> gen_addr_add(ctx, t1, t0, 8);
> - gen_qemu_st64_i64(ctx, cpu_fpr[(rd + 1) % 32], t1);
> + get_fpr(t2, (rd + 1) % 32);
> + gen_qemu_st64_i64(ctx, t2, t1);
> tcg_temp_free(t1);
> - if (ra != 0)
> + if (ra != 0) {
> tcg_gen_mov_tl(cpu_gpr[ra], t0);
> + }
> tcg_temp_free(t0);
> + tcg_temp_free_i64(t2);
> }
>
> /* stfqux */
> @@ -1049,17 +1310,23 @@ static void gen_stfqux(DisasContext *ctx)
> int ra = rA(ctx->opcode);
> int rd = rD(ctx->opcode);
> TCGv t0, t1;
> + TCGv_i64 t2;
> gen_set_access_type(ctx, ACCESS_FLOAT);
> + t2 = tcg_temp_new_i64();
> t0 = tcg_temp_new();
> gen_addr_reg_index(ctx, t0);
> - gen_qemu_st64_i64(ctx, cpu_fpr[rd], t0);
> + get_fpr(t2, rd);
> + gen_qemu_st64_i64(ctx, t2, t0);
> t1 = tcg_temp_new();
> gen_addr_add(ctx, t1, t0, 8);
> - gen_qemu_st64_i64(ctx, cpu_fpr[(rd + 1) % 32], t1);
> + get_fpr(t2, (rd + 1) % 32);
> + gen_qemu_st64_i64(ctx, t2, t1);
> tcg_temp_free(t1);
> - if (ra != 0)
> + if (ra != 0) {
> tcg_gen_mov_tl(cpu_gpr[ra], t0);
> + }
> tcg_temp_free(t0);
> + tcg_temp_free_i64(t2);
> }
>
> /* stfqx */
> @@ -1067,13 +1334,18 @@ static void gen_stfqx(DisasContext *ctx)
> {
> int rd = rD(ctx->opcode);
> TCGv t0;
> + TCGv_i64 t1;
> gen_set_access_type(ctx, ACCESS_FLOAT);
> + t1 = tcg_temp_new_i64();
> t0 = tcg_temp_new();
> gen_addr_reg_index(ctx, t0);
> - gen_qemu_st64_i64(ctx, cpu_fpr[rd], t0);
> + get_fpr(t1, rd);
> + gen_qemu_st64_i64(ctx, t1, t0);
> gen_addr_add(ctx, t0, t0, 8);
> - gen_qemu_st64_i64(ctx, cpu_fpr[(rd + 1) % 32], t0);
> + get_fpr(t1, (rd + 1) % 32);
> + gen_qemu_st64_i64(ctx, t1, t0);
> tcg_temp_free(t0);
> + tcg_temp_free_i64(t1);
> }
>
> #undef _GEN_FLOAT_ACB
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
On 12/9/18 11:17 PM, David Gibson wrote: > On Fri, Dec 07, 2018 at 08:56:30AM +0000, Mark Cave-Ayland wrote: >> These helpers allow us to move FP register values to/from the specified TCGv_i64 >> argument. >> >> To prevent FP helpers accessing the cpu_fpr array directly, add extra TCG >> temporaries as required. > > It's not obvious to me why that's a desirable thing. I'm assuming > it's somehow necessary for the stuff later in the series, but I think > we need a brief rationale here to explain why this isn't just adding > extra reg copies for the sake of it. Note that while this introduces extra opcodes, in many cases it does not change the number of machine instructions that are generated. Recall that accessing cpu_fpr[N] implies a load from env. This change makes the load explicit. The change does currently prevent caching cpu_fpr[N] in a host register. That can and will be fixed by optimizing on memory operations instead. (There is a patch that has been outstanding for 13 months to do this. I intend to finally get around to merging it during the 4.0 cycle.) r~
On Mon, Dec 10, 2018 at 12:25:26PM -0600, Richard Henderson wrote: > On 12/9/18 11:17 PM, David Gibson wrote: > > On Fri, Dec 07, 2018 at 08:56:30AM +0000, Mark Cave-Ayland wrote: > >> These helpers allow us to move FP register values to/from the specified TCGv_i64 > >> argument. > >> > >> To prevent FP helpers accessing the cpu_fpr array directly, add extra TCG > >> temporaries as required. > > > > It's not obvious to me why that's a desirable thing. I'm assuming > > it's somehow necessary for the stuff later in the series, but I think > > we need a brief rationale here to explain why this isn't just adding > > extra reg copies for the sake of it. > > Note that while this introduces extra opcodes, in many cases it does not change > the number of machine instructions that are generated. Recall that accessing > cpu_fpr[N] implies a load from env. This change makes the load explicit. I realised that a bit later in looking at the series. I think a paraphrasing of the above in the commit message would still be helpful. > The change does currently prevent caching cpu_fpr[N] in a host register. That > can and will be fixed by optimizing on memory operations instead. (There is a > patch that has been outstanding for 13 months to do this. I intend to finally > get around to merging it during the 4.0 cycle.) > > > r~ > -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
On 10/12/2018 05:17, David Gibson wrote: > On Fri, Dec 07, 2018 at 08:56:30AM +0000, Mark Cave-Ayland wrote: >> These helpers allow us to move FP register values to/from the specified TCGv_i64 >> argument. >> >> To prevent FP helpers accessing the cpu_fpr array directly, add extra TCG >> temporaries as required. > > It's not obvious to me why that's a desirable thing. I'm assuming > it's somehow necessary for the stuff later in the series, but I think > we need a brief rationale here to explain why this isn't just adding > extra reg copies for the sake of it. Ah okay. It's because the VSX registers extend the set of VMX and FPR registers (see the cpu_vsrh() and cpu_vsrl() helpers at the top of target/ppc/translate/vsx-impl.inc.c). So in order to remove the static TCGv_i64 arrays then these helpers must also be converted. ATB, Mark.
On 12/7/18 2:56 AM, Mark Cave-Ayland wrote:
> - gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env, \
> - cpu_fpr[rA(ctx->opcode)], \
> - cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \
> + get_fpr(t0, rA(ctx->opcode)); \
> + get_fpr(t1, rC(ctx->opcode)); \
> + get_fpr(t2, rB(ctx->opcode)); \
> + gen_helper_f##op(t3, cpu_env, t0, t1, t2); \
> + set_fpr(rD(ctx->opcode), t3); \
> if (isfloat) { \
> - gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env, \
> - cpu_fpr[rD(ctx->opcode)]); \
> + get_fpr(t0, rD(ctx->opcode)); \
> + gen_helper_frsp(t3, cpu_env, t0); \
> + set_fpr(rD(ctx->opcode), t3); \
> } \
This is an accurate conversion, but the writeback to the rD register need not
happen until after helper_frsp. Just move it below the isfloat block.
I do see that helper_frsp can raise an exception for invalid_op for SNaN. If
that code were actually reachable, this would have been an existing bug, in
that we should not have written back to rD after the first operation. However,
any SNaN will already have been eliminated by the first operation (via
squashing to QNaN or by exiting via exception).
Similarly in GEN_FLOAT_AB.
> + get_fpr(t0, rB(ctx->opcode));
> + gen_helper_frsqrte(t1, cpu_env, t0);
> + set_fpr(rD(ctx->opcode), t1);
> + gen_helper_frsp(t1, cpu_env, t1);
> + gen_compute_fprf_float64(t1);
gen_frsqrtes has the set_fpr in the wrong place. Likewise gen_fsqrts.
r~
On 10/12/2018 18:43, Richard Henderson wrote:
> On 12/7/18 2:56 AM, Mark Cave-Ayland wrote:
>> - gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env, \
>> - cpu_fpr[rA(ctx->opcode)], \
>> - cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \
>> + get_fpr(t0, rA(ctx->opcode)); \
>> + get_fpr(t1, rC(ctx->opcode)); \
>> + get_fpr(t2, rB(ctx->opcode)); \
>> + gen_helper_f##op(t3, cpu_env, t0, t1, t2); \
>> + set_fpr(rD(ctx->opcode), t3); \
>> if (isfloat) { \
>> - gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env, \
>> - cpu_fpr[rD(ctx->opcode)]); \
>> + get_fpr(t0, rD(ctx->opcode)); \
>> + gen_helper_frsp(t3, cpu_env, t0); \
>> + set_fpr(rD(ctx->opcode), t3); \
>> } \
>
> This is an accurate conversion, but the writeback to the rD register need not
> happen until after helper_frsp. Just move it below the isfloat block.
Okay - I'll fix this up in the next iteration.
> I do see that helper_frsp can raise an exception for invalid_op for SNaN. If
> that code were actually reachable, this would have been an existing bug, in
> that we should not have written back to rD after the first operation. However,
> any SNaN will already have been eliminated by the first operation (via
> squashing to QNaN or by exiting via exception).
>
> Similarly in GEN_FLOAT_AB.
Noted.
>> + get_fpr(t0, rB(ctx->opcode));
>> + gen_helper_frsqrte(t1, cpu_env, t0);
>> + set_fpr(rD(ctx->opcode), t1);
>> + gen_helper_frsp(t1, cpu_env, t1);
>> + gen_compute_fprf_float64(t1);
>
> gen_frsqrtes has the set_fpr in the wrong place. Likewise gen_fsqrts.
Ooops. I remember having a think a bit harder about these two functions, so I'll go
and take another look.
ATB,
Mark.
© 2016 - 2026 Red Hat, Inc.