extract and deposit_z are similar operations, only differing in
that extract shifts the operand right and deposit_z shifts it left.
Like extract, it is possible to implement deposit_z as either AND+SHL or
SHL+SHR. Use tcg_op_imm_match to check whether the processor supports the
immediate that is needed for the mask, and if not fall back to two shifts.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
tcg/tcg-op.c | 28 ++++++++++++++++++++++++----
1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
index ccf66382623..e7d6702f9c4 100644
--- a/tcg/tcg-op.c
+++ b/tcg/tcg-op.c
@@ -960,8 +960,18 @@ void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg,
tcg_gen_extract_i32(ret, ret, 0, ofs + len);
return;
}
- tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
- tcg_gen_shli_i32(ret, ret, ofs);
+ /*
+ * Use TCG_TARGET_extract_valid to check for 8- and 16-bit extension
+ * opcodes, which tcg_gen_andi_i32 can produce.
+ */
+ if (TCG_TARGET_extract_valid(TCG_TYPE_I32, 0, len) ||
+ tcg_op_imm_match(INDEX_op_and, TCG_TYPE_I32, (1u << len) - 1)) {
+ tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
+ tcg_gen_shli_i32(ret, ret, ofs);
+ } else {
+ tcg_gen_shli_i32(ret, arg, 32 - len);
+ tcg_gen_shri_i32(ret, ret, 32 - len - ofs);
+ }
}
}
@@ -2628,8 +2638,18 @@ void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg,
tcg_gen_extract_i64(ret, ret, 0, ofs + len);
return;
}
- tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
- tcg_gen_shli_i64(ret, ret, ofs);
+ /*
+ * Use TCG_TARGET_extract_valid to check for 8-, 16- and 32-bit extension
+ * opcodes, which tcg_gen_andi_i64 can produce.
+ */
+ if (TCG_TARGET_extract_valid(TCG_TYPE_I64, 0, len) ||
+ tcg_op_imm_match(INDEX_op_and, TCG_TYPE_I64, (1ull << len) - 1)) {
+ tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
+ tcg_gen_shli_i64(ret, ret, ofs);
+ } else {
+ tcg_gen_shli_i64(ret, arg, 64 - len);
+ tcg_gen_shri_i64(ret, ret, 64 - len - ofs);
+ }
}
}
--
2.52.0
On 1/15/26 13:54, Paolo Bonzini wrote:
>
> @@ -2628,8 +2638,18 @@ void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg,
> tcg_gen_extract_i64(ret, ret, 0, ofs + len);
> return;
> }
> - tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
> - tcg_gen_shli_i64(ret, ret, ofs);
> + /*
> + * Use TCG_TARGET_extract_valid to check for 8-, 16- and 32-bit extension
> + * opcodes, which tcg_gen_andi_i64 can produce.
> + */
> + if (TCG_TARGET_extract_valid(TCG_TYPE_I64, 0, len) ||
> + tcg_op_imm_match(INDEX_op_and, TCG_TYPE_I64, (1ull << len) - 1)) {
> + tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
> + tcg_gen_shli_i64(ret, ret, ofs);
> + } else {
> + tcg_gen_shli_i64(ret, arg, 64 - len);
> + tcg_gen_shri_i64(ret, ret, 64 - len - ofs);
> + }
> }
> }
>
Also just a couple of coding standards issues - "Use
TCG_TARGET_extract_valid" comment is over 80 characters and you have a
tab at the start of the call to tcp_op_imm_match. Otherwise, looks good.
Jim
© 2016 - 2026 Red Hat, Inc.