summaryrefslogtreecommitdiff
path: root/DevTools/UserspaceEmulator/SoftCPU.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'DevTools/UserspaceEmulator/SoftCPU.cpp')
-rw-r--r--DevTools/UserspaceEmulator/SoftCPU.cpp81
1 files changed, 78 insertions, 3 deletions
diff --git a/DevTools/UserspaceEmulator/SoftCPU.cpp b/DevTools/UserspaceEmulator/SoftCPU.cpp
index 72fd0edff7..f7a7f9fe05 100644
--- a/DevTools/UserspaceEmulator/SoftCPU.cpp
+++ b/DevTools/UserspaceEmulator/SoftCPU.cpp
@@ -157,6 +157,38 @@ u32 SoftCPU::pop32()
return value;
}
+template<bool check_zf, typename Callback>
+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()) {
+ callback();
+ set_ecx(ecx() - 1);
+ if constexpr (check_zf) {
+ if (insn.rep_prefix() == X86::Prefix::REPZ && !zf())
+ break;
+ if (insn.rep_prefix() == X86::Prefix::REPNZ && zf())
+ break;
+ }
+ }
+}
+
template<typename Destination, typename Source>
static typename TypeDoubler<Destination>::type op_xor(SoftCPU& cpu, const Destination& dest, const Source& src)
{
@@ -1064,9 +1096,52 @@ void SoftCPU::SMSW_RM16(const X86::Instruction&) { TODO(); }
void SoftCPU::STC(const X86::Instruction&) { TODO(); }
void SoftCPU::STD(const X86::Instruction&) { TODO(); }
void SoftCPU::STI(const X86::Instruction&) { TODO(); }
-void SoftCPU::STOSB(const X86::Instruction&) { TODO(); }
-void SoftCPU::STOSD(const X86::Instruction&) { TODO(); }
-void SoftCPU::STOSW(const X86::Instruction&) { TODO(); }
+
+void SoftCPU::STOSB(const X86::Instruction& insn)
+{
+ if (insn.has_address_size_override_prefix()) {
+ do_once_or_repeat<false>(insn, [&] {
+ write_memory8({ es(), di() }, al());
+ set_di(di() + (df() ? -1 : 1));
+ });
+ } else {
+ do_once_or_repeat<false>(insn, [&] {
+ write_memory8({ es(), edi() }, al());
+ set_edi(edi() + (df() ? -1 : 1));
+ });
+ }
+}
+
+void SoftCPU::STOSD(const X86::Instruction& insn)
+{
+ if (insn.has_address_size_override_prefix()) {
+ do_once_or_repeat<false>(insn, [&] {
+ write_memory32({ es(), di() }, eax());
+ set_di(di() + (df() ? -4 : 4));
+ });
+ } else {
+ do_once_or_repeat<false>(insn, [&] {
+ write_memory32({ es(), edi() }, eax());
+ set_edi(edi() + (df() ? -4 : 4));
+ });
+ }
+}
+
+void SoftCPU::STOSW(const X86::Instruction& insn)
+{
+ if (insn.has_address_size_override_prefix()) {
+ do_once_or_repeat<false>(insn, [&] {
+ write_memory16({ es(), di() }, ax());
+ set_di(di() + (df() ? -2 : 2));
+ });
+ } else {
+ do_once_or_repeat<false>(insn, [&] {
+ write_memory16({ es(), edi() }, ax());
+ set_edi(edi() + (df() ? -2 : 2));
+ });
+ }
+}
+
void SoftCPU::STR_RM16(const X86::Instruction&) { TODO(); }
void SoftCPU::UD0(const X86::Instruction&) { TODO(); }
void SoftCPU::UD1(const X86::Instruction&) { TODO(); }