diff options
author | Richard Henderson <rth@twiddle.net> | 2016-11-21 11:13:39 +0100 |
---|---|---|
committer | Richard Henderson <rth@twiddle.net> | 2017-01-10 08:48:56 -0800 |
commit | a768e4e99247911f00c5c0267c12d4e207d5f6cc (patch) | |
tree | 050f67bd90c849c64c774361c76020896efaf433 /tcg/tcg-op.c | |
parent | 3946c6aa3d402614140f2c6a044abcdfb439217a (diff) | |
download | qemu-a768e4e99247911f00c5c0267c12d4e207d5f6cc.zip qemu-a768e4e99247911f00c5c0267c12d4e207d5f6cc.tar.gz qemu-a768e4e99247911f00c5c0267c12d4e207d5f6cc.tar.bz2 |
tcg: Add opcode for ctpop
The number of actual invocations of ctpop itself does not warrent
an opcode, but it is very helpful for POWER7 to use in generating
an expansion for ctz.
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'tcg/tcg-op.c')
-rw-r--r-- | tcg/tcg-op.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c index 620e268..6f4b1b6 100644 --- a/tcg/tcg-op.c +++ b/tcg/tcg-op.c @@ -550,6 +550,21 @@ void tcg_gen_clrsb_i32(TCGv_i32 ret, TCGv_i32 arg) } } +void tcg_gen_ctpop_i32(TCGv_i32 ret, TCGv_i32 arg1) +{ + if (TCG_TARGET_HAS_ctpop_i32) { + tcg_gen_op2_i32(INDEX_op_ctpop_i32, ret, arg1); + } else if (TCG_TARGET_HAS_ctpop_i64) { + TCGv_i64 t = tcg_temp_new_i64(); + tcg_gen_extu_i32_i64(t, arg1); + tcg_gen_ctpop_i64(t, t); + tcg_gen_extrl_i64_i32(ret, t); + tcg_temp_free_i64(t); + } else { + gen_helper_ctpop_i32(ret, arg1); + } +} + void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) { if (TCG_TARGET_HAS_rot_i32) { @@ -1874,6 +1889,20 @@ void tcg_gen_clrsb_i64(TCGv_i64 ret, TCGv_i64 arg) } } +void tcg_gen_ctpop_i64(TCGv_i64 ret, TCGv_i64 arg1) +{ + if (TCG_TARGET_HAS_ctpop_i64) { + tcg_gen_op2_i64(INDEX_op_ctpop_i64, ret, arg1); + } else if (TCG_TARGET_REG_BITS == 32 && TCG_TARGET_HAS_ctpop_i32) { + tcg_gen_ctpop_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1)); + tcg_gen_ctpop_i32(TCGV_LOW(ret), TCGV_LOW(arg1)); + tcg_gen_add_i32(TCGV_LOW(ret), TCGV_LOW(ret), TCGV_HIGH(ret)); + tcg_gen_movi_i32(TCGV_HIGH(ret), 0); + } else { + gen_helper_ctpop_i64(ret, arg1); + } +} + void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) { if (TCG_TARGET_HAS_rot_i64) { |