mirror of
https://github.com/qemu/qemu.git
synced 2026-04-05 22:00:58 +00:00
tcg: target-dependent lowering of extract to shr/and
Instead of assuming only small immediates are available for AND, consult the backend in order to decide between SHL/SHR and SHR/AND. Reviewed-by: Jim MacArthur <jim.macarthur@linaro.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> [rth: Split from a larger patch] Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-ID: <20260303010833.1115741-7-richard.henderson@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
This commit is contained in:
committed by
Philippe Mathieu-Daudé
parent
bb5b6bbb10
commit
bfe9264835
36
tcg/tcg-op.c
36
tcg/tcg-op.c
@@ -907,6 +907,8 @@ void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg,
|
||||
void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg,
|
||||
unsigned int ofs, unsigned int len)
|
||||
{
|
||||
uint32_t mask;
|
||||
|
||||
tcg_debug_assert(ofs < 32);
|
||||
tcg_debug_assert(len > 0);
|
||||
tcg_debug_assert(len <= 32);
|
||||
@@ -922,8 +924,10 @@ void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg,
|
||||
tcg_gen_op4ii_i32(INDEX_op_extract, ret, arg, ofs, len);
|
||||
return;
|
||||
}
|
||||
|
||||
mask = (1u << len) - 1;
|
||||
if (ofs == 0) {
|
||||
tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
|
||||
tcg_gen_andi_i32(ret, arg, mask);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -934,18 +938,12 @@ void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg,
|
||||
return;
|
||||
}
|
||||
|
||||
/* ??? Ideally we'd know what values are available for immediate AND.
|
||||
Assume that 8 bits are available, plus the special case of 16,
|
||||
so that we get ext8u, ext16u. */
|
||||
switch (len) {
|
||||
case 1 ... 8: case 16:
|
||||
if (tcg_op_imm_match(INDEX_op_and, TCG_TYPE_I32, mask)) {
|
||||
tcg_gen_shri_i32(ret, arg, ofs);
|
||||
tcg_gen_andi_i32(ret, ret, (1u << len) - 1);
|
||||
break;
|
||||
default:
|
||||
tcg_gen_andi_i32(ret, ret, mask);
|
||||
} else {
|
||||
tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
|
||||
tcg_gen_shri_i32(ret, ret, 32 - len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2121,6 +2119,8 @@ void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg,
|
||||
void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg,
|
||||
unsigned int ofs, unsigned int len)
|
||||
{
|
||||
uint64_t mask;
|
||||
|
||||
tcg_debug_assert(ofs < 64);
|
||||
tcg_debug_assert(len > 0);
|
||||
tcg_debug_assert(len <= 64);
|
||||
@@ -2136,8 +2136,10 @@ void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg,
|
||||
tcg_gen_op4ii_i64(INDEX_op_extract, ret, arg, ofs, len);
|
||||
return;
|
||||
}
|
||||
|
||||
mask = (1ull << len) - 1;
|
||||
if (ofs == 0) {
|
||||
tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
|
||||
tcg_gen_andi_i64(ret, arg, mask);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2148,18 +2150,12 @@ void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg,
|
||||
return;
|
||||
}
|
||||
|
||||
/* ??? Ideally we'd know what values are available for immediate AND.
|
||||
Assume that 8 bits are available, plus the special cases of 16 and 32,
|
||||
so that we get ext8u, ext16u, and ext32u. */
|
||||
switch (len) {
|
||||
case 1 ... 8: case 16: case 32:
|
||||
if (tcg_op_imm_match(INDEX_op_and, TCG_TYPE_I64, mask)) {
|
||||
tcg_gen_shri_i64(ret, arg, ofs);
|
||||
tcg_gen_andi_i64(ret, ret, (1ull << len) - 1);
|
||||
break;
|
||||
default:
|
||||
tcg_gen_andi_i64(ret, ret, mask);
|
||||
} else {
|
||||
tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
|
||||
tcg_gen_shri_i64(ret, ret, 64 - len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user