target/i386/tcg/cc_helper.c | 4 +++- target/i386/tcg/emit.c.inc | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-)
The value that is pushed by PUSHF is the full EFLAGS, while CC_OP_EFLAGS
only wants arithmetic flags in CC_SRC. To avoid this, follow what other
helpers to and set CC_SRC/CC_OP directly in helper_read_eflags. This
is basically free and fixes an issue booting Windows 3.11.
Reported-by: Mark Cave-Ayland <mark.caveayland@nutanix.com>
Fixes: e661e2d7a37 ("target/i386/tcg: update cc_op after PUSHF", 2025-12-27)
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/cc_helper.c | 4 +++-
target/i386/tcg/emit.c.inc | 3 +--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/target/i386/tcg/cc_helper.c b/target/i386/tcg/cc_helper.c
index 91e492196af..6ddd64fcb07 100644
--- a/target/i386/tcg/cc_helper.c
+++ b/target/i386/tcg/cc_helper.c
@@ -414,7 +414,9 @@ target_ulong helper_read_eflags(CPUX86State *env)
{
uint32_t eflags;
- eflags = cpu_cc_compute_all(env);
+ CC_SRC = eflags = cpu_cc_compute_all(env);
+ CC_OP = CC_OP_EFLAGS;
+
eflags |= (env->df & DF_MASK);
eflags |= env->eflags & ~(VM_MASK | RF_MASK);
return eflags;
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index 0fde3d669d9..e55b65176fc 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -3253,8 +3253,7 @@ static void gen_PUSHF(DisasContext *s, X86DecodedInsn *decode)
gen_update_cc_op(s);
gen_helper_read_eflags(s->T0, tcg_env);
gen_push_v(s, s->T0);
- decode->cc_src = s->T0;
- decode->cc_op = CC_OP_EFLAGS;
+ assume_cc_op(s, CC_OP_EFLAGS);
}
static MemOp gen_shift_count(DisasContext *s, X86DecodedInsn *decode,
--
2.52.0
On 07/01/2026 04:52, Paolo Bonzini wrote:
> The value that is pushed by PUSHF is the full EFLAGS, while CC_OP_EFLAGS
> only wants arithmetic flags in CC_SRC. To avoid this, follow what other
> helpers to and set CC_SRC/CC_OP directly in helper_read_eflags. This
> is basically free and fixes an issue booting Windows 3.11.
>
> Reported-by: Mark Cave-Ayland <mark.caveayland@nutanix.com>
> Fixes: e661e2d7a37 ("target/i386/tcg: update cc_op after PUSHF", 2025-12-27)
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> target/i386/tcg/cc_helper.c | 4 +++-
> target/i386/tcg/emit.c.inc | 3 +--
> 2 files changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/target/i386/tcg/cc_helper.c b/target/i386/tcg/cc_helper.c
> index 91e492196af..6ddd64fcb07 100644
> --- a/target/i386/tcg/cc_helper.c
> +++ b/target/i386/tcg/cc_helper.c
> @@ -414,7 +414,9 @@ target_ulong helper_read_eflags(CPUX86State *env)
> {
> uint32_t eflags;
>
> - eflags = cpu_cc_compute_all(env);
> + CC_SRC = eflags = cpu_cc_compute_all(env);
> + CC_OP = CC_OP_EFLAGS;
> +
> eflags |= (env->df & DF_MASK);
> eflags |= env->eflags & ~(VM_MASK | RF_MASK);
> return eflags;
> diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
> index 0fde3d669d9..e55b65176fc 100644
> --- a/target/i386/tcg/emit.c.inc
> +++ b/target/i386/tcg/emit.c.inc
> @@ -3253,8 +3253,7 @@ static void gen_PUSHF(DisasContext *s, X86DecodedInsn *decode)
> gen_update_cc_op(s);
> gen_helper_read_eflags(s->T0, tcg_env);
> gen_push_v(s, s->T0);
> - decode->cc_src = s->T0;
> - decode->cc_op = CC_OP_EFLAGS;
> + assume_cc_op(s, CC_OP_EFLAGS);
> }
>
> static MemOp gen_shift_count(DisasContext *s, X86DecodedInsn *decode,
Thanks Paolo! I've given this a quick test and it fixes the issue here:
Tested-by: Mark Cave-Ayland <mark.caveayland@nutanix.com>
ATB,
Mark.
On Wed, 7 Jan 2026, Mark Cave-Ayland wrote:
> On 07/01/2026 04:52, Paolo Bonzini wrote:
>
>> The value that is pushed by PUSHF is the full EFLAGS, while CC_OP_EFLAGS
>> only wants arithmetic flags in CC_SRC. To avoid this, follow what other
>> helpers to and set CC_SRC/CC_OP directly in helper_read_eflags. This
Small typo: other helpers do
Regards,
BALATON Zoltan
>> is basically free and fixes an issue booting Windows 3.11.
>>
>> Reported-by: Mark Cave-Ayland <mark.caveayland@nutanix.com>
>> Fixes: e661e2d7a37 ("target/i386/tcg: update cc_op after PUSHF",
>> 2025-12-27)
>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
>> ---
>> target/i386/tcg/cc_helper.c | 4 +++-
>> target/i386/tcg/emit.c.inc | 3 +--
>> 2 files changed, 4 insertions(+), 3 deletions(-)
>>
>> diff --git a/target/i386/tcg/cc_helper.c b/target/i386/tcg/cc_helper.c
>> index 91e492196af..6ddd64fcb07 100644
>> --- a/target/i386/tcg/cc_helper.c
>> +++ b/target/i386/tcg/cc_helper.c
>> @@ -414,7 +414,9 @@ target_ulong helper_read_eflags(CPUX86State *env)
>> {
>> uint32_t eflags;
>> - eflags = cpu_cc_compute_all(env);
>> + CC_SRC = eflags = cpu_cc_compute_all(env);
>> + CC_OP = CC_OP_EFLAGS;
>> +
>> eflags |= (env->df & DF_MASK);
>> eflags |= env->eflags & ~(VM_MASK | RF_MASK);
>> return eflags;
>> diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
>> index 0fde3d669d9..e55b65176fc 100644
>> --- a/target/i386/tcg/emit.c.inc
>> +++ b/target/i386/tcg/emit.c.inc
>> @@ -3253,8 +3253,7 @@ static void gen_PUSHF(DisasContext *s, X86DecodedInsn
>> *decode)
>> gen_update_cc_op(s);
>> gen_helper_read_eflags(s->T0, tcg_env);
>> gen_push_v(s, s->T0);
>> - decode->cc_src = s->T0;
>> - decode->cc_op = CC_OP_EFLAGS;
>> + assume_cc_op(s, CC_OP_EFLAGS);
>> }
>> static MemOp gen_shift_count(DisasContext *s, X86DecodedInsn *decode,
>
> Thanks Paolo! I've given this a quick test and it fixes the issue here:
>
> Tested-by: Mark Cave-Ayland <mark.caveayland@nutanix.com>
>
>
> ATB,
>
> Mark.
>
>
>
© 2016 - 2026 Red Hat, Inc.