diff --git a/DevTools/UserspaceEmulator/SoftCPU.cpp b/DevTools/UserspaceEmulator/SoftCPU.cpp index 6edb92358b..5cdbd24d3a 100644 --- a/DevTools/UserspaceEmulator/SoftCPU.cpp +++ b/DevTools/UserspaceEmulator/SoftCPU.cpp @@ -761,12 +761,16 @@ ALWAYS_INLINE void SoftCPU::generic_RM16_unsigned_imm8(Op op, const X86::Instruc insn.modrm().write16(*this, insn, result); } -template +template ALWAYS_INLINE void SoftCPU::generic_RM16_reg16(Op op, const X86::Instruction& insn) { auto dest = insn.modrm().read16>(*this, insn); auto src = const_gpr16(insn.reg16()); auto result = op(*this, dest, src); + if (dont_taint_for_same_operand && insn.modrm().is_register() && insn.modrm().register_index() == insn.register_index()) { + result.set_initialized(); + m_flags_tainted = false; + } if (update_dest) insn.modrm().write16(*this, insn, result); } @@ -801,12 +805,16 @@ ALWAYS_INLINE void SoftCPU::generic_RM32_unsigned_imm8(Op op, const X86::Instruc insn.modrm().write32(*this, insn, result); } -template +template ALWAYS_INLINE void SoftCPU::generic_RM32_reg32(Op op, const X86::Instruction& insn) { auto dest = insn.modrm().read32>(*this, insn); auto src = const_gpr32(insn.reg32()); auto result = op(*this, dest, src); + if (dont_taint_for_same_operand && insn.modrm().is_register() && insn.modrm().register_index() == insn.register_index()) { + result.set_initialized(); + m_flags_tainted = false; + } if (update_dest) insn.modrm().write32(*this, insn, result); } @@ -821,42 +829,58 @@ ALWAYS_INLINE void SoftCPU::generic_RM8_imm8(Op op, const X86::Instruction& insn insn.modrm().write8(*this, insn, result); } -template +template ALWAYS_INLINE void SoftCPU::generic_RM8_reg8(Op op, const X86::Instruction& insn) { auto dest = insn.modrm().read8>(*this, insn); auto src = const_gpr8(insn.reg8()); auto result = op(*this, dest, src); + if (dont_taint_for_same_operand && insn.modrm().is_register() && insn.modrm().register_index() == insn.register_index()) { + result.set_initialized(); + m_flags_tainted = false; + } if (update_dest) insn.modrm().write8(*this, insn, result); } -template +template ALWAYS_INLINE void SoftCPU::generic_reg16_RM16(Op op, const X86::Instruction& insn) { auto dest = const_gpr16(insn.reg16()); auto src = insn.modrm().read16>(*this, insn); auto result = op(*this, dest, src); + if (dont_taint_for_same_operand && insn.modrm().is_register() && insn.modrm().register_index() == insn.register_index()) { + result.set_initialized(); + m_flags_tainted = false; + } if (update_dest) gpr16(insn.reg16()) = result; } -template +template ALWAYS_INLINE void SoftCPU::generic_reg32_RM32(Op op, const X86::Instruction& insn) { auto dest = const_gpr32(insn.reg32()); auto src = insn.modrm().read32>(*this, insn); auto result = op(*this, dest, src); + if (dont_taint_for_same_operand && insn.modrm().is_register() && insn.modrm().register_index() == insn.register_index()) { + result.set_initialized(); + m_flags_tainted = false; + } if (update_dest) gpr32(insn.reg32()) = result; } -template +template ALWAYS_INLINE void SoftCPU::generic_reg8_RM8(Op op, const X86::Instruction& insn) { auto dest = const_gpr8(insn.reg8()); auto src = insn.modrm().read8>(*this, insn); auto result = op(*this, dest, src); + if (dont_taint_for_same_operand && insn.modrm().is_register() && insn.modrm().register_index() == insn.register_index()) { + result.set_initialized(); + m_flags_tainted = false; + } if (update_dest) gpr8(insn.reg8()) = result; } @@ -2506,34 +2530,34 @@ void SoftCPU::XLAT(const X86::Instruction& insn) set_al(read_memory8({ segment(insn.segment_prefix().value_or(X86::SegmentRegister::DS)), offset })); } -#define DEFINE_GENERIC_INSN_HANDLERS_PARTIAL(mnemonic, op, update_dest) \ - void SoftCPU::mnemonic##_AL_imm8(const X86::Instruction& insn) { generic_AL_imm8(op>, insn); } \ - void SoftCPU::mnemonic##_AX_imm16(const X86::Instruction& insn) { generic_AX_imm16(op>, insn); } \ - void SoftCPU::mnemonic##_EAX_imm32(const X86::Instruction& insn) { generic_EAX_imm32(op>, insn); } \ - void SoftCPU::mnemonic##_RM16_imm16(const X86::Instruction& insn) { generic_RM16_imm16(op>, insn); } \ - void SoftCPU::mnemonic##_RM16_reg16(const X86::Instruction& insn) { generic_RM16_reg16(op>, insn); } \ - void SoftCPU::mnemonic##_RM32_imm32(const X86::Instruction& insn) { generic_RM32_imm32(op>, insn); } \ - void SoftCPU::mnemonic##_RM32_reg32(const X86::Instruction& insn) { generic_RM32_reg32(op>, insn); } \ - void SoftCPU::mnemonic##_RM8_imm8(const X86::Instruction& insn) { generic_RM8_imm8(op>, insn); } \ - void SoftCPU::mnemonic##_RM8_reg8(const X86::Instruction& insn) { generic_RM8_reg8(op>, insn); } +#define DEFINE_GENERIC_INSN_HANDLERS_PARTIAL(mnemonic, op, update_dest, is_zero_idiom_if_both_operands_same) \ + void SoftCPU::mnemonic##_AL_imm8(const X86::Instruction& insn) { generic_AL_imm8(op>, insn); } \ + void SoftCPU::mnemonic##_AX_imm16(const X86::Instruction& insn) { generic_AX_imm16(op>, insn); } \ + void SoftCPU::mnemonic##_EAX_imm32(const X86::Instruction& insn) { generic_EAX_imm32(op>, insn); } \ + void SoftCPU::mnemonic##_RM16_imm16(const X86::Instruction& insn) { generic_RM16_imm16(op>, insn); } \ + void SoftCPU::mnemonic##_RM16_reg16(const X86::Instruction& insn) { generic_RM16_reg16(op>, insn); } \ + void SoftCPU::mnemonic##_RM32_imm32(const X86::Instruction& insn) { generic_RM32_imm32(op>, insn); } \ + void SoftCPU::mnemonic##_RM32_reg32(const X86::Instruction& insn) { generic_RM32_reg32(op>, insn); } \ + void SoftCPU::mnemonic##_RM8_imm8(const X86::Instruction& insn) { generic_RM8_imm8(op>, insn); } \ + void SoftCPU::mnemonic##_RM8_reg8(const X86::Instruction& insn) { generic_RM8_reg8(op>, insn); } -#define DEFINE_GENERIC_INSN_HANDLERS(mnemonic, op, update_dest) \ - DEFINE_GENERIC_INSN_HANDLERS_PARTIAL(mnemonic, op, update_dest) \ - void SoftCPU::mnemonic##_RM16_imm8(const X86::Instruction& insn) { generic_RM16_imm8(op>, insn); } \ - void SoftCPU::mnemonic##_RM32_imm8(const X86::Instruction& insn) { generic_RM32_imm8(op>, insn); } \ - void SoftCPU::mnemonic##_reg16_RM16(const X86::Instruction& insn) { generic_reg16_RM16(op>, insn); } \ - void SoftCPU::mnemonic##_reg32_RM32(const X86::Instruction& insn) { generic_reg32_RM32(op>, insn); } \ - void SoftCPU::mnemonic##_reg8_RM8(const X86::Instruction& insn) { generic_reg8_RM8(op>, insn); } +#define DEFINE_GENERIC_INSN_HANDLERS(mnemonic, op, update_dest, is_zero_idiom_if_both_operands_same) \ + DEFINE_GENERIC_INSN_HANDLERS_PARTIAL(mnemonic, op, update_dest, is_zero_idiom_if_both_operands_same) \ + void SoftCPU::mnemonic##_RM16_imm8(const X86::Instruction& insn) { generic_RM16_imm8(op>, insn); } \ + void SoftCPU::mnemonic##_RM32_imm8(const X86::Instruction& insn) { generic_RM32_imm8(op>, insn); } \ + void SoftCPU::mnemonic##_reg16_RM16(const X86::Instruction& insn) { generic_reg16_RM16(op>, insn); } \ + void SoftCPU::mnemonic##_reg32_RM32(const X86::Instruction& insn) { generic_reg32_RM32(op>, insn); } \ + void SoftCPU::mnemonic##_reg8_RM8(const X86::Instruction& insn) { generic_reg8_RM8(op>, insn); } -DEFINE_GENERIC_INSN_HANDLERS(XOR, op_xor, true) -DEFINE_GENERIC_INSN_HANDLERS(OR, op_or, true) -DEFINE_GENERIC_INSN_HANDLERS(ADD, op_add, true) -DEFINE_GENERIC_INSN_HANDLERS(ADC, op_adc, true) -DEFINE_GENERIC_INSN_HANDLERS(SUB, op_sub, true) -DEFINE_GENERIC_INSN_HANDLERS(SBB, op_sbb, true) -DEFINE_GENERIC_INSN_HANDLERS(AND, op_and, true) -DEFINE_GENERIC_INSN_HANDLERS(CMP, op_sub, false) -DEFINE_GENERIC_INSN_HANDLERS_PARTIAL(TEST, op_and, false) +DEFINE_GENERIC_INSN_HANDLERS(XOR, op_xor, true, true) +DEFINE_GENERIC_INSN_HANDLERS(OR, op_or, true, false) +DEFINE_GENERIC_INSN_HANDLERS(ADD, op_add, true, false) +DEFINE_GENERIC_INSN_HANDLERS(ADC, op_adc, true, false) +DEFINE_GENERIC_INSN_HANDLERS(SUB, op_sub, true, true) +DEFINE_GENERIC_INSN_HANDLERS(SBB, op_sbb, true, false) +DEFINE_GENERIC_INSN_HANDLERS(AND, op_and, true, false) +DEFINE_GENERIC_INSN_HANDLERS(CMP, op_sub, false, false) +DEFINE_GENERIC_INSN_HANDLERS_PARTIAL(TEST, op_and, false, false) void SoftCPU::MOVQ_mm1_mm2m64(const X86::Instruction&) { TODO(); } void SoftCPU::EMMS(const X86::Instruction&) { TODO(); } diff --git a/DevTools/UserspaceEmulator/SoftCPU.h b/DevTools/UserspaceEmulator/SoftCPU.h index 2acd0ff65c..8148dd8353 100644 --- a/DevTools/UserspaceEmulator/SoftCPU.h +++ b/DevTools/UserspaceEmulator/SoftCPU.h @@ -950,7 +950,7 @@ private: void generic_RM16_imm8(Op, const X86::Instruction&); template void generic_RM16_unsigned_imm8(Op, const X86::Instruction&); - template + template void generic_RM16_reg16(Op, const X86::Instruction&); template void generic_RM32_imm32(Op, const X86::Instruction&); @@ -958,17 +958,17 @@ private: void generic_RM32_imm8(Op, const X86::Instruction&); template void generic_RM32_unsigned_imm8(Op, const X86::Instruction&); - template + template void generic_RM32_reg32(Op, const X86::Instruction&); template void generic_RM8_imm8(Op, const X86::Instruction&); - template + template void generic_RM8_reg8(Op, const X86::Instruction&); - template + template void generic_reg16_RM16(Op, const X86::Instruction&); - template + template void generic_reg32_RM32(Op, const X86::Instruction&); - template + template void generic_reg8_RM8(Op, const X86::Instruction&); template diff --git a/DevTools/UserspaceEmulator/ValueWithShadow.h b/DevTools/UserspaceEmulator/ValueWithShadow.h index a30aa62bb1..a0bb3e1b7c 100644 --- a/DevTools/UserspaceEmulator/ValueWithShadow.h +++ b/DevTools/UserspaceEmulator/ValueWithShadow.h @@ -59,6 +59,16 @@ public: return (m_shadow & 0x01) != 0x01; } + void set_initialized() + { + if constexpr (sizeof(T) == 4) + m_shadow = 0x01010101; + if constexpr (sizeof(T) == 2) + m_shadow = 0x0101; + if constexpr (sizeof(T) == 1) + m_shadow = 0x01; + } + private: T m_value; T m_shadow;