From abdcc5c8eff0879c76aeb9f16d0c13044bfecbda Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 16 May 2024 23:04:28 +0200 Subject: [PATCH] target/i386: set CC_OP in helpers if they want CC_OP_EFLAGS Mark cc_op as clean and do not spill it at the end of the translation block. Technically this is a tiny bit less efficient, but: * it results in translations that are a tiny bit smaller * for most of these instructions, it is not unlikely that they are close to the end of the basic block, in which case cc_op would not be overwritten * anyway the cost is probably dwarfed by that of computing flags. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h | 8 ++++++++ target/i386/tcg/emit.c.inc | 22 +++++++++++----------- target/i386/tcg/fpu_helper.c | 2 ++ target/i386/tcg/int_helper.c | 13 +++++++++---- target/i386/tcg/seg_helper.c | 16 ++++++++-------- target/i386/tcg/translate.c | 12 ++++++------ 6 files changed, 44 insertions(+), 29 deletions(-) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index 6a465a35fd..f0aa1894aa 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -1111,6 +1111,7 @@ void helper_ucomiss(CPUX86State *env, Reg *d, Reg *s) s1 = s->ZMM_S(0); ret = float32_compare_quiet(s0, s1, &env->sse_status); CC_SRC = comis_eflags[ret + 1]; + CC_OP = CC_OP_EFLAGS; } void helper_comiss(CPUX86State *env, Reg *d, Reg *s) @@ -1122,6 +1123,7 @@ void helper_comiss(CPUX86State *env, Reg *d, Reg *s) s1 = s->ZMM_S(0); ret = float32_compare(s0, s1, &env->sse_status); CC_SRC = comis_eflags[ret + 1]; + CC_OP = CC_OP_EFLAGS; } void helper_ucomisd(CPUX86State *env, Reg *d, Reg *s) @@ -1133,6 +1135,7 @@ void helper_ucomisd(CPUX86State *env, Reg *d, Reg *s) d1 = s->ZMM_D(0); ret = float64_compare_quiet(d0, d1, &env->sse_status); CC_SRC = comis_eflags[ret + 1]; + CC_OP = CC_OP_EFLAGS; } void helper_comisd(CPUX86State *env, Reg *d, Reg *s) @@ -1144,6 +1147,7 @@ void helper_comisd(CPUX86State *env, Reg *d, Reg *s) d1 = s->ZMM_D(0); ret = float64_compare(d0, d1, &env->sse_status); CC_SRC = comis_eflags[ret + 1]; + CC_OP = CC_OP_EFLAGS; } #endif @@ -1610,6 +1614,7 @@ void glue(helper_ptest, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) cf |= (s->Q(i) & ~d->Q(i)); } CC_SRC = (zf ? 0 : CC_Z) | (cf ? 0 : CC_C); + CC_OP = CC_OP_EFLAGS; } #define FMOVSLDUP(i) s->L((i) & ~1) @@ -1966,6 +1971,7 @@ static inline unsigned pcmpxstrx(CPUX86State *env, Reg *d, Reg *s, validd--; CC_SRC = (valids < upper ? CC_Z : 0) | (validd < upper ? CC_S : 0); + CC_OP = CC_OP_EFLAGS; switch ((ctrl >> 2) & 3) { case 0: @@ -2297,6 +2303,7 @@ void glue(helper_vtestps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) cf |= (s->L(i) & ~d->L(i)); } CC_SRC = ((zf >> 31) ? 0 : CC_Z) | ((cf >> 31) ? 0 : CC_C); + CC_OP = CC_OP_EFLAGS; } void glue(helper_vtestpd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) @@ -2309,6 +2316,7 @@ void glue(helper_vtestpd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) cf |= (s->Q(i) & ~d->Q(i)); } CC_SRC = ((zf >> 63) ? 0 : CC_Z) | ((cf >> 63) ? 0 : CC_C); + CC_OP = CC_OP_EFLAGS; } void glue(helper_vpmaskmovd_st, SUFFIX)(CPUX86State *env, diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index 3f2ae0aa7e..e0ac21abe2 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -918,7 +918,7 @@ static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod } else { \ gen_helper_##lname##_ymm(tcg_env, OP_PTR1, OP_PTR2); \ } \ - set_cc_op(s, CC_OP_EFLAGS); \ + assume_cc_op(s, CC_OP_EFLAGS); \ } UNARY_CMP_SSE(VPTEST, ptest) UNARY_CMP_SSE(VTESTPS, vtestps) @@ -1079,7 +1079,7 @@ static void gen_AAA(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { gen_update_cc_op(s); gen_helper_aaa(tcg_env); - set_cc_op(s, CC_OP_EFLAGS); + assume_cc_op(s, CC_OP_EFLAGS); } static void gen_AAD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) @@ -1102,7 +1102,7 @@ static void gen_AAS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { gen_update_cc_op(s); gen_helper_aas(tcg_env); - set_cc_op(s, CC_OP_EFLAGS); + assume_cc_op(s, CC_OP_EFLAGS); } static void gen_ADC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) @@ -1566,14 +1566,14 @@ static void gen_DAA(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { gen_update_cc_op(s); gen_helper_daa(tcg_env); - set_cc_op(s, CC_OP_EFLAGS); + assume_cc_op(s, CC_OP_EFLAGS); } static void gen_DAS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { gen_update_cc_op(s); gen_helper_das(tcg_env); - set_cc_op(s, CC_OP_EFLAGS); + assume_cc_op(s, CC_OP_EFLAGS); } static void gen_DEC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) @@ -2353,14 +2353,14 @@ static void gen_PCMPESTRI(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec { TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); gen_helper_pcmpestri_xmm(tcg_env, OP_PTR1, OP_PTR2, imm); - set_cc_op(s, CC_OP_EFLAGS); + assume_cc_op(s, CC_OP_EFLAGS); } static void gen_PCMPESTRM(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); gen_helper_pcmpestrm_xmm(tcg_env, OP_PTR1, OP_PTR2, imm); - set_cc_op(s, CC_OP_EFLAGS); + assume_cc_op(s, CC_OP_EFLAGS); if ((s->prefix & PREFIX_VEX) && !s->vex_l) { tcg_gen_gvec_dup_imm(MO_64, offsetof(CPUX86State, xmm_regs[0].ZMM_X(1)), 16, 16, 0); @@ -2371,14 +2371,14 @@ static void gen_PCMPISTRI(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec { TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); gen_helper_pcmpistri_xmm(tcg_env, OP_PTR1, OP_PTR2, imm); - set_cc_op(s, CC_OP_EFLAGS); + assume_cc_op(s, CC_OP_EFLAGS); } static void gen_PCMPISTRM(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); gen_helper_pcmpistrm_xmm(tcg_env, OP_PTR1, OP_PTR2, imm); - set_cc_op(s, CC_OP_EFLAGS); + assume_cc_op(s, CC_OP_EFLAGS); if ((s->prefix & PREFIX_VEX) && !s->vex_l) { tcg_gen_gvec_dup_imm(MO_64, offsetof(CPUX86State, xmm_regs[0].ZMM_X(1)), 16, 16, 0); @@ -3595,7 +3595,7 @@ static void gen_VCOMI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) SSEFunc_0_epp fn; fn = s->prefix & PREFIX_DATA ? gen_helper_comisd : gen_helper_comiss; fn(tcg_env, OP_PTR1, OP_PTR2); - set_cc_op(s, CC_OP_EFLAGS); + assume_cc_op(s, CC_OP_EFLAGS); } static void gen_VCVTPD2PS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) @@ -3982,7 +3982,7 @@ static void gen_VUCOMI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode SSEFunc_0_epp fn; fn = s->prefix & PREFIX_DATA ? gen_helper_ucomisd : gen_helper_ucomiss; fn(tcg_env, OP_PTR1, OP_PTR2); - set_cc_op(s, CC_OP_EFLAGS); + assume_cc_op(s, CC_OP_EFLAGS); } static void gen_VZEROALL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c index ece22a3553..8df8cae631 100644 --- a/target/i386/tcg/fpu_helper.c +++ b/target/i386/tcg/fpu_helper.c @@ -487,6 +487,7 @@ void helper_fcomi_ST0_FT0(CPUX86State *env) ret = floatx80_compare(ST0, FT0, &env->fp_status); eflags = cpu_cc_compute_all(env) & ~(CC_Z | CC_P | CC_C); CC_SRC = eflags | fcomi_ccval[ret + 1]; + CC_OP = CC_OP_EFLAGS; merge_exception_flags(env, old_flags); } @@ -499,6 +500,7 @@ void helper_fucomi_ST0_FT0(CPUX86State *env) ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status); eflags = cpu_cc_compute_all(env) & ~(CC_Z | CC_P | CC_C); CC_SRC = eflags | fcomi_ccval[ret + 1]; + CC_OP = CC_OP_EFLAGS; merge_exception_flags(env, old_flags); } diff --git a/target/i386/tcg/int_helper.c b/target/i386/tcg/int_helper.c index 4cc59f1520..e1f9240528 100644 --- a/target/i386/tcg/int_helper.c +++ b/target/i386/tcg/int_helper.c @@ -187,6 +187,7 @@ void helper_aaa(CPUX86State *env) } env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | al | (ah << 8); CC_SRC = eflags; + CC_OP = CC_OP_EFLAGS; } void helper_aas(CPUX86State *env) @@ -211,6 +212,7 @@ void helper_aas(CPUX86State *env) } env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | al | (ah << 8); CC_SRC = eflags; + CC_OP = CC_OP_EFLAGS; } void helper_daa(CPUX86State *env) @@ -238,6 +240,7 @@ void helper_daa(CPUX86State *env) eflags |= parity_table[al]; /* pf */ eflags |= (al & 0x80); /* sf */ CC_SRC = eflags; + CC_OP = CC_OP_EFLAGS; } void helper_das(CPUX86State *env) @@ -269,6 +272,7 @@ void helper_das(CPUX86State *env) eflags |= parity_table[al]; /* pf */ eflags |= (al & 0x80); /* sf */ CC_SRC = eflags; + CC_OP = CC_OP_EFLAGS; } #ifdef TARGET_X86_64 @@ -449,10 +453,11 @@ target_ulong HELPER(rdrand)(CPUX86State *env) error_free(err); /* Failure clears CF and all other flags, and returns 0. */ env->cc_src = 0; - return 0; + ret = 0; + } else { + /* Success sets CF and clears all others. */ + env->cc_src = CC_C; } - - /* Success sets CF and clears all others. */ - env->cc_src = CC_C; + env->cc_op = CC_OP_EFLAGS; return ret; } diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c index 34ccabd8ce..0301459004 100644 --- a/target/i386/tcg/seg_helper.c +++ b/target/i386/tcg/seg_helper.c @@ -2326,7 +2326,7 @@ void helper_verr(CPUX86State *env, target_ulong selector1) int rpl, dpl, cpl; selector = selector1 & 0xffff; - eflags = cpu_cc_compute_all(env); + eflags = cpu_cc_compute_all(env) | CC_Z; if ((selector & 0xfffc) == 0) { goto fail; } @@ -2351,11 +2351,11 @@ void helper_verr(CPUX86State *env, target_ulong selector1) } else { if (dpl < cpl || dpl < rpl) { fail: - CC_SRC = eflags & ~CC_Z; - return; + eflags &= ~CC_Z; } } - CC_SRC = eflags | CC_Z; + CC_SRC = eflags; + CC_OP = CC_OP_EFLAGS; } void helper_verw(CPUX86State *env, target_ulong selector1) @@ -2364,7 +2364,7 @@ void helper_verw(CPUX86State *env, target_ulong selector1) int rpl, dpl, cpl; selector = selector1 & 0xffff; - eflags = cpu_cc_compute_all(env); + eflags = cpu_cc_compute_all(env) | CC_Z; if ((selector & 0xfffc) == 0) { goto fail; } @@ -2385,9 +2385,9 @@ void helper_verw(CPUX86State *env, target_ulong selector1) } if (!(e2 & DESC_W_MASK)) { fail: - CC_SRC = eflags & ~CC_Z; - return; + eflags &= ~CC_Z; } } - CC_SRC = eflags | CC_Z; + CC_SRC = eflags; + CC_OP = CC_OP_EFLAGS; } diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 25c973e20c..1b0485e01b 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -2984,7 +2984,7 @@ static bool disas_insn_x87(DisasContext *s, CPUState *cpu, int b) gen_update_cc_op(s); gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); gen_helper_fucomi_ST0_FT0(tcg_env); - set_cc_op(s, CC_OP_EFLAGS); + assume_cc_op(s, CC_OP_EFLAGS); break; case 0x1e: /* fcomi */ if (!(s->cpuid_features & CPUID_CMOV)) { @@ -2993,7 +2993,7 @@ static bool disas_insn_x87(DisasContext *s, CPUState *cpu, int b) gen_update_cc_op(s); gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); gen_helper_fcomi_ST0_FT0(tcg_env); - set_cc_op(s, CC_OP_EFLAGS); + assume_cc_op(s, CC_OP_EFLAGS); break; case 0x28: /* ffree sti */ gen_helper_ffree_STN(tcg_env, tcg_constant_i32(opreg)); @@ -3052,7 +3052,7 @@ static bool disas_insn_x87(DisasContext *s, CPUState *cpu, int b) gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); gen_helper_fucomi_ST0_FT0(tcg_env); gen_helper_fpop(tcg_env); - set_cc_op(s, CC_OP_EFLAGS); + assume_cc_op(s, CC_OP_EFLAGS); break; case 0x3e: /* fcomip */ if (!(s->cpuid_features & CPUID_CMOV)) { @@ -3062,7 +3062,7 @@ static bool disas_insn_x87(DisasContext *s, CPUState *cpu, int b) gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); gen_helper_fcomi_ST0_FT0(tcg_env); gen_helper_fpop(tcg_env); - set_cc_op(s, CC_OP_EFLAGS); + assume_cc_op(s, CC_OP_EFLAGS); break; case 0x10 ... 0x13: /* fcmovxx */ case 0x18 ... 0x1b: @@ -3268,7 +3268,7 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b) gen_helper_rdrand(s->T0, tcg_env); rm = (modrm & 7) | REX_B(s); gen_op_mov_reg_v(s, dflag, rm, s->T0); - set_cc_op(s, CC_OP_EFLAGS); + assume_cc_op(s, CC_OP_EFLAGS); break; default: @@ -3655,7 +3655,7 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b) } else { gen_helper_verw(tcg_env, s->T0); } - set_cc_op(s, CC_OP_EFLAGS); + assume_cc_op(s, CC_OP_EFLAGS); break; default: goto unknown_op;