aboutsummaryrefslogtreecommitdiff
path: root/target-mips
diff options
context:
space:
mode:
authoraurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162>2008-11-11 11:47:06 +0000
committeraurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162>2008-11-11 11:47:06 +0000
commit49bcf33cc7c94655c0a48f8de9b3473d29bb6ed0 (patch)
tree94df6bd0899b13b0e9d5cbc00551bf7472ff1d49 /target-mips
parent505ad7c2ffd1caf82a6789b610bff82b8b6ad472 (diff)
downloadqemu-49bcf33cc7c94655c0a48f8de9b3473d29bb6ed0.zip
qemu-49bcf33cc7c94655c0a48f8de9b3473d29bb6ed0.tar.gz
qemu-49bcf33cc7c94655c0a48f8de9b3473d29bb6ed0.tar.bz2
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
Diffstat (limited to 'target-mips')
-rw-r--r--target-mips/helper.h7
-rw-r--r--target-mips/op_helper.c19
-rw-r--r--target-mips/translate.c106
3 files changed, 56 insertions, 76 deletions
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 5926921..f67c82a 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -269,10 +269,3 @@ DEF_HELPER(target_ulong, do_rdhwr_cc, (void))
DEF_HELPER(target_ulong, do_rdhwr_ccres, (void))
DEF_HELPER(void, do_pmon, (int function))
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
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index b642593..3fe62fb 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1781,25 +1781,6 @@ target_ulong do_rdhwr_ccres(void)
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)
{
function /= 2;
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 00122f1..f637d2b 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -2771,6 +2771,60 @@ fail:
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
/* CP0 (MMU and control) */
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:
check_insn(env, ctx, ISA_MIPS32R2);
op2 = MASK_BSHFL(ctx->opcode);
- {
- 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);
- }
+ gen_bshfl(ctx, op2, rt, rd);
break;
case OPC_RDHWR:
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_mips_64(ctx);
op2 = MASK_DBSHFL(ctx->opcode);
- {
- 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);
- }
+ gen_bshfl(ctx, op2, rt, rd);
break;
#endif
default: /* Invalid */