target-mips: convert bit shuffle ops to TCG
Bit shuffle operations can be written with very few TCG instructions (between 5 and 8), so it is worth converting them to TCG. This code also move all bit shuffle generation code to a separate function in order to have a cleaner exception code path, that is it doesn't store back the TCG register to the target register after the exception, as the TCG register doesn't exist anymore. Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5679 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
505ad7c2ff
commit
49bcf33cc7
@ -269,10 +269,3 @@ DEF_HELPER(target_ulong, do_rdhwr_cc, (void))
|
|||||||
DEF_HELPER(target_ulong, do_rdhwr_ccres, (void))
|
DEF_HELPER(target_ulong, do_rdhwr_ccres, (void))
|
||||||
DEF_HELPER(void, do_pmon, (int function))
|
DEF_HELPER(void, do_pmon, (int function))
|
||||||
DEF_HELPER(void, do_wait, (void))
|
DEF_HELPER(void, do_wait, (void))
|
||||||
|
|
||||||
/* Bit shuffle operations. */
|
|
||||||
DEF_HELPER(target_ulong, do_wsbh, (target_ulong t1))
|
|
||||||
#ifdef TARGET_MIPS64
|
|
||||||
DEF_HELPER(target_ulong, do_dsbh, (target_ulong t1))
|
|
||||||
DEF_HELPER(target_ulong, do_dshd, (target_ulong t1))
|
|
||||||
#endif
|
|
||||||
|
@ -1781,25 +1781,6 @@ target_ulong do_rdhwr_ccres(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bit shuffle operations. */
|
|
||||||
target_ulong do_wsbh(target_ulong t1)
|
|
||||||
{
|
|
||||||
return (int32_t)(((t1 << 8) & ~0x00FF00FF) | ((t1 >> 8) & 0x00FF00FF));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(TARGET_MIPS64)
|
|
||||||
target_ulong do_dsbh(target_ulong t1)
|
|
||||||
{
|
|
||||||
return ((t1 << 8) & ~0x00FF00FF00FF00FFULL) | ((t1 >> 8) & 0x00FF00FF00FF00FFULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
target_ulong do_dshd(target_ulong t1)
|
|
||||||
{
|
|
||||||
t1 = ((t1 << 16) & ~0x0000FFFF0000FFFFULL) | ((t1 >> 16) & 0x0000FFFF0000FFFFULL);
|
|
||||||
return (t1 << 32) | (t1 >> 32);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void do_pmon (int function)
|
void do_pmon (int function)
|
||||||
{
|
{
|
||||||
function /= 2;
|
function /= 2;
|
||||||
|
@ -2771,6 +2771,60 @@ fail:
|
|||||||
tcg_temp_free(t1);
|
tcg_temp_free(t1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
|
||||||
|
{
|
||||||
|
TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
|
||||||
|
TCGv t1 = tcg_temp_new(TCG_TYPE_TL);
|
||||||
|
|
||||||
|
gen_load_gpr(t1, rt);
|
||||||
|
switch (op2) {
|
||||||
|
case OPC_WSBH:
|
||||||
|
tcg_gen_shri_tl(t0, t1, 8);
|
||||||
|
tcg_gen_andi_tl(t0, t0, 0x00FF00FF);
|
||||||
|
tcg_gen_shli_tl(t1, t1, 8);
|
||||||
|
tcg_gen_andi_tl(t1, t1, ~0x00FF00FF);
|
||||||
|
tcg_gen_or_tl(t0, t0, t1);
|
||||||
|
tcg_gen_ext32s_tl(t0, t0);
|
||||||
|
break;
|
||||||
|
case OPC_SEB:
|
||||||
|
tcg_gen_ext8s_tl(t0, t1);
|
||||||
|
break;
|
||||||
|
case OPC_SEH:
|
||||||
|
tcg_gen_ext16s_tl(t0, t1);
|
||||||
|
break;
|
||||||
|
#if defined(TARGET_MIPS64)
|
||||||
|
case OPC_DSBH:
|
||||||
|
gen_load_gpr(t1, rt);
|
||||||
|
tcg_gen_shri_tl(t0, t1, 8);
|
||||||
|
tcg_gen_andi_tl(t0, t0, 0x00FF00FF00FF00FFULL);
|
||||||
|
tcg_gen_shli_tl(t1, t1, 8);
|
||||||
|
tcg_gen_andi_tl(t1, t1, ~0x00FF00FF00FF00FFULL);
|
||||||
|
tcg_gen_or_tl(t0, t0, t1);
|
||||||
|
break;
|
||||||
|
case OPC_DSHD:
|
||||||
|
gen_load_gpr(t1, rt);
|
||||||
|
tcg_gen_shri_tl(t0, t1, 16);
|
||||||
|
tcg_gen_andi_tl(t0, t0, 0x0000FFFF0000FFFFULL);
|
||||||
|
tcg_gen_shli_tl(t1, t1, 16);
|
||||||
|
tcg_gen_andi_tl(t1, t1, ~0x0000FFFF0000FFFFULL);
|
||||||
|
tcg_gen_or_tl(t1, t0, t1);
|
||||||
|
tcg_gen_shri_tl(t0, t1, 32);
|
||||||
|
tcg_gen_shli_tl(t1, t1, 32);
|
||||||
|
tcg_gen_or_tl(t0, t0, t1);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
MIPS_INVAL("bsfhl");
|
||||||
|
generate_exception(ctx, EXCP_RI);
|
||||||
|
tcg_temp_free(t0);
|
||||||
|
tcg_temp_free(t1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gen_store_gpr(t0, rd);
|
||||||
|
tcg_temp_free(t0);
|
||||||
|
tcg_temp_free(t1);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
/* CP0 (MMU and control) */
|
/* CP0 (MMU and control) */
|
||||||
static inline void gen_mfc0_load32 (TCGv t, target_ulong off)
|
static inline void gen_mfc0_load32 (TCGv t, target_ulong off)
|
||||||
@ -7953,34 +8007,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
|||||||
case OPC_BSHFL:
|
case OPC_BSHFL:
|
||||||
check_insn(env, ctx, ISA_MIPS32R2);
|
check_insn(env, ctx, ISA_MIPS32R2);
|
||||||
op2 = MASK_BSHFL(ctx->opcode);
|
op2 = MASK_BSHFL(ctx->opcode);
|
||||||
{
|
gen_bshfl(ctx, op2, rt, rd);
|
||||||
TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
|
|
||||||
TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
|
|
||||||
|
|
||||||
switch (op2) {
|
|
||||||
case OPC_WSBH:
|
|
||||||
gen_load_gpr(t1, rt);
|
|
||||||
tcg_gen_helper_1_1(do_wsbh, t0, t1);
|
|
||||||
gen_store_gpr(t0, rd);
|
|
||||||
break;
|
|
||||||
case OPC_SEB:
|
|
||||||
gen_load_gpr(t1, rt);
|
|
||||||
tcg_gen_ext8s_tl(t0, t1);
|
|
||||||
gen_store_gpr(t0, rd);
|
|
||||||
break;
|
|
||||||
case OPC_SEH:
|
|
||||||
gen_load_gpr(t1, rt);
|
|
||||||
tcg_gen_ext16s_tl(t0, t1);
|
|
||||||
gen_store_gpr(t0, rd);
|
|
||||||
break;
|
|
||||||
default: /* Invalid */
|
|
||||||
MIPS_INVAL("bshfl");
|
|
||||||
generate_exception(ctx, EXCP_RI);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tcg_temp_free(t0);
|
|
||||||
tcg_temp_free(t1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case OPC_RDHWR:
|
case OPC_RDHWR:
|
||||||
check_insn(env, ctx, ISA_MIPS32R2);
|
check_insn(env, ctx, ISA_MIPS32R2);
|
||||||
@ -8056,28 +8083,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
|||||||
check_insn(env, ctx, ISA_MIPS64R2);
|
check_insn(env, ctx, ISA_MIPS64R2);
|
||||||
check_mips_64(ctx);
|
check_mips_64(ctx);
|
||||||
op2 = MASK_DBSHFL(ctx->opcode);
|
op2 = MASK_DBSHFL(ctx->opcode);
|
||||||
{
|
gen_bshfl(ctx, op2, rt, rd);
|
||||||
TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
|
|
||||||
TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
|
|
||||||
|
|
||||||
switch (op2) {
|
|
||||||
case OPC_DSBH:
|
|
||||||
gen_load_gpr(t1, rt);
|
|
||||||
tcg_gen_helper_1_1(do_dsbh, t0, t1);
|
|
||||||
break;
|
|
||||||
case OPC_DSHD:
|
|
||||||
gen_load_gpr(t1, rt);
|
|
||||||
tcg_gen_helper_1_1(do_dshd, t0, t1);
|
|
||||||
break;
|
|
||||||
default: /* Invalid */
|
|
||||||
MIPS_INVAL("dbshfl");
|
|
||||||
generate_exception(ctx, EXCP_RI);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
gen_store_gpr(t0, rd);
|
|
||||||
tcg_temp_free(t0);
|
|
||||||
tcg_temp_free(t1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default: /* Invalid */
|
default: /* Invalid */
|
||||||
|
Loading…
Reference in New Issue
Block a user