@samitouri / QOSamiQemu / commits / 0924d9d3db

target/i386: Clear OF, SF, and AF for fcomi/fucomi

helper_fcomi_ST0_FT0() and helper_fucomi_ST0_FT0() only cleared CC_Z, CC_P, and CC_C before merging in the comparison result, leaving CC_O, CC_S, and CC_A untouched from whatever they were set to beforehand. The Intel SDM documents FCOMI/FCOMIP/FUCOMI/FUCOMIP as setting OF, SF, and AF to 0 unconditionally. The AMD manual doesn't mention them at all. However, testing on multiple real Intel and AMD systems confirms all three are unconditionally cleared regardless of the comparison result or their prior value. Since fcomi_ccval[] only ever contains CC_C, CC_Z, 0, or CC_Z|CC_P|CC_C, and CC_O|CC_S|CC_Z|CC_A|CC_P|CC_C already covers every flag bit, CC_SRC can be assigned from fcomi_ccval[ret + 1] directly instead of ORing it into a masked cpu_cc_compute_all() result. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4133 Signed-off-by: Simon Scherer <scherer.simon89@gmail.com> Link: https://lore.kernel.org/r/20260807062831.19618-1-scherer.simon89@gmail.com Cc: qemu-stable@nongnu.org Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Simon Scherer committed Aug 7, 2026 at 08:28 UTC 0924d9d3db3617f49ba9282acc6d85b349404ce6
1 file changed +4 -6
target/i386/tcg/fpu_helper.c
+4 -6
@@ -550,12 +550,11 @@ static const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C};
550 void helper_fcomi_ST0_FT0(CPUX86State *env)
551 {
552 int old_flags = save_exception_flags(env);
553 - int eflags;
553 FloatRelation ret;
554
555 ret = floatx80_compare(ST0, FT0, &env->fp_status);
557 - eflags = cpu_cc_compute_all(env) & ~(CC_Z | CC_P | CC_C);
558 - CC_SRC = eflags | fcomi_ccval[ret + 1];
556 + /* OF, SF, and AF are unconditionally cleared to 0 */
557 + CC_SRC = fcomi_ccval[ret + 1];
558 CC_OP = CC_OP_EFLAGS;
559 merge_exception_flags(env, old_flags);
560 }
@@ -563,12 +562,11 @@ void helper_fcomi_ST0_FT0(CPUX86State *env)
562 void helper_fucomi_ST0_FT0(CPUX86State *env)
563 {
564 int old_flags = save_exception_flags(env);
566 - int eflags;
565 FloatRelation ret;
566
567 ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
570 - eflags = cpu_cc_compute_all(env) & ~(CC_Z | CC_P | CC_C);
571 - CC_SRC = eflags | fcomi_ccval[ret + 1];
568 + /* OF, SF, and AF are unconditionally cleared to 0 */
569 + CC_SRC = fcomi_ccval[ret + 1];
570 CC_OP = CC_OP_EFLAGS;
571 merge_exception_flags(env, old_flags);
572 }