From f23c25829064e68236022a69f831511d4ccf3f9d Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 11 Jul 2020 19:25:36 +0200 Subject: [PATCH] UserspaceEmulator: Implement the AND and TEST instructions --- DevTools/UserspaceEmulator/SoftCPU.cpp | 67 +++++++++++++++----------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/DevTools/UserspaceEmulator/SoftCPU.cpp b/DevTools/UserspaceEmulator/SoftCPU.cpp index d2a2a923da..b30983894a 100644 --- a/DevTools/UserspaceEmulator/SoftCPU.cpp +++ b/DevTools/UserspaceEmulator/SoftCPU.cpp @@ -250,6 +250,37 @@ static Destination op_add(SoftCPU& cpu, Destination& dest, const Source& src) return result; } +template +static Destination op_and(SoftCPU& cpu, Destination& dest, const Source& src) +{ + Destination result = 0; + u32 new_flags = 0; + + if constexpr (sizeof(Destination) == 4) { + asm volatile("andl %%ecx, %%eax\n" + : "=a"(result) + : "a"(dest), "c"((u32)src)); + } else if constexpr (sizeof(Destination) == 2) { + asm volatile("andw %%cx, %%ax\n" + : "=a"(result) + : "a"(dest), "c"((u16)src)); + } else if constexpr (sizeof(Destination) == 1) { + asm volatile("andb %%cl, %%al\n" + : "=a"(result) + : "a"(dest), "c"((u8)src)); + } else { + ASSERT_NOT_REACHED(); + } + + asm volatile( + "pushf\n" + "pop %%ebx" + : "=b"(new_flags)); + + cpu.set_flags_oszpc(new_flags); + return result; +} + template void SoftCPU::generic_AL_imm8(Op op, const X86::Instruction& insn) { @@ -408,20 +439,6 @@ void SoftCPU::ADC_RM8_reg8(const X86::Instruction&) { TODO(); } void SoftCPU::ADC_reg16_RM16(const X86::Instruction&) { TODO(); } void SoftCPU::ADC_reg32_RM32(const X86::Instruction&) { TODO(); } void SoftCPU::ADC_reg8_RM8(const X86::Instruction&) { TODO(); } -void SoftCPU::AND_AL_imm8(const X86::Instruction&) { TODO(); } -void SoftCPU::AND_AX_imm16(const X86::Instruction&) { TODO(); } -void SoftCPU::AND_EAX_imm32(const X86::Instruction&) { TODO(); } -void SoftCPU::AND_RM16_imm16(const X86::Instruction&) { TODO(); } -void SoftCPU::AND_RM16_imm8(const X86::Instruction&) { TODO(); } -void SoftCPU::AND_RM16_reg16(const X86::Instruction&) { TODO(); } -void SoftCPU::AND_RM32_imm32(const X86::Instruction&) { TODO(); } -void SoftCPU::AND_RM32_imm8(const X86::Instruction&) { TODO(); } -void SoftCPU::AND_RM32_reg32(const X86::Instruction&) { TODO(); } -void SoftCPU::AND_RM8_imm8(const X86::Instruction&) { TODO(); } -void SoftCPU::AND_RM8_reg8(const X86::Instruction&) { TODO(); } -void SoftCPU::AND_reg16_RM16(const X86::Instruction&) { TODO(); } -void SoftCPU::AND_reg32_RM32(const X86::Instruction&) { TODO(); } -void SoftCPU::AND_reg8_RM8(const X86::Instruction&) { TODO(); } void SoftCPU::ARPL(const X86::Instruction&) { TODO(); } void SoftCPU::BOUND(const X86::Instruction&) { TODO(); } void SoftCPU::BSF_reg16_RM16(const X86::Instruction&) { TODO(); } @@ -991,15 +1008,6 @@ void SoftCPU::STOSB(const X86::Instruction&) { TODO(); } void SoftCPU::STOSD(const X86::Instruction&) { TODO(); } void SoftCPU::STOSW(const X86::Instruction&) { TODO(); } void SoftCPU::STR_RM16(const X86::Instruction&) { TODO(); } -void SoftCPU::TEST_AL_imm8(const X86::Instruction&) { TODO(); } -void SoftCPU::TEST_AX_imm16(const X86::Instruction&) { TODO(); } -void SoftCPU::TEST_EAX_imm32(const X86::Instruction&) { TODO(); } -void SoftCPU::TEST_RM16_imm16(const X86::Instruction&) { TODO(); } -void SoftCPU::TEST_RM16_reg16(const X86::Instruction&) { TODO(); } -void SoftCPU::TEST_RM32_imm32(const X86::Instruction&) { TODO(); } -void SoftCPU::TEST_RM32_reg32(const X86::Instruction&) { TODO(); } -void SoftCPU::TEST_RM8_imm8(const X86::Instruction&) { TODO(); } -void SoftCPU::TEST_RM8_reg8(const X86::Instruction&) { TODO(); } void SoftCPU::UD0(const X86::Instruction&) { TODO(); } void SoftCPU::UD1(const X86::Instruction&) { TODO(); } void SoftCPU::UD2(const X86::Instruction&) { TODO(); } @@ -1017,18 +1025,21 @@ void SoftCPU::XCHG_reg32_RM32(const X86::Instruction&) { TODO(); } void SoftCPU::XCHG_reg8_RM8(const X86::Instruction&) { TODO(); } void SoftCPU::XLAT(const X86::Instruction&) { TODO(); } -#define DEFINE_GENERIC_INSN_HANDLERS(mnemonic, op, update_dest) \ +#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_imm8(const X86::Instruction& insn) { generic_RM16_imm8(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_imm8(const X86::Instruction& insn) { generic_RM32_imm8(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); } \ + 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); } @@ -1036,7 +1047,9 @@ void SoftCPU::XLAT(const X86::Instruction&) { TODO(); } DEFINE_GENERIC_INSN_HANDLERS(XOR, op_xor, true) DEFINE_GENERIC_INSN_HANDLERS(ADD, op_add, true) DEFINE_GENERIC_INSN_HANDLERS(SUB, op_sub, 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) void SoftCPU::MOVQ_mm1_mm2m64(const X86::Instruction&) { TODO(); } void SoftCPU::EMMS(const X86::Instruction&) { TODO(); }