summaryrefslogtreecommitdiff
path: root/DevTools/UserspaceEmulator/SoftCPU.cpp
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-07-18 00:10:21 +0200
committerAndreas Kling <kling@serenityos.org>2020-07-18 00:25:02 +0200
commit485d1faf09fcadd3f9830ea18e585076ce7eb2d6 (patch)
treebdd818b86449381039beac886459447ffedbee01 /DevTools/UserspaceEmulator/SoftCPU.cpp
parent28b6ba56aa5115efc127068fbf5839f06149c5e7 (diff)
downloadserenity-485d1faf09fcadd3f9830ea18e585076ce7eb2d6.zip
UserspaceEmulator: Add helpers for making loop instructions generic
Use them to implement CMPSB/CMPSW/CMPSD.
Diffstat (limited to 'DevTools/UserspaceEmulator/SoftCPU.cpp')
-rw-r--r--DevTools/UserspaceEmulator/SoftCPU.cpp48
1 files changed, 29 insertions, 19 deletions
diff --git a/DevTools/UserspaceEmulator/SoftCPU.cpp b/DevTools/UserspaceEmulator/SoftCPU.cpp
index 270dbb7c66..4e2d6bc817 100644
--- a/DevTools/UserspaceEmulator/SoftCPU.cpp
+++ b/DevTools/UserspaceEmulator/SoftCPU.cpp
@@ -195,23 +195,9 @@ void SoftCPU::do_once_or_repeat(const X86::Instruction& insn, Callback callback)
if (!insn.has_rep_prefix())
return callback();
- if (insn.has_address_size_override_prefix()) {
- while (cx()) {
- callback();
- set_cx(cx() - 1);
- if constexpr (check_zf) {
- if (insn.rep_prefix() == X86::Prefix::REPZ && !zf())
- break;
- if (insn.rep_prefix() == X86::Prefix::REPNZ && zf())
- break;
- }
- }
- return;
- }
-
- while (ecx()) {
+ while (loop_index(insn.a32())) {
callback();
- set_ecx(ecx() - 1);
+ decrement_loop_index(insn.a32());
if constexpr (check_zf) {
if (insn.rep_prefix() == X86::Prefix::REPZ && !zf())
break;
@@ -1057,9 +1043,33 @@ void SoftCPU::CMOVcc_reg32_RM32(const X86::Instruction& insn)
gpr32(insn.reg32()) = insn.modrm().read32(*this, insn);
}
-void SoftCPU::CMPSB(const X86::Instruction&) { TODO(); }
-void SoftCPU::CMPSD(const X86::Instruction&) { TODO(); }
-void SoftCPU::CMPSW(const X86::Instruction&) { TODO(); }
+template<typename T>
+ALWAYS_INLINE static void do_cmps(SoftCPU& cpu, const X86::Instruction& insn)
+{
+ auto src_segment = cpu.segment(insn.segment_prefix().value_or(X86::SegmentRegister::DS));
+ cpu.do_once_or_repeat<true>(insn, [&] {
+ auto src = cpu.read_memory<T>({ src_segment, cpu.source_index(insn.a32()) });
+ auto dest = cpu.read_memory<T>({ cpu.es(), cpu.destination_index(insn.a32()) });
+ op_sub(cpu, dest, src);
+ cpu.step_source_index(insn.a32(), sizeof(T));
+ cpu.step_destination_index(insn.a32(), sizeof(T));
+ });
+}
+
+void SoftCPU::CMPSB(const X86::Instruction& insn)
+{
+ do_cmps<u8>(*this, insn);
+}
+
+void SoftCPU::CMPSD(const X86::Instruction& insn)
+{
+ do_cmps<u32>(*this, insn);
+}
+
+void SoftCPU::CMPSW(const X86::Instruction& insn)
+{
+ do_cmps<u16>(*this, insn);
+}
void SoftCPU::CMPXCHG_RM16_reg16(const X86::Instruction& insn)
{