[PATCH] target/i386: Clear OF, SF, and AF for fcomi/fucomi
Simon Scherer <[email protected]>
| Newsgroups | gmane.comp.emulators.qemu |
|---|---|
| Message-ID | <[email protected]> |
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. Widen the mask so OF/SF/AF are cleared along with CF/ZF/PF instead of being carried over from before the instruction. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4133 Signed-off-by: Simon Scherer <[email protected]> --- target/i386/tcg/fpu_helper.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c index 978eb1411b..215547110a 100644 --- a/target/i386/tcg/fpu_helper.c +++ b/target/i386/tcg/fpu_helper.c @@ -554,7 +554,9 @@ void helper_fcomi_ST0_FT0(CPUX86State *env) FloatRelation ret; ret = floatx80_compare(ST0, FT0, &env->fp_status); - eflags = cpu_cc_compute_all(env) & ~(CC_Z | CC_P | CC_C); + /* OF, SF, and AF are unconditionally cleared to 0 */ + eflags = cpu_cc_compute_all(env) & + ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); CC_SRC = eflags | fcomi_ccval[ret + 1]; CC_OP = CC_OP_EFLAGS; merge_exception_flags(env, old_flags); @@ -567,7 +569,9 @@ void helper_fucomi_ST0_FT0(CPUX86State *env) FloatRelation ret; ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status); - eflags = cpu_cc_compute_all(env) & ~(CC_Z | CC_P | CC_C); + /* OF, SF, and AF are unconditionally cleared to 0 */ + eflags = cpu_cc_compute_all(env) & + ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); CC_SRC = eflags | fcomi_ccval[ret + 1]; CC_OP = CC_OP_EFLAGS; merge_exception_flags(env, old_flags); -- 2.53.0