target-sparc: Use DisasCompare and movcond in FMOVR, FMOVCC

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
Richard Henderson 2012-10-05 16:54:59 -07:00 committed by Blue Swirl
parent 3a49e7598b
commit 7e480893cc

View file

@ -2281,6 +2281,57 @@ static inline TCGv get_src2(unsigned int insn, TCGv def)
}
#ifdef TARGET_SPARC64
static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
{
TCGv_i32 c32, zero, dst, s1, s2;
/* We have two choices here: extend the 32 bit data and use movcond_i64,
or fold the comparison down to 32 bits and use movcond_i32. Choose
the later. */
c32 = tcg_temp_new_i32();
if (cmp->is_bool) {
tcg_gen_trunc_i64_i32(c32, cmp->c1);
} else {
TCGv_i64 c64 = tcg_temp_new_i64();
tcg_gen_setcond_i64(cmp->cond, c64, cmp->c1, cmp->c2);
tcg_gen_trunc_i64_i32(c32, c64);
tcg_temp_free_i64(c64);
}
s1 = gen_load_fpr_F(dc, rs);
s2 = gen_load_fpr_F(dc, rd);
dst = gen_dest_fpr_F();
zero = tcg_const_i32(0);
tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2);
tcg_temp_free_i32(c32);
tcg_temp_free_i32(zero);
gen_store_fpr_F(dc, rd, dst);
}
static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
{
TCGv_i64 dst = gen_dest_fpr_D();
tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, cmp->c2,
gen_load_fpr_D(dc, rs),
gen_load_fpr_D(dc, rd));
gen_store_fpr_D(dc, rd, dst);
}
static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
{
int qd = QFPREG(rd);
int qs = QFPREG(rs);
tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2], cmp->c1, cmp->c2,
cpu_fpr[qs / 2], cpu_fpr[qd / 2]);
tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2 + 1], cmp->c1, cmp->c2,
cpu_fpr[qs / 2 + 1], cpu_fpr[qd / 2 + 1]);
gen_update_fprs_dirty(qd);
}
static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_ptr cpu_env)
{
TCGv_i32 r_tl = tcg_temp_new_i32();
@ -3163,168 +3214,86 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
#endif
switch (xop) {
#ifdef TARGET_SPARC64
#define FMOVSCC(fcc) \
{ \
TCGv r_cond; \
int l1; \
\
l1 = gen_new_label(); \
r_cond = tcg_temp_new(); \
#define FMOVCC(fcc, sz) \
do { \
DisasCompare cmp; \
cond = GET_FIELD_SP(insn, 14, 17); \
gen_fcond(r_cond, fcc, cond); \
tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
0, l1); \
cpu_src1_32 = gen_load_fpr_F(dc, rs2); \
gen_store_fpr_F(dc, rd, cpu_src1_32); \
gen_set_label(l1); \
tcg_temp_free(r_cond); \
}
#define FMOVDCC(fcc) \
{ \
TCGv r_cond; \
int l1; \
\
l1 = gen_new_label(); \
r_cond = tcg_temp_new(); \
cond = GET_FIELD_SP(insn, 14, 17); \
gen_fcond(r_cond, fcc, cond); \
tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
0, l1); \
cpu_src1_64 = gen_load_fpr_D(dc, rs2); \
gen_store_fpr_D(dc, rd, cpu_src1_64); \
gen_set_label(l1); \
tcg_temp_free(r_cond); \
}
#define FMOVQCC(fcc) \
{ \
TCGv r_cond; \
int l1; \
\
l1 = gen_new_label(); \
r_cond = tcg_temp_new(); \
cond = GET_FIELD_SP(insn, 14, 17); \
gen_fcond(r_cond, fcc, cond); \
tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
0, l1); \
gen_move_Q(rd, rs2); \
gen_set_label(l1); \
tcg_temp_free(r_cond); \
}
gen_fcompare(&cmp, fcc, cond); \
gen_fmov##sz(dc, &cmp, rd, rs2); \
free_compare(&cmp); \
} while (0)
case 0x001: /* V9 fmovscc %fcc0 */
FMOVSCC(0);
FMOVCC(0, s);
break;
case 0x002: /* V9 fmovdcc %fcc0 */
FMOVDCC(0);
FMOVCC(0, d);
break;
case 0x003: /* V9 fmovqcc %fcc0 */
CHECK_FPU_FEATURE(dc, FLOAT128);
FMOVQCC(0);
FMOVCC(0, q);
break;
case 0x041: /* V9 fmovscc %fcc1 */
FMOVSCC(1);
FMOVCC(1, s);
break;
case 0x042: /* V9 fmovdcc %fcc1 */
FMOVDCC(1);
FMOVCC(1, d);
break;
case 0x043: /* V9 fmovqcc %fcc1 */
CHECK_FPU_FEATURE(dc, FLOAT128);
FMOVQCC(1);
FMOVCC(1, q);
break;
case 0x081: /* V9 fmovscc %fcc2 */
FMOVSCC(2);
FMOVCC(2, s);
break;
case 0x082: /* V9 fmovdcc %fcc2 */
FMOVDCC(2);
FMOVCC(2, d);
break;
case 0x083: /* V9 fmovqcc %fcc2 */
CHECK_FPU_FEATURE(dc, FLOAT128);
FMOVQCC(2);
FMOVCC(2, q);
break;
case 0x0c1: /* V9 fmovscc %fcc3 */
FMOVSCC(3);
FMOVCC(3, s);
break;
case 0x0c2: /* V9 fmovdcc %fcc3 */
FMOVDCC(3);
FMOVCC(3, d);
break;
case 0x0c3: /* V9 fmovqcc %fcc3 */
CHECK_FPU_FEATURE(dc, FLOAT128);
FMOVQCC(3);
FMOVCC(3, q);
break;
#undef FMOVSCC
#undef FMOVDCC
#undef FMOVQCC
#define FMOVSCC(icc) \
{ \
TCGv r_cond; \
int l1; \
\
l1 = gen_new_label(); \
r_cond = tcg_temp_new(); \
#undef FMOVCC
#define FMOVCC(xcc, sz) \
do { \
DisasCompare cmp; \
cond = GET_FIELD_SP(insn, 14, 17); \
gen_cond(r_cond, icc, cond, dc); \
tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
0, l1); \
cpu_src1_32 = gen_load_fpr_F(dc, rs2); \
gen_store_fpr_F(dc, rd, cpu_src1_32); \
gen_set_label(l1); \
tcg_temp_free(r_cond); \
}
#define FMOVDCC(icc) \
{ \
TCGv r_cond; \
int l1; \
\
l1 = gen_new_label(); \
r_cond = tcg_temp_new(); \
cond = GET_FIELD_SP(insn, 14, 17); \
gen_cond(r_cond, icc, cond, dc); \
tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
0, l1); \
cpu_src1_64 = gen_load_fpr_D(dc, rs2); \
gen_store_fpr_D(dc, rd, cpu_src1_64); \
gen_update_fprs_dirty(DFPREG(rd)); \
gen_set_label(l1); \
tcg_temp_free(r_cond); \
}
#define FMOVQCC(icc) \
{ \
TCGv r_cond; \
int l1; \
\
l1 = gen_new_label(); \
r_cond = tcg_temp_new(); \
cond = GET_FIELD_SP(insn, 14, 17); \
gen_cond(r_cond, icc, cond, dc); \
tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
0, l1); \
gen_move_Q(rd, rs2); \
gen_set_label(l1); \
tcg_temp_free(r_cond); \
}
gen_compare(&cmp, xcc, cond, dc); \
gen_fmov##sz(dc, &cmp, rd, rs2); \
free_compare(&cmp); \
} while (0)
case 0x101: /* V9 fmovscc %icc */
FMOVSCC(0);
FMOVCC(0, s);
break;
case 0x102: /* V9 fmovdcc %icc */
FMOVDCC(0);
FMOVCC(0, d);
break;
case 0x103: /* V9 fmovqcc %icc */
CHECK_FPU_FEATURE(dc, FLOAT128);
FMOVQCC(0);
FMOVCC(0, q);
break;
case 0x181: /* V9 fmovscc %xcc */
FMOVSCC(1);
FMOVCC(1, s);
break;
case 0x182: /* V9 fmovdcc %xcc */
FMOVDCC(1);
FMOVCC(1, d);
break;
case 0x183: /* V9 fmovqcc %xcc */
CHECK_FPU_FEATURE(dc, FLOAT128);
FMOVQCC(1);
FMOVCC(1, q);
break;
#undef FMOVSCC
#undef FMOVDCC
#undef FMOVQCC
#undef FMOVCC
#endif
case 0x51: /* fcmps, V9 %fcc */
cpu_src1_32 = gen_load_fpr_F(dc, rs1);