mirror of https://gitee.com/openkylin/qemu.git
target-mips: optimize gen_muldiv()
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6940 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
ab36421e54
commit
d45f89f4e4
|
@ -1803,8 +1803,23 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
|||
int rs, int rt)
|
||||
{
|
||||
const char *opn = "mul/div";
|
||||
TCGv t0 = tcg_temp_local_new();
|
||||
TCGv t1 = tcg_temp_local_new();
|
||||
TCGv t0, t1;
|
||||
|
||||
switch (opc) {
|
||||
case OPC_DIV:
|
||||
case OPC_DIVU:
|
||||
#if defined(TARGET_MIPS64)
|
||||
case OPC_DDIV:
|
||||
case OPC_DDIVU:
|
||||
#endif
|
||||
t0 = tcg_temp_local_new();
|
||||
t1 = tcg_temp_local_new();
|
||||
break;
|
||||
default:
|
||||
t0 = tcg_temp_new();
|
||||
t1 = tcg_temp_new();
|
||||
break;
|
||||
}
|
||||
|
||||
gen_load_gpr(t0, rs);
|
||||
gen_load_gpr(t1, rt);
|
||||
|
@ -1812,30 +1827,22 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
|||
case OPC_DIV:
|
||||
{
|
||||
int l1 = gen_new_label();
|
||||
int l2 = gen_new_label();
|
||||
|
||||
tcg_gen_ext32s_tl(t0, t0);
|
||||
tcg_gen_ext32s_tl(t1, t1);
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
|
||||
{
|
||||
int l2 = gen_new_label();
|
||||
TCGv_i32 r_tmp1 = tcg_temp_local_new_i32();
|
||||
TCGv_i32 r_tmp2 = tcg_temp_local_new_i32();
|
||||
TCGv_i32 r_tmp3 = tcg_temp_local_new_i32();
|
||||
tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
|
||||
tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
|
||||
|
||||
tcg_gen_trunc_tl_i32(r_tmp1, t0);
|
||||
tcg_gen_trunc_tl_i32(r_tmp2, t1);
|
||||
tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp1, -1 << 31, l2);
|
||||
tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp2, -1, l2);
|
||||
tcg_gen_ext32s_tl(cpu_LO[0], t0);
|
||||
tcg_gen_movi_tl(cpu_HI[0], 0);
|
||||
tcg_gen_br(l1);
|
||||
gen_set_label(l2);
|
||||
tcg_gen_div_i32(r_tmp3, r_tmp1, r_tmp2);
|
||||
tcg_gen_rem_i32(r_tmp2, r_tmp1, r_tmp2);
|
||||
tcg_gen_ext_i32_tl(cpu_LO[0], r_tmp3);
|
||||
tcg_gen_ext_i32_tl(cpu_HI[0], r_tmp2);
|
||||
tcg_temp_free_i32(r_tmp1);
|
||||
tcg_temp_free_i32(r_tmp2);
|
||||
tcg_temp_free_i32(r_tmp3);
|
||||
}
|
||||
tcg_gen_mov_tl(cpu_LO[0], t0);
|
||||
tcg_gen_movi_tl(cpu_HI[0], 0);
|
||||
tcg_gen_br(l1);
|
||||
gen_set_label(l2);
|
||||
tcg_gen_div_tl(cpu_LO[0], t0, t1);
|
||||
tcg_gen_rem_tl(cpu_HI[0], t0, t1);
|
||||
tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
|
||||
tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
|
||||
gen_set_label(l1);
|
||||
}
|
||||
opn = "div";
|
||||
|
@ -1844,40 +1851,28 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
|||
{
|
||||
int l1 = gen_new_label();
|
||||
|
||||
tcg_gen_ext32s_tl(t1, t1);
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
|
||||
{
|
||||
TCGv_i32 r_tmp1 = tcg_temp_new_i32();
|
||||
TCGv_i32 r_tmp2 = tcg_temp_new_i32();
|
||||
TCGv_i32 r_tmp3 = tcg_temp_new_i32();
|
||||
|
||||
tcg_gen_trunc_tl_i32(r_tmp1, t0);
|
||||
tcg_gen_trunc_tl_i32(r_tmp2, t1);
|
||||
tcg_gen_divu_i32(r_tmp3, r_tmp1, r_tmp2);
|
||||
tcg_gen_remu_i32(r_tmp1, r_tmp1, r_tmp2);
|
||||
tcg_gen_ext_i32_tl(cpu_LO[0], r_tmp3);
|
||||
tcg_gen_ext_i32_tl(cpu_HI[0], r_tmp1);
|
||||
tcg_temp_free_i32(r_tmp1);
|
||||
tcg_temp_free_i32(r_tmp2);
|
||||
tcg_temp_free_i32(r_tmp3);
|
||||
}
|
||||
tcg_gen_divu_tl(cpu_LO[0], t0, t1);
|
||||
tcg_gen_remu_tl(cpu_HI[0], t0, t1);
|
||||
tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
|
||||
tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
|
||||
gen_set_label(l1);
|
||||
}
|
||||
opn = "divu";
|
||||
break;
|
||||
case OPC_MULT:
|
||||
{
|
||||
TCGv_i64 r_tmp1 = tcg_temp_new_i64();
|
||||
TCGv_i64 r_tmp2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t3 = tcg_temp_new_i64();
|
||||
|
||||
tcg_gen_ext_tl_i64(r_tmp1, t0);
|
||||
tcg_gen_ext_tl_i64(r_tmp2, t1);
|
||||
tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
|
||||
tcg_temp_free_i64(r_tmp2);
|
||||
tcg_gen_trunc_i64_tl(t0, r_tmp1);
|
||||
tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
|
||||
tcg_gen_trunc_i64_tl(t1, r_tmp1);
|
||||
tcg_temp_free_i64(r_tmp1);
|
||||
tcg_gen_ext_tl_i64(t2, t0);
|
||||
tcg_gen_ext_tl_i64(t3, t1);
|
||||
tcg_gen_mul_i64(t2, t2, t3);
|
||||
tcg_temp_free_i64(t3);
|
||||
tcg_gen_trunc_i64_tl(t0, t2);
|
||||
tcg_gen_shri_i64(t2, t2, 32);
|
||||
tcg_gen_trunc_i64_tl(t1, t2);
|
||||
tcg_temp_free_i64(t2);
|
||||
tcg_gen_ext32s_tl(cpu_LO[0], t0);
|
||||
tcg_gen_ext32s_tl(cpu_HI[0], t1);
|
||||
}
|
||||
|
@ -1885,19 +1880,19 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
|||
break;
|
||||
case OPC_MULTU:
|
||||
{
|
||||
TCGv_i64 r_tmp1 = tcg_temp_new_i64();
|
||||
TCGv_i64 r_tmp2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t3 = tcg_temp_new_i64();
|
||||
|
||||
tcg_gen_ext32u_tl(t0, t0);
|
||||
tcg_gen_ext32u_tl(t1, t1);
|
||||
tcg_gen_extu_tl_i64(r_tmp1, t0);
|
||||
tcg_gen_extu_tl_i64(r_tmp2, t1);
|
||||
tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
|
||||
tcg_temp_free_i64(r_tmp2);
|
||||
tcg_gen_trunc_i64_tl(t0, r_tmp1);
|
||||
tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
|
||||
tcg_gen_trunc_i64_tl(t1, r_tmp1);
|
||||
tcg_temp_free_i64(r_tmp1);
|
||||
tcg_gen_extu_tl_i64(t2, t0);
|
||||
tcg_gen_extu_tl_i64(t3, t1);
|
||||
tcg_gen_mul_i64(t2, t2, t3);
|
||||
tcg_temp_free_i64(t3);
|
||||
tcg_gen_trunc_i64_tl(t0, t2);
|
||||
tcg_gen_shri_i64(t2, t2, 32);
|
||||
tcg_gen_trunc_i64_tl(t1, t2);
|
||||
tcg_temp_free_i64(t2);
|
||||
tcg_gen_ext32s_tl(cpu_LO[0], t0);
|
||||
tcg_gen_ext32s_tl(cpu_HI[0], t1);
|
||||
}
|
||||
|
@ -1907,20 +1902,17 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
|||
case OPC_DDIV:
|
||||
{
|
||||
int l1 = gen_new_label();
|
||||
int l2 = gen_new_label();
|
||||
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
|
||||
{
|
||||
int l2 = gen_new_label();
|
||||
|
||||
tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
|
||||
tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
|
||||
tcg_gen_mov_tl(cpu_LO[0], t0);
|
||||
tcg_gen_movi_tl(cpu_HI[0], 0);
|
||||
tcg_gen_br(l1);
|
||||
gen_set_label(l2);
|
||||
tcg_gen_div_i64(cpu_LO[0], t0, t1);
|
||||
tcg_gen_rem_i64(cpu_HI[0], t0, t1);
|
||||
}
|
||||
tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
|
||||
tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
|
||||
tcg_gen_mov_tl(cpu_LO[0], t0);
|
||||
tcg_gen_movi_tl(cpu_HI[0], 0);
|
||||
tcg_gen_br(l1);
|
||||
gen_set_label(l2);
|
||||
tcg_gen_div_i64(cpu_LO[0], t0, t1);
|
||||
tcg_gen_rem_i64(cpu_HI[0], t0, t1);
|
||||
gen_set_label(l1);
|
||||
}
|
||||
opn = "ddiv";
|
||||
|
@ -1947,19 +1939,19 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
|||
#endif
|
||||
case OPC_MADD:
|
||||
{
|
||||
TCGv_i64 r_tmp1 = tcg_temp_new_i64();
|
||||
TCGv_i64 r_tmp2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t3 = tcg_temp_new_i64();
|
||||
|
||||
tcg_gen_ext_tl_i64(r_tmp1, t0);
|
||||
tcg_gen_ext_tl_i64(r_tmp2, t1);
|
||||
tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
|
||||
tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]);
|
||||
tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2);
|
||||
tcg_temp_free_i64(r_tmp2);
|
||||
tcg_gen_trunc_i64_tl(t0, r_tmp1);
|
||||
tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
|
||||
tcg_gen_trunc_i64_tl(t1, r_tmp1);
|
||||
tcg_temp_free_i64(r_tmp1);
|
||||
tcg_gen_ext_tl_i64(t2, t0);
|
||||
tcg_gen_ext_tl_i64(t3, t1);
|
||||
tcg_gen_mul_i64(t2, t2, t3);
|
||||
tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
|
||||
tcg_gen_add_i64(t2, t2, t3);
|
||||
tcg_temp_free_i64(t3);
|
||||
tcg_gen_trunc_i64_tl(t0, t2);
|
||||
tcg_gen_shri_i64(t2, t2, 32);
|
||||
tcg_gen_trunc_i64_tl(t1, t2);
|
||||
tcg_temp_free_i64(t2);
|
||||
tcg_gen_ext32s_tl(cpu_LO[0], t0);
|
||||
tcg_gen_ext32s_tl(cpu_LO[1], t1);
|
||||
}
|
||||
|
@ -1967,21 +1959,21 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
|||
break;
|
||||
case OPC_MADDU:
|
||||
{
|
||||
TCGv_i64 r_tmp1 = tcg_temp_new_i64();
|
||||
TCGv_i64 r_tmp2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t3 = tcg_temp_new_i64();
|
||||
|
||||
tcg_gen_ext32u_tl(t0, t0);
|
||||
tcg_gen_ext32u_tl(t1, t1);
|
||||
tcg_gen_extu_tl_i64(r_tmp1, t0);
|
||||
tcg_gen_extu_tl_i64(r_tmp2, t1);
|
||||
tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
|
||||
tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]);
|
||||
tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2);
|
||||
tcg_temp_free_i64(r_tmp2);
|
||||
tcg_gen_trunc_i64_tl(t0, r_tmp1);
|
||||
tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
|
||||
tcg_gen_trunc_i64_tl(t1, r_tmp1);
|
||||
tcg_temp_free_i64(r_tmp1);
|
||||
tcg_gen_extu_tl_i64(t2, t0);
|
||||
tcg_gen_extu_tl_i64(t3, t1);
|
||||
tcg_gen_mul_i64(t2, t2, t3);
|
||||
tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
|
||||
tcg_gen_add_i64(t2, t2, t3);
|
||||
tcg_temp_free_i64(t3);
|
||||
tcg_gen_trunc_i64_tl(t0, t2);
|
||||
tcg_gen_shri_i64(t2, t2, 32);
|
||||
tcg_gen_trunc_i64_tl(t1, t2);
|
||||
tcg_temp_free_i64(t2);
|
||||
tcg_gen_ext32s_tl(cpu_LO[0], t0);
|
||||
tcg_gen_ext32s_tl(cpu_HI[0], t1);
|
||||
}
|
||||
|
@ -1989,19 +1981,19 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
|||
break;
|
||||
case OPC_MSUB:
|
||||
{
|
||||
TCGv_i64 r_tmp1 = tcg_temp_new_i64();
|
||||
TCGv_i64 r_tmp2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t3 = tcg_temp_new_i64();
|
||||
|
||||
tcg_gen_ext_tl_i64(r_tmp1, t0);
|
||||
tcg_gen_ext_tl_i64(r_tmp2, t1);
|
||||
tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
|
||||
tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]);
|
||||
tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2);
|
||||
tcg_temp_free_i64(r_tmp2);
|
||||
tcg_gen_trunc_i64_tl(t0, r_tmp1);
|
||||
tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
|
||||
tcg_gen_trunc_i64_tl(t1, r_tmp1);
|
||||
tcg_temp_free_i64(r_tmp1);
|
||||
tcg_gen_ext_tl_i64(t2, t0);
|
||||
tcg_gen_ext_tl_i64(t3, t1);
|
||||
tcg_gen_mul_i64(t2, t2, t3);
|
||||
tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
|
||||
tcg_gen_sub_i64(t2, t2, t3);
|
||||
tcg_temp_free_i64(t3);
|
||||
tcg_gen_trunc_i64_tl(t0, t2);
|
||||
tcg_gen_shri_i64(t2, t2, 32);
|
||||
tcg_gen_trunc_i64_tl(t1, t2);
|
||||
tcg_temp_free_i64(t2);
|
||||
tcg_gen_ext32s_tl(cpu_LO[0], t0);
|
||||
tcg_gen_ext32s_tl(cpu_HI[0], t1);
|
||||
}
|
||||
|
@ -2009,21 +2001,21 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
|||
break;
|
||||
case OPC_MSUBU:
|
||||
{
|
||||
TCGv_i64 r_tmp1 = tcg_temp_new_i64();
|
||||
TCGv_i64 r_tmp2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t3 = tcg_temp_new_i64();
|
||||
|
||||
tcg_gen_ext32u_tl(t0, t0);
|
||||
tcg_gen_ext32u_tl(t1, t1);
|
||||
tcg_gen_extu_tl_i64(r_tmp1, t0);
|
||||
tcg_gen_extu_tl_i64(r_tmp2, t1);
|
||||
tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
|
||||
tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]);
|
||||
tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2);
|
||||
tcg_temp_free_i64(r_tmp2);
|
||||
tcg_gen_trunc_i64_tl(t0, r_tmp1);
|
||||
tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
|
||||
tcg_gen_trunc_i64_tl(t1, r_tmp1);
|
||||
tcg_temp_free_i64(r_tmp1);
|
||||
tcg_gen_extu_tl_i64(t2, t0);
|
||||
tcg_gen_extu_tl_i64(t3, t1);
|
||||
tcg_gen_mul_i64(t2, t2, t3);
|
||||
tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
|
||||
tcg_gen_sub_i64(t2, t2, t3);
|
||||
tcg_temp_free_i64(t3);
|
||||
tcg_gen_trunc_i64_tl(t0, t2);
|
||||
tcg_gen_shri_i64(t2, t2, 32);
|
||||
tcg_gen_trunc_i64_tl(t1, t2);
|
||||
tcg_temp_free_i64(t2);
|
||||
tcg_gen_ext32s_tl(cpu_LO[0], t0);
|
||||
tcg_gen_ext32s_tl(cpu_HI[0], t1);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue