mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 17:27:35 +00:00
UserspaceEmulator: Implement STOSB/STOSW/STOSD
...and add a template to handle REP* instruction prefixes. This can be further generalized, but let's go one step at a time.
This commit is contained in:
parent
6688ce41b2
commit
0af485dfff
2 changed files with 83 additions and 3 deletions
|
@ -157,6 +157,38 @@ u32 SoftCPU::pop32()
|
||||||
return value;
|
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>
|
template<typename Destination, typename Source>
|
||||||
static typename TypeDoubler<Destination>::type op_xor(SoftCPU& cpu, const Destination& dest, const Source& src)
|
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::STC(const X86::Instruction&) { TODO(); }
|
||||||
void SoftCPU::STD(const X86::Instruction&) { TODO(); }
|
void SoftCPU::STD(const X86::Instruction&) { TODO(); }
|
||||||
void SoftCPU::STI(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::STOSB(const X86::Instruction& insn)
|
||||||
void SoftCPU::STOSW(const X86::Instruction&) { TODO(); }
|
{
|
||||||
|
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::STR_RM16(const X86::Instruction&) { TODO(); }
|
||||||
void SoftCPU::UD0(const X86::Instruction&) { TODO(); }
|
void SoftCPU::UD0(const X86::Instruction&) { TODO(); }
|
||||||
void SoftCPU::UD1(const X86::Instruction&) { TODO(); }
|
void SoftCPU::UD1(const X86::Instruction&) { TODO(); }
|
||||||
|
|
|
@ -190,6 +190,7 @@ public:
|
||||||
bool af() const { return m_eflags & Flags::AF; }
|
bool af() const { return m_eflags & Flags::AF; }
|
||||||
bool pf() const { return m_eflags & Flags::PF; }
|
bool pf() const { return m_eflags & Flags::PF; }
|
||||||
bool cf() const { return m_eflags & Flags::CF; }
|
bool cf() const { return m_eflags & Flags::CF; }
|
||||||
|
bool df() const { return m_eflags & Flags::DF; }
|
||||||
|
|
||||||
void set_flag(Flags::Flag flag, bool value)
|
void set_flag(Flags::Flag flag, bool value)
|
||||||
{
|
{
|
||||||
|
@ -205,6 +206,7 @@ public:
|
||||||
void set_af(bool value) { set_flag(Flags::AF, value); }
|
void set_af(bool value) { set_flag(Flags::AF, value); }
|
||||||
void set_pf(bool value) { set_flag(Flags::PF, value); }
|
void set_pf(bool value) { set_flag(Flags::PF, value); }
|
||||||
void set_cf(bool value) { set_flag(Flags::CF, value); }
|
void set_cf(bool value) { set_flag(Flags::CF, value); }
|
||||||
|
void set_df(bool value) { set_flag(Flags::DF, value); }
|
||||||
|
|
||||||
void set_flags_oszapc(u32 new_flags)
|
void set_flags_oszapc(u32 new_flags)
|
||||||
{
|
{
|
||||||
|
@ -785,6 +787,9 @@ private:
|
||||||
template<bool update_dest, typename Op>
|
template<bool update_dest, typename Op>
|
||||||
void generic_reg8_RM8(Op, const X86::Instruction&);
|
void generic_reg8_RM8(Op, const X86::Instruction&);
|
||||||
|
|
||||||
|
template<bool check_zf, typename Callback>
|
||||||
|
void do_once_or_repeat(const X86::Instruction& insn, Callback);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Emulator& m_emulator;
|
Emulator& m_emulator;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue