pve-qemu-qoup/debian/patches/extra/0025-target-i386-Fix-BEXTR-instruction.patch
Fiona Ebner e752bbe5e2 cherry-pick TCG-related stable fixes for 7.2
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>
2023-03-17 15:46:20 +01:00

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);