diff options
author | Andreas Kling <kling@serenityos.org> | 2020-07-18 16:02:51 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-07-18 17:57:40 +0200 |
commit | 30d512144e694cf63cc78b6fff8c9d52ac89385e (patch) | |
tree | d5d06cfff959b63cd31b866c5d187dd3c25951b6 | |
parent | a4b2d6cf1e8d1bcd8af39a8f8530045d08629b48 (diff) | |
download | serenity-30d512144e694cf63cc78b6fff8c9d52ac89385e.zip |
UserspaceEmulator: Implement the BSF and BSF instructions
BSF maps nicely to __builtin_ctz(), but for BSR we have to bust out
some inline assembly to get exactly what we want.
-rw-r--r-- | DevTools/UserspaceEmulator/SoftCPU.cpp | 59 |
1 files changed, 55 insertions, 4 deletions
diff --git a/DevTools/UserspaceEmulator/SoftCPU.cpp b/DevTools/UserspaceEmulator/SoftCPU.cpp index 73323d322d..0dee78aca7 100644 --- a/DevTools/UserspaceEmulator/SoftCPU.cpp +++ b/DevTools/UserspaceEmulator/SoftCPU.cpp @@ -852,10 +852,61 @@ void SoftCPU::AAM(const X86::Instruction&) { TODO(); } void SoftCPU::AAS(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&) { } -void SoftCPU::BSF_reg32_RM32(const X86::Instruction&) { } -void SoftCPU::BSR_reg16_RM16(const X86::Instruction&) { } -void SoftCPU::BSR_reg32_RM32(const X86::Instruction&) { } + +template<typename T> +ALWAYS_INLINE static unsigned op_bsf(SoftCPU&, T value) +{ + return __builtin_ctz(value); +} + +template<typename T> +ALWAYS_INLINE static unsigned op_bsr(SoftCPU&, T value) +{ + T bit_index = 0; + if constexpr (sizeof(T) == 4) { + asm volatile("bsrl %%eax, %%edx" + : "=d"(bit_index) + : "a"(value)); + } + if constexpr (sizeof(T) == 2) { + asm volatile("bsrw %%ax, %%dx" + : "=d"(bit_index) + : "a"(value)); + } + return bit_index; +} + +void SoftCPU::BSF_reg16_RM16(const X86::Instruction& insn) +{ + auto src = insn.modrm().read16(*this, insn); + set_zf(!src); + if (src) + gpr16(insn.reg16()) = op_bsf(*this, src); +} + +void SoftCPU::BSF_reg32_RM32(const X86::Instruction& insn) +{ + auto src = insn.modrm().read32(*this, insn); + set_zf(!src); + if (src) + gpr32(insn.reg32()) = op_bsf(*this, insn.modrm().read32(*this, insn)); +} + +void SoftCPU::BSR_reg16_RM16(const X86::Instruction& insn) +{ + auto src = insn.modrm().read16(*this, insn); + set_zf(!src); + if (src) + gpr16(insn.reg16()) = op_bsr(*this, insn.modrm().read16(*this, insn)); +} + +void SoftCPU::BSR_reg32_RM32(const X86::Instruction& insn) +{ + auto src = insn.modrm().read32(*this, insn); + set_zf(!src); + if (src) + gpr32(insn.reg32()) = op_bsr(*this, insn.modrm().read32(*this, insn)); +} void SoftCPU::BSWAP_reg32(const X86::Instruction& insn) { |