diff options
author | aurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-11-11 11:46:58 +0000 |
---|---|---|
committer | aurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-11-11 11:46:58 +0000 |
commit | 505ad7c2ffd1caf82a6789b610bff82b8b6ad472 (patch) | |
tree | acdc27b38fb8a32d1ac3abc7630b5d1fff3ce7c2 /target-mips | |
parent | 2623c1ecfc87a0a86188c75598410e6b3d0f18a3 (diff) | |
download | qemu-505ad7c2ffd1caf82a6789b610bff82b8b6ad472.zip qemu-505ad7c2ffd1caf82a6789b610bff82b8b6ad472.tar.gz qemu-505ad7c2ffd1caf82a6789b610bff82b8b6ad472.tar.bz2 |
target-mips: convert bitfield ops to TCG
Bitfield operations can be written with very few TCG instructions
(between 2 and 5), so it is worth converting them to TCG.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5678 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-mips')
-rw-r--r-- | target-mips/helper.h | 6 | ||||
-rw-r--r-- | target-mips/op_helper.c | 26 | ||||
-rw-r--r-- | target-mips/translate.c | 55 |
3 files changed, 41 insertions, 46 deletions
diff --git a/target-mips/helper.h b/target-mips/helper.h index 525ccbb..5926921 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -270,13 +270,9 @@ DEF_HELPER(target_ulong, do_rdhwr_ccres, (void)) DEF_HELPER(void, do_pmon, (int function)) DEF_HELPER(void, do_wait, (void)) -/* Bitfield operations. */ -DEF_HELPER(target_ulong, do_ext, (target_ulong t1, uint32_t pos, uint32_t size)) -DEF_HELPER(target_ulong, do_ins, (target_ulong t0, target_ulong t1, uint32_t pos, uint32_t size)) +/* Bit shuffle operations. */ DEF_HELPER(target_ulong, do_wsbh, (target_ulong t1)) #ifdef TARGET_MIPS64 -DEF_HELPER(target_ulong, do_dext, (target_ulong t1, uint32_t pos, uint32_t size)) -DEF_HELPER(target_ulong, do_dins, (target_ulong t0, target_ulong t1, uint32_t pos, uint32_t size)) 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 3744728..b642593 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1781,37 +1781,13 @@ target_ulong do_rdhwr_ccres(void) return 0; } -/* Bitfield operations. */ -target_ulong do_ext(target_ulong t1, uint32_t pos, uint32_t size) -{ - return (int32_t)((t1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0)); -} - -target_ulong do_ins(target_ulong t0, target_ulong t1, uint32_t pos, uint32_t size) -{ - target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos; - - return (int32_t)((t0 & ~mask) | ((t1 << pos) & mask)); -} - +/* 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_dext(target_ulong t1, uint32_t pos, uint32_t size) -{ - return (t1 >> pos) & ((size < 64) ? ((1ULL << size) - 1) : ~0ULL); -} - -target_ulong do_dins(target_ulong t0, target_ulong t1, uint32_t pos, uint32_t size) -{ - target_ulong mask = ((size < 64) ? ((1ULL << size) - 1) : ~0ULL) << pos; - - return (t0 & ~mask) | ((t1 << pos) & mask); -} - target_ulong do_dsbh(target_ulong t1) { return ((t1 << 8) & ~0x00FF00FF00FF00FFULL) | ((t1 >> 8) & 0x00FF00FF00FF00FFULL); diff --git a/target-mips/translate.c b/target-mips/translate.c index ab78c14..00122f1 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -2682,57 +2682,80 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt, int rs, int lsb, int msb) { - TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL); - TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL); + TCGv t0 = tcg_temp_new(TCG_TYPE_TL); + TCGv t1 = tcg_temp_new(TCG_TYPE_TL); + target_ulong mask; gen_load_gpr(t1, rs); switch (opc) { case OPC_EXT: if (lsb + msb > 31) goto fail; - tcg_gen_helper_1_1ii(do_ext, t0, t1, lsb, msb + 1); + tcg_gen_shri_tl(t0, t1, lsb); + if (msb != 31) { + tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1); + } else { + tcg_gen_ext32s_tl(t0, t0); + } break; #if defined(TARGET_MIPS64) case OPC_DEXTM: - if (lsb + msb > 63) - goto fail; - tcg_gen_helper_1_1ii(do_dext, t0, t1, lsb, msb + 1 + 32); + tcg_gen_shri_tl(t0, t1, lsb); + if (msb != 31) { + tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1); + } break; case OPC_DEXTU: - if (lsb + msb > 63) - goto fail; - tcg_gen_helper_1_1ii(do_dext, t0, t1, lsb + 32, msb + 1); + tcg_gen_shri_tl(t0, t1, lsb + 32); + tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1); break; case OPC_DEXT: - if (lsb + msb > 63) - goto fail; - tcg_gen_helper_1_1ii(do_dext, t0, t1, lsb, msb + 1); + tcg_gen_shri_tl(t0, t1, lsb); + tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1); break; #endif case OPC_INS: if (lsb > msb) goto fail; + mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb; gen_load_gpr(t0, rt); - tcg_gen_helper_1_2ii(do_ins, t0, t0, t1, lsb, msb - lsb + 1); + tcg_gen_andi_tl(t0, t0, ~mask); + tcg_gen_shli_tl(t1, t1, lsb); + tcg_gen_andi_tl(t1, t1, mask); + tcg_gen_or_tl(t0, t0, t1); + tcg_gen_ext32s_tl(t0, t0); break; #if defined(TARGET_MIPS64) case OPC_DINSM: if (lsb > msb) goto fail; + mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb; gen_load_gpr(t0, rt); - tcg_gen_helper_1_2ii(do_dins, t0, t0, t1, lsb, msb - lsb + 1 + 32); + tcg_gen_andi_tl(t0, t0, ~mask); + tcg_gen_shli_tl(t1, t1, lsb); + tcg_gen_andi_tl(t1, t1, mask); + tcg_gen_or_tl(t0, t0, t1); break; case OPC_DINSU: if (lsb > msb) goto fail; + mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb; gen_load_gpr(t0, rt); - tcg_gen_helper_1_2ii(do_dins, t0, t0, t1, lsb + 32, msb - lsb + 1); + tcg_gen_andi_tl(t0, t0, ~mask); + tcg_gen_shli_tl(t1, t1, lsb + 32); + tcg_gen_andi_tl(t1, t1, mask); + tcg_gen_or_tl(t0, t0, t1); break; case OPC_DINS: if (lsb > msb) goto fail; gen_load_gpr(t0, rt); - tcg_gen_helper_1_2ii(do_dins, t0, t0, t1, lsb, msb - lsb + 1); + mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb; + gen_load_gpr(t0, rt); + tcg_gen_andi_tl(t0, t0, ~mask); + tcg_gen_shli_tl(t1, t1, lsb); + tcg_gen_andi_tl(t1, t1, mask); + tcg_gen_or_tl(t0, t0, t1); break; #endif default: |