From 08b462dd9970a88d7f0e7c61ca48502463b0b78d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 10 Apr 2025 17:42:52 +0200 Subject: [PATCH 01/34] scsi: add conversion from ENODEV to sense This is mostly for completeness; I noticed it because ENODEV is used internally within scsi-disk.c, but when scsi_sense_from_errno(ENODEV) is called the resulting sense is never used and instead scsi_sense_from_host_status() is called later by scsi_req_complete_failed(). Signed-off-by: Paolo Bonzini --- scsi/utils.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/scsi/utils.c b/scsi/utils.c index 357b036671..545956f4f9 100644 --- a/scsi/utils.c +++ b/scsi/utils.c @@ -587,20 +587,27 @@ int scsi_sense_from_errno(int errno_value, SCSISense *sense) return GOOD; case EDOM: return TASK_SET_FULL; +#if ENODEV != ENOMEDIUM + case ENODEV: + /* + * Some of the BSDs have ENODEV and ENOMEDIUM as synonyms. For + * everyone else, give a more severe sense code for ENODEV. + */ +#endif #ifdef CONFIG_LINUX /* These errno mapping are specific to Linux. For more information: * - scsi_check_sense and scsi_decide_disposition in drivers/scsi/scsi_error.c * - scsi_result_to_blk_status in drivers/scsi/scsi_lib.c * - blk_errors[] in block/blk-core.c */ + case EREMOTEIO: + *sense = SENSE_CODE(TARGET_FAILURE); + return CHECK_CONDITION; case EBADE: return RESERVATION_CONFLICT; case ENODATA: *sense = SENSE_CODE(READ_ERROR); return CHECK_CONDITION; - case EREMOTEIO: - *sense = SENSE_CODE(TARGET_FAILURE); - return CHECK_CONDITION; #endif case ENOMEDIUM: *sense = SENSE_CODE(NO_MEDIUM); From 280712b78781c43511d6286d40f9a518a4de25ff Mon Sep 17 00:00:00 2001 From: Ewan Hai Date: Mon, 14 Apr 2025 03:53:42 -0400 Subject: [PATCH 02/34] target/i386: Fix model number of Zhaoxin YongFeng vCPU template The model number was mistakenly set to 0x0b (11) in commit ff04bc1ac4. The correct value is 0x5b. This mistake occurred because the extended model bits in cpuid[eax=0x1].eax were overlooked, and only the base model was used. Using the wrong model number can affect guest behavior. One known issue is that vPMU (which relies on the model number) may fail to operate correctly. This patch corrects the model field by introducing a new vCPU version. Fixes: ff04bc1ac4 ("target/i386: Introduce Zhaoxin Yongfeng CPU model") Signed-off-by: Ewan Hai Link: https://lore.kernel.org/r/20250414075342.411626-1-ewanhai-oc@zhaoxin.com Signed-off-by: Paolo Bonzini --- target/i386/cpu.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 1b64ceaaba..3fb1ec62da 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -5621,6 +5621,18 @@ static const X86CPUDefinition builtin_x86_defs[] = { .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, .xlevel = 0x80000008, .model_id = "Zhaoxin YongFeng Processor", + .versions = (X86CPUVersionDefinition[]) { + { .version = 1 }, + { + .version = 2, + .note = "with the correct model number", + .props = (PropValue[]) { + { "model", "0x5b" }, + { /* end of list */ } + } + }, + { /* end of list */ } + } }, }; From f6b5f71f04529d3f56b35f91badac9f5e7e225ca Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Thu, 27 Mar 2025 19:24:16 +0100 Subject: [PATCH 03/34] target/i386: Reset parked vCPUs together with the online ones Commit 3f2a05b31ee9 ("target/i386: Reset TSCs of parked vCPUs too on VM reset") introduced a way to reset TSCs of parked vCPUs during VM reset to prevent them getting desynchronized with the online vCPUs and therefore causing the KVM PV clock to lose PVCLOCK_TSC_STABLE_BIT. The way this was done was by registering a parked vCPU-specific QEMU reset callback via qemu_register_reset(). However, it turns out that on particularly device-rich VMs QEMU reset callbacks can take a long time to execute (which isn't surprising, considering that they involve resetting all of VM devices). In particular, their total runtime can exceed the 1-second TSC synchronization window introduced in KVM commit 5d3cb0f6a8e3 ("KVM: Improve TSC offset matching"). Since the TSCs of online vCPUs are only reset from "synchronize_post_reset" AccelOps handler (which runs after all qemu_register_reset() handlers) this essentially makes that fix ineffective on these VMs. The easiest way to guarantee that these parked vCPUs are reset at the same time as the online ones (regardless how long it takes for VM devices to reset) is to piggyback on post-reset vCPU synchronization handler for one of online vCPUs - as there is no generic post-reset AccelOps handler that isn't per-vCPU. The first online vCPU was selected for that since it is easily available under "first_cpu" define. This does not create an ordering issue since the order of vCPU TSC resets does not matter. Fixes: 3f2a05b31ee9 ("target/i386: Reset TSCs of parked vCPUs too on VM reset") Signed-off-by: Maciej S. Szmigiero Link: https://lore.kernel.org/r/e8b85a5915f79aa177ca49eccf0e9b534470c1cd.1743099810.git.maciej.szmigiero@oracle.com Cc: qemu-stable@nongnu.org Signed-off-by: Paolo Bonzini --- accel/kvm/kvm-all.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index f89568bfa3..951e8214e0 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -437,9 +437,8 @@ int kvm_unpark_vcpu(KVMState *s, unsigned long vcpu_id) return kvm_fd; } -static void kvm_reset_parked_vcpus(void *param) +static void kvm_reset_parked_vcpus(KVMState *s) { - KVMState *s = param; struct KVMParkedVcpu *cpu; QLIST_FOREACH(cpu, &s->kvm_parked_vcpus, node) { @@ -2738,7 +2737,6 @@ static int kvm_init(MachineState *ms) } qemu_register_reset(kvm_unpoison_all, NULL); - qemu_register_reset(kvm_reset_parked_vcpus, s); if (s->kernel_irqchip_allowed) { kvm_irqchip_create(s); @@ -2908,6 +2906,10 @@ static void do_kvm_cpu_synchronize_post_reset(CPUState *cpu, run_on_cpu_data arg void kvm_cpu_synchronize_post_reset(CPUState *cpu) { run_on_cpu(cpu, do_kvm_cpu_synchronize_post_reset, RUN_ON_CPU_NULL); + + if (cpu == first_cpu) { + kvm_reset_parked_vcpus(kvm_state); + } } static void do_kvm_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg) From 94a159f3dc737d00749cc930adaec112abe07b3c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Apr 2025 21:39:54 +0200 Subject: [PATCH 04/34] target/i386/hvf: fix lflags_to_rflags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clear the flags before adding in the ones computed from lflags. Cc: Wei Liu Cc: qemu-stable@nongnu.org Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- target/i386/hvf/x86_flags.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/i386/hvf/x86_flags.c b/target/i386/hvf/x86_flags.c index 03d6de5efc..fedc70a1b8 100644 --- a/target/i386/hvf/x86_flags.c +++ b/target/i386/hvf/x86_flags.c @@ -293,6 +293,7 @@ void set_SF(CPUX86State *env, bool val) void lflags_to_rflags(CPUX86State *env) { + env->eflags &= ~(CC_C|CC_P|CC_A|CC_Z|CC_S|CC_O); env->eflags |= get_CF(env) ? CC_C : 0; env->eflags |= get_PF(env) ? CC_P : 0; env->eflags |= get_AF(env) ? CC_A : 0; From bd65810538bfa4baef4f9e2fe40166d008a2a64c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Feb 2025 10:21:02 +0100 Subject: [PATCH 05/34] target/i386: special case ADC/SBB x,0 and SBB x,x Avoid the three-operand CC_OP_ADD and CC_OP_ADC in these relatively common cases. Signed-off-by: Paolo Bonzini --- target/i386/tcg/emit.c.inc | 71 +++++++++++++++++++++++++++++++++---- target/i386/tcg/translate.c | 20 +++++++++++ 2 files changed, 85 insertions(+), 6 deletions(-) diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index 0fa1664a24..f477a2da99 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -1170,11 +1170,28 @@ static void gen_AAS(DisasContext *s, X86DecodedInsn *decode) assume_cc_op(s, CC_OP_EFLAGS); } +static void gen_ADD(DisasContext *s, X86DecodedInsn *decode); static void gen_ADC(DisasContext *s, X86DecodedInsn *decode) { MemOp ot = decode->op[1].ot; - TCGv c_in = tcg_temp_new(); + TCGv c_in; + /* + * Try to avoid CC_OP_ADC by transforming as follows: + * CC_ADC: src1 = dst + c_in, src2 = 0, src3 = c_in + * CC_ADD: src1 = dst + c_in, src2 = c_in (no src3) + * + * In general src2 vs. src3 matters when computing AF and OF, but not here: + * - AF is bit 4 of dst^src1^src2, which is bit 4 of dst^src1 in both cases + * - OF is a function of the two MSBs, and in both cases they are zero for src2 + */ + if (decode->e.op2 == X86_TYPE_I && decode->immediate == 0) { + gen_compute_eflags_c(s, s->T1); + gen_ADD(s, decode); + return; + } + + c_in = tcg_temp_new(); gen_compute_eflags_c(s, c_in); if (s->prefix & PREFIX_LOCK) { tcg_gen_add_tl(s->T0, c_in, s->T1); @@ -3830,22 +3847,64 @@ static void gen_SARX(DisasContext *s, X86DecodedInsn *decode) tcg_gen_sar_tl(s->T0, s->T0, s->T1); } +static void gen_SUB(DisasContext *s, X86DecodedInsn *decode); static void gen_SBB(DisasContext *s, X86DecodedInsn *decode) { MemOp ot = decode->op[0].ot; - TCGv c_in = tcg_temp_new(); + TCGv c_in; + /* + * Try to avoid CC_OP_SBB by transforming as follows: + * CC_SBB: src1 = dst + c_in, src2 = 0, src3 = c_in + * CC_SUB: src1 = dst + c_in, src2 = c_in (no src3) + * + * In general src2 vs. src3 matters when computing AF and OF, but not here: + * - AF is bit 4 of dst^src1^src2, which is bit 4 of dst^src1 in both cases + * - OF is a function of the two MSBs, and in both cases they are zero for src2 + */ + if (decode->e.op2 == X86_TYPE_I && decode->immediate == 0) { + gen_compute_eflags_c(s, s->T1); + gen_SUB(s, decode); + return; + } + + c_in = tcg_temp_new(); gen_compute_eflags_c(s, c_in); + + /* + * Here the change is as follows: + * CC_SBB: src1 = T0, src2 = T0, src3 = c_in + * CC_SUB: src1 = 0, src2 = c_in (no src3) + * + * The difference also does not matter: + * - AF is bit 4 of dst^src1^src2, but bit 4 of src1^src2 is zero in both cases + * therefore AF comes straight from dst (in fact it is c_in) + * - for OF, src1 and src2 have the same sign in both cases, meaning there + * can be no overflow + */ + if (decode->e.op2 != X86_TYPE_I && !decode->op[0].has_ea && decode->op[0].n == decode->op[2].n) { + if (s->cc_op == CC_OP_DYNAMIC) { + tcg_gen_neg_tl(s->T0, c_in); + } else { + /* + * Do not negate c_in because it will often be dead and only the + * instruction generated by negsetcond will survive. + */ + gen_neg_setcc(s, JCC_B << 1, s->T0); + } + tcg_gen_movi_tl(s->cc_srcT, 0); + decode->cc_src = c_in; + decode->cc_dst = s->T0; + decode->cc_op = CC_OP_SUBB + ot; + return; + } + if (s->prefix & PREFIX_LOCK) { tcg_gen_add_tl(s->T0, s->T1, c_in); tcg_gen_neg_tl(s->T0, s->T0); tcg_gen_atomic_add_fetch_tl(s->T0, s->A0, s->T0, s->mem_index, ot | MO_LE); } else { - /* - * TODO: SBB reg, reg could use gen_prepare_eflags_c followed by - * negsetcond, and CC_OP_SUBB as the cc_op. - */ tcg_gen_sub_tl(s->T0, s->T0, s->T1); tcg_gen_sub_tl(s->T0, s->T0, c_in); } diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index a8935f487a..aee3342898 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -1183,6 +1183,26 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) return cc; } +static void gen_neg_setcc(DisasContext *s, int b, TCGv reg) +{ + CCPrepare cc = gen_prepare_cc(s, b, reg); + + if (cc.no_setcond) { + if (cc.cond == TCG_COND_EQ) { + tcg_gen_addi_tl(reg, cc.reg, -1); + } else { + tcg_gen_neg_tl(reg, cc.reg); + } + return; + } + + if (cc.use_reg2) { + tcg_gen_negsetcond_tl(cc.cond, reg, cc.reg, cc.reg2); + } else { + tcg_gen_negsetcondi_tl(cc.cond, reg, cc.reg, cc.imm); + } +} + static void gen_setcc(DisasContext *s, int b, TCGv reg) { CCPrepare cc = gen_prepare_cc(s, b, reg); From ec6019f2308b5d27b4ee33497b06174e9f58b100 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 13 Feb 2025 18:45:06 +0100 Subject: [PATCH 06/34] target/i386: tcg: remove tmp0 and tmp4 from SHLD/SHRD Apply some of the simplifications used for RCL and RCR. tmp4 is not used anywhere else, so remove it. Signed-off-by: Paolo Bonzini --- target/i386/tcg/emit.c.inc | 6 ++--- target/i386/tcg/translate.c | 51 +++++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index f477a2da99..a41afb7fe4 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -4015,8 +4015,7 @@ static void gen_SHLD(DisasContext *s, X86DecodedInsn *decode) } decode->cc_dst = s->T0; - decode->cc_src = s->tmp0; - gen_shiftd_rm_T1(s, ot, false, count); + decode->cc_src = gen_shiftd_rm_T1(s, ot, false, count); if (can_be_zero) { gen_shift_dynamic_flags(s, decode, count, CC_OP_SHLB + ot); } else { @@ -4068,8 +4067,7 @@ static void gen_SHRD(DisasContext *s, X86DecodedInsn *decode) } decode->cc_dst = s->T0; - decode->cc_src = s->tmp0; - gen_shiftd_rm_T1(s, ot, true, count); + decode->cc_src = gen_shiftd_rm_T1(s, ot, true, count); if (can_be_zero) { gen_shift_dynamic_flags(s, decode, count, CC_OP_SARB + ot); } else { diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index aee3342898..5529327680 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -135,7 +135,6 @@ typedef struct DisasContext { /* TCG local register indexes (only used inside old micro ops) */ TCGv tmp0; - TCGv tmp4; TCGv_i32 tmp2_i32; TCGv_i32 tmp3_i32; TCGv_i64 tmp1_i64; @@ -1580,10 +1579,13 @@ static bool check_cpl0(DisasContext *s) } /* XXX: add faster immediate case */ -static void gen_shiftd_rm_T1(DisasContext *s, MemOp ot, +static TCGv gen_shiftd_rm_T1(DisasContext *s, MemOp ot, bool is_right, TCGv count) { target_ulong mask = (ot == MO_64 ? 63 : 31); + TCGv cc_src = tcg_temp_new(); + TCGv tmp = tcg_temp_new(); + TCGv hishift; switch (ot) { case MO_16: @@ -1591,9 +1593,9 @@ static void gen_shiftd_rm_T1(DisasContext *s, MemOp ot, This means "shrdw C, B, A" shifts A:B:A >> C. Build the B:A portion by constructing it as a 32-bit value. */ if (is_right) { - tcg_gen_deposit_tl(s->tmp0, s->T0, s->T1, 16, 16); + tcg_gen_deposit_tl(tmp, s->T0, s->T1, 16, 16); tcg_gen_mov_tl(s->T1, s->T0); - tcg_gen_mov_tl(s->T0, s->tmp0); + tcg_gen_mov_tl(s->T0, tmp); } else { tcg_gen_deposit_tl(s->T1, s->T0, s->T1, 16, 16); } @@ -1604,47 +1606,53 @@ static void gen_shiftd_rm_T1(DisasContext *s, MemOp ot, case MO_32: #ifdef TARGET_X86_64 /* Concatenate the two 32-bit values and use a 64-bit shift. */ - tcg_gen_subi_tl(s->tmp0, count, 1); + tcg_gen_subi_tl(tmp, count, 1); if (is_right) { tcg_gen_concat_tl_i64(s->T0, s->T0, s->T1); - tcg_gen_shr_i64(s->tmp0, s->T0, s->tmp0); + tcg_gen_shr_i64(cc_src, s->T0, tmp); tcg_gen_shr_i64(s->T0, s->T0, count); } else { tcg_gen_concat_tl_i64(s->T0, s->T1, s->T0); - tcg_gen_shl_i64(s->tmp0, s->T0, s->tmp0); + tcg_gen_shl_i64(cc_src, s->T0, tmp); tcg_gen_shl_i64(s->T0, s->T0, count); - tcg_gen_shri_i64(s->tmp0, s->tmp0, 32); + tcg_gen_shri_i64(cc_src, cc_src, 32); tcg_gen_shri_i64(s->T0, s->T0, 32); } break; #endif default: - tcg_gen_subi_tl(s->tmp0, count, 1); + hishift = tcg_temp_new(); + tcg_gen_subi_tl(tmp, count, 1); if (is_right) { - tcg_gen_shr_tl(s->tmp0, s->T0, s->tmp0); + tcg_gen_shr_tl(cc_src, s->T0, tmp); - tcg_gen_subfi_tl(s->tmp4, mask + 1, count); + /* mask + 1 - count = mask - tmp = mask ^ tmp */ + tcg_gen_xori_tl(hishift, tmp, mask); tcg_gen_shr_tl(s->T0, s->T0, count); - tcg_gen_shl_tl(s->T1, s->T1, s->tmp4); + tcg_gen_shl_tl(s->T1, s->T1, hishift); } else { - tcg_gen_shl_tl(s->tmp0, s->T0, s->tmp0); + tcg_gen_shl_tl(cc_src, s->T0, tmp); + if (ot == MO_16) { /* Only needed if count > 16, for Intel behaviour. */ - tcg_gen_subfi_tl(s->tmp4, 33, count); - tcg_gen_shr_tl(s->tmp4, s->T1, s->tmp4); - tcg_gen_or_tl(s->tmp0, s->tmp0, s->tmp4); + tcg_gen_subfi_tl(tmp, 33, count); + tcg_gen_shr_tl(tmp, s->T1, tmp); + tcg_gen_or_tl(cc_src, cc_src, tmp); } - tcg_gen_subfi_tl(s->tmp4, mask + 1, count); + /* mask + 1 - count = mask - tmp = mask ^ tmp */ + tcg_gen_xori_tl(hishift, tmp, mask); tcg_gen_shl_tl(s->T0, s->T0, count); - tcg_gen_shr_tl(s->T1, s->T1, s->tmp4); + tcg_gen_shr_tl(s->T1, s->T1, hishift); } - tcg_gen_movi_tl(s->tmp4, 0); - tcg_gen_movcond_tl(TCG_COND_EQ, s->T1, count, s->tmp4, - s->tmp4, s->T1); + tcg_gen_movcond_tl(TCG_COND_EQ, s->T1, + count, tcg_constant_tl(0), + tcg_constant_tl(0), s->T1); tcg_gen_or_tl(s->T0, s->T0, s->T1); break; } + + return cc_src; } #define X86_MAX_INSN_LENGTH 15 @@ -3768,7 +3776,6 @@ static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu) dc->tmp1_i64 = tcg_temp_new_i64(); dc->tmp2_i32 = tcg_temp_new_i32(); dc->tmp3_i32 = tcg_temp_new_i32(); - dc->tmp4 = tcg_temp_new(); dc->cc_srcT = tcg_temp_new(); } From a440975cc33b48316f26d4ba0f1714375ff47738 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 13 Feb 2025 19:25:41 +0100 Subject: [PATCH 07/34] target/i386: tcg: remove subf from SHLD/SHRD expansion It is computing 33-count but 32-count had just been used, so just shift further by one. Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 5529327680..822dbb2e9a 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -1633,17 +1633,16 @@ static TCGv gen_shiftd_rm_T1(DisasContext *s, MemOp ot, } else { tcg_gen_shl_tl(cc_src, s->T0, tmp); - if (ot == MO_16) { - /* Only needed if count > 16, for Intel behaviour. */ - tcg_gen_subfi_tl(tmp, 33, count); - tcg_gen_shr_tl(tmp, s->T1, tmp); - tcg_gen_or_tl(cc_src, cc_src, tmp); - } - /* mask + 1 - count = mask - tmp = mask ^ tmp */ tcg_gen_xori_tl(hishift, tmp, mask); tcg_gen_shl_tl(s->T0, s->T0, count); tcg_gen_shr_tl(s->T1, s->T1, hishift); + + if (ot == MO_16) { + /* Only needed if count > 16, for Intel behaviour. */ + tcg_gen_shri_tl(tmp, s->T1, 1); + tcg_gen_or_tl(cc_src, cc_src, tmp); + } } tcg_gen_movcond_tl(TCG_COND_EQ, s->T1, count, tcg_constant_tl(0), From d387eb7fa989f3397d681111324f6a54c1b32484 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 13 Feb 2025 19:30:20 +0100 Subject: [PATCH 08/34] target/i386: tcg: remove tmp0 Signed-off-by: Paolo Bonzini --- target/i386/tcg/emit.c.inc | 20 ++++++++++---------- target/i386/tcg/translate.c | 27 +++++++++++++++------------ 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index a41afb7fe4..bd24438230 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -1710,22 +1710,22 @@ static void gen_CMPccXADD(DisasContext *s, X86DecodedInsn *decode) switch (jcc_op) { case JCC_O: /* (src1 ^ src2) & (src1 ^ dst). newv is only used here for a moment */ + cmp_lhs = tcg_temp_new(), cmp_rhs = tcg_constant_tl(0); tcg_gen_xor_tl(newv, s->cc_srcT, s->T0); - tcg_gen_xor_tl(s->tmp0, s->cc_srcT, cmpv); - tcg_gen_and_tl(s->tmp0, s->tmp0, newv); - tcg_gen_sextract_tl(s->tmp0, s->tmp0, 0, 8 << ot); - cmp_lhs = s->tmp0, cmp_rhs = tcg_constant_tl(0); + tcg_gen_xor_tl(cmp_lhs, s->cc_srcT, cmpv); + tcg_gen_and_tl(cmp_lhs, cmp_lhs, newv); + tcg_gen_sextract_tl(cmp_lhs, cmp_lhs, 0, 8 << ot); break; case JCC_P: - tcg_gen_ext8u_tl(s->tmp0, s->T0); - tcg_gen_ctpop_tl(s->tmp0, s->tmp0); - cmp_lhs = s->tmp0, cmp_rhs = tcg_constant_tl(1); + cmp_lhs = tcg_temp_new(), cmp_rhs = tcg_constant_tl(1); + tcg_gen_ext8u_tl(cmp_lhs, s->T0); + tcg_gen_ctpop_tl(cmp_lhs, cmp_lhs); break; case JCC_S: - tcg_gen_sextract_tl(s->tmp0, s->T0, 0, 8 << ot); - cmp_lhs = s->tmp0, cmp_rhs = tcg_constant_tl(0); + cmp_lhs = tcg_temp_new(), cmp_rhs = tcg_constant_tl(0); + tcg_gen_sextract_tl(cmp_lhs, s->T0, 0, 8 << ot); break; default: @@ -1876,7 +1876,7 @@ static void gen_CMPXCHG8B(DisasContext *s, X86DecodedInsn *decode) s->mem_index, MO_TEUQ); } - /* Set tmp0 to match the required value of Z. */ + /* Compute the required value of Z. */ tcg_gen_setcond_i64(TCG_COND_EQ, cmp, old, cmp); Z = tcg_temp_new(); tcg_gen_trunc_i64_tl(Z, cmp); diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 822dbb2e9a..5d433f8522 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -134,7 +134,6 @@ typedef struct DisasContext { TCGv T1; /* TCG local register indexes (only used inside old micro ops) */ - TCGv tmp0; TCGv_i32 tmp2_i32; TCGv_i32 tmp3_i32; TCGv_i64 tmp1_i64; @@ -2175,14 +2174,17 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) level &= 31; if (level != 0) { int i; + if (level > 1) { + TCGv fp = tcg_temp_new(); - /* Copy level-1 pointers from the previous frame. */ - for (i = 1; i < level; ++i) { - gen_lea_ss_ofs(s, s->A0, cpu_regs[R_EBP], -size * i); - gen_op_ld_v(s, d_ot, s->tmp0, s->A0); + /* Copy level-1 pointers from the previous frame. */ + for (i = 1; i < level; ++i) { + gen_lea_ss_ofs(s, s->A0, cpu_regs[R_EBP], -size * i); + gen_op_ld_v(s, d_ot, fp, s->A0); - gen_lea_ss_ofs(s, s->A0, s->T1, -size * i); - gen_op_st_v(s, d_ot, s->tmp0, s->A0); + gen_lea_ss_ofs(s, s->A0, s->T1, -size * i); + gen_op_st_v(s, d_ot, fp, s->A0); + } } /* Push the current FrameTemp as the last level. */ @@ -2405,10 +2407,11 @@ static void gen_ldy_env_A0(DisasContext *s, int offset, bool align) int mem_index = s->mem_index; TCGv_i128 t0 = tcg_temp_new_i128(); TCGv_i128 t1 = tcg_temp_new_i128(); + TCGv a0_hi = tcg_temp_new(); tcg_gen_qemu_ld_i128(t0, s->A0, mem_index, mop | (align ? MO_ALIGN_32 : 0)); - tcg_gen_addi_tl(s->tmp0, s->A0, 16); - tcg_gen_qemu_ld_i128(t1, s->tmp0, mem_index, mop); + tcg_gen_addi_tl(a0_hi, s->A0, 16); + tcg_gen_qemu_ld_i128(t1, a0_hi, mem_index, mop); tcg_gen_st_i128(t0, tcg_env, offset + offsetof(YMMReg, YMM_X(0))); tcg_gen_st_i128(t1, tcg_env, offset + offsetof(YMMReg, YMM_X(1))); @@ -2419,12 +2422,13 @@ static void gen_sty_env_A0(DisasContext *s, int offset, bool align) MemOp mop = MO_128 | MO_LE | MO_ATOM_IFALIGN_PAIR; int mem_index = s->mem_index; TCGv_i128 t = tcg_temp_new_i128(); + TCGv a0_hi = tcg_temp_new(); tcg_gen_ld_i128(t, tcg_env, offset + offsetof(YMMReg, YMM_X(0))); tcg_gen_qemu_st_i128(t, s->A0, mem_index, mop | (align ? MO_ALIGN_32 : 0)); - tcg_gen_addi_tl(s->tmp0, s->A0, 16); + tcg_gen_addi_tl(a0_hi, s->A0, 16); tcg_gen_ld_i128(t, tcg_env, offset + offsetof(YMMReg, YMM_X(1))); - tcg_gen_qemu_st_i128(t, s->tmp0, mem_index, mop); + tcg_gen_qemu_st_i128(t, a0_hi, mem_index, mop); } #include "emit.c.inc" @@ -3771,7 +3775,6 @@ static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu) dc->T1 = tcg_temp_new(); dc->A0 = tcg_temp_new(); - dc->tmp0 = tcg_temp_new(); dc->tmp1_i64 = tcg_temp_new_i64(); dc->tmp2_i32 = tcg_temp_new_i32(); dc->tmp3_i32 = tcg_temp_new_i32(); From 9a688e70bdb2f23112afeddefd91bd45674d4db9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 13 Feb 2025 18:51:34 +0100 Subject: [PATCH 09/34] target/i386: tcg: remove some more uses of temporaries Remove all uses of 32-bit temporaries in emit.c.inc. Remove uses in translate.c outside the large multiplexed generator functions. tmp3_i32 is not used anymore and can go away. Signed-off-by: Paolo Bonzini --- target/i386/tcg/emit.c.inc | 83 +++++++++++++++++++++++-------------- target/i386/tcg/translate.c | 43 +++++++++++-------- 2 files changed, 77 insertions(+), 49 deletions(-) diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index bd24438230..4e09e96fc1 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -1916,9 +1916,10 @@ static void gen_CPUID(DisasContext *s, X86DecodedInsn *decode) static void gen_CRC32(DisasContext *s, X86DecodedInsn *decode) { MemOp ot = decode->op[2].ot; + TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); - gen_helper_crc32(s->T0, s->tmp2_i32, s->T1, tcg_constant_i32(8 << ot)); + tcg_gen_trunc_tl_i32(tmp, s->T0); + gen_helper_crc32(s->T0, tmp, s->T1, tcg_constant_i32(8 << ot)); } static void gen_CVTPI2Px(DisasContext *s, X86DecodedInsn *decode) @@ -2376,8 +2377,10 @@ static void gen_LAR(DisasContext *s, X86DecodedInsn *decode) static void gen_LDMXCSR(DisasContext *s, X86DecodedInsn *decode) { - tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); - gen_helper_ldmxcsr(tcg_env, s->tmp2_i32); + TCGv_i32 tmp = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(tmp, s->T0); + gen_helper_ldmxcsr(tcg_env, tmp); } static void gen_lxx_seg(DisasContext *s, X86DecodedInsn *decode, int seg) @@ -2590,11 +2593,13 @@ static void gen_MOVDQ(DisasContext *s, X86DecodedInsn *decode) static void gen_MOVMSK(DisasContext *s, X86DecodedInsn *decode) { typeof(gen_helper_movmskps_ymm) *ps, *pd, *fn; + TCGv_i32 tmp = tcg_temp_new_i32(); + ps = s->vex_l ? gen_helper_movmskps_ymm : gen_helper_movmskps_xmm; pd = s->vex_l ? gen_helper_movmskpd_ymm : gen_helper_movmskpd_xmm; fn = s->prefix & PREFIX_DATA ? pd : ps; - fn(s->tmp2_i32, tcg_env, OP_PTR2); - tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32); + fn(tmp, tcg_env, OP_PTR2); + tcg_gen_extu_i32_tl(s->T0, tmp); } static void gen_MOVQ(DisasContext *s, X86DecodedInsn *decode) @@ -2691,13 +2696,17 @@ static void gen_MULX(DisasContext *s, X86DecodedInsn *decode) switch (ot) { case MO_32: #ifdef TARGET_X86_64 - tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); - tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1); - tcg_gen_mulu2_i32(s->tmp2_i32, s->tmp3_i32, - s->tmp2_i32, s->tmp3_i32); - tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], s->tmp2_i32); - tcg_gen_extu_i32_tl(s->T0, s->tmp3_i32); - break; + { + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(t0, s->T0); + tcg_gen_trunc_tl_i32(t1, s->T1); + tcg_gen_mulu2_i32(t0, t1, t0, t1); + tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], t0); + tcg_gen_extu_i32_tl(s->T0, t1); + break; + } case MO_64: #endif @@ -3741,10 +3750,14 @@ static void gen_RORX(DisasContext *s, X86DecodedInsn *decode) switch (ot) { case MO_32: #ifdef TARGET_X86_64 - tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); - tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, b); - tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32); - break; + { + TCGv_i32 tmp = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(tmp, s->T0); + tcg_gen_rotri_i32(tmp, tmp, b); + tcg_gen_extu_i32_tl(s->T0, tmp); + break; + } case MO_64: #endif @@ -4334,7 +4347,7 @@ static void gen_VCVTSI2Sx(DisasContext *s, X86DecodedInsn *decode) } return; } - in = s->tmp2_i32; + in = tcg_temp_new_i32(); tcg_gen_trunc_tl_i32(in, s->T1); #else in = s->T1; @@ -4364,7 +4377,7 @@ static inline void gen_VCVTtSx2SI(DisasContext *s, X86DecodedInsn *decode, return; } - out = s->tmp2_i32; + out = tcg_temp_new_i32(); #else out = s->T0; #endif @@ -4416,7 +4429,7 @@ static void gen_VEXTRACTPS(DisasContext *s, X86DecodedInsn *decode) gen_pextr(s, decode, MO_32); } -static void gen_vinsertps(DisasContext *s, X86DecodedInsn *decode) +static void gen_vinsertps(DisasContext *s, X86DecodedInsn *decode, TCGv_i32 tmp) { int val = decode->immediate; int dest_word = (val >> 4) & 3; @@ -4433,7 +4446,7 @@ static void gen_vinsertps(DisasContext *s, X86DecodedInsn *decode) } if (new_mask != (val & 15)) { - tcg_gen_st_i32(s->tmp2_i32, tcg_env, + tcg_gen_st_i32(tmp, tcg_env, vector_elem_offset(&decode->op[0], MO_32, dest_word)); } @@ -4452,15 +4465,19 @@ static void gen_vinsertps(DisasContext *s, X86DecodedInsn *decode) static void gen_VINSERTPS_r(DisasContext *s, X86DecodedInsn *decode) { int val = decode->immediate; - tcg_gen_ld_i32(s->tmp2_i32, tcg_env, + TCGv_i32 tmp = tcg_temp_new_i32(); + + tcg_gen_ld_i32(tmp, tcg_env, vector_elem_offset(&decode->op[2], MO_32, (val >> 6) & 3)); - gen_vinsertps(s, decode); + gen_vinsertps(s, decode, tmp); } static void gen_VINSERTPS_m(DisasContext *s, X86DecodedInsn *decode) { - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL); - gen_vinsertps(s, decode); + TCGv_i32 tmp = tcg_temp_new_i32(); + + tcg_gen_qemu_ld_i32(tmp, s->A0, s->mem_index, MO_LEUL); + gen_vinsertps(s, decode, tmp); } static void gen_VINSERTx128(DisasContext *s, X86DecodedInsn *decode) @@ -4581,25 +4598,29 @@ static void gen_VMOVSD_ld(DisasContext *s, X86DecodedInsn *decode) static void gen_VMOVSS(DisasContext *s, X86DecodedInsn *decode) { int vec_len = vector_len(s, decode); + TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_ld_i32(s->tmp2_i32, OP_PTR2, offsetof(ZMMReg, ZMM_L(0))); + tcg_gen_ld_i32(tmp, OP_PTR2, offsetof(ZMMReg, ZMM_L(0))); tcg_gen_gvec_mov(MO_64, decode->op[0].offset, decode->op[1].offset, vec_len, vec_len); - tcg_gen_st_i32(s->tmp2_i32, OP_PTR0, offsetof(ZMMReg, ZMM_L(0))); + tcg_gen_st_i32(tmp, OP_PTR0, offsetof(ZMMReg, ZMM_L(0))); } static void gen_VMOVSS_ld(DisasContext *s, X86DecodedInsn *decode) { int vec_len = vector_len(s, decode); + TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL); + tcg_gen_qemu_ld_i32(tmp, s->A0, s->mem_index, MO_LEUL); tcg_gen_gvec_dup_imm(MO_64, decode->op[0].offset, vec_len, vec_len, 0); - tcg_gen_st_i32(s->tmp2_i32, OP_PTR0, offsetof(ZMMReg, ZMM_L(0))); + tcg_gen_st_i32(tmp, OP_PTR0, offsetof(ZMMReg, ZMM_L(0))); } static void gen_VMOVSS_st(DisasContext *s, X86DecodedInsn *decode) { - tcg_gen_ld_i32(s->tmp2_i32, OP_PTR2, offsetof(ZMMReg, ZMM_L(0))); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL); + TCGv_i32 tmp = tcg_temp_new_i32(); + + tcg_gen_ld_i32(tmp, OP_PTR2, offsetof(ZMMReg, ZMM_L(0))); + tcg_gen_qemu_st_i32(tmp, s->A0, s->mem_index, MO_LEUL); } static void gen_VPMASKMOV_st(DisasContext *s, X86DecodedInsn *decode) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 5d433f8522..abe210cc4e 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -135,7 +135,6 @@ typedef struct DisasContext { /* TCG local register indexes (only used inside old micro ops) */ TCGv_i32 tmp2_i32; - TCGv_i32 tmp3_i32; TCGv_i64 tmp1_i64; sigjmp_buf jmpbuf; @@ -1318,30 +1317,35 @@ static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot) static void gen_ins(DisasContext *s, MemOp ot, TCGv dshift) { + TCGv_i32 port = tcg_temp_new_i32(); + gen_string_movl_A0_EDI(s); /* Note: we must do this dummy write first to be restartable in case of page fault. */ tcg_gen_movi_tl(s->T0, 0); gen_op_st_v(s, ot, s->T0, s->A0); - tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]); - tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0xffff); - gen_helper_in_func(ot, s->T0, s->tmp2_i32); + tcg_gen_trunc_tl_i32(port, cpu_regs[R_EDX]); + tcg_gen_andi_i32(port, port, 0xffff); + gen_helper_in_func(ot, s->T0, port); gen_op_st_v(s, ot, s->T0, s->A0); gen_op_add_reg(s, s->aflag, R_EDI, dshift); - gen_bpt_io(s, s->tmp2_i32, ot); + gen_bpt_io(s, port, ot); } static void gen_outs(DisasContext *s, MemOp ot, TCGv dshift) { + TCGv_i32 port = tcg_temp_new_i32(); + TCGv_i32 value = tcg_temp_new_i32(); + gen_string_movl_A0_ESI(s); gen_op_ld_v(s, ot, s->T0, s->A0); - tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]); - tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0xffff); - tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T0); - gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32); + tcg_gen_trunc_tl_i32(port, cpu_regs[R_EDX]); + tcg_gen_andi_i32(port, port, 0xffff); + tcg_gen_trunc_tl_i32(value, s->T0); + gen_helper_out_func(ot, port, value); gen_op_add_reg(s, s->aflag, R_ESI, dshift); - gen_bpt_io(s, s->tmp2_i32, ot); + gen_bpt_io(s, port, ot); } #define REP_MAX 65535 @@ -1869,14 +1873,16 @@ static void gen_bndck(DisasContext *s, X86DecodedInsn *decode, TCGCond cond, TCGv_i64 bndv) { TCGv ea = gen_lea_modrm_1(s, decode->mem, false); + TCGv_i32 t32 = tcg_temp_new_i32(); + TCGv_i64 t64 = tcg_temp_new_i64(); - tcg_gen_extu_tl_i64(s->tmp1_i64, ea); + tcg_gen_extu_tl_i64(t64, ea); if (!CODE64(s)) { - tcg_gen_ext32u_i64(s->tmp1_i64, s->tmp1_i64); + tcg_gen_ext32u_i64(t64, t64); } - tcg_gen_setcond_i64(cond, s->tmp1_i64, s->tmp1_i64, bndv); - tcg_gen_extrl_i64_i32(s->tmp2_i32, s->tmp1_i64); - gen_helper_bndck(tcg_env, s->tmp2_i32); + tcg_gen_setcond_i64(cond, t64, t64, bndv); + tcg_gen_extrl_i64_i32(t32, t64); + gen_helper_bndck(tcg_env, t32); } /* generate modrm load of memory or register. */ @@ -2021,8 +2027,10 @@ static void gen_op_movl_seg_real(DisasContext *s, X86Seg seg_reg, TCGv seg) static void gen_movl_seg(DisasContext *s, X86Seg seg_reg, TCGv src) { if (PE(s) && !VM86(s)) { - tcg_gen_trunc_tl_i32(s->tmp2_i32, src); - gen_helper_load_seg(tcg_env, tcg_constant_i32(seg_reg), s->tmp2_i32); + TCGv_i32 sel = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(sel, src); + gen_helper_load_seg(tcg_env, tcg_constant_i32(seg_reg), sel); /* abort translation because the addseg value may change or because ss32 may change. For R_SS, translation must always stop as a special handling must be done to disable hardware @@ -3777,7 +3785,6 @@ static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu) dc->tmp1_i64 = tcg_temp_new_i64(); dc->tmp2_i32 = tcg_temp_new_i32(); - dc->tmp3_i32 = tcg_temp_new_i32(); dc->cc_srcT = tcg_temp_new(); } From 3fec86e95cd44ac7db639686ef1dda143af59aea Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Apr 2025 14:06:37 +0200 Subject: [PATCH 10/34] target/i386: tcg: simplify computation of AF after INC/DEC No difference in generated code, but the XOR-based formula is easily understood on its own. This will make more sense once ADD/SUB stop using dst^src1^src2 to compute AF. Signed-off-by: Paolo Bonzini --- target/i386/tcg/cc_helper_template.h.inc | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/target/i386/tcg/cc_helper_template.h.inc b/target/i386/tcg/cc_helper_template.h.inc index 9aff16b880..b821e5bca3 100644 --- a/target/i386/tcg/cc_helper_template.h.inc +++ b/target/i386/tcg/cc_helper_template.h.inc @@ -175,13 +175,10 @@ static uint32_t glue(compute_all_logic, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) static uint32_t glue(compute_all_inc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) { uint32_t cf, pf, af, zf, sf, of; - DATA_TYPE src2; cf = src1; - src1 = dst - 1; - src2 = 1; pf = compute_pf(dst); - af = (dst ^ src1 ^ src2) & CC_A; + af = (dst ^ (dst - 1)) & CC_A; /* bits 0..3 are all clear */ zf = (dst == 0) * CC_Z; sf = lshift(dst, 8 - DATA_BITS) & CC_S; of = (dst == SIGN_MASK) * CC_O; @@ -191,13 +188,10 @@ static uint32_t glue(compute_all_inc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) static uint32_t glue(compute_all_dec, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) { uint32_t cf, pf, af, zf, sf, of; - DATA_TYPE src2; cf = src1; - src1 = dst + 1; - src2 = 1; pf = compute_pf(dst); - af = (dst ^ src1 ^ src2) & CC_A; + af = (dst ^ (dst + 1)) & CC_A; /* bits 0..3 are all set */ zf = (dst == 0) * CC_Z; sf = lshift(dst, 8 - DATA_BITS) & CC_S; of = (dst == SIGN_MASK - 1) * CC_O; From 767149d3d078356073a32238b313cee9d02db5d8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 20 Mar 2025 14:55:42 +0100 Subject: [PATCH 11/34] target/i386: emulate: microoptimize and explain ADD_COUT_VEC/SUB_COUT_VEC The logic is the same, but the majority(NOT a, b, c) is brought out to a separate macro and implemented without NOT operations. Signed-off-by: Paolo Bonzini --- target/i386/hvf/x86_flags.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/target/i386/hvf/x86_flags.c b/target/i386/hvf/x86_flags.c index fedc70a1b8..60ab4f01a2 100644 --- a/target/i386/hvf/x86_flags.c +++ b/target/i386/hvf/x86_flags.c @@ -45,14 +45,30 @@ #define LF_MASK_CF (0x01 << LF_BIT_CF) #define LF_MASK_PO (0x01 << LF_BIT_PO) +/* majority(NOT a, b, c) = (a ^ b) ? b : c */ +#define MAJ_INV1(a, b, c) ((((a) ^ (b)) & ((b) ^ (c))) ^ (c)) + +/* + * ADD_COUT_VEC(x, y) = majority((x + y) ^ x ^ y, x, y) + * + * If two corresponding bits in x and y are the same, that's the carry + * independent of the value (x+y)^x^y. Hence x^y can be replaced with + * 1 in (x+y)^x^y, resulting in majority(NOT (x+y), x, y) + */ #define ADD_COUT_VEC(op1, op2, result) \ - (((op1) & (op2)) | (((op1) | (op2)) & (~(result)))) + MAJ_INV1(result, op1, op2) +/* + * SUB_COUT_VEC(x, y) = NOT majority(x, NOT y, (x - y) ^ x ^ NOT y) + * = majority(NOT x, y, (x - y) ^ x ^ y) + * + * Note that the carry out is actually a borrow, i.e. it is inverted. + * If two corresponding bits in x and y are different, the value of the + * bit in (x-y)^x^y likewise does not matter. Hence, x^y can be replaced + * with 0 in (x-y)^x^y, resulting in majority(NOT x, y, x-y) + */ #define SUB_COUT_VEC(op1, op2, result) \ - (((~(op1)) & (op2)) | (((~(op1)) ^ (op2)) & (result))) - -#define GET_ADD_OVERFLOW(op1, op2, result, mask) \ - ((((op1) ^ (result)) & ((op2) ^ (result))) & (mask)) + MAJ_INV1(op1, op2, result) /* ******************* */ /* OSZAPC */ From 5dcdbd071253e249a76c7771bcf78eca3763a131 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Apr 2025 18:20:06 +0200 Subject: [PATCH 12/34] target/i386: tcg: use cout to commonize add/adc/sub/sbb cases Use the carry-out vector as the basis to compute AF, CF and OF. The cost is pretty much the same, because the carry-out is just four boolean operations, and the code is much smaller because add/adc/sub/sbb now share most of it. A similar algorithm to what is used in target/i386/emulate can also be used for APX, in order to build the result of CCMP/CTEST with a new CC_OP_*. CCMP needs to place into the flags from either a subtraction or a constant value; CTEST likewise place into the flags either an AND or a constant value. The new CC_OP for CCMP and CTEST would store for a successful predcate: - in DST and SRC2, the result of the operation; - in SRC, a carry-out vector for CCMP or zero for CTEST; If the default flag value is used, DST/SRC/SRC2 can be filled with constants: - in DST the negated ZF; - in SRC's top 2 bits, a value that results in the desired OF and CF; - in SRC2 a suitable value (any of 0/1/~0/~1) that can be used instead of DST to compute the desired SF and PF. Signed-off-by: Paolo Bonzini --- target/i386/cpu.h | 25 ++++++++ target/i386/hvf/x86_flags.c | 25 -------- target/i386/tcg/cc_helper_template.h.inc | 80 ++++++++---------------- 3 files changed, 52 insertions(+), 78 deletions(-) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 76f24446a5..7a8d695bdb 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -2843,4 +2843,29 @@ static inline bool ctl_has_irq(CPUX86State *env) # define TARGET_VSYSCALL_PAGE (UINT64_C(-10) << 20) #endif +/* majority(NOT a, b, c) = (a ^ b) ? b : c */ +#define MAJ_INV1(a, b, c) ((((a) ^ (b)) & ((b) ^ (c))) ^ (c)) + +/* + * ADD_COUT_VEC(x, y) = majority((x + y) ^ x ^ y, x, y) + * + * If two corresponding bits in x and y are the same, that's the carry + * independent of the value (x+y)^x^y. Hence x^y can be replaced with + * 1 in (x+y)^x^y, resulting in majority(NOT (x+y), x, y) + */ +#define ADD_COUT_VEC(op1, op2, result) \ + MAJ_INV1(result, op1, op2) + +/* + * SUB_COUT_VEC(x, y) = NOT majority(x, NOT y, (x - y) ^ x ^ NOT y) + * = majority(NOT x, y, (x - y) ^ x ^ y) + * + * Note that the carry out is actually a borrow, i.e. it is inverted. + * If two corresponding bits in x and y are different, the value of the + * bit in (x-y)^x^y likewise does not matter. Hence, x^y can be replaced + * with 0 in (x-y)^x^y, resulting in majority(NOT x, y, x-y) + */ +#define SUB_COUT_VEC(op1, op2, result) \ + MAJ_INV1(op1, op2, result) + #endif /* I386_CPU_H */ diff --git a/target/i386/hvf/x86_flags.c b/target/i386/hvf/x86_flags.c index 60ab4f01a2..0c75e0419c 100644 --- a/target/i386/hvf/x86_flags.c +++ b/target/i386/hvf/x86_flags.c @@ -45,31 +45,6 @@ #define LF_MASK_CF (0x01 << LF_BIT_CF) #define LF_MASK_PO (0x01 << LF_BIT_PO) -/* majority(NOT a, b, c) = (a ^ b) ? b : c */ -#define MAJ_INV1(a, b, c) ((((a) ^ (b)) & ((b) ^ (c))) ^ (c)) - -/* - * ADD_COUT_VEC(x, y) = majority((x + y) ^ x ^ y, x, y) - * - * If two corresponding bits in x and y are the same, that's the carry - * independent of the value (x+y)^x^y. Hence x^y can be replaced with - * 1 in (x+y)^x^y, resulting in majority(NOT (x+y), x, y) - */ -#define ADD_COUT_VEC(op1, op2, result) \ - MAJ_INV1(result, op1, op2) - -/* - * SUB_COUT_VEC(x, y) = NOT majority(x, NOT y, (x - y) ^ x ^ NOT y) - * = majority(NOT x, y, (x - y) ^ x ^ y) - * - * Note that the carry out is actually a borrow, i.e. it is inverted. - * If two corresponding bits in x and y are different, the value of the - * bit in (x-y)^x^y likewise does not matter. Hence, x^y can be replaced - * with 0 in (x-y)^x^y, resulting in majority(NOT x, y, x-y) - */ -#define SUB_COUT_VEC(op1, op2, result) \ - MAJ_INV1(op1, op2, result) - /* ******************* */ /* OSZAPC */ /* ******************* */ diff --git a/target/i386/tcg/cc_helper_template.h.inc b/target/i386/tcg/cc_helper_template.h.inc index b821e5bca3..d8fd976ca1 100644 --- a/target/i386/tcg/cc_helper_template.h.inc +++ b/target/i386/tcg/cc_helper_template.h.inc @@ -44,18 +44,32 @@ /* dynamic flags computation */ -static uint32_t glue(compute_all_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) +static uint32_t glue(compute_all_cout, SUFFIX)(DATA_TYPE dst, DATA_TYPE carries) { - uint32_t cf, pf, af, zf, sf, of; - DATA_TYPE src2 = dst - src1; + uint32_t af_cf, pf, zf, sf, of; - cf = dst < src1; + /* PF, ZF, SF computed from result. */ pf = compute_pf(dst); - af = (dst ^ src1 ^ src2) & CC_A; zf = (dst == 0) * CC_Z; sf = lshift(dst, 8 - DATA_BITS) & CC_S; - of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 12 - DATA_BITS) & CC_O; - return cf + pf + af + zf + sf + of; + + /* + * AF, CF, OF computed from carry out vector. To compute AF and CF, rotate it + * left by one so cout(DATA_BITS - 1) is in bit 0 and cout(3) in bit 4. + * + * To compute OF, place the highest two carry bits into OF and the bit + * immediately to the right of it; then, adding CC_O / 2 XORs them. + */ + af_cf = ((carries << 1) | (carries >> (DATA_BITS - 1))) & (CC_A | CC_C); + of = (lshift(carries, 12 - DATA_BITS) + CC_O / 2) & CC_O; + return pf + zf + sf + af_cf + of; +} + +static uint32_t glue(compute_all_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) +{ + DATA_TYPE src2 = dst - src1; + DATA_TYPE carries = ADD_COUT_VEC(src1, src2, dst); + return glue(compute_all_cout, SUFFIX)(dst, carries); } static int glue(compute_c_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) @@ -66,25 +80,9 @@ static int glue(compute_c_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) static uint32_t glue(compute_all_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1, DATA_TYPE src3) { - uint32_t cf, pf, af, zf, sf, of; - -#ifdef WIDER_TYPE - WIDER_TYPE src13 = (WIDER_TYPE) src1 + (WIDER_TYPE) src3; - DATA_TYPE src2 = dst - src13; - - cf = dst < src13; -#else DATA_TYPE src2 = dst - src1 - src3; - - cf = (src3 ? dst <= src1 : dst < src1); -#endif - - pf = compute_pf(dst); - af = (dst ^ src1 ^ src2) & 0x10; - zf = (dst == 0) << 6; - sf = lshift(dst, 8 - DATA_BITS) & 0x80; - of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 12 - DATA_BITS) & CC_O; - return cf + pf + af + zf + sf + of; + DATA_TYPE carries = ADD_COUT_VEC(src1, src2, dst); + return glue(compute_all_cout, SUFFIX)(dst, carries); } static int glue(compute_c_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1, @@ -101,16 +99,9 @@ static int glue(compute_c_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1, static uint32_t glue(compute_all_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2) { - uint32_t cf, pf, af, zf, sf, of; DATA_TYPE src1 = dst + src2; - - cf = src1 < src2; - pf = compute_pf(dst); - af = (dst ^ src1 ^ src2) & CC_A; - zf = (dst == 0) * CC_Z; - sf = lshift(dst, 8 - DATA_BITS) & CC_S; - of = lshift((src1 ^ src2) & (src1 ^ dst), 12 - DATA_BITS) & CC_O; - return cf + pf + af + zf + sf + of; + DATA_TYPE carries = SUB_COUT_VEC(src1, src2, dst); + return glue(compute_all_cout, SUFFIX)(dst, carries); } static int glue(compute_c_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2) @@ -123,25 +114,9 @@ static int glue(compute_c_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2) static uint32_t glue(compute_all_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2, DATA_TYPE src3) { - uint32_t cf, pf, af, zf, sf, of; - -#ifdef WIDER_TYPE - WIDER_TYPE src23 = (WIDER_TYPE) src2 + (WIDER_TYPE) src3; - DATA_TYPE src1 = dst + src23; - - cf = src1 < src23; -#else DATA_TYPE src1 = dst + src2 + src3; - - cf = (src3 ? src1 <= src2 : src1 < src2); -#endif - - pf = compute_pf(dst); - af = (dst ^ src1 ^ src2) & 0x10; - zf = (dst == 0) << 6; - sf = lshift(dst, 8 - DATA_BITS) & 0x80; - of = lshift((src1 ^ src2) & (src1 ^ dst), 12 - DATA_BITS) & CC_O; - return cf + pf + af + zf + sf + of; + DATA_TYPE carries = SUB_COUT_VEC(src1, src2, dst); + return glue(compute_all_cout, SUFFIX)(dst, carries); } static int glue(compute_c_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2, @@ -286,6 +261,5 @@ static int glue(compute_c_blsi, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) #undef DATA_BITS #undef SIGN_MASK #undef DATA_TYPE -#undef DATA_MASK #undef SUFFIX #undef WIDER_TYPE From 26a44d9d2d4296701ceebc1085ab28171a1e7e3b Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Fri, 7 Mar 2025 11:55:12 -0800 Subject: [PATCH 13/34] target/i386/hvf: introduce x86_emul_ops This will be used to remove HVF specific code from the instruction emulator. For now we only introduce two hooks for x86_decode.c. More hooks will be added when the code is refactored. The emulator initialization function now takes in a pointer to the ops structure. Signed-off-by: Wei Liu Link: https://lore.kernel.org/r/1741377325-28175-2-git-send-email-liuwe@linux.microsoft.com Signed-off-by: Paolo Bonzini --- target/i386/hvf/hvf.c | 20 +++++++++++++++++++- target/i386/hvf/x86_emu.c | 5 ++++- target/i386/hvf/x86_emu.h | 10 +++++++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index 9ba0e04ac7..03456ffbc7 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -229,6 +229,24 @@ hv_return_t hvf_arch_vm_create(MachineState *ms, uint32_t pa_range) return hv_vm_create(HV_VM_DEFAULT); } +static void hvf_read_segment_descriptor(CPUState *s, struct x86_segment_descriptor *desc, + X86Seg seg) +{ + struct vmx_segment vmx_segment; + vmx_read_segment_descriptor(s, &vmx_segment, seg); + vmx_segment_to_x86_descriptor(s, &vmx_segment, desc); +} + +static void hvf_read_mem(CPUState *cpu, void *data, target_ulong gva, int bytes) +{ + vmx_read_mem(cpu, data, gva, bytes); +} + +static const struct x86_emul_ops hvf_x86_emul_ops = { + .read_mem = hvf_read_mem, + .read_segment_descriptor = hvf_read_segment_descriptor, +}; + int hvf_arch_init_vcpu(CPUState *cpu) { X86CPU *x86cpu = X86_CPU(cpu); @@ -237,7 +255,7 @@ int hvf_arch_init_vcpu(CPUState *cpu) int r; uint64_t reqCap; - init_emu(); + init_emu(&hvf_x86_emul_ops); init_decoder(); if (hvf_state->hvf_caps == NULL) { diff --git a/target/i386/hvf/x86_emu.c b/target/i386/hvf/x86_emu.c index ebba80a36b..c15b5a7ca8 100644 --- a/target/i386/hvf/x86_emu.c +++ b/target/i386/hvf/x86_emu.c @@ -1231,6 +1231,8 @@ static struct cmd_handler { static struct cmd_handler _cmd_handler[X86_DECODE_CMD_LAST]; +const struct x86_emul_ops *emul_ops; + static void init_cmd_handler(void) { int i; @@ -1253,7 +1255,8 @@ bool exec_instruction(CPUX86State *env, struct x86_decode *ins) return true; } -void init_emu(void) +void init_emu(const struct x86_emul_ops *o) { + emul_ops = o; init_cmd_handler(); } diff --git a/target/i386/hvf/x86_emu.h b/target/i386/hvf/x86_emu.h index bc0fc72c76..1422d06ea1 100644 --- a/target/i386/hvf/x86_emu.h +++ b/target/i386/hvf/x86_emu.h @@ -23,7 +23,15 @@ #include "x86_decode.h" #include "cpu.h" -void init_emu(void); +struct x86_emul_ops { + void (*read_mem)(CPUState *cpu, void *data, target_ulong addr, int bytes); + void (*read_segment_descriptor)(CPUState *cpu, struct x86_segment_descriptor *desc, + enum X86Seg seg); +}; + +extern const struct x86_emul_ops *emul_ops; + +void init_emu(const struct x86_emul_ops *ops); bool exec_instruction(CPUX86State *env, struct x86_decode *ins); void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_code); From 0860abbe849e7345fee28c08fa200f7cc315f175 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Fri, 7 Mar 2025 11:55:13 -0800 Subject: [PATCH 14/34] target/i386/hvf: remove HVF specific calls from x86_decode.c Use the newly defined emul_ops. This allows the module to be reused by other accelerator in the future. No functional change intended. Signed-off-by: Wei Liu Link: https://lore.kernel.org/r/1741377325-28175-3-git-send-email-liuwe@linux.microsoft.com Signed-off-by: Paolo Bonzini --- target/i386/hvf/x86_decode.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/target/i386/hvf/x86_decode.c b/target/i386/hvf/x86_decode.c index 5fea2dd3cc..728e159638 100644 --- a/target/i386/hvf/x86_decode.c +++ b/target/i386/hvf/x86_decode.c @@ -21,6 +21,7 @@ #include "panic.h" #include "x86_decode.h" #include "vmx.h" +#include "x86_emu.h" #include "x86_mmu.h" #include "x86_descr.h" @@ -74,7 +75,7 @@ static inline uint64_t decode_bytes(CPUX86State *env, struct x86_decode *decode, break; } target_ulong va = linear_rip(env_cpu(env), env->eip) + decode->len; - vmx_read_mem(env_cpu(env), &val, va, size); + emul_ops->read_mem(env_cpu(env), &val, va, size); decode->len += size; return val; @@ -1893,16 +1894,6 @@ static void decode_prefix(CPUX86State *env, struct x86_decode *decode) } } -static struct x86_segment_descriptor get_cs_descriptor(CPUState *s) -{ - struct vmx_segment vmx_cs; - x86_segment_descriptor cs; - vmx_read_segment_descriptor(s, &vmx_cs, R_CS); - vmx_segment_to_x86_descriptor(s, &vmx_cs, &cs); - - return cs; -} - void set_addressing_size(CPUX86State *env, struct x86_decode *decode) { decode->addressing_size = -1; @@ -1914,7 +1905,8 @@ void set_addressing_size(CPUX86State *env, struct x86_decode *decode) } } else if (!x86_is_long_mode(env_cpu(env))) { /* protected */ - x86_segment_descriptor cs = get_cs_descriptor(env_cpu(env)); + x86_segment_descriptor cs; + emul_ops->read_segment_descriptor(env_cpu(env), &cs, R_CS); /* check db */ if (cs.db) { if (decode->addr_size_override) { @@ -1950,7 +1942,8 @@ void set_operand_size(CPUX86State *env, struct x86_decode *decode) } } else if (!x86_is_long_mode(env_cpu(env))) { /* protected */ - x86_segment_descriptor cs = get_cs_descriptor(env_cpu(env)); + x86_segment_descriptor cs; + emul_ops->read_segment_descriptor(env_cpu(env), &cs, R_CS); /* check db */ if (cs.db) { if (decode->op_size_override) { From 444bae08bbdae175b14cc96a11af8640eb262963 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Fri, 7 Mar 2025 11:55:14 -0800 Subject: [PATCH 15/34] target/i386/hvf: provide and use handle_io in emul_ops This drops the calls to hvf_handle_io from x86_emu.c. Signed-off-by: Wei Liu Link: https://lore.kernel.org/r/1741377325-28175-4-git-send-email-liuwe@linux.microsoft.com Signed-off-by: Paolo Bonzini --- target/i386/hvf/hvf.c | 1 + target/i386/hvf/x86_emu.c | 29 +++++++++++++++-------------- target/i386/hvf/x86_emu.h | 2 ++ 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index 03456ffbc7..7da03f9c08 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -245,6 +245,7 @@ static void hvf_read_mem(CPUState *cpu, void *data, target_ulong gva, int bytes) static const struct x86_emul_ops hvf_x86_emul_ops = { .read_mem = hvf_read_mem, .read_segment_descriptor = hvf_read_segment_descriptor, + .handle_io = hvf_handle_io, }; int hvf_arch_init_vcpu(CPUState *cpu) diff --git a/target/i386/hvf/x86_emu.c b/target/i386/hvf/x86_emu.c index c15b5a7ca8..7b01ccde5d 100644 --- a/target/i386/hvf/x86_emu.c +++ b/target/i386/hvf/x86_emu.c @@ -396,18 +396,18 @@ static void exec_out(CPUX86State *env, struct x86_decode *decode) { switch (decode->opcode[0]) { case 0xe6: - hvf_handle_io(env_cpu(env), decode->op[0].val, &AL(env), 1, 1, 1); + emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 1, 1, 1); break; case 0xe7: - hvf_handle_io(env_cpu(env), decode->op[0].val, &RAX(env), 1, - decode->operand_size, 1); + emul_ops->handle_io(env_cpu(env), decode->op[0].val, &RAX(env), 1, + decode->operand_size, 1); break; case 0xee: - hvf_handle_io(env_cpu(env), DX(env), &AL(env), 1, 1, 1); + emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 1, 1, 1); break; case 0xef: - hvf_handle_io(env_cpu(env), DX(env), &RAX(env), 1, - decode->operand_size, 1); + emul_ops->handle_io(env_cpu(env), DX(env), &RAX(env), 1, + decode->operand_size, 1); break; default: VM_PANIC("Bad out opcode\n"); @@ -421,10 +421,10 @@ static void exec_in(CPUX86State *env, struct x86_decode *decode) target_ulong val = 0; switch (decode->opcode[0]) { case 0xe4: - hvf_handle_io(env_cpu(env), decode->op[0].val, &AL(env), 0, 1, 1); + emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 0, 1, 1); break; case 0xe5: - hvf_handle_io(env_cpu(env), decode->op[0].val, &val, 0, + emul_ops->handle_io(env_cpu(env), decode->op[0].val, &val, 0, decode->operand_size, 1); if (decode->operand_size == 2) { AX(env) = val; @@ -433,10 +433,11 @@ static void exec_in(CPUX86State *env, struct x86_decode *decode) } break; case 0xec: - hvf_handle_io(env_cpu(env), DX(env), &AL(env), 0, 1, 1); + emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 0, 1, 1); break; case 0xed: - hvf_handle_io(env_cpu(env), DX(env), &val, 0, decode->operand_size, 1); + emul_ops->handle_io(env_cpu(env), DX(env), &val, 0, + decode->operand_size, 1); if (decode->operand_size == 2) { AX(env) = val; } else { @@ -486,8 +487,8 @@ static void exec_ins_single(CPUX86State *env, struct x86_decode *decode) target_ulong addr = linear_addr_size(env_cpu(env), RDI(env), decode->addressing_size, R_ES); - hvf_handle_io(env_cpu(env), DX(env), env->hvf_mmio_buf, 0, - decode->operand_size, 1); + emul_ops->handle_io(env_cpu(env), DX(env), env->hvf_mmio_buf, 0, + decode->operand_size, 1); vmx_write_mem(env_cpu(env), addr, env->hvf_mmio_buf, decode->operand_size); @@ -511,8 +512,8 @@ static void exec_outs_single(CPUX86State *env, struct x86_decode *decode) vmx_read_mem(env_cpu(env), env->hvf_mmio_buf, addr, decode->operand_size); - hvf_handle_io(env_cpu(env), DX(env), env->hvf_mmio_buf, 1, - decode->operand_size, 1); + emul_ops->handle_io(env_cpu(env), DX(env), env->hvf_mmio_buf, 1, + decode->operand_size, 1); string_increment_reg(env, R_ESI, decode); } diff --git a/target/i386/hvf/x86_emu.h b/target/i386/hvf/x86_emu.h index 1422d06ea1..40cc786694 100644 --- a/target/i386/hvf/x86_emu.h +++ b/target/i386/hvf/x86_emu.h @@ -27,6 +27,8 @@ struct x86_emul_ops { void (*read_mem)(CPUState *cpu, void *data, target_ulong addr, int bytes); void (*read_segment_descriptor)(CPUState *cpu, struct x86_segment_descriptor *desc, enum X86Seg seg); + void (*handle_io)(CPUState *cpu, uint16_t port, void *data, int direction, + int size, int count); }; extern const struct x86_emul_ops *emul_ops; From e9c40026b641da21c96c877153cbe08706b2aac9 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Fri, 7 Mar 2025 11:55:15 -0800 Subject: [PATCH 16/34] target/i386: rename hvf_mmio_buf to emu_mmio_buf We want to refactor HVF's instruction emulator to a common component. Renaming hvf_mmio_buf removes the association between HVF and the instruction emulator. The definition of the field is still guarded by CONFIG_HVF for now, since it is the only user. No functional change. Signed-off-by: Wei Liu Link: https://lore.kernel.org/r/1741377325-28175-5-git-send-email-liuwe@linux.microsoft.com Signed-off-by: Paolo Bonzini --- target/i386/cpu.h | 2 +- target/i386/hvf/hvf.c | 4 ++-- target/i386/hvf/x86_emu.c | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 7a8d695bdb..3c5c39ce3d 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -2109,7 +2109,7 @@ typedef struct CPUArchState { #endif #if defined(CONFIG_HVF) HVFX86LazyFlags hvf_lflags; - void *hvf_mmio_buf; + void *emu_mmio_buf; #endif uint64_t mcg_cap; diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index 7da03f9c08..1cecb76595 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -168,7 +168,7 @@ void hvf_arch_vcpu_destroy(CPUState *cpu) X86CPU *x86_cpu = X86_CPU(cpu); CPUX86State *env = &x86_cpu->env; - g_free(env->hvf_mmio_buf); + g_free(env->emu_mmio_buf); } static void init_tsc_freq(CPUX86State *env) @@ -262,7 +262,7 @@ int hvf_arch_init_vcpu(CPUState *cpu) if (hvf_state->hvf_caps == NULL) { hvf_state->hvf_caps = g_new0(struct hvf_vcpu_caps, 1); } - env->hvf_mmio_buf = g_new(char, 4096); + env->emu_mmio_buf = g_new(char, 4096); if (x86cpu->vmware_cpuid_freq) { init_tsc_freq(env); diff --git a/target/i386/hvf/x86_emu.c b/target/i386/hvf/x86_emu.c index 7b01ccde5d..e59a73e00d 100644 --- a/target/i386/hvf/x86_emu.c +++ b/target/i386/hvf/x86_emu.c @@ -184,8 +184,8 @@ void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int siz uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes) { - vmx_read_mem(env_cpu(env), env->hvf_mmio_buf, ptr, bytes); - return env->hvf_mmio_buf; + vmx_read_mem(env_cpu(env), env->emu_mmio_buf, ptr, bytes); + return env->emu_mmio_buf; } @@ -487,9 +487,9 @@ static void exec_ins_single(CPUX86State *env, struct x86_decode *decode) target_ulong addr = linear_addr_size(env_cpu(env), RDI(env), decode->addressing_size, R_ES); - emul_ops->handle_io(env_cpu(env), DX(env), env->hvf_mmio_buf, 0, + emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 0, decode->operand_size, 1); - vmx_write_mem(env_cpu(env), addr, env->hvf_mmio_buf, + vmx_write_mem(env_cpu(env), addr, env->emu_mmio_buf, decode->operand_size); string_increment_reg(env, R_EDI, decode); @@ -510,9 +510,9 @@ static void exec_outs_single(CPUX86State *env, struct x86_decode *decode) { target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS); - vmx_read_mem(env_cpu(env), env->hvf_mmio_buf, addr, + vmx_read_mem(env_cpu(env), env->emu_mmio_buf, addr, decode->operand_size); - emul_ops->handle_io(env_cpu(env), DX(env), env->hvf_mmio_buf, 1, + emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 1, decode->operand_size, 1); string_increment_reg(env, R_ESI, decode); From ae3c6134ecb4c7d3ba1c6bae3ff5b5dd6cf05d56 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Fri, 7 Mar 2025 11:55:16 -0800 Subject: [PATCH 17/34] target/i386/hvf: use emul_ops->read_mem in x86_emu.c No functional change. Signed-off-by: Wei Liu Link: https://lore.kernel.org/r/1741377325-28175-6-git-send-email-liuwe@linux.microsoft.com Signed-off-by: Paolo Bonzini --- target/i386/hvf/x86_emu.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/target/i386/hvf/x86_emu.c b/target/i386/hvf/x86_emu.c index e59a73e00d..7b816b5a1d 100644 --- a/target/i386/hvf/x86_emu.c +++ b/target/i386/hvf/x86_emu.c @@ -184,7 +184,7 @@ void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int siz uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes) { - vmx_read_mem(env_cpu(env), env->emu_mmio_buf, ptr, bytes); + emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, ptr, bytes); return env->emu_mmio_buf; } @@ -510,8 +510,8 @@ static void exec_outs_single(CPUX86State *env, struct x86_decode *decode) { target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS); - vmx_read_mem(env_cpu(env), env->emu_mmio_buf, addr, - decode->operand_size); + emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, addr, + decode->operand_size); emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 1, decode->operand_size, 1); @@ -620,7 +620,7 @@ static void exec_scas_single(CPUX86State *env, struct x86_decode *decode) addr = linear_addr_size(env_cpu(env), RDI(env), decode->addressing_size, R_ES); decode->op[1].type = X86_VAR_IMMEDIATE; - vmx_read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size); + emul_ops->read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size); EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false); string_increment_reg(env, R_EDI, decode); @@ -645,7 +645,7 @@ static void exec_lods_single(CPUX86State *env, struct x86_decode *decode) target_ulong val = 0; addr = decode_linear_addr(env, decode, RSI(env), R_DS); - vmx_read_mem(env_cpu(env), &val, addr, decode->operand_size); + emul_ops->read_mem(env_cpu(env), &val, addr, decode->operand_size); write_reg(env, R_EAX, val, decode->operand_size); string_increment_reg(env, R_ESI, decode); From 63d8bc669302ec22bd394c45380848a2d5947943 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Fri, 7 Mar 2025 11:55:17 -0800 Subject: [PATCH 18/34] target/i386/hvf: provide and use write_mem in emul_ops Signed-off-by: Wei Liu Link: https://lore.kernel.org/r/1741377325-28175-7-git-send-email-liuwe@linux.microsoft.com Signed-off-by: Paolo Bonzini --- target/i386/hvf/hvf.c | 6 ++++++ target/i386/hvf/x86_emu.c | 8 ++++---- target/i386/hvf/x86_emu.h | 1 + 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index 1cecb76595..e4f48a79fb 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -242,8 +242,14 @@ static void hvf_read_mem(CPUState *cpu, void *data, target_ulong gva, int bytes) vmx_read_mem(cpu, data, gva, bytes); } +static void hvf_write_mem(CPUState *cpu, void *data, target_ulong gva, int bytes) +{ + vmx_write_mem(cpu, gva, data, bytes); +} + static const struct x86_emul_ops hvf_x86_emul_ops = { .read_mem = hvf_read_mem, + .write_mem = hvf_write_mem, .read_segment_descriptor = hvf_read_segment_descriptor, .handle_io = hvf_handle_io, }; diff --git a/target/i386/hvf/x86_emu.c b/target/i386/hvf/x86_emu.c index 7b816b5a1d..3ff41c35d8 100644 --- a/target/i386/hvf/x86_emu.c +++ b/target/i386/hvf/x86_emu.c @@ -179,7 +179,7 @@ void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int siz write_val_to_reg(ptr, val, size); return; } - vmx_write_mem(env_cpu(env), ptr, &val, size); + emul_ops->write_mem(env_cpu(env), &val, ptr, size); } uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes) @@ -489,8 +489,8 @@ static void exec_ins_single(CPUX86State *env, struct x86_decode *decode) emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 0, decode->operand_size, 1); - vmx_write_mem(env_cpu(env), addr, env->emu_mmio_buf, - decode->operand_size); + emul_ops->write_mem(env_cpu(env), env->emu_mmio_buf, addr, + decode->operand_size); string_increment_reg(env, R_EDI, decode); } @@ -596,7 +596,7 @@ static void exec_stos_single(CPUX86State *env, struct x86_decode *decode) addr = linear_addr_size(env_cpu(env), RDI(env), decode->addressing_size, R_ES); val = read_reg(env, R_EAX, decode->operand_size); - vmx_write_mem(env_cpu(env), addr, &val, decode->operand_size); + emul_ops->write_mem(env_cpu(env), &val, addr, decode->operand_size); string_increment_reg(env, R_EDI, decode); } diff --git a/target/i386/hvf/x86_emu.h b/target/i386/hvf/x86_emu.h index 40cc786694..107c1f1ac8 100644 --- a/target/i386/hvf/x86_emu.h +++ b/target/i386/hvf/x86_emu.h @@ -25,6 +25,7 @@ struct x86_emul_ops { void (*read_mem)(CPUState *cpu, void *data, target_ulong addr, int bytes); + void (*write_mem)(CPUState *cpu, void *data, target_ulong addr, int bytes); void (*read_segment_descriptor)(CPUState *cpu, struct x86_segment_descriptor *desc, enum X86Seg seg); void (*handle_io)(CPUState *cpu, uint16_t port, void *data, int direction, From 585678640c778ee35a86638eacb22372bda70ee1 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Fri, 7 Mar 2025 11:55:18 -0800 Subject: [PATCH 19/34] target/i386/hvf: provide and use simulate_{wrmsr, rdmsr} in emul_ops Change the first argument's type to be CPUState to match other hooks. Signed-off-by: Wei Liu Link: https://lore.kernel.org/r/1741377325-28175-8-git-send-email-liuwe@linux.microsoft.com Signed-off-by: Paolo Bonzini --- target/i386/hvf/hvf-i386.h | 4 ++-- target/i386/hvf/hvf.c | 18 ++++++++++-------- target/i386/hvf/x86_emu.c | 4 ++-- target/i386/hvf/x86_emu.h | 2 ++ 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/target/i386/hvf/hvf-i386.h b/target/i386/hvf/hvf-i386.h index 044ad236ae..8c42ae6b01 100644 --- a/target/i386/hvf/hvf-i386.h +++ b/target/i386/hvf/hvf-i386.h @@ -19,8 +19,8 @@ uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx, int reg); void hvf_handle_io(CPUState *, uint16_t, void *, int, int, int); -void hvf_simulate_rdmsr(CPUX86State *env); -void hvf_simulate_wrmsr(CPUX86State *env); +void hvf_simulate_rdmsr(CPUState *cpu); +void hvf_simulate_wrmsr(CPUState *cpu); /* Host specific functions */ int hvf_inject_interrupt(CPUArchState *env, int vector); diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index e4f48a79fb..8c31d2e0cf 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -252,6 +252,8 @@ static const struct x86_emul_ops hvf_x86_emul_ops = { .write_mem = hvf_write_mem, .read_segment_descriptor = hvf_read_segment_descriptor, .handle_io = hvf_handle_io, + .simulate_rdmsr = hvf_simulate_rdmsr, + .simulate_wrmsr = hvf_simulate_wrmsr, }; int hvf_arch_init_vcpu(CPUState *cpu) @@ -506,10 +508,10 @@ void hvf_store_regs(CPUState *cs) macvm_set_rip(cs, env->eip); } -void hvf_simulate_rdmsr(CPUX86State *env) +void hvf_simulate_rdmsr(CPUState *cs) { - X86CPU *cpu = env_archcpu(env); - CPUState *cs = env_cpu(env); + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; uint32_t msr = ECX(env); uint64_t val = 0; @@ -611,10 +613,10 @@ void hvf_simulate_rdmsr(CPUX86State *env) RDX(env) = (uint32_t)(val >> 32); } -void hvf_simulate_wrmsr(CPUX86State *env) +void hvf_simulate_wrmsr(CPUState *cs) { - X86CPU *cpu = env_archcpu(env); - CPUState *cs = env_cpu(env); + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; uint32_t msr = ECX(env); uint64_t data = ((uint64_t)EDX(env) << 32) | EAX(env); @@ -900,9 +902,9 @@ int hvf_vcpu_exec(CPUState *cpu) { hvf_load_regs(cpu); if (exit_reason == EXIT_REASON_RDMSR) { - hvf_simulate_rdmsr(env); + hvf_simulate_rdmsr(cpu); } else { - hvf_simulate_wrmsr(env); + hvf_simulate_wrmsr(cpu); } env->eip += ins_len; hvf_store_regs(cpu); diff --git a/target/i386/hvf/x86_emu.c b/target/i386/hvf/x86_emu.c index 3ff41c35d8..aec7a8a3fa 100644 --- a/target/i386/hvf/x86_emu.c +++ b/target/i386/hvf/x86_emu.c @@ -672,13 +672,13 @@ void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_c static void exec_rdmsr(CPUX86State *env, struct x86_decode *decode) { - hvf_simulate_rdmsr(env); + emul_ops->simulate_rdmsr(env_cpu(env)); env->eip += decode->len; } static void exec_wrmsr(CPUX86State *env, struct x86_decode *decode) { - hvf_simulate_wrmsr(env); + emul_ops->simulate_wrmsr(env_cpu(env)); env->eip += decode->len; } diff --git a/target/i386/hvf/x86_emu.h b/target/i386/hvf/x86_emu.h index 107c1f1ac8..555b567e2c 100644 --- a/target/i386/hvf/x86_emu.h +++ b/target/i386/hvf/x86_emu.h @@ -30,6 +30,8 @@ struct x86_emul_ops { enum X86Seg seg); void (*handle_io)(CPUState *cpu, uint16_t port, void *data, int direction, int size, int count); + void (*simulate_rdmsr)(CPUState *cs); + void (*simulate_wrmsr)(CPUState *cs); }; extern const struct x86_emul_ops *emul_ops; From 7517ee9ec23801d4b6c4e5acbc0ad1bfa06c755a Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Fri, 7 Mar 2025 11:55:19 -0800 Subject: [PATCH 20/34] target/i386: rename lazy flags field and its type The same structure and code can be used by other accelerators. Drop the hvf prefix in the type and field name. No functional change. Signed-off-by: Wei Liu Link: https://lore.kernel.org/r/1741377325-28175-9-git-send-email-liuwe@linux.microsoft.com Signed-off-by: Paolo Bonzini --- target/i386/cpu.h | 6 ++-- target/i386/hvf/x86_flags.c | 56 ++++++++++++++++++------------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 3c5c39ce3d..119efc6c60 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1811,10 +1811,10 @@ typedef struct CPUCaches { CPUCacheInfo *l3_cache; } CPUCaches; -typedef struct HVFX86LazyFlags { +typedef struct X86LazyFlags { target_ulong result; target_ulong auxbits; -} HVFX86LazyFlags; +} X86LazyFlags; typedef struct CPUArchState { /* standard registers */ @@ -2108,7 +2108,7 @@ typedef struct CPUArchState { QemuMutex xen_timers_lock; #endif #if defined(CONFIG_HVF) - HVFX86LazyFlags hvf_lflags; + X86LazyFlags lflags; void *emu_mmio_buf; #endif diff --git a/target/i386/hvf/x86_flags.c b/target/i386/hvf/x86_flags.c index 0c75e0419c..84e27364a0 100644 --- a/target/i386/hvf/x86_flags.c +++ b/target/i386/hvf/x86_flags.c @@ -53,7 +53,7 @@ #define SET_FLAGS_OSZAPC_SIZE(size, lf_carries, lf_result) { \ target_ulong temp = ((lf_carries) & (LF_MASK_AF)) | \ (((lf_carries) >> (size - 2)) << LF_BIT_PO); \ - env->hvf_lflags.result = (target_ulong)(int##size##_t)(lf_result); \ + env->lflags.result = (target_ulong)(int##size##_t)(lf_result); \ if ((size) == 32) { \ temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \ } else if ((size) == 16) { \ @@ -63,7 +63,7 @@ } else { \ VM_PANIC("unimplemented"); \ } \ - env->hvf_lflags.auxbits = (target_ulong)(uint32_t)temp; \ + env->lflags.auxbits = (target_ulong)(uint32_t)temp; \ } /* carries, result */ @@ -90,10 +90,10 @@ } else { \ VM_PANIC("unimplemented"); \ } \ - env->hvf_lflags.result = (target_ulong)(int##size##_t)(lf_result); \ - target_ulong delta_c = (env->hvf_lflags.auxbits ^ temp) & LF_MASK_CF; \ + env->lflags.result = (target_ulong)(int##size##_t)(lf_result); \ + target_ulong delta_c = (env->lflags.auxbits ^ temp) & LF_MASK_CF; \ delta_c ^= (delta_c >> 1); \ - env->hvf_lflags.auxbits = (target_ulong)(uint32_t)(temp ^ delta_c); \ + env->lflags.auxbits = (target_ulong)(uint32_t)(temp ^ delta_c); \ } /* carries, result */ @@ -107,8 +107,8 @@ void SET_FLAGS_OxxxxC(CPUX86State *env, uint32_t new_of, uint32_t new_cf) { uint32_t temp_po = new_of ^ new_cf; - env->hvf_lflags.auxbits &= ~(LF_MASK_PO | LF_MASK_CF); - env->hvf_lflags.auxbits |= (temp_po << LF_BIT_PO) | (new_cf << LF_BIT_CF); + env->lflags.auxbits &= ~(LF_MASK_PO | LF_MASK_CF); + env->lflags.auxbits |= (temp_po << LF_BIT_PO) | (new_cf << LF_BIT_CF); } void SET_FLAGS_OSZAPC_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2, @@ -204,27 +204,27 @@ void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State *env, uint8_t v1, uint8_t v2, bool get_PF(CPUX86State *env) { - uint32_t temp = (255 & env->hvf_lflags.result); - temp = temp ^ (255 & (env->hvf_lflags.auxbits >> LF_BIT_PDB)); + uint32_t temp = (255 & env->lflags.result); + temp = temp ^ (255 & (env->lflags.auxbits >> LF_BIT_PDB)); temp = (temp ^ (temp >> 4)) & 0x0F; return (0x9669U >> temp) & 1; } void set_PF(CPUX86State *env, bool val) { - uint32_t temp = (255 & env->hvf_lflags.result) ^ (!val); - env->hvf_lflags.auxbits &= ~(LF_MASK_PDB); - env->hvf_lflags.auxbits |= (temp << LF_BIT_PDB); + uint32_t temp = (255 & env->lflags.result) ^ (!val); + env->lflags.auxbits &= ~(LF_MASK_PDB); + env->lflags.auxbits |= (temp << LF_BIT_PDB); } bool get_OF(CPUX86State *env) { - return ((env->hvf_lflags.auxbits + (1U << LF_BIT_PO)) >> LF_BIT_CF) & 1; + return ((env->lflags.auxbits + (1U << LF_BIT_PO)) >> LF_BIT_CF) & 1; } bool get_CF(CPUX86State *env) { - return (env->hvf_lflags.auxbits >> LF_BIT_CF) & 1; + return (env->lflags.auxbits >> LF_BIT_CF) & 1; } void set_OF(CPUX86State *env, bool val) @@ -241,45 +241,45 @@ void set_CF(CPUX86State *env, bool val) bool get_AF(CPUX86State *env) { - return (env->hvf_lflags.auxbits >> LF_BIT_AF) & 1; + return (env->lflags.auxbits >> LF_BIT_AF) & 1; } void set_AF(CPUX86State *env, bool val) { - env->hvf_lflags.auxbits &= ~(LF_MASK_AF); - env->hvf_lflags.auxbits |= val << LF_BIT_AF; + env->lflags.auxbits &= ~(LF_MASK_AF); + env->lflags.auxbits |= val << LF_BIT_AF; } bool get_ZF(CPUX86State *env) { - return !env->hvf_lflags.result; + return !env->lflags.result; } void set_ZF(CPUX86State *env, bool val) { if (val) { - env->hvf_lflags.auxbits ^= - (((env->hvf_lflags.result >> LF_SIGN_BIT) & 1) << LF_BIT_SD); + env->lflags.auxbits ^= + (((env->lflags.result >> LF_SIGN_BIT) & 1) << LF_BIT_SD); /* merge the parity bits into the Parity Delta Byte */ - uint32_t temp_pdb = (255 & env->hvf_lflags.result); - env->hvf_lflags.auxbits ^= (temp_pdb << LF_BIT_PDB); + uint32_t temp_pdb = (255 & env->lflags.result); + env->lflags.auxbits ^= (temp_pdb << LF_BIT_PDB); /* now zero the .result value */ - env->hvf_lflags.result = 0; + env->lflags.result = 0; } else { - env->hvf_lflags.result |= (1 << 8); + env->lflags.result |= (1 << 8); } } bool get_SF(CPUX86State *env) { - return ((env->hvf_lflags.result >> LF_SIGN_BIT) ^ - (env->hvf_lflags.auxbits >> LF_BIT_SD)) & 1; + return ((env->lflags.result >> LF_SIGN_BIT) ^ + (env->lflags.auxbits >> LF_BIT_SD)) & 1; } void set_SF(CPUX86State *env, bool val) { bool temp_sf = get_SF(env); - env->hvf_lflags.auxbits ^= (temp_sf ^ val) << LF_BIT_SD; + env->lflags.auxbits ^= (temp_sf ^ val) << LF_BIT_SD; } void lflags_to_rflags(CPUX86State *env) @@ -295,7 +295,7 @@ void lflags_to_rflags(CPUX86State *env) void rflags_to_lflags(CPUX86State *env) { - env->hvf_lflags.auxbits = env->hvf_lflags.result = 0; + env->lflags.auxbits = env->lflags.result = 0; set_OF(env, env->eflags & CC_O); set_SF(env, env->eflags & CC_S); set_ZF(env, env->eflags & CC_Z); From 3667f0bb58427edadc4a049080141d395b48fc29 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Fri, 7 Mar 2025 11:55:20 -0800 Subject: [PATCH 21/34] target/i386/hvf: drop unused headers Signed-off-by: Wei Liu Link: https://lore.kernel.org/r/1741377325-28175-10-git-send-email-liuwe@linux.microsoft.com Signed-off-by: Paolo Bonzini --- target/i386/hvf/x86_decode.c | 3 --- target/i386/hvf/x86_emu.c | 4 ---- 2 files changed, 7 deletions(-) diff --git a/target/i386/hvf/x86_decode.c b/target/i386/hvf/x86_decode.c index 728e159638..ddd7b60bcf 100644 --- a/target/i386/hvf/x86_decode.c +++ b/target/i386/hvf/x86_decode.c @@ -20,10 +20,7 @@ #include "panic.h" #include "x86_decode.h" -#include "vmx.h" #include "x86_emu.h" -#include "x86_mmu.h" -#include "x86_descr.h" #define OPCODE_ESCAPE 0xf diff --git a/target/i386/hvf/x86_emu.c b/target/i386/hvf/x86_emu.c index aec7a8a3fa..26a4876aac 100644 --- a/target/i386/hvf/x86_emu.c +++ b/target/i386/hvf/x86_emu.c @@ -40,11 +40,7 @@ #include "x86_decode.h" #include "x86.h" #include "x86_emu.h" -#include "x86_mmu.h" #include "x86_flags.h" -#include "vmcs.h" -#include "vmx.h" -#include "hvf-i386.h" #define EXEC_2OP_FLAGS_CMD(env, decode, cmd, FLAGS_FUNC, save_res) \ { \ From fb8ebedd2a9d2c2c098464dee4ec7bd1c8c463a1 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Fri, 7 Mar 2025 11:55:21 -0800 Subject: [PATCH 22/34] target/i386/hvf: rename some include guards These headers will be moved out to its own component. Signed-off-by: Wei Liu Link: https://lore.kernel.org/r/1741377325-28175-11-git-send-email-liuwe@linux.microsoft.com Signed-off-by: Paolo Bonzini --- target/i386/hvf/x86.h | 4 ++-- target/i386/hvf/x86_decode.h | 4 ++-- target/i386/hvf/x86_flags.h | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/target/i386/hvf/x86.h b/target/i386/hvf/x86.h index 063cd0b83e..73edccfba0 100644 --- a/target/i386/hvf/x86.h +++ b/target/i386/hvf/x86.h @@ -16,8 +16,8 @@ * License along with this program; if not, see . */ -#ifndef HVF_X86_H -#define HVF_X86_H +#ifndef X86_EMU_DEFS_H +#define X86_EMU_DEFS_H typedef struct x86_register { union { diff --git a/target/i386/hvf/x86_decode.h b/target/i386/hvf/x86_decode.h index a2d7a2a27b..930d965164 100644 --- a/target/i386/hvf/x86_decode.h +++ b/target/i386/hvf/x86_decode.h @@ -15,8 +15,8 @@ * License along with this program; if not, see . */ -#ifndef HVF_X86_DECODE_H -#define HVF_X86_DECODE_H +#ifndef X86_EMU_DECODE_H +#define X86_EMU_DECODE_H #include "cpu.h" #include "x86.h" diff --git a/target/i386/hvf/x86_flags.h b/target/i386/hvf/x86_flags.h index 75c2a7feab..6c175007b5 100644 --- a/target/i386/hvf/x86_flags.h +++ b/target/i386/hvf/x86_flags.h @@ -21,8 +21,8 @@ * x86 eflags functions */ -#ifndef X86_FLAGS_H -#define X86_FLAGS_H +#ifndef X86_EMU_FLAGS_H +#define X86_EMU_FLAGS_H #include "cpu.h" void lflags_to_rflags(CPUX86State *env); @@ -78,4 +78,4 @@ void SET_FLAGS_OSZAPC_LOGIC16(CPUX86State *env, uint16_t v1, uint16_t v2, void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State *env, uint8_t v1, uint8_t v2, uint8_t diff); -#endif /* X86_FLAGS_H */ +#endif /* X86_EMU_FLAGS_H */ From 5ffd2705f797ffe59165f3f29ad1065f648d6add Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Fri, 7 Mar 2025 11:55:22 -0800 Subject: [PATCH 23/34] target/i386: add a directory for x86 instruction emulator Signed-off-by: Wei Liu Link: https://lore.kernel.org/r/1741377325-28175-12-git-send-email-liuwe@linux.microsoft.com Signed-off-by: Paolo Bonzini --- target/i386/emulate/meson.build | 0 target/i386/meson.build | 1 + 2 files changed, 1 insertion(+) create mode 100644 target/i386/emulate/meson.build diff --git a/target/i386/emulate/meson.build b/target/i386/emulate/meson.build new file mode 100644 index 0000000000..e69de29bb2 diff --git a/target/i386/meson.build b/target/i386/meson.build index 2e9c472f49..c1aacea613 100644 --- a/target/i386/meson.build +++ b/target/i386/meson.build @@ -31,6 +31,7 @@ subdir('whpx') subdir('nvmm') subdir('hvf') subdir('tcg') +subdir('emulate') target_arch += {'i386': i386_ss} target_system_arch += {'i386': i386_system_ss} From 2d4f09523fd48bdb42a163e3b53a420c799217f3 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Fri, 7 Mar 2025 11:55:23 -0800 Subject: [PATCH 24/34] target/i386/emulate: add a panic.h The macros will be used by the instruction emulator. The code is the same as the one under hvf. Signed-off-by: Wei Liu Link: https://lore.kernel.org/r/1741377325-28175-13-git-send-email-liuwe@linux.microsoft.com Signed-off-by: Paolo Bonzini --- target/i386/emulate/panic.h | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 target/i386/emulate/panic.h diff --git a/target/i386/emulate/panic.h b/target/i386/emulate/panic.h new file mode 100644 index 0000000000..71c24874ba --- /dev/null +++ b/target/i386/emulate/panic.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016 Veertu Inc, + * Copyright (C) 2017 Google Inc, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ +#ifndef X86_EMU_PANIC_H +#define X86_EMU_PANIC_H + +#define VM_PANIC(x) {\ + printf("%s\n", x); \ + abort(); \ +} + +#define VM_PANIC_ON(x) {\ + if (x) { \ + printf("%s\n", #x); \ + abort(); \ + } \ +} + +#define VM_PANIC_EX(...) {\ + printf(__VA_ARGS__); \ + abort(); \ +} + +#define VM_PANIC_ON_EX(x, ...) {\ + if (x) { \ + printf(__VA_ARGS__); \ + abort(); \ + } \ +} + +#endif From 27458df871097d7fc14b19d9e01c35d29737b9b3 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Fri, 7 Mar 2025 11:55:24 -0800 Subject: [PATCH 25/34] target/i386: move x86 instruction emulator out of hvf Move x86_decode, x86_emu, x86_flags and some headers to the new location. Fix up all the inclusion sites in hvf. Signed-off-by: Wei Liu Link: https://lore.kernel.org/r/1741377325-28175-14-git-send-email-liuwe@linux.microsoft.com Signed-off-by: Paolo Bonzini --- target/i386/emulate/meson.build | 5 +++++ target/i386/{hvf => emulate}/x86.h | 0 target/i386/{hvf => emulate}/x86_decode.c | 0 target/i386/{hvf => emulate}/x86_decode.h | 0 target/i386/{hvf => emulate}/x86_emu.c | 0 target/i386/{hvf => emulate}/x86_emu.h | 0 target/i386/{hvf => emulate}/x86_flags.c | 0 target/i386/{hvf => emulate}/x86_flags.h | 0 target/i386/hvf/hvf.c | 8 ++++---- target/i386/hvf/meson.build | 3 --- target/i386/hvf/vmx.h | 2 +- target/i386/hvf/x86.c | 4 ++-- target/i386/hvf/x86_cpuid.c | 2 +- target/i386/hvf/x86_descr.h | 2 +- target/i386/hvf/x86_mmu.c | 2 +- target/i386/hvf/x86_task.c | 6 +++--- target/i386/hvf/x86hvf.c | 2 +- 17 files changed, 19 insertions(+), 17 deletions(-) rename target/i386/{hvf => emulate}/x86.h (100%) rename target/i386/{hvf => emulate}/x86_decode.c (100%) rename target/i386/{hvf => emulate}/x86_decode.h (100%) rename target/i386/{hvf => emulate}/x86_emu.c (100%) rename target/i386/{hvf => emulate}/x86_emu.h (100%) rename target/i386/{hvf => emulate}/x86_flags.c (100%) rename target/i386/{hvf => emulate}/x86_flags.h (100%) diff --git a/target/i386/emulate/meson.build b/target/i386/emulate/meson.build index e69de29bb2..4edd4f462f 100644 --- a/target/i386/emulate/meson.build +++ b/target/i386/emulate/meson.build @@ -0,0 +1,5 @@ +i386_system_ss.add(when: [hvf, 'CONFIG_HVF'], if_true: files( + 'x86_decode.c', + 'x86_emu.c', + 'x86_flags.c', +)) diff --git a/target/i386/hvf/x86.h b/target/i386/emulate/x86.h similarity index 100% rename from target/i386/hvf/x86.h rename to target/i386/emulate/x86.h diff --git a/target/i386/hvf/x86_decode.c b/target/i386/emulate/x86_decode.c similarity index 100% rename from target/i386/hvf/x86_decode.c rename to target/i386/emulate/x86_decode.c diff --git a/target/i386/hvf/x86_decode.h b/target/i386/emulate/x86_decode.h similarity index 100% rename from target/i386/hvf/x86_decode.h rename to target/i386/emulate/x86_decode.h diff --git a/target/i386/hvf/x86_emu.c b/target/i386/emulate/x86_emu.c similarity index 100% rename from target/i386/hvf/x86_emu.c rename to target/i386/emulate/x86_emu.c diff --git a/target/i386/hvf/x86_emu.h b/target/i386/emulate/x86_emu.h similarity index 100% rename from target/i386/hvf/x86_emu.h rename to target/i386/emulate/x86_emu.h diff --git a/target/i386/hvf/x86_flags.c b/target/i386/emulate/x86_flags.c similarity index 100% rename from target/i386/hvf/x86_flags.c rename to target/i386/emulate/x86_flags.c diff --git a/target/i386/hvf/x86_flags.h b/target/i386/emulate/x86_flags.h similarity index 100% rename from target/i386/hvf/x86_flags.h rename to target/i386/emulate/x86_flags.h diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index 8c31d2e0cf..23ebf2550a 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -59,12 +59,12 @@ #include "hvf-i386.h" #include "vmcs.h" #include "vmx.h" -#include "x86.h" +#include "emulate/x86.h" #include "x86_descr.h" -#include "x86_flags.h" +#include "emulate/x86_flags.h" #include "x86_mmu.h" -#include "x86_decode.h" -#include "x86_emu.h" +#include "emulate/x86_decode.h" +#include "emulate/x86_emu.h" #include "x86_task.h" #include "x86hvf.h" diff --git a/target/i386/hvf/meson.build b/target/i386/hvf/meson.build index 05c3c8cf18..519d190f0e 100644 --- a/target/i386/hvf/meson.build +++ b/target/i386/hvf/meson.build @@ -2,10 +2,7 @@ i386_system_ss.add(when: [hvf, 'CONFIG_HVF'], if_true: files( 'hvf.c', 'x86.c', 'x86_cpuid.c', - 'x86_decode.c', 'x86_descr.c', - 'x86_emu.c', - 'x86_flags.c', 'x86_mmu.c', 'x86_task.c', 'x86hvf.c', diff --git a/target/i386/hvf/vmx.h b/target/i386/hvf/vmx.h index 80ce26279b..3c56afc9d3 100644 --- a/target/i386/hvf/vmx.h +++ b/target/i386/hvf/vmx.h @@ -29,7 +29,7 @@ #include #include "vmcs.h" #include "cpu.h" -#include "x86.h" +#include "emulate/x86.h" #include "system/hvf.h" #include "system/hvf_int.h" diff --git a/target/i386/hvf/x86.c b/target/i386/hvf/x86.c index a0ede13886..5c75ec9a00 100644 --- a/target/i386/hvf/x86.c +++ b/target/i386/hvf/x86.c @@ -19,8 +19,8 @@ #include "qemu/osdep.h" #include "cpu.h" -#include "x86_decode.h" -#include "x86_emu.h" +#include "emulate/x86_decode.h" +#include "emulate/x86_emu.h" #include "vmcs.h" #include "vmx.h" #include "x86_mmu.h" diff --git a/target/i386/hvf/x86_cpuid.c b/target/i386/hvf/x86_cpuid.c index ae836f65cc..fa131b18c6 100644 --- a/target/i386/hvf/x86_cpuid.c +++ b/target/i386/hvf/x86_cpuid.c @@ -24,7 +24,7 @@ #include "qemu/cpuid.h" #include "host/cpuinfo.h" #include "cpu.h" -#include "x86.h" +#include "emulate/x86.h" #include "vmx.h" #include "system/hvf.h" #include "hvf-i386.h" diff --git a/target/i386/hvf/x86_descr.h b/target/i386/hvf/x86_descr.h index ce5de98349..24af4946cd 100644 --- a/target/i386/hvf/x86_descr.h +++ b/target/i386/hvf/x86_descr.h @@ -19,7 +19,7 @@ #ifndef HVF_X86_DESCR_H #define HVF_X86_DESCR_H -#include "x86.h" +#include "emulate/x86.h" typedef struct vmx_segment { uint16_t sel; diff --git a/target/i386/hvf/x86_mmu.c b/target/i386/hvf/x86_mmu.c index 579d0c3a4c..afc5c17d5d 100644 --- a/target/i386/hvf/x86_mmu.c +++ b/target/i386/hvf/x86_mmu.c @@ -19,7 +19,7 @@ #include "qemu/osdep.h" #include "panic.h" #include "cpu.h" -#include "x86.h" +#include "emulate/x86.h" #include "x86_mmu.h" #include "vmcs.h" #include "vmx.h" diff --git a/target/i386/hvf/x86_task.c b/target/i386/hvf/x86_task.c index 161217991f..bdf8b51ae6 100644 --- a/target/i386/hvf/x86_task.c +++ b/target/i386/hvf/x86_task.c @@ -14,11 +14,11 @@ #include "hvf-i386.h" #include "vmcs.h" #include "vmx.h" -#include "x86.h" +#include "emulate/x86.h" #include "x86_descr.h" #include "x86_mmu.h" -#include "x86_decode.h" -#include "x86_emu.h" +#include "emulate/x86_decode.h" +#include "emulate/x86_emu.h" #include "x86_task.h" #include "x86hvf.h" diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c index 531a340b37..2057314892 100644 --- a/target/i386/hvf/x86hvf.c +++ b/target/i386/hvf/x86hvf.c @@ -24,7 +24,7 @@ #include "vmcs.h" #include "cpu.h" #include "x86_descr.h" -#include "x86_decode.h" +#include "emulate/x86_decode.h" #include "system/hw_accel.h" #include "hw/i386/apic_internal.h" From 6aa0d0391c56e411d43bbf9f9c6acd1fea6f55c4 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Fri, 7 Mar 2025 11:55:25 -0800 Subject: [PATCH 26/34] MAINTAINERS: add an entry for the x86 instruction emulator Add myself as a reviewer. Signed-off-by: Wei Liu Link: https://lore.kernel.org/r/1741377325-28175-15-git-send-email-liuwe@linux.microsoft.com Signed-off-by: Paolo Bonzini --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index d54b5578f8..67228401f0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -534,6 +534,14 @@ S: Supported F: target/i386/whpx/ F: include/system/whpx.h +X86 Instruction Emulator +M: Cameron Esfahani +M: Roman Bolshakov +R: Phil Dennis-Jordan +R: Wei Liu +S: Maintained +F: target/i386/emulate/ + Guest CPU Cores (Xen) --------------------- X86 Xen CPUs From c901905ea6703a2feb5867537a8559dc129447f7 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Apr 2025 21:45:36 +0200 Subject: [PATCH 27/34] target/i386/emulate: remove flags_mask The field is written but never read. Cc: Wei Liu Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/emulate/x86_decode.c | 864 +++++++++++++++---------------- target/i386/emulate/x86_decode.h | 2 - 2 files changed, 424 insertions(+), 442 deletions(-) diff --git a/target/i386/emulate/x86_decode.c b/target/i386/emulate/x86_decode.c index ddd7b60bcf..7fee219687 100644 --- a/target/i386/emulate/x86_decode.c +++ b/target/i386/emulate/x86_decode.c @@ -429,7 +429,6 @@ struct decode_tbl { void (*decode_op4)(CPUX86State *env, struct x86_decode *decode, struct x86_decode_op *op4); void (*decode_postfix)(CPUX86State *env, struct x86_decode *decode); - uint32_t flags_mask; }; struct decode_x87_tbl { @@ -445,7 +444,6 @@ struct decode_x87_tbl { void (*decode_op2)(CPUX86State *env, struct x86_decode *decode, struct x86_decode_op *op2); void (*decode_postfix)(CPUX86State *env, struct x86_decode *decode); - uint32_t flags_mask; }; struct decode_tbl invl_inst = {0x0, 0, 0, false, NULL, NULL, NULL, NULL, @@ -470,7 +468,6 @@ static void decode_x87_ins(CPUX86State *env, struct x86_decode *decode) if (decoder->operand_size) { decode->operand_size = decoder->operand_size; } - decode->flags_mask = decoder->flags_mask; decode->fpop_stack = decoder->pop; decode->frev = decoder->rev; @@ -503,9 +500,6 @@ static void decode_ffgroup(CPUX86State *env, struct x86_decode *decode) X86_DECODE_CMD_INVL }; decode->cmd = group[decode->modrm.reg]; - if (decode->modrm.reg > 2) { - decode->flags_mask = 0; - } } static void decode_sldtgroup(CPUX86State *env, struct x86_decode *decode) @@ -693,733 +687,724 @@ static void decode_db_4(CPUX86State *env, struct x86_decode *decode) } -#define RFLAGS_MASK_NONE 0 -#define RFLAGS_MASK_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C) -#define RFLAGS_MASK_LAHF (CC_S | CC_Z | CC_A | CC_P | CC_C) -#define RFLAGS_MASK_CF (CC_C) -#define RFLAGS_MASK_IF (IF_MASK) -#define RFLAGS_MASK_TF (TF_MASK) -#define RFLAGS_MASK_DF (DF_MASK) -#define RFLAGS_MASK_ZF (CC_Z) - struct decode_tbl _1op_inst[] = { {0x0, X86_DECODE_CMD_ADD, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, - NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL}, {0x1, X86_DECODE_CMD_ADD, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, - NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL}, {0x2, X86_DECODE_CMD_ADD, 1, true, decode_modrm_reg, decode_modrm_rm, NULL, - NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL}, {0x3, X86_DECODE_CMD_ADD, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, - NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL}, {0x4, X86_DECODE_CMD_ADD, 1, false, decode_rax, decode_imm8, NULL, NULL, - NULL, RFLAGS_MASK_OSZAPC}, + NULL}, {0x5, X86_DECODE_CMD_ADD, 0, false, decode_rax, decode_imm, NULL, NULL, - NULL, RFLAGS_MASK_OSZAPC}, + NULL}, {0x6, X86_DECODE_CMD_PUSH_SEG, 0, false, false, NULL, NULL, NULL, - decode_pushseg, RFLAGS_MASK_NONE}, + decode_pushseg}, {0x7, X86_DECODE_CMD_POP_SEG, 0, false, false, NULL, NULL, NULL, - decode_popseg, RFLAGS_MASK_NONE}, + decode_popseg}, {0x8, X86_DECODE_CMD_OR, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, - NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL}, {0x9, X86_DECODE_CMD_OR, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, - NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL}, {0xa, X86_DECODE_CMD_OR, 1, true, decode_modrm_reg, decode_modrm_rm, NULL, - NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL}, {0xb, X86_DECODE_CMD_OR, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0xc, X86_DECODE_CMD_OR, 1, false, decode_rax, decode_imm8, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0xd, X86_DECODE_CMD_OR, 0, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0xe, X86_DECODE_CMD_PUSH_SEG, 0, false, false, - NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_pushseg}, {0xf, X86_DECODE_CMD_POP_SEG, 0, false, false, - NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_popseg}, {0x10, X86_DECODE_CMD_ADC, 1, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x11, X86_DECODE_CMD_ADC, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x12, X86_DECODE_CMD_ADC, 1, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x13, X86_DECODE_CMD_ADC, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x14, X86_DECODE_CMD_ADC, 1, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x15, X86_DECODE_CMD_ADC, 0, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x16, X86_DECODE_CMD_PUSH_SEG, 0, false, false, - NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_pushseg}, {0x17, X86_DECODE_CMD_POP_SEG, 0, false, false, - NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_popseg}, {0x18, X86_DECODE_CMD_SBB, 1, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x19, X86_DECODE_CMD_SBB, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x1a, X86_DECODE_CMD_SBB, 1, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x1b, X86_DECODE_CMD_SBB, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x1c, X86_DECODE_CMD_SBB, 1, false, decode_rax, decode_imm8, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x1d, X86_DECODE_CMD_SBB, 0, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x1e, X86_DECODE_CMD_PUSH_SEG, 0, false, false, - NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_pushseg}, {0x1f, X86_DECODE_CMD_POP_SEG, 0, false, false, - NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_popseg}, {0x20, X86_DECODE_CMD_AND, 1, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x21, X86_DECODE_CMD_AND, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x22, X86_DECODE_CMD_AND, 1, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x23, X86_DECODE_CMD_AND, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x24, X86_DECODE_CMD_AND, 1, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x25, X86_DECODE_CMD_AND, 0, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x28, X86_DECODE_CMD_SUB, 1, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x29, X86_DECODE_CMD_SUB, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x2a, X86_DECODE_CMD_SUB, 1, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x2b, X86_DECODE_CMD_SUB, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x2c, X86_DECODE_CMD_SUB, 1, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x2d, X86_DECODE_CMD_SUB, 0, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x2f, X86_DECODE_CMD_DAS, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, NULL}, {0x30, X86_DECODE_CMD_XOR, 1, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x31, X86_DECODE_CMD_XOR, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x32, X86_DECODE_CMD_XOR, 1, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x33, X86_DECODE_CMD_XOR, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x34, X86_DECODE_CMD_XOR, 1, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x35, X86_DECODE_CMD_XOR, 0, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x38, X86_DECODE_CMD_CMP, 1, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x39, X86_DECODE_CMD_CMP, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x3a, X86_DECODE_CMD_CMP, 1, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x3b, X86_DECODE_CMD_CMP, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x3c, X86_DECODE_CMD_CMP, 1, false, decode_rax, decode_imm8, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x3d, X86_DECODE_CMD_CMP, 0, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x3f, X86_DECODE_CMD_AAS, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, NULL}, {0x40, X86_DECODE_CMD_INC, 0, false, - NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, decode_incgroup}, {0x41, X86_DECODE_CMD_INC, 0, false, - NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, decode_incgroup}, {0x42, X86_DECODE_CMD_INC, 0, false, - NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, decode_incgroup}, {0x43, X86_DECODE_CMD_INC, 0, false, - NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, decode_incgroup}, {0x44, X86_DECODE_CMD_INC, 0, false, - NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, decode_incgroup}, {0x45, X86_DECODE_CMD_INC, 0, false, - NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, decode_incgroup}, {0x46, X86_DECODE_CMD_INC, 0, false, - NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, decode_incgroup}, {0x47, X86_DECODE_CMD_INC, 0, false, - NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, decode_incgroup}, {0x48, X86_DECODE_CMD_DEC, 0, false, - NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, decode_decgroup}, {0x49, X86_DECODE_CMD_DEC, 0, false, - NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, decode_decgroup}, {0x4a, X86_DECODE_CMD_DEC, 0, false, - NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, decode_decgroup}, {0x4b, X86_DECODE_CMD_DEC, 0, false, - NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, decode_decgroup}, {0x4c, X86_DECODE_CMD_DEC, 0, false, - NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, decode_decgroup}, {0x4d, X86_DECODE_CMD_DEC, 0, false, - NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, decode_decgroup}, {0x4e, X86_DECODE_CMD_DEC, 0, false, - NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, decode_decgroup}, {0x4f, X86_DECODE_CMD_DEC, 0, false, - NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, decode_decgroup}, {0x50, X86_DECODE_CMD_PUSH, 0, false, - NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_pushgroup}, {0x51, X86_DECODE_CMD_PUSH, 0, false, - NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_pushgroup}, {0x52, X86_DECODE_CMD_PUSH, 0, false, - NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_pushgroup}, {0x53, X86_DECODE_CMD_PUSH, 0, false, - NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_pushgroup}, {0x54, X86_DECODE_CMD_PUSH, 0, false, - NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_pushgroup}, {0x55, X86_DECODE_CMD_PUSH, 0, false, - NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_pushgroup}, {0x56, X86_DECODE_CMD_PUSH, 0, false, - NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_pushgroup}, {0x57, X86_DECODE_CMD_PUSH, 0, false, - NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_pushgroup}, {0x58, X86_DECODE_CMD_POP, 0, false, - NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_popgroup}, {0x59, X86_DECODE_CMD_POP, 0, false, - NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_popgroup}, {0x5a, X86_DECODE_CMD_POP, 0, false, - NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_popgroup}, {0x5b, X86_DECODE_CMD_POP, 0, false, - NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_popgroup}, {0x5c, X86_DECODE_CMD_POP, 0, false, - NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_popgroup}, {0x5d, X86_DECODE_CMD_POP, 0, false, - NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_popgroup}, {0x5e, X86_DECODE_CMD_POP, 0, false, - NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_popgroup}, {0x5f, X86_DECODE_CMD_POP, 0, false, - NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_popgroup}, {0x60, X86_DECODE_CMD_PUSHA, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, NULL}, {0x61, X86_DECODE_CMD_POPA, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, NULL}, {0x68, X86_DECODE_CMD_PUSH, 0, false, decode_imm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0x6a, X86_DECODE_CMD_PUSH, 0, false, decode_imm8_signed, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0x69, X86_DECODE_CMD_IMUL_3, 0, true, decode_modrm_reg, - decode_modrm_rm, decode_imm, NULL, NULL, RFLAGS_MASK_OSZAPC}, + decode_modrm_rm, decode_imm, NULL, NULL}, {0x6b, X86_DECODE_CMD_IMUL_3, 0, true, decode_modrm_reg, decode_modrm_rm, - decode_imm8_signed, NULL, NULL, RFLAGS_MASK_OSZAPC}, + decode_imm8_signed, NULL, NULL}, {0x6c, X86_DECODE_CMD_INS, 1, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, NULL}, {0x6d, X86_DECODE_CMD_INS, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, NULL}, {0x6e, X86_DECODE_CMD_OUTS, 1, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, NULL}, {0x6f, X86_DECODE_CMD_OUTS, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, NULL}, {0x70, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x71, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x72, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x73, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x74, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x75, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x76, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x77, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x78, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x79, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x7a, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x7b, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x7c, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x7d, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x7e, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x7f, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x80, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8, - NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, decode_addgroup}, {0x81, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm, - NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, decode_addgroup}, {0x82, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8, - NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, decode_addgroup}, {0x83, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8_signed, - NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, decode_addgroup}, {0x84, X86_DECODE_CMD_TST, 1, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x85, X86_DECODE_CMD_TST, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0x86, X86_DECODE_CMD_XCHG, 1, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x87, X86_DECODE_CMD_XCHG, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x88, X86_DECODE_CMD_MOV, 1, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x89, X86_DECODE_CMD_MOV, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x8a, X86_DECODE_CMD_MOV, 1, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x8b, X86_DECODE_CMD_MOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x8c, X86_DECODE_CMD_MOV_FROM_SEG, 0, true, decode_modrm_rm, - decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + decode_modrm_reg, NULL, NULL, NULL}, {0x8d, X86_DECODE_CMD_LEA, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x8e, X86_DECODE_CMD_MOV_TO_SEG, 0, true, decode_modrm_reg, - decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + decode_modrm_rm, NULL, NULL, NULL}, {0x8f, X86_DECODE_CMD_POP, 0, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0x90, X86_DECODE_CMD_NOP, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, NULL}, {0x91, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, - NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + NULL, NULL, decode_xchgroup}, {0x92, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, - NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + NULL, NULL, decode_xchgroup}, {0x93, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, - NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + NULL, NULL, decode_xchgroup}, {0x94, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, - NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + NULL, NULL, decode_xchgroup}, {0x95, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, - NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + NULL, NULL, decode_xchgroup}, {0x96, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, - NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + NULL, NULL, decode_xchgroup}, {0x97, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, - NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + NULL, NULL, decode_xchgroup}, {0x98, X86_DECODE_CMD_CBW, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x99, X86_DECODE_CMD_CWD, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x9a, X86_DECODE_CMD_CALL_FAR, 0, false, NULL, - NULL, NULL, NULL, decode_farjmp, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_farjmp}, {0x9c, X86_DECODE_CMD_PUSHF, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, /*{0x9d, X86_DECODE_CMD_POPF, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_POPF},*/ + NULL, NULL, NULL},*/ {0x9e, X86_DECODE_CMD_SAHF, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x9f, X86_DECODE_CMD_LAHF, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_LAHF}, + NULL, NULL, NULL}, {0xa0, X86_DECODE_CMD_MOV, 1, false, decode_rax, fetch_moffs, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xa1, X86_DECODE_CMD_MOV, 0, false, decode_rax, fetch_moffs, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xa2, X86_DECODE_CMD_MOV, 1, false, fetch_moffs, decode_rax, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xa3, X86_DECODE_CMD_MOV, 0, false, fetch_moffs, decode_rax, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xa4, X86_DECODE_CMD_MOVS, 1, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xa5, X86_DECODE_CMD_MOVS, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xa6, X86_DECODE_CMD_CMPS, 1, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0xa7, X86_DECODE_CMD_CMPS, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0xaa, X86_DECODE_CMD_STOS, 1, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xab, X86_DECODE_CMD_STOS, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xac, X86_DECODE_CMD_LODS, 1, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xad, X86_DECODE_CMD_LODS, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xae, X86_DECODE_CMD_SCAS, 1, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0xaf, X86_DECODE_CMD_SCAS, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0xa8, X86_DECODE_CMD_TST, 1, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0xa9, X86_DECODE_CMD_TST, 0, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0xb0, X86_DECODE_CMD_MOV, 1, false, NULL, - NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_movgroup8}, {0xb1, X86_DECODE_CMD_MOV, 1, false, NULL, - NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_movgroup8}, {0xb2, X86_DECODE_CMD_MOV, 1, false, NULL, - NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_movgroup8}, {0xb3, X86_DECODE_CMD_MOV, 1, false, NULL, - NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_movgroup8}, {0xb4, X86_DECODE_CMD_MOV, 1, false, NULL, - NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_movgroup8}, {0xb5, X86_DECODE_CMD_MOV, 1, false, NULL, - NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_movgroup8}, {0xb6, X86_DECODE_CMD_MOV, 1, false, NULL, - NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_movgroup8}, {0xb7, X86_DECODE_CMD_MOV, 1, false, NULL, - NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_movgroup8}, {0xb8, X86_DECODE_CMD_MOV, 0, false, NULL, - NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_movgroup}, {0xb9, X86_DECODE_CMD_MOV, 0, false, NULL, - NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_movgroup}, {0xba, X86_DECODE_CMD_MOV, 0, false, NULL, - NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_movgroup}, {0xbb, X86_DECODE_CMD_MOV, 0, false, NULL, - NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_movgroup}, {0xbc, X86_DECODE_CMD_MOV, 0, false, NULL, - NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_movgroup}, {0xbd, X86_DECODE_CMD_MOV, 0, false, NULL, - NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_movgroup}, {0xbe, X86_DECODE_CMD_MOV, 0, false, NULL, - NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_movgroup}, {0xbf, X86_DECODE_CMD_MOV, 0, false, NULL, - NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_movgroup}, {0xc0, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8, - NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, decode_rotgroup}, {0xc1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8, - NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, decode_rotgroup}, {0xc2, X86_DECODE_RET_NEAR, 0, false, decode_imm16, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0xc3, X86_DECODE_RET_NEAR, 0, false, NULL, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0xc4, X86_DECODE_CMD_LES, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xc5, X86_DECODE_CMD_LDS, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xc6, X86_DECODE_CMD_MOV, 1, true, decode_modrm_rm, decode_imm8, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xc7, X86_DECODE_CMD_MOV, 0, true, decode_modrm_rm, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xc8, X86_DECODE_CMD_ENTER, 0, false, decode_imm16, decode_imm8, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xc9, X86_DECODE_CMD_LEAVE, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xca, X86_DECODE_RET_FAR, 0, false, decode_imm16, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xcb, X86_DECODE_RET_FAR, 0, false, decode_imm_0, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xcd, X86_DECODE_CMD_INT, 0, false, decode_imm8, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, /*{0xcf, X86_DECODE_CMD_IRET, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_IRET},*/ + NULL, NULL, NULL},*/ {0xd0, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm_1, - NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, decode_rotgroup}, {0xd1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm_1, - NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, decode_rotgroup}, {0xd2, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_rcx, - NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, decode_rotgroup}, {0xd3, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_rcx, - NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, decode_rotgroup}, {0xd4, X86_DECODE_CMD_AAM, 0, false, decode_imm8, - NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL}, {0xd5, X86_DECODE_CMD_AAD, 0, false, decode_imm8, - NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL}, {0xd7, X86_DECODE_CMD_XLAT, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, NULL}, {0xd8, X86_DECODE_CMD_INVL, 0, true, NULL, - NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_x87_ins}, {0xd9, X86_DECODE_CMD_INVL, 0, true, NULL, - NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_x87_ins}, {0xda, X86_DECODE_CMD_INVL, 0, true, NULL, - NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_x87_ins}, {0xdb, X86_DECODE_CMD_INVL, 0, true, NULL, - NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_x87_ins}, {0xdc, X86_DECODE_CMD_INVL, 0, true, NULL, - NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_x87_ins}, {0xdd, X86_DECODE_CMD_INVL, 0, true, NULL, - NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_x87_ins}, {0xde, X86_DECODE_CMD_INVL, 0, true, NULL, - NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_x87_ins}, {0xdf, X86_DECODE_CMD_INVL, 0, true, NULL, - NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_x87_ins}, {0xe0, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0xe1, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0xe2, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0xe3, X86_DECODE_CMD_JCXZ, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0xe4, X86_DECODE_CMD_IN, 1, false, decode_imm8, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0xe5, X86_DECODE_CMD_IN, 0, false, decode_imm8, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0xe6, X86_DECODE_CMD_OUT, 1, false, decode_imm8, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0xe7, X86_DECODE_CMD_OUT, 0, false, decode_imm8, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0xe8, X86_DECODE_CMD_CALL_NEAR, 0, false, decode_imm_signed, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0xe9, X86_DECODE_CMD_JMP_NEAR, 0, false, decode_imm_signed, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0xea, X86_DECODE_CMD_JMP_FAR, 0, false, - NULL, NULL, NULL, NULL, decode_farjmp, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_farjmp}, {0xeb, X86_DECODE_CMD_JMP_NEAR, 1, false, decode_imm8_signed, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0xec, X86_DECODE_CMD_IN, 1, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, NULL}, {0xed, X86_DECODE_CMD_IN, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, NULL}, {0xee, X86_DECODE_CMD_OUT, 1, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, NULL}, {0xef, X86_DECODE_CMD_OUT, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, NULL}, {0xf4, X86_DECODE_CMD_HLT, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, NULL}, {0xf5, X86_DECODE_CMD_CMC, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF}, + NULL, NULL, NULL, NULL, NULL}, {0xf6, X86_DECODE_CMD_INVL, 1, true, - NULL, NULL, NULL, NULL, decode_f7group, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, decode_f7group}, {0xf7, X86_DECODE_CMD_INVL, 0, true, - NULL, NULL, NULL, NULL, decode_f7group, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, NULL, decode_f7group}, {0xf8, X86_DECODE_CMD_CLC, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF}, + NULL, NULL, NULL, NULL, NULL}, {0xf9, X86_DECODE_CMD_STC, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF}, + NULL, NULL, NULL, NULL, NULL}, {0xfa, X86_DECODE_CMD_CLI, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_IF}, + NULL, NULL, NULL, NULL, NULL}, {0xfb, X86_DECODE_CMD_STI, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_IF}, + NULL, NULL, NULL, NULL, NULL}, {0xfc, X86_DECODE_CMD_CLD, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_DF}, + NULL, NULL, NULL, NULL, NULL}, {0xfd, X86_DECODE_CMD_STD, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_DF}, + NULL, NULL, NULL, NULL, NULL}, {0xfe, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, - NULL, NULL, NULL, decode_incgroup2, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, decode_incgroup2}, {0xff, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, - NULL, NULL, NULL, decode_ffgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL, decode_ffgroup}, }; struct decode_tbl _2op_inst[] = { {0x0, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, - NULL, NULL, NULL, decode_sldtgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_sldtgroup}, {0x1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, - NULL, NULL, NULL, decode_lidtgroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_lidtgroup}, {0x6, X86_DECODE_CMD_CLTS, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_TF}, + NULL, NULL, NULL, NULL, NULL}, {0x9, X86_DECODE_CMD_WBINVD, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, NULL}, {0x18, X86_DECODE_CMD_PREFETCH, 0, true, - NULL, NULL, NULL, NULL, decode_x87_general, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_x87_general}, {0x1f, X86_DECODE_CMD_NOP, 0, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0x20, X86_DECODE_CMD_MOV_FROM_CR, 0, true, decode_modrm_rm, - decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + decode_modrm_reg, NULL, NULL, NULL}, {0x21, X86_DECODE_CMD_MOV_FROM_DR, 0, true, decode_modrm_rm, - decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + decode_modrm_reg, NULL, NULL, NULL}, {0x22, X86_DECODE_CMD_MOV_TO_CR, 0, true, decode_modrm_reg, - decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + decode_modrm_rm, NULL, NULL, NULL}, {0x23, X86_DECODE_CMD_MOV_TO_DR, 0, true, decode_modrm_reg, - decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + decode_modrm_rm, NULL, NULL, NULL}, {0x30, X86_DECODE_CMD_WRMSR, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, NULL}, {0x31, X86_DECODE_CMD_RDTSC, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, NULL}, {0x32, X86_DECODE_CMD_RDMSR, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, NULL}, {0x40, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x41, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x42, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x43, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x44, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x45, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x46, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x47, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x48, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x49, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x4a, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x4b, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x4c, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x4d, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x4e, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x4f, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0x77, X86_DECODE_CMD_EMMS, 0, false, - NULL, NULL, NULL, NULL, decode_x87_general, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_x87_general}, {0x82, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x83, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x84, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x85, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x86, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x87, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x88, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x89, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x8a, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x8b, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x8c, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x8d, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x8e, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x8f, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_jxx}, {0x90, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0x91, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0x92, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0x93, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0x94, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0x95, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0x96, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0x97, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0x98, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0x99, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0x9a, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0x9b, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0x9c, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0x9d, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0x9e, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0x9f, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL}, {0xb0, X86_DECODE_CMD_CMPXCHG, 1, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xb1, X86_DECODE_CMD_CMPXCHG, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xb6, X86_DECODE_CMD_MOVZX, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xb7, X86_DECODE_CMD_MOVZX, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xb8, X86_DECODE_CMD_POPCNT, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0xbe, X86_DECODE_CMD_MOVSX, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xbf, X86_DECODE_CMD_MOVSX, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xa0, X86_DECODE_CMD_PUSH_SEG, 0, false, false, - NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_pushseg}, {0xa1, X86_DECODE_CMD_POP_SEG, 0, false, false, - NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_popseg}, {0xa2, X86_DECODE_CMD_CPUID, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, NULL}, {0xa3, X86_DECODE_CMD_BT, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_CF}, + NULL, NULL, NULL}, {0xa4, X86_DECODE_CMD_SHLD, 0, true, decode_modrm_rm, decode_modrm_reg, - decode_imm8, NULL, NULL, RFLAGS_MASK_OSZAPC}, + decode_imm8, NULL, NULL}, {0xa5, X86_DECODE_CMD_SHLD, 0, true, decode_modrm_rm, decode_modrm_reg, - decode_rcx, NULL, NULL, RFLAGS_MASK_OSZAPC}, + decode_rcx, NULL, NULL}, {0xa8, X86_DECODE_CMD_PUSH_SEG, 0, false, false, - NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_pushseg}, {0xa9, X86_DECODE_CMD_POP_SEG, 0, false, false, - NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_popseg}, {0xab, X86_DECODE_CMD_BTS, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_CF}, + NULL, NULL, NULL}, {0xac, X86_DECODE_CMD_SHRD, 0, true, decode_modrm_rm, decode_modrm_reg, - decode_imm8, NULL, NULL, RFLAGS_MASK_OSZAPC}, + decode_imm8, NULL, NULL}, {0xad, X86_DECODE_CMD_SHRD, 0, true, decode_modrm_rm, decode_modrm_reg, - decode_rcx, NULL, NULL, RFLAGS_MASK_OSZAPC}, + decode_rcx, NULL, NULL}, {0xae, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, - NULL, NULL, NULL, decode_aegroup, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, decode_aegroup}, {0xaf, X86_DECODE_CMD_IMUL_2, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0xb2, X86_DECODE_CMD_LSS, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, + NULL, NULL, NULL}, {0xb3, X86_DECODE_CMD_BTR, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0xba, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8, - NULL, NULL, decode_btgroup, RFLAGS_MASK_OSZAPC}, + NULL, NULL, decode_btgroup}, {0xbb, X86_DECODE_CMD_BTC, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0xbc, X86_DECODE_CMD_BSF, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0xbd, X86_DECODE_CMD_BSR, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0xc1, X86_DECODE_CMD_XADD, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + NULL, NULL, NULL}, {0xc7, X86_DECODE_CMD_CMPXCHG8B, 0, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_ZF}, + NULL, NULL, NULL, NULL}, {0xc8, X86_DECODE_CMD_BSWAP, 0, false, - NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_bswap}, {0xc9, X86_DECODE_CMD_BSWAP, 0, false, - NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_bswap}, {0xca, X86_DECODE_CMD_BSWAP, 0, false, - NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_bswap}, {0xcb, X86_DECODE_CMD_BSWAP, 0, false, - NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_bswap}, {0xcc, X86_DECODE_CMD_BSWAP, 0, false, - NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_bswap}, {0xcd, X86_DECODE_CMD_BSWAP, 0, false, - NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_bswap}, {0xce, X86_DECODE_CMD_BSWAP, 0, false, - NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_bswap}, {0xcf, X86_DECODE_CMD_BSWAP, 0, false, - NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + NULL, NULL, NULL, NULL, decode_bswap}, }; struct decode_x87_tbl invl_inst_x87 = {0x0, 0, 0, 0, 0, false, false, NULL, @@ -1427,207 +1412,207 @@ struct decode_x87_tbl invl_inst_x87 = {0x0, 0, 0, 0, 0, false, false, NULL, struct decode_x87_tbl _x87_inst[] = { {0xd8, 0, 3, X86_DECODE_CMD_FADD, 10, false, false, - decode_x87_modrm_st0, decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_decode_x87_modrm_st0, NULL}, {0xd8, 0, 0, X86_DECODE_CMD_FADD, 4, false, false, decode_x87_modrm_st0, - decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_floatp, NULL}, {0xd8, 1, 3, X86_DECODE_CMD_FMUL, 10, false, false, decode_x87_modrm_st0, - decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_decode_x87_modrm_st0, NULL}, {0xd8, 1, 0, X86_DECODE_CMD_FMUL, 4, false, false, decode_x87_modrm_st0, - decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_floatp, NULL}, {0xd8, 4, 3, X86_DECODE_CMD_FSUB, 10, false, false, decode_x87_modrm_st0, - decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, NULL}, {0xd8, 4, 0, X86_DECODE_CMD_FSUB, 4, false, false, decode_x87_modrm_st0, - decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_floatp, NULL}, {0xd8, 5, 3, X86_DECODE_CMD_FSUB, 10, true, false, decode_x87_modrm_st0, - decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, NULL}, {0xd8, 5, 0, X86_DECODE_CMD_FSUB, 4, true, false, decode_x87_modrm_st0, - decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_floatp, NULL}, {0xd8, 6, 3, X86_DECODE_CMD_FDIV, 10, false, false, decode_x87_modrm_st0, - decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, NULL}, {0xd8, 6, 0, X86_DECODE_CMD_FDIV, 4, false, false, decode_x87_modrm_st0, - decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_floatp, NULL}, {0xd8, 7, 3, X86_DECODE_CMD_FDIV, 10, true, false, decode_x87_modrm_st0, - decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, NULL}, {0xd8, 7, 0, X86_DECODE_CMD_FDIV, 4, true, false, decode_x87_modrm_st0, - decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_floatp, NULL}, {0xd9, 0, 3, X86_DECODE_CMD_FLD, 10, false, false, - decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, NULL, NULL}, {0xd9, 0, 0, X86_DECODE_CMD_FLD, 4, false, false, - decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_floatp, NULL, NULL}, {0xd9, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false, decode_x87_modrm_st0, - decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, NULL}, {0xd9, 1, 0, X86_DECODE_CMD_INVL, 10, false, false, - decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, NULL, NULL}, {0xd9, 2, 3, X86_DECODE_CMD_INVL, 10, false, false, - decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, NULL, NULL}, {0xd9, 2, 0, X86_DECODE_CMD_FST, 4, false, false, - decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_floatp, NULL, NULL}, {0xd9, 3, 3, X86_DECODE_CMD_INVL, 10, false, false, - decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, NULL, NULL}, {0xd9, 3, 0, X86_DECODE_CMD_FST, 4, false, true, - decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_floatp, NULL, NULL}, {0xd9, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, - decode_x87_modrm_st0, NULL, decode_d9_4, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, NULL, decode_d9_4}, {0xd9, 4, 0, X86_DECODE_CMD_INVL, 4, false, false, - decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_bytep, NULL, NULL}, {0xd9, 5, 3, X86_DECODE_CMD_FLDxx, 10, false, false, NULL, NULL, NULL, RFLAGS_MASK_NONE}, {0xd9, 5, 0, X86_DECODE_CMD_FLDCW, 2, false, false, - decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_bytep, NULL, NULL}, {0xd9, 7, 3, X86_DECODE_CMD_FNSTCW, 2, false, false, - decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_bytep, NULL, NULL}, {0xd9, 7, 0, X86_DECODE_CMD_FNSTCW, 2, false, false, - decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_bytep, NULL, NULL}, {0xda, 0, 3, X86_DECODE_CMD_FCMOV, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xda, 0, 0, X86_DECODE_CMD_FADD, 4, false, false, decode_x87_modrm_st0, - decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_intp, NULL}, {0xda, 1, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, - decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_decode_x87_modrm_st0, NULL}, {0xda, 1, 0, X86_DECODE_CMD_FMUL, 4, false, false, decode_x87_modrm_st0, - decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_intp, NULL}, {0xda, 2, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, - decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, NULL}, {0xda, 3, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, - decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, NULL}, {0xda, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, RFLAGS_MASK_NONE}, {0xda, 4, 0, X86_DECODE_CMD_FSUB, 4, false, false, decode_x87_modrm_st0, - decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_intp, NULL}, {0xda, 5, 3, X86_DECODE_CMD_FUCOM, 10, false, true, decode_x87_modrm_st0, - decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_decode_x87_modrm_st0, NULL}, {0xda, 5, 0, X86_DECODE_CMD_FSUB, 4, true, false, decode_x87_modrm_st0, - decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_intp, NULL}, {0xda, 6, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, RFLAGS_MASK_NONE}, {0xda, 6, 0, X86_DECODE_CMD_FDIV, 4, false, false, decode_x87_modrm_st0, - decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_intp, NULL}, {0xda, 7, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, RFLAGS_MASK_NONE}, {0xda, 7, 0, X86_DECODE_CMD_FDIV, 4, true, false, decode_x87_modrm_st0, - decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_intp, NULL}, {0xdb, 0, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, - decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, NULL}, {0xdb, 0, 0, X86_DECODE_CMD_FLD, 4, false, false, - decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_intp, NULL, NULL}, {0xdb, 1, 3, X86_DECODE_CMD_FCMOV, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xdb, 2, 3, X86_DECODE_CMD_FCMOV, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xdb, 2, 0, X86_DECODE_CMD_FST, 4, false, false, - decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_intp, NULL, NULL}, {0xdb, 3, 3, X86_DECODE_CMD_FCMOV, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xdb, 3, 0, X86_DECODE_CMD_FST, 4, false, true, - decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_intp, NULL, NULL}, {0xdb, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, - decode_db_4, RFLAGS_MASK_NONE}, + decode_db_4}, {0xdb, 4, 0, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, RFLAGS_MASK_NONE}, {0xdb, 5, 3, X86_DECODE_CMD_FUCOMI, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xdb, 5, 0, X86_DECODE_CMD_FLD, 10, false, false, - decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_floatp, NULL, NULL}, {0xdb, 7, 0, X86_DECODE_CMD_FST, 10, false, true, - decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_floatp, NULL, NULL}, {0xdc, 0, 3, X86_DECODE_CMD_FADD, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xdc, 0, 0, X86_DECODE_CMD_FADD, 8, false, false, - decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL}, {0xdc, 1, 3, X86_DECODE_CMD_FMUL, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xdc, 1, 0, X86_DECODE_CMD_FMUL, 8, false, false, - decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL}, {0xdc, 4, 3, X86_DECODE_CMD_FSUB, 10, true, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xdc, 4, 0, X86_DECODE_CMD_FSUB, 8, false, false, - decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL}, {0xdc, 5, 3, X86_DECODE_CMD_FSUB, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xdc, 5, 0, X86_DECODE_CMD_FSUB, 8, true, false, - decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL}, {0xdc, 6, 3, X86_DECODE_CMD_FDIV, 10, true, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xdc, 6, 0, X86_DECODE_CMD_FDIV, 8, false, false, - decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL}, {0xdc, 7, 3, X86_DECODE_CMD_FDIV, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xdc, 7, 0, X86_DECODE_CMD_FDIV, 8, true, false, - decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL}, {0xdd, 0, 0, X86_DECODE_CMD_FLD, 8, false, false, - decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_floatp, NULL, NULL}, {0xdd, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xdd, 2, 3, X86_DECODE_CMD_FST, 10, false, false, - decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, NULL, NULL}, {0xdd, 2, 0, X86_DECODE_CMD_FST, 8, false, false, - decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_floatp, NULL, NULL}, {0xdd, 3, 3, X86_DECODE_CMD_FST, 10, false, true, - decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, NULL, NULL}, {0xdd, 3, 0, X86_DECODE_CMD_FST, 8, false, true, - decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_floatp, NULL, NULL}, {0xdd, 4, 3, X86_DECODE_CMD_FUCOM, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xdd, 4, 0, X86_DECODE_CMD_FRSTOR, 8, false, false, - decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_bytep, NULL, NULL}, {0xdd, 5, 3, X86_DECODE_CMD_FUCOM, 10, false, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xdd, 7, 0, X86_DECODE_CMD_FNSTSW, 0, false, false, - decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_bytep, NULL, NULL}, {0xdd, 7, 3, X86_DECODE_CMD_FNSTSW, 0, false, false, - decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_bytep, NULL, NULL}, {0xde, 0, 3, X86_DECODE_CMD_FADD, 10, false, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xde, 0, 0, X86_DECODE_CMD_FADD, 2, false, false, - decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_intp, NULL}, {0xde, 1, 3, X86_DECODE_CMD_FMUL, 10, false, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xde, 1, 0, X86_DECODE_CMD_FMUL, 2, false, false, - decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_intp, NULL}, {0xde, 4, 3, X86_DECODE_CMD_FSUB, 10, true, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xde, 4, 0, X86_DECODE_CMD_FSUB, 2, false, false, - decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_intp, NULL}, {0xde, 5, 3, X86_DECODE_CMD_FSUB, 10, false, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xde, 5, 0, X86_DECODE_CMD_FSUB, 2, true, false, - decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_intp, NULL}, {0xde, 6, 3, X86_DECODE_CMD_FDIV, 10, true, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xde, 6, 0, X86_DECODE_CMD_FDIV, 2, false, false, - decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_intp, NULL}, {0xde, 7, 3, X86_DECODE_CMD_FDIV, 10, false, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xde, 7, 0, X86_DECODE_CMD_FDIV, 2, true, false, - decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_intp, NULL}, {0xdf, 0, 0, X86_DECODE_CMD_FLD, 2, false, false, - decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_intp, NULL, NULL}, {0xdf, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xdf, 2, 3, X86_DECODE_CMD_FST, 10, false, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xdf, 2, 0, X86_DECODE_CMD_FST, 2, false, false, - decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_intp, NULL, NULL}, {0xdf, 3, 3, X86_DECODE_CMD_FST, 10, false, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xdf, 3, 0, X86_DECODE_CMD_FST, 2, false, true, - decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_intp, NULL, NULL}, {0xdf, 4, 3, X86_DECODE_CMD_FNSTSW, 2, false, true, - decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_bytep, NULL, NULL}, {0xdf, 5, 3, X86_DECODE_CMD_FUCOMI, 10, false, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL}, {0xdf, 5, 0, X86_DECODE_CMD_FLD, 8, false, false, - decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_intp, NULL, NULL}, {0xdf, 7, 0, X86_DECODE_CMD_FST, 8, false, true, - decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + decode_x87_modrm_intp, NULL, NULL}, }; void calc_modrm_operand16(CPUX86State *env, struct x86_decode *decode, @@ -2045,7 +2030,6 @@ static inline void decode_opcode_general(CPUX86State *env, if (inst_decoder->operand_size) { decode->operand_size = inst_decoder->operand_size; } - decode->flags_mask = inst_decoder->flags_mask; if (inst_decoder->is_modrm) { decode_modrm(env, decode); diff --git a/target/i386/emulate/x86_decode.h b/target/i386/emulate/x86_decode.h index 930d965164..87cc728598 100644 --- a/target/i386/emulate/x86_decode.h +++ b/target/i386/emulate/x86_decode.h @@ -295,8 +295,6 @@ typedef struct x86_decode { struct x86_modrm modrm; struct x86_decode_op op[4]; bool is_fpu; - uint32_t flags_mask; - } x86_decode; uint64_t sign(uint64_t val, int size); From ae39acef49e29169f90cd3a799d6cd0b50bc65d2 Mon Sep 17 00:00:00 2001 From: Zhao Liu Date: Thu, 10 Apr 2025 15:56:19 +0800 Subject: [PATCH 28/34] i386/cpu: Consolidate the helper to get Host's vendor Extend host_cpu_vendor_fms() to help more cases to get Host's vendor information. Cc: Dongli Zhang Signed-off-by: Zhao Liu Link: https://lore.kernel.org/r/20250410075619.145792-1-zhao1.liu@intel.com Signed-off-by: Paolo Bonzini --- target/i386/host-cpu.c | 10 ++++++---- target/i386/kvm/vmsr_energy.c | 3 +-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/target/i386/host-cpu.c b/target/i386/host-cpu.c index 3e4e85e729..072731a4dd 100644 --- a/target/i386/host-cpu.c +++ b/target/i386/host-cpu.c @@ -109,9 +109,13 @@ void host_cpu_vendor_fms(char *vendor, int *family, int *model, int *stepping) { uint32_t eax, ebx, ecx, edx; - host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx); + host_cpuid(0x0, 0, NULL, &ebx, &ecx, &edx); x86_cpu_vendor_words2str(vendor, ebx, edx, ecx); + if (!family && !model && !stepping) { + return; + } + host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx); if (family) { *family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF); @@ -129,11 +133,9 @@ void host_cpu_instance_init(X86CPU *cpu) X86CPUClass *xcc = X86_CPU_GET_CLASS(cpu); if (xcc->model) { - uint32_t ebx = 0, ecx = 0, edx = 0; char vendor[CPUID_VENDOR_SZ + 1]; - host_cpuid(0, 0, NULL, &ebx, &ecx, &edx); - x86_cpu_vendor_words2str(vendor, ebx, edx, ecx); + host_cpu_vendor_fms(vendor, NULL, NULL, NULL); object_property_set_str(OBJECT(cpu), "vendor", vendor, &error_abort); } } diff --git a/target/i386/kvm/vmsr_energy.c b/target/i386/kvm/vmsr_energy.c index 31508d4e77..f499ec6e8b 100644 --- a/target/i386/kvm/vmsr_energy.c +++ b/target/i386/kvm/vmsr_energy.c @@ -29,10 +29,9 @@ char *vmsr_compute_default_paths(void) bool is_host_cpu_intel(void) { - int family, model, stepping; char vendor[CPUID_VENDOR_SZ + 1]; - host_cpu_vendor_fms(vendor, &family, &model, &stepping); + host_cpu_vendor_fms(vendor, NULL, NULL, NULL); return g_str_equal(vendor, CPUID_VENDOR_INTEL); } From 8163eeee4e5b6ce5ecb2f7300b80ae8a6f868afd Mon Sep 17 00:00:00 2001 From: Zhao Liu Date: Mon, 14 Apr 2025 22:49:40 +0800 Subject: [PATCH 29/34] rust/hpet: convert num_timers to u8 type The C version of HPET uses the uint8_t type for num_timers, and usize type in Rust version will break migration between the C and Rust versions. So convert num_timers' type to u8 (consistent with the C version of HPET) to make it friendly for vmstate support. Note the commit 7bda68e8e2b0 ("qdev, rust/hpet: fix type of HPET 'timers property") supports the usize type property, but the uint8 property has to be re-supported now. Signed-off-by: Zhao Liu Link: https://lore.kernel.org/r/20250414144943.1112885-7-zhao1.liu@intel.com Signed-off-by: Paolo Bonzini --- rust/hw/timer/hpet/src/hpet.rs | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/rust/hw/timer/hpet/src/hpet.rs b/rust/hw/timer/hpet/src/hpet.rs index 3ae3ec25f1..1afa891362 100644 --- a/rust/hw/timer/hpet/src/hpet.rs +++ b/rust/hw/timer/hpet/src/hpet.rs @@ -12,7 +12,7 @@ use std::{ use qemu_api::{ bindings::{ address_space_memory, address_space_stl_le, qdev_prop_bit, qdev_prop_bool, - qdev_prop_uint32, qdev_prop_usize, + qdev_prop_uint32, qdev_prop_uint8, }, c_str, cell::{BqlCell, BqlRefCell}, @@ -34,9 +34,9 @@ use crate::fw_cfg::HPETFwConfig; const HPET_REG_SPACE_LEN: u64 = 0x400; // 1024 bytes /// Minimum recommended hardware implementation. -const HPET_MIN_TIMERS: usize = 3; +const HPET_MIN_TIMERS: u8 = 3; /// Maximum timers in each timer block. -const HPET_MAX_TIMERS: usize = 32; +const HPET_MAX_TIMERS: u8 = 32; /// Flags that HPETState.flags supports. const HPET_FLAG_MSI_SUPPORT_SHIFT: usize = 0; @@ -559,14 +559,19 @@ pub struct HPETState { /// HPET timer array managed by this timer block. #[doc(alias = "timer")] - timers: [BqlRefCell; HPET_MAX_TIMERS], - num_timers: BqlCell, + timers: [BqlRefCell; HPET_MAX_TIMERS as usize], + num_timers: BqlCell, /// Instance id (HPET timer block ID). hpet_id: BqlCell, } impl HPETState { + // Get num_timers with `usize` type, which is useful to play with array index. + fn get_num_timers(&self) -> usize { + self.num_timers.get().into() + } + const fn has_msi_flag(&self) -> bool { self.flags & (1 << HPET_FLAG_MSI_SUPPORT_SHIFT) != 0 } @@ -628,7 +633,7 @@ impl HPETState { self.hpet_offset .set(ticks_to_ns(self.counter.get()) - CLOCK_VIRTUAL.get_ns()); - for timer in self.timers.iter().take(self.num_timers.get()) { + for timer in self.timers.iter().take(self.get_num_timers()) { let mut t = timer.borrow_mut(); if t.is_int_enabled() && t.is_int_active() { @@ -640,7 +645,7 @@ impl HPETState { // Halt main counter and disable interrupt generation. self.counter.set(self.get_ticks()); - for timer in self.timers.iter().take(self.num_timers.get()) { + for timer in self.timers.iter().take(self.get_num_timers()) { timer.borrow_mut().del_timer(); } } @@ -663,7 +668,7 @@ impl HPETState { let new_val = val << shift; let cleared = new_val & self.int_status.get(); - for (index, timer) in self.timers.iter().take(self.num_timers.get()).enumerate() { + for (index, timer) in self.timers.iter().take(self.get_num_timers()).enumerate() { if cleared & (1 << index) != 0 { timer.borrow_mut().update_irq(false); } @@ -737,7 +742,7 @@ impl HPETState { 1 << HPET_CAP_COUNT_SIZE_CAP_SHIFT | 1 << HPET_CAP_LEG_RT_CAP_SHIFT | HPET_CAP_VENDER_ID_VALUE << HPET_CAP_VENDER_ID_SHIFT | - ((self.num_timers.get() - 1) as u64) << HPET_CAP_NUM_TIM_SHIFT | // indicate the last timer + ((self.get_num_timers() - 1) as u64) << HPET_CAP_NUM_TIM_SHIFT | // indicate the last timer (HPET_CLK_PERIOD * FS_PER_NS) << HPET_CAP_CNT_CLK_PERIOD_SHIFT, // 10 ns ); @@ -746,7 +751,7 @@ impl HPETState { } fn reset_hold(&self, _type: ResetType) { - for timer in self.timers.iter().take(self.num_timers.get()) { + for timer in self.timers.iter().take(self.get_num_timers()) { timer.borrow_mut().reset(); } @@ -774,7 +779,7 @@ impl HPETState { GlobalRegister::try_from(addr).map(HPETRegister::Global) } else { let timer_id: usize = ((addr - 0x100) / 0x20) as usize; - if timer_id <= self.num_timers.get() { + if timer_id <= self.get_num_timers() { // TODO: Add trace point - trace_hpet_ram_[read|write]_timer_id(timer_id) TimerRegister::try_from(addr & 0x18) .map(|reg| HPETRegister::Timer(&self.timers[timer_id], reg)) @@ -859,8 +864,8 @@ qemu_api::declare_properties! { c_str!("timers"), HPETState, num_timers, - unsafe { &qdev_prop_usize }, - usize, + unsafe { &qdev_prop_uint8 }, + u8, default = HPET_MIN_TIMERS ), qemu_api::define_property!( From 64e1256b21395eb7c8a9419faba4187dea73970d Mon Sep 17 00:00:00 2001 From: Zhao Liu Date: Mon, 14 Apr 2025 22:49:41 +0800 Subject: [PATCH 30/34] rust/hpet: convert HPETTimer index to u8 type The C version of HPET uses the uint8_t type for timer index ("tn"), and usize type in Rust version will break migration between the C and Rust versions. So convert HPETTimer index' type to u8 (consistent with the C version of HPET) to make it friendly for vmstate support. Signed-off-by: Zhao Liu Link: https://lore.kernel.org/r/20250414144943.1112885-8-zhao1.liu@intel.com Signed-off-by: Paolo Bonzini --- rust/hw/timer/hpet/src/hpet.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rust/hw/timer/hpet/src/hpet.rs b/rust/hw/timer/hpet/src/hpet.rs index 1afa891362..dc8a23f29d 100644 --- a/rust/hw/timer/hpet/src/hpet.rs +++ b/rust/hw/timer/hpet/src/hpet.rs @@ -184,7 +184,7 @@ fn timer_handler(timer_cell: &BqlRefCell) { pub struct HPETTimer { /// timer N index within the timer block (`HPETState`) #[doc(alias = "tn")] - index: usize, + index: u8, qemu_timer: Timer, /// timer block abstraction containing this timer state: NonNull, @@ -210,7 +210,7 @@ pub struct HPETTimer { } impl HPETTimer { - fn init(&mut self, index: usize, state: &HPETState) { + fn init(&mut self, index: u8, state: &HPETState) { *self = HPETTimer { index, // SAFETY: the HPETTimer will only be used after the timer @@ -235,7 +235,7 @@ impl HPETTimer { Timer::NS, 0, timer_handler, - &state.timers[self.index], + &state.timers[self.index as usize], ) } @@ -246,7 +246,7 @@ impl HPETTimer { } fn is_int_active(&self) -> bool { - self.get_state().is_timer_int_active(self.index) + self.get_state().is_timer_int_active(self.index.into()) } const fn is_fsb_route_enabled(&self) -> bool { @@ -611,7 +611,7 @@ impl HPETState { fn init_timer(&self) { for (index, timer) in self.timers.iter().enumerate() { - timer.borrow_mut().init(index, self); + timer.borrow_mut().init(index.try_into().unwrap(), self); } } From ad3ab01bb7380f8cc8cf86dd260ce751148d6d21 Mon Sep 17 00:00:00 2001 From: Zhao Liu Date: Mon, 14 Apr 2025 22:49:43 +0800 Subject: [PATCH 31/34] rust/hpet: Fix a clippy error Carge clippy complained about: error: casts from `u8` to `u32` can be expressed infallibly using `From` So use `From` to convert `u8` to `u32`. Signed-off-by: Zhao Liu Link: https://lore.kernel.org/r/20250414144943.1112885-10-zhao1.liu@intel.com Signed-off-by: Paolo Bonzini --- rust/hw/timer/hpet/src/hpet.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/hw/timer/hpet/src/hpet.rs b/rust/hw/timer/hpet/src/hpet.rs index dc8a23f29d..cbd2ed4f6b 100644 --- a/rust/hw/timer/hpet/src/hpet.rs +++ b/rust/hw/timer/hpet/src/hpet.rs @@ -353,7 +353,7 @@ impl HPETTimer { // still operate and generate appropriate status bits, but // will not cause an interrupt" self.get_state() - .update_int_status(self.index as u32, set && self.is_int_level_triggered()); + .update_int_status(self.index.into(), set && self.is_int_level_triggered()); self.set_irq(set); } From d031d2fac9b94126ed0cd440da9e69e229d88aef Mon Sep 17 00:00:00 2001 From: Zhao Liu Date: Mon, 14 Apr 2025 22:49:38 +0800 Subject: [PATCH 32/34] rust/vmstate_test: Fix typo in test_vmstate_macro_array_of_pointer_wrapped() test_vmstate_macro_array_of_pointer_wrapped() tests the 3rd element, so fix the index. Signed-off-by: Zhao Liu Link: https://lore.kernel.org/r/20250414144943.1112885-5-zhao1.liu@intel.com Signed-off-by: Paolo Bonzini --- rust/qemu-api/tests/vmstate_tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/qemu-api/tests/vmstate_tests.rs b/rust/qemu-api/tests/vmstate_tests.rs index b8d8b45b19..8b93492a68 100644 --- a/rust/qemu-api/tests/vmstate_tests.rs +++ b/rust/qemu-api/tests/vmstate_tests.rs @@ -383,12 +383,12 @@ fn test_vmstate_macro_array_of_pointer_wrapped() { ); assert_eq!(foo_fields[3].offset, (FOO_ARRAY_MAX + 2) * PTR_SIZE); assert_eq!(foo_fields[3].num_offset, 0); - assert_eq!(foo_fields[2].info, unsafe { &vmstate_info_uint8 }); + assert_eq!(foo_fields[3].info, unsafe { &vmstate_info_uint8 }); assert_eq!(foo_fields[3].version_id, 0); assert_eq!(foo_fields[3].size, PTR_SIZE); assert_eq!(foo_fields[3].num, FOO_ARRAY_MAX as i32); assert_eq!( - foo_fields[2].flags.0, + foo_fields[3].flags.0, VMStateFlags::VMS_ARRAY.0 | VMStateFlags::VMS_ARRAY_OF_POINTER.0 ); assert!(foo_fields[3].vmsd.is_null()); From efc5603292bfde97fd82fabcedce86310bedbc65 Mon Sep 17 00:00:00 2001 From: Rakesh Jeyasingh Date: Mon, 7 Apr 2025 23:43:26 +0530 Subject: [PATCH 33/34] rust/hw/char/pl011: Extract extract DR read logic into separate function - Split `read()` DR case into `read_data_register()` Signed-off-by: Rakesh Jeyasingh Link: https://lore.kernel.org/r/20250407181327.171563-2-rakeshjb010@gmail.com Signed-off-by: Paolo Bonzini --- rust/hw/char/pl011/src/device.rs | 39 ++++++++++++++++---------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/device.rs index bf88e0b00a..87153cdae1 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -190,25 +190,7 @@ impl PL011Registers { let mut update = false; let result = match offset { - DR => { - self.flags.set_receive_fifo_full(false); - let c = self.read_fifo[self.read_pos]; - if self.read_count > 0 { - self.read_count -= 1; - self.read_pos = (self.read_pos + 1) & (self.fifo_depth() - 1); - } - if self.read_count == 0 { - self.flags.set_receive_fifo_empty(true); - } - if self.read_count + 1 == self.read_trigger { - self.int_level &= !Interrupt::RX.0; - } - // Update error bits. - self.receive_status_error_clear.set_from_data(c); - // Must call qemu_chr_fe_accept_input - update = true; - u32::from(c) - } + DR => self.read_data_register(&mut update), RSR => u32::from(self.receive_status_error_clear), FR => u32::from(self.flags), FBRD => self.fbrd, @@ -306,6 +288,25 @@ impl PL011Registers { false } + fn read_data_register(&mut self, update: &mut bool) -> u32 { + self.flags.set_receive_fifo_full(false); + let c = self.read_fifo[self.read_pos]; + + if self.read_count > 0 { + self.read_count -= 1; + self.read_pos = (self.read_pos + 1) & (self.fifo_depth() - 1); + } + if self.read_count == 0 { + self.flags.set_receive_fifo_empty(true); + } + if self.read_count + 1 == self.read_trigger { + self.int_level &= !Interrupt::RX.0; + } + self.receive_status_error_clear.set_from_data(c); + *update = true; + u32::from(c) + } + #[inline] #[must_use] fn loopback_tx(&mut self, value: registers::Data) -> bool { From 6d8c6dee3a767e7650e5d0640e13adb9f01fa37c Mon Sep 17 00:00:00 2001 From: Rakesh Jeyasingh Date: Mon, 7 Apr 2025 23:43:27 +0530 Subject: [PATCH 34/34] rust/hw/char/pl011: Extract DR write logic into separate function - Split `write()` DR case into `write_data_register()` Signed-off-by: Rakesh Jeyasingh Link: https://lore.kernel.org/r/20250407181327.171563-3-rakeshjb010@gmail.com Signed-off-by: Paolo Bonzini --- rust/hw/char/pl011/src/device.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/device.rs index 87153cdae1..bb2a0f207a 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -221,12 +221,7 @@ impl PL011Registers { // eprintln!("write offset {offset} value {value}"); use RegisterOffset::*; match offset { - DR => { - // interrupts always checked - let _ = self.loopback_tx(value.into()); - self.int_level |= Interrupt::TX.0; - return true; - } + DR => return self.write_data_register(value), RSR => { self.receive_status_error_clear = 0.into(); } @@ -307,6 +302,13 @@ impl PL011Registers { u32::from(c) } + fn write_data_register(&mut self, value: u32) -> bool { + // interrupts always checked + let _ = self.loopback_tx(value.into()); + self.int_level |= Interrupt::TX.0; + true + } + #[inline] #[must_use] fn loopback_tx(&mut self, value: registers::Data) -> bool {