aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2011-10-14 15:47:35 -0700
committerRichard Henderson <rth@twiddle.net>2011-10-26 13:50:45 -0700
commit96eda024123402a14e39f6d336d7bee7e2bcbcf9 (patch)
tree428408aa0f11668141936d1ca4c330b3f59b53f7
parent141ae5c13f2a0ac51c7ae7dfe17dbfb91d931110 (diff)
target-sparc: Add accessors for double-precision fpr access.
Begin using i64 quantities to manipulate double-precision values. On a 64-bit host this will, for the moment, generate less efficient code; on a 32-bit host code quality should be largely unchanged. Code quality for 64-bit will be adjusted with a subsequent patch. Signed-off-by: Richard Henderson <rth@twiddle.net>
-rw-r--r--target-sparc/translate.c242
1 files changed, 130 insertions, 112 deletions
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 26f7e36c92..937e711284 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -82,6 +82,8 @@ typedef struct DisasContext {
uint32_t cc_op; /* current CC operation */
struct TranslationBlock *tb;
sparc_def_t *def;
+ TCGv_i64 t64[3];
+ int n_t64;
} DisasContext;
// This function uses non-native bit order
@@ -129,7 +131,7 @@ static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src)
static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v)
{
- tcg_gen_mov_i32 (cpu__fpr[dst], v);
+ tcg_gen_mov_i32(cpu__fpr[dst], v);
gen_update_fprs_dirty(dst);
}
@@ -138,6 +140,52 @@ static TCGv_i32 gen_dest_fpr_F(void)
return cpu_tmp32;
}
+static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src)
+{
+ TCGv_i64 ret = tcg_temp_new_i64();
+ src = DFPREG(src);
+
+#if TCG_TARGET_REG_BITS == 32
+ tcg_gen_mov_i32(TCGV_HIGH(ret), cpu__fpr[src]);
+ tcg_gen_mov_i32(TCGV_LOW(ret), cpu__fpr[src + 1]);
+#else
+ {
+ TCGv_i64 t = tcg_temp_new_i64();
+ tcg_gen_extu_i32_i64(ret, cpu__fpr[src]);
+ tcg_gen_extu_i32_i64(t, cpu__fpr[src + 1]);
+ tcg_gen_shli_i64(ret, ret, 32);
+ tcg_gen_or_i64(ret, ret, t);
+ tcg_temp_free_i64(t);
+ }
+#endif
+
+ dc->t64[dc->n_t64++] = ret;
+ assert(dc->n_t64 <= ARRAY_SIZE(dc->t64));
+
+ return ret;
+}
+
+static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v)
+{
+ dst = DFPREG(dst);
+
+#if TCG_TARGET_REG_BITS == 32
+ tcg_gen_mov_i32(cpu__fpu[dst], TCGV_HIGH(v));
+ tcg_gen_mov_i32(cpu__fpu[dst + 1], TCGV_LOW(v));
+#else
+ tcg_gen_trunc_i64_i32(cpu__fpr[dst + 1], v);
+ tcg_gen_shri_i64(v, v, 32);
+ tcg_gen_trunc_i64_i32(cpu__fpr[dst], v);
+#endif
+
+ gen_update_fprs_dirty(dst);
+}
+
+static TCGv_i64 gen_dest_fpr_D(void)
+{
+ return cpu_tmp64;
+}
+
static void gen_op_load_fpr_DT0(unsigned int src)
{
tcg_gen_st_i32(cpu__fpr[src], cpu_env, offsetof(CPUSPARCState, dt0) +
@@ -1909,6 +1957,7 @@ static void disas_sparc_insn(DisasContext * dc)
unsigned int insn, opc, rs1, rs2, rd;
TCGv cpu_src1, cpu_src2, cpu_tmp1, cpu_tmp2;
TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32;
+ TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64;
target_long simm;
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
@@ -2661,11 +2710,8 @@ static void disas_sparc_insn(DisasContext * dc)
break;
#ifdef TARGET_SPARC64
case 0x2: /* V9 fmovd */
- tcg_gen_mov_i32(cpu__fpr[DFPREG(rd)],
- cpu__fpr[DFPREG(rs2)]);
- tcg_gen_mov_i32(cpu__fpr[DFPREG(rd) + 1],
- cpu__fpr[DFPREG(rs2) + 1]);
- gen_update_fprs_dirty(DFPREG(rd));
+ cpu_src1_64 = gen_load_fpr_D(dc, rs2);
+ gen_store_fpr_D(dc, rd, cpu_src1_64);
break;
case 0x3: /* V9 fmovq */
CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2791,9 +2837,8 @@ static void disas_sparc_insn(DisasContext * dc)
cpu_src1 = get_src1(insn, cpu_src1);
tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1,
0, l1);
- tcg_gen_mov_i32(cpu__fpr[DFPREG(rd)], cpu__fpr[DFPREG(rs2)]);
- tcg_gen_mov_i32(cpu__fpr[DFPREG(rd) + 1], cpu__fpr[DFPREG(rs2) + 1]);
- gen_update_fprs_dirty(DFPREG(rd));
+ cpu_src1_64 = gen_load_fpr_D(dc, rs2);
+ gen_store_fpr_D(dc, rd, cpu_src1_64);
gen_set_label(l1);
break;
} else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
@@ -2843,11 +2888,8 @@ static void disas_sparc_insn(DisasContext * dc)
gen_fcond(r_cond, fcc, cond); \
tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
0, l1); \
- tcg_gen_mov_i32(cpu__fpr[DFPREG(rd)], \
- cpu__fpr[DFPREG(rs2)]); \
- tcg_gen_mov_i32(cpu__fpr[DFPREG(rd) + 1], \
- cpu__fpr[DFPREG(rs2) + 1]); \
- gen_update_fprs_dirty(DFPREG(rd)); \
+ 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); \
}
@@ -2944,10 +2986,8 @@ static void disas_sparc_insn(DisasContext * dc)
gen_cond(r_cond, icc, cond, dc); \
tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
0, l1); \
- tcg_gen_mov_i32(cpu__fpr[DFPREG(rd)], \
- cpu__fpr[DFPREG(rs2)]); \
- tcg_gen_mov_i32(cpu__fpr[DFPREG(rd) + 1], \
- cpu__fpr[DFPREG(rs2) + 1]); \
+ 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); \
@@ -4124,9 +4164,9 @@ static void disas_sparc_insn(DisasContext * dc)
break;
case 0x060: /* VIS I fzero */
CHECK_FPU_FEATURE(dc, VIS1);
- tcg_gen_movi_i32(cpu__fpr[DFPREG(rd)], 0);
- tcg_gen_movi_i32(cpu__fpr[DFPREG(rd) + 1], 0);
- gen_update_fprs_dirty(DFPREG(rd));
+ cpu_dst_64 = gen_dest_fpr_D();
+ tcg_gen_movi_i64(cpu_dst_64, 0);
+ gen_store_fpr_D(dc, rd, cpu_dst_64);
break;
case 0x061: /* VIS I fzeros */
CHECK_FPU_FEATURE(dc, VIS1);
@@ -4136,13 +4176,11 @@ static void disas_sparc_insn(DisasContext * dc)
break;
case 0x062: /* VIS I fnor */
CHECK_FPU_FEATURE(dc, VIS1);
- tcg_gen_nor_i32(cpu__fpr[DFPREG(rd)],
- cpu__fpr[DFPREG(rs1)],
- cpu__fpr[DFPREG(rs2)]);
- tcg_gen_nor_i32(cpu__fpr[DFPREG(rd) + 1],
- cpu__fpr[DFPREG(rs1) + 1],
- cpu__fpr[DFPREG(rs2) + 1]);
- gen_update_fprs_dirty(DFPREG(rd));
+ cpu_src1_64 = gen_load_fpr_D(dc, rs1);
+ cpu_src2_64 = gen_load_fpr_D(dc, rs2);
+ cpu_dst_64 = gen_dest_fpr_D();
+ tcg_gen_nor_i64(cpu_dst_64, cpu_src1_64, cpu_src2_64);
+ gen_store_fpr_D(dc, rd, cpu_dst_64);
break;
case 0x063: /* VIS I fnors */
CHECK_FPU_FEATURE(dc, VIS1);
@@ -4154,13 +4192,11 @@ static void disas_sparc_insn(DisasContext * dc)
break;
case 0x064: /* VIS I fandnot2 */
CHECK_FPU_FEATURE(dc, VIS1);
- tcg_gen_andc_i32(cpu__fpr[DFPREG(rd)],
- cpu__fpr[DFPREG(rs1)],
- cpu__fpr[DFPREG(rs2)]);
- tcg_gen_andc_i32(cpu__fpr[DFPREG(rd) + 1],
- cpu__fpr[DFPREG(rs1) + 1],
- cpu__fpr[DFPREG(rs2) + 1]);
- gen_update_fprs_dirty(DFPREG(rd));
+ cpu_src1_64 = gen_load_fpr_D(dc, rs1);
+ cpu_src2_64 = gen_load_fpr_D(dc, rs2);
+ cpu_dst_64 = gen_dest_fpr_D();
+ tcg_gen_andc_i64(cpu_dst_64, cpu_src1_64, cpu_src2_64);
+ gen_store_fpr_D(dc, rd, cpu_dst_64);
break;
case 0x065: /* VIS I fandnot2s */
CHECK_FPU_FEATURE(dc, VIS1);
@@ -4172,11 +4208,10 @@ static void disas_sparc_insn(DisasContext * dc)
break;
case 0x066: /* VIS I fnot2 */
CHECK_FPU_FEATURE(dc, VIS1);
- tcg_gen_not_i32(cpu__fpr[DFPREG(rd)],
- cpu__fpr[DFPREG(rs2)]);
- tcg_gen_not_i32(cpu__fpr[DFPREG(rd) + 1],
- cpu__fpr[DFPREG(rs2) + 1]);
- gen_update_fprs_dirty(DFPREG(rd));
+ cpu_src1_64 = gen_load_fpr_D(dc, rs2);
+ cpu_dst_64 = gen_dest_fpr_D();
+ tcg_gen_not_i64(cpu_dst_64, cpu_src1_64);
+ gen_store_fpr_D(dc, rd, cpu_dst_64);
break;
case 0x067: /* VIS I fnot2s */
CHECK_FPU_FEATURE(dc, VIS1);
@@ -4187,13 +4222,11 @@ static void disas_sparc_insn(DisasContext * dc)
break;
case 0x068: /* VIS I fandnot1 */
CHECK_FPU_FEATURE(dc, VIS1);
- tcg_gen_andc_i32(cpu__fpr[DFPREG(rd)],
- cpu__fpr[DFPREG(rs2)],
- cpu__fpr[DFPREG(rs1)]);
- tcg_gen_andc_i32(cpu__fpr[DFPREG(rd) + 1],
- cpu__fpr[DFPREG(rs2) + 1],
- cpu__fpr[DFPREG(rs1) + 1]);
- gen_update_fprs_dirty(DFPREG(rd));
+ cpu_src1_64 = gen_load_fpr_D(dc, rs1);
+ cpu_src2_64 = gen_load_fpr_D(dc, rs2);
+ cpu_dst_64 = gen_dest_fpr_D();
+ tcg_gen_andc_i64(cpu_dst_64, cpu_src2_64, cpu_src1_64);
+ gen_store_fpr_D(dc, rd, cpu_dst_64);
break;
case 0x069: /* VIS I fandnot1s */
CHECK_FPU_FEATURE(dc, VIS1);
@@ -4205,11 +4238,10 @@ static void disas_sparc_insn(DisasContext * dc)
break;
case 0x06a: /* VIS I fnot1 */
CHECK_FPU_FEATURE(dc, VIS1);
- tcg_gen_not_i32(cpu__fpr[DFPREG(rd)],
- cpu__fpr[DFPREG(rs1)]);
- tcg_gen_not_i32(cpu__fpr[DFPREG(rd) + 1],
- cpu__fpr[DFPREG(rs1) + 1]);
- gen_update_fprs_dirty(DFPREG(rd));
+ cpu_src1_64 = gen_load_fpr_D(dc, rs1);
+ cpu_dst_64 = gen_dest_fpr_D();
+ tcg_gen_not_i64(cpu_dst_64, cpu_src1_64);
+ gen_store_fpr_D(dc, rd, cpu_dst_64);
break;
case 0x06b: /* VIS I fnot1s */
CHECK_FPU_FEATURE(dc, VIS1);
@@ -4220,13 +4252,11 @@ static void disas_sparc_insn(DisasContext * dc)
break;
case 0x06c: /* VIS I fxor */
CHECK_FPU_FEATURE(dc, VIS1);
- tcg_gen_xor_i32(cpu__fpr[DFPREG(rd)],
- cpu__fpr[DFPREG(rs1)],
- cpu__fpr[DFPREG(rs2)]);
- tcg_gen_xor_i32(cpu__fpr[DFPREG(rd) + 1],
- cpu__fpr[DFPREG(rs1) + 1],
- cpu__fpr[DFPREG(rs2) + 1]);
- gen_update_fprs_dirty(DFPREG(rd));
+ cpu_src1_64 = gen_load_fpr_D(dc, rs1);
+ cpu_src2_64 = gen_load_fpr_D(dc, rs2);
+ cpu_dst_64 = gen_dest_fpr_D();
+ tcg_gen_xor_i64(cpu_dst_64, cpu_src1_64, cpu_src2_64);
+ gen_store_fpr_D(dc, rd, cpu_dst_64);
break;
case 0x06d: /* VIS I fxors */
CHECK_FPU_FEATURE(dc, VIS1);
@@ -4238,13 +4268,11 @@ static void disas_sparc_insn(DisasContext * dc)
break;
case 0x06e: /* VIS I fnand */
CHECK_FPU_FEATURE(dc, VIS1);
- tcg_gen_nand_i32(cpu__fpr[DFPREG(rd)],
- cpu__fpr[DFPREG(rs1)],
- cpu__fpr[DFPREG(rs2)]);
- tcg_gen_nand_i32(cpu__fpr[DFPREG(rd) + 1],
- cpu__fpr[DFPREG(rs1) + 1],
- cpu__fpr[DFPREG(rs2) + 1]);
- gen_update_fprs_dirty(DFPREG(rd));
+ cpu_src1_64 = gen_load_fpr_D(dc, rs1);
+ cpu_src2_64 = gen_load_fpr_D(dc, rs2);
+ cpu_dst_64 = gen_dest_fpr_D();
+ tcg_gen_nand_i64(cpu_dst_64, cpu_src1_64, cpu_src2_64);
+ gen_store_fpr_D(dc, rd, cpu_dst_64);
break;
case 0x06f: /* VIS I fnands */
CHECK_FPU_FEATURE(dc, VIS1);
@@ -4256,13 +4284,11 @@ static void disas_sparc_insn(DisasContext * dc)
break;
case 0x070: /* VIS I fand */
CHECK_FPU_FEATURE(dc, VIS1);
- tcg_gen_and_i32(cpu__fpr[DFPREG(rd)],
- cpu__fpr[DFPREG(rs1)],
- cpu__fpr[DFPREG(rs2)]);
- tcg_gen_and_i32(cpu__fpr[DFPREG(rd) + 1],
- cpu__fpr[DFPREG(rs1) + 1],
- cpu__fpr[DFPREG(rs2) + 1]);
- gen_update_fprs_dirty(DFPREG(rd));
+ cpu_src1_64 = gen_load_fpr_D(dc, rs1);
+ cpu_src2_64 = gen_load_fpr_D(dc, rs2);
+ cpu_dst_64 = gen_dest_fpr_D();
+ tcg_gen_and_i64(cpu_dst_64, cpu_src1_64, cpu_src2_64);
+ gen_store_fpr_D(dc, rd, cpu_dst_64);
break;
case 0x071: /* VIS I fands */
CHECK_FPU_FEATURE(dc, VIS1);
@@ -4274,13 +4300,11 @@ static void disas_sparc_insn(DisasContext * dc)
break;
case 0x072: /* VIS I fxnor */
CHECK_FPU_FEATURE(dc, VIS1);
- tcg_gen_eqv_i32(cpu__fpr[DFPREG(rd)],
- cpu__fpr[DFPREG(rs1)],
- cpu__fpr[DFPREG(rs2)]);
- tcg_gen_eqv_i32(cpu__fpr[DFPREG(rd) + 1],
- cpu__fpr[DFPREG(rs1) + 1],
- cpu__fpr[DFPREG(rs2) + 1]);
- gen_update_fprs_dirty(DFPREG(rd));
+ cpu_src1_64 = gen_load_fpr_D(dc, rs1);
+ cpu_src2_64 = gen_load_fpr_D(dc, rs2);
+ cpu_dst_64 = gen_dest_fpr_D();
+ tcg_gen_eqv_i64(cpu_dst_64, cpu_src1_64, cpu_src2_64);
+ gen_store_fpr_D(dc, rd, cpu_dst_64);
break;
case 0x073: /* VIS I fxnors */
CHECK_FPU_FEATURE(dc, VIS1);
@@ -4292,11 +4316,8 @@ static void disas_sparc_insn(DisasContext * dc)
break;
case 0x074: /* VIS I fsrc1 */
CHECK_FPU_FEATURE(dc, VIS1);
- tcg_gen_mov_i32(cpu__fpr[DFPREG(rd)],
- cpu__fpr[DFPREG(rs1)]);
- tcg_gen_mov_i32(cpu__fpr[DFPREG(rd) + 1],
- cpu__fpr[DFPREG(rs1) + 1]);
- gen_update_fprs_dirty(DFPREG(rd));
+ cpu_src1_64 = gen_load_fpr_D(dc, rs1);
+ gen_store_fpr_D(dc, rd, cpu_src1_64);
break;
case 0x075: /* VIS I fsrc1s */
CHECK_FPU_FEATURE(dc, VIS1);
@@ -4305,13 +4326,11 @@ static void disas_sparc_insn(DisasContext * dc)
break;
case 0x076: /* VIS I fornot2 */
CHECK_FPU_FEATURE(dc, VIS1);
- tcg_gen_orc_i32(cpu__fpr[DFPREG(rd)],
- cpu__fpr[DFPREG(rs1)],
- cpu__fpr[DFPREG(rs2)]);
- tcg_gen_orc_i32(cpu__fpr[DFPREG(rd) + 1],
- cpu__fpr[DFPREG(rs1) + 1],
- cpu__fpr[DFPREG(rs2) + 1]);
- gen_update_fprs_dirty(DFPREG(rd));
+ cpu_src1_64 = gen_load_fpr_D(dc, rs1);
+ cpu_src2_64 = gen_load_fpr_D(dc, rs2);
+ cpu_dst_64 = gen_dest_fpr_D();
+ tcg_gen_orc_i64(cpu_dst_64, cpu_src1_64, cpu_src2_64);
+ gen_store_fpr_D(dc, rd, cpu_dst_64);
break;
case 0x077: /* VIS I fornot2s */
CHECK_FPU_FEATURE(dc, VIS1);
@@ -4323,9 +4342,8 @@ static void disas_sparc_insn(DisasContext * dc)
break;
case 0x078: /* VIS I fsrc2 */
CHECK_FPU_FEATURE(dc, VIS1);
- gen_op_load_fpr_DT0(DFPREG(rs2));
- gen_op_store_DT0_fpr(DFPREG(rd));
- gen_update_fprs_dirty(DFPREG(rd));
+ cpu_src1_64 = gen_load_fpr_D(dc, rs2);
+ gen_store_fpr_D(dc, rd, cpu_src1_64);
break;
case 0x079: /* VIS I fsrc2s */
CHECK_FPU_FEATURE(dc, VIS1);
@@ -4334,13 +4352,11 @@ static void disas_sparc_insn(DisasContext * dc)
break;
case 0x07a: /* VIS I fornot1 */
CHECK_FPU_FEATURE(dc, VIS1);
- tcg_gen_orc_i32(cpu__fpr[DFPREG(rd)],
- cpu__fpr[DFPREG(rs2)],
- cpu__fpr[DFPREG(rs1)]);
- tcg_gen_orc_i32(cpu__fpr[DFPREG(rd) + 1],
- cpu__fpr[DFPREG(rs2) + 1],
- cpu__fpr[DFPREG(rs1) + 1]);
- gen_update_fprs_dirty(DFPREG(rd));
+ cpu_src1_64 = gen_load_fpr_D(dc, rs1);
+ cpu_src2_64 = gen_load_fpr_D(dc, rs2);
+ cpu_dst_64 = gen_dest_fpr_D();
+ tcg_gen_orc_i64(cpu_dst_64, cpu_src2_64, cpu_src1_64);
+ gen_store_fpr_D(dc, rd, cpu_dst_64);
break;
case 0x07b: /* VIS I fornot1s */
CHECK_FPU_FEATURE(dc, VIS1);
@@ -4352,13 +4368,11 @@ static void disas_sparc_insn(DisasContext * dc)
break;
case 0x07c: /* VIS I for */
CHECK_FPU_FEATURE(dc, VIS1);
- tcg_gen_or_i32(cpu__fpr[DFPREG(rd)],
- cpu__fpr[DFPREG(rs1)],
- cpu__fpr[DFPREG(rs2)]);
- tcg_gen_or_i32(cpu__fpr[DFPREG(rd) + 1],
- cpu__fpr[DFPREG(rs1) + 1],
- cpu__fpr[DFPREG(rs2) + 1]);
- gen_update_fprs_dirty(DFPREG(rd));
+ cpu_src1_64 = gen_load_fpr_D(dc, rs1);
+ cpu_src2_64 = gen_load_fpr_D(dc, rs2);
+ cpu_dst_64 = gen_dest_fpr_D();
+ tcg_gen_or_i64(cpu_dst_64, cpu_src1_64, cpu_src2_64);
+ gen_store_fpr_D(dc, rd, cpu_dst_64);
break;
case 0x07d: /* VIS I fors */
CHECK_FPU_FEATURE(dc, VIS1);
@@ -4370,9 +4384,9 @@ static void disas_sparc_insn(DisasContext * dc)
break;
case 0x07e: /* VIS I fone */
CHECK_FPU_FEATURE(dc, VIS1);
- tcg_gen_movi_i32(cpu__fpr[DFPREG(rd)], -1);
- tcg_gen_movi_i32(cpu__fpr[DFPREG(rd) + 1], -1);
- gen_update_fprs_dirty(DFPREG(rd));
+ cpu_dst_64 = gen_dest_fpr_D();
+ tcg_gen_movi_i64(cpu_dst_64, -1);
+ gen_store_fpr_D(dc, rd, cpu_dst_64);
break;
case 0x07f: /* VIS I fones */
CHECK_FPU_FEATURE(dc, VIS1);
@@ -5199,6 +5213,10 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
tcg_temp_free_i64(cpu_tmp64);
tcg_temp_free_i32(cpu_tmp32);
tcg_temp_free(cpu_tmp0);
+ for (j = dc->n_t64 - 1; j >= 0; --j) {
+ tcg_temp_free_i64(dc->t64[j]);
+ }
+
if (tb->cflags & CF_LAST_IO)
gen_io_end();
if (!dc->is_br) {