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:
aurel32 2008-11-11 11:47:06 +00:00
parent 505ad7c2ff
commit 49bcf33cc7
3 changed files with 56 additions and 76 deletions

View File

@ -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

View File

@ -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;

View File

@ -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 */