aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target-arm/translate.c35
-rw-r--r--target-mips/translate.c23
-rw-r--r--target-ppc/translate.c7
-rw-r--r--target-sh4/translate.c9
-rw-r--r--tcg/README4
-rw-r--r--tcg/tcg-op.h17
6 files changed, 44 insertions, 51 deletions
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 836b356dc8..5d71349a7f 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -1447,10 +1447,7 @@ static void gen_iwmmxt_movl_T0_T1_wRn(int rn)
static void gen_iwmmxt_movl_wRn_T0_T1(int rn)
{
- tcg_gen_extu_i32_i64(cpu_V0, cpu_T[0]);
- tcg_gen_extu_i32_i64(cpu_V1, cpu_T[0]);
- tcg_gen_shli_i64(cpu_V1, cpu_V1, 32);
- tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
+ tcg_gen_concat_i32_i64(cpu_V0, cpu_T[0], cpu_T[1]);
iwmmxt_store_reg(cpu_V0, rn);
}
@@ -4663,14 +4660,11 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
} else {
tmp = neon_load_reg(rm + pass, 0);
gen_neon_shift_narrow(size, tmp, tmp2, q, u);
- tcg_gen_extu_i32_i64(cpu_V0, tmp);
+ tmp3 = neon_load_reg(rm + pass, 1);
+ gen_neon_shift_narrow(size, tmp3, tmp2, q, u);
+ tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
dead_tmp(tmp);
- tmp = neon_load_reg(rm + pass, 1);
- gen_neon_shift_narrow(size, tmp, tmp2, q, u);
- tcg_gen_extu_i32_i64(cpu_V1, tmp);
- dead_tmp(tmp);
- tcg_gen_shli_i64(cpu_V1, cpu_V1, 32);
- tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
+ dead_tmp(tmp3);
}
tmp = new_tmp();
if (op == 8 && !u) {
@@ -5600,7 +5594,7 @@ static void gen_addq_lo(DisasContext *s, TCGv val, int rlow)
TCGv tmp;
TCGv tmp2;
- /* Load 64-bit value rd:rn. */
+ /* Load value and extend to 64 bits. */
tmp = tcg_temp_new(TCG_TYPE_I64);
tmp2 = load_reg(s, rlow);
tcg_gen_extu_i32_i64(tmp, tmp2);
@@ -5612,19 +5606,16 @@ static void gen_addq_lo(DisasContext *s, TCGv val, int rlow)
static void gen_addq(DisasContext *s, TCGv val, int rlow, int rhigh)
{
TCGv tmp;
- TCGv tmp2;
+ TCGv tmpl;
+ TCGv tmph;
/* Load 64-bit value rd:rn. */
+ tmpl = load_reg(s, rlow);
+ tmph = load_reg(s, rhigh);
tmp = tcg_temp_new(TCG_TYPE_I64);
- tmp2 = load_reg(s, rhigh);
- tcg_gen_extu_i32_i64(tmp, tmp2);
- dead_tmp(tmp2);
- tcg_gen_shli_i64(tmp, tmp, 32);
- tcg_gen_add_i64(val, val, tmp);
-
- tmp2 = load_reg(s, rlow);
- tcg_gen_extu_i32_i64(tmp, tmp2);
- dead_tmp(tmp2);
+ tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
+ dead_tmp(tmpl);
+ dead_tmp(tmph);
tcg_gen_add_i64(val, val, tmp);
}
diff --git a/target-mips/translate.c b/target-mips/translate.c
index b553b5f173..3ac0f60f2f 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -693,13 +693,7 @@ static inline void gen_load_fpr64 (DisasContext *ctx, TCGv t, int reg)
if (ctx->hflags & MIPS_HFLAG_F64)
tcg_gen_mov_i64(t, fpu_fpr64[reg]);
else {
- TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
-
- tcg_gen_extu_i32_i64(t, fpu_fpr32[reg | 1]);
- tcg_gen_shli_i64(t, t, 32);
- tcg_gen_extu_i32_i64(r_tmp2, fpu_fpr32[reg & ~1]);
- tcg_gen_or_i64(t, t, r_tmp2);
- tcg_temp_free(r_tmp2);
+ tcg_gen_concat_i32_i64(t, fpu_fpr32[reg & ~1], fpu_fpr32[reg | 1]);
}
}
@@ -6546,22 +6540,17 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
case FOP(38, 16):
check_cp1_64bitmode(ctx);
{
- TCGv fp64_0 = tcg_temp_new(TCG_TYPE_I64);
- TCGv fp64_1 = tcg_temp_new(TCG_TYPE_I64);
+ TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
TCGv fp32_0 = tcg_temp_new(TCG_TYPE_I32);
TCGv fp32_1 = tcg_temp_new(TCG_TYPE_I32);
gen_load_fpr32(fp32_0, fs);
gen_load_fpr32(fp32_1, ft);
- tcg_gen_extu_i32_i64(fp64_0, fp32_0);
- tcg_gen_extu_i32_i64(fp64_1, fp32_1);
- tcg_temp_free(fp32_0);
+ tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
tcg_temp_free(fp32_1);
- tcg_gen_shli_i64(fp64_1, fp64_1, 32);
- tcg_gen_or_i64(fp64_0, fp64_0, fp64_1);
- tcg_temp_free(fp64_1);
- gen_store_fpr64(ctx, fp64_0, fd);
- tcg_temp_free(fp64_0);
+ tcg_temp_free(fp32_0);
+ gen_store_fpr64(ctx, fp64, fd);
+ tcg_temp_free(fp64);
}
opn = "cvt.ps.s";
break;
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 2d646b9afc..275f7807c9 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -5300,12 +5300,7 @@ static always_inline void gen_load_gpr64(TCGv t, int reg) {
#if defined(TARGET_PPC64)
tcg_gen_mov_i64(t, cpu_gpr[reg]);
#else
- tcg_gen_extu_i32_i64(t, cpu_gprh[reg]);
- tcg_gen_shli_i64(t, t, 32);
- TCGv tmp = tcg_temp_local_new(TCG_TYPE_I64);
- tcg_gen_extu_i32_i64(tmp, cpu_gpr[reg]);
- tcg_gen_or_i64(t, t, tmp);
- tcg_temp_free(tmp);
+ tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
#endif
}
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index b9dcbc2f03..4614c8674b 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -400,15 +400,12 @@ static inline void gen_load_fpr32(TCGv t, int reg)
static inline void gen_load_fpr64(TCGv t, int reg)
{
TCGv tmp1 = tcg_temp_new(TCG_TYPE_I32);
- TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
+ TCGv tmp2 = tcg_temp_new(TCG_TYPE_I32);
tcg_gen_ld_i32(tmp1, cpu_env, offsetof(CPUState, fregs[reg]));
- tcg_gen_extu_i32_i64(t, tmp1);
- tcg_gen_shli_i64(t, t, 32);
- tcg_gen_ld_i32(tmp1, cpu_env, offsetof(CPUState, fregs[reg + 1]));
- tcg_gen_extu_i32_i64(tmp2, tmp1);
+ tcg_gen_ld_i32(tmp2, cpu_env, offsetof(CPUState, fregs[reg + 1]));
+ tcg_gen_concat_i32_i64(t, tmp2, tmp1);
tcg_temp_free(tmp1);
- tcg_gen_or_i64(t, t, tmp2);
tcg_temp_free(tmp2);
}
diff --git a/tcg/README b/tcg/README
index b03432e23a..b4d07b6f42 100644
--- a/tcg/README
+++ b/tcg/README
@@ -265,6 +265,10 @@ Convert t1 (32 bit) to t0 (64 bit) and does zero extension
* trunc_i64_i32 t0, t1
Truncate t1 (64 bit) to t0 (32 bit)
+* concat_i32_i64 t0, t1, t2
+Construct t0 (64-bit) taking the low half from t1 (32 bit) and the high half
+from t2 (32 bit).
+
********* Load/Store
* ld_i32/i64 t0, t1, offset
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index bc6be8537e..7b39fe865a 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -1395,6 +1395,23 @@ static inline void tcg_gen_discard_i64(TCGv arg)
}
#endif
+static inline void tcg_gen_concat_i32_i64(TCGv dest, TCGv low, TCGv high)
+{
+#if TCG_TARGET_REG_BITS == 32
+ tcg_gen_mov_i32(dest, low);
+ tcg_gen_mov_i32(TCGV_HIGH(dest), high);
+#else
+ TCGv tmp = tcg_temp_new (TCG_TYPE_I64);
+ /* This extension is only needed for type correctness.
+ We may be able to do better given target specific information. */
+ tcg_gen_extu_i32_i64(tmp, high);
+ tcg_gen_shli_i64(tmp, tmp, 32);
+ tcg_gen_extu_i32_i64(dest, low);
+ tcg_gen_or_i64(dest, dest, tmp);
+ tcg_temp_free(tmp);
+#endif
+}
+
/***************************************/
/* QEMU specific operations. Their type depend on the QEMU CPU
type. */