e752bbe5e2
When turning off the "KVM hardware virtualization" checkbox in Proxmox VE, the TCG accelerator is used, so these fixes are relevant then. The first patch is included to allow cherry-picking the others without changes. Reported-by: Thomas Lamprecht <t.lamprecht@proxmox.com> Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
98 lines
3.5 KiB
Diff
98 lines
3.5 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Richard Henderson <richard.henderson@linaro.org>
|
|
Date: Sat, 14 Jan 2023 13:05:42 -1000
|
|
Subject: [PATCH] target/i386: Fix BEXTR instruction
|
|
|
|
There were two problems here: not limiting the input to operand bits,
|
|
and not correctly handling large extraction length.
|
|
|
|
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1372
|
|
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
|
|
Message-Id: <20230114230542.3116013-3-richard.henderson@linaro.org>
|
|
Cc: qemu-stable@nongnu.org
|
|
Fixes: 1d0b926150e5 ("target/i386: move scalar 0F 38 and 0F 3A instruction to new decoder", 2022-10-18)
|
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
(cherry-picked from commit b14c0098975264ed03144f145bca0179a6763a07)
|
|
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
|
|
---
|
|
target/i386/tcg/emit.c.inc | 22 +++++++++++-----------
|
|
tests/tcg/i386/test-i386-bmi2.c | 12 ++++++++++++
|
|
2 files changed, 23 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
|
|
index 7037ff91c6..99f6ba6e19 100644
|
|
--- a/target/i386/tcg/emit.c.inc
|
|
+++ b/target/i386/tcg/emit.c.inc
|
|
@@ -1078,30 +1078,30 @@ static void gen_ANDN(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
|
|
static void gen_BEXTR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
|
|
{
|
|
MemOp ot = decode->op[0].ot;
|
|
- TCGv bound, zero;
|
|
+ TCGv bound = tcg_constant_tl(ot == MO_64 ? 63 : 31);
|
|
+ TCGv zero = tcg_constant_tl(0);
|
|
+ TCGv mone = tcg_constant_tl(-1);
|
|
|
|
/*
|
|
* Extract START, and shift the operand.
|
|
* Shifts larger than operand size get zeros.
|
|
*/
|
|
tcg_gen_ext8u_tl(s->A0, s->T1);
|
|
+ if (TARGET_LONG_BITS == 64 && ot == MO_32) {
|
|
+ tcg_gen_ext32u_tl(s->T0, s->T0);
|
|
+ }
|
|
tcg_gen_shr_tl(s->T0, s->T0, s->A0);
|
|
|
|
- bound = tcg_constant_tl(ot == MO_64 ? 63 : 31);
|
|
- zero = tcg_constant_tl(0);
|
|
tcg_gen_movcond_tl(TCG_COND_LEU, s->T0, s->A0, bound, s->T0, zero);
|
|
|
|
/*
|
|
- * Extract the LEN into a mask. Lengths larger than
|
|
- * operand size get all ones.
|
|
+ * Extract the LEN into an inverse mask. Lengths larger than
|
|
+ * operand size get all zeros, length 0 gets all ones.
|
|
*/
|
|
tcg_gen_extract_tl(s->A0, s->T1, 8, 8);
|
|
- tcg_gen_movcond_tl(TCG_COND_LEU, s->A0, s->A0, bound, s->A0, bound);
|
|
-
|
|
- tcg_gen_movi_tl(s->T1, 1);
|
|
- tcg_gen_shl_tl(s->T1, s->T1, s->A0);
|
|
- tcg_gen_subi_tl(s->T1, s->T1, 1);
|
|
- tcg_gen_and_tl(s->T0, s->T0, s->T1);
|
|
+ tcg_gen_shl_tl(s->T1, mone, s->A0);
|
|
+ tcg_gen_movcond_tl(TCG_COND_LEU, s->T1, s->A0, bound, s->T1, zero);
|
|
+ tcg_gen_andc_tl(s->T0, s->T0, s->T1);
|
|
|
|
gen_op_update1_cc(s);
|
|
set_cc_op(s, CC_OP_LOGICB + ot);
|
|
diff --git a/tests/tcg/i386/test-i386-bmi2.c b/tests/tcg/i386/test-i386-bmi2.c
|
|
index 3c3ef85513..982d4abda4 100644
|
|
--- a/tests/tcg/i386/test-i386-bmi2.c
|
|
+++ b/tests/tcg/i386/test-i386-bmi2.c
|
|
@@ -99,6 +99,9 @@ int main(int argc, char *argv[]) {
|
|
result = bextrq(mask, 0x10f8);
|
|
assert(result == 0);
|
|
|
|
+ result = bextrq(0xfedcba9876543210ull, 0x7f00);
|
|
+ assert(result == 0xfedcba9876543210ull);
|
|
+
|
|
result = blsiq(0x30);
|
|
assert(result == 0x10);
|
|
|
|
@@ -164,6 +167,15 @@ int main(int argc, char *argv[]) {
|
|
result = bextrl(mask, 0x1038);
|
|
assert(result == 0);
|
|
|
|
+ result = bextrl((reg_t)0x8f635a775ad3b9b4ull, 0x3018);
|
|
+ assert(result == 0x5a);
|
|
+
|
|
+ result = bextrl((reg_t)0xfedcba9876543210ull, 0x7f00);
|
|
+ assert(result == 0x76543210u);
|
|
+
|
|
+ result = bextrl(-1, 0);
|
|
+ assert(result == 0);
|
|
+
|
|
result = blsil(0xffff);
|
|
assert(result == 1);
|
|
|