|
@@ -26,6 +26,7 @@
|
|
|
|
|
|
#pragma once
|
|
#pragma once
|
|
|
|
|
|
|
|
+#include "ValueWithShadow.h"
|
|
#include <LibX86/Instruction.h>
|
|
#include <LibX86/Instruction.h>
|
|
#include <LibX86/Interpreter.h>
|
|
#include <LibX86/Interpreter.h>
|
|
|
|
|
|
@@ -77,82 +78,96 @@ public:
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
|
|
- void push32(u32);
|
|
|
|
- u32 pop32();
|
|
|
|
|
|
+ void push32(ValueWithShadow<u32>);
|
|
|
|
+ ValueWithShadow<u32> pop32();
|
|
|
|
|
|
- void push16(u16);
|
|
|
|
- u16 pop16();
|
|
|
|
|
|
+ void push16(ValueWithShadow<u16>);
|
|
|
|
+ ValueWithShadow<u16> pop16();
|
|
|
|
|
|
void push_string(const StringView&);
|
|
void push_string(const StringView&);
|
|
|
|
|
|
u16 segment(X86::SegmentRegister seg) const { return m_segment[(int)seg]; }
|
|
u16 segment(X86::SegmentRegister seg) const { return m_segment[(int)seg]; }
|
|
u16& segment(X86::SegmentRegister seg) { return m_segment[(int)seg]; }
|
|
u16& segment(X86::SegmentRegister seg) { return m_segment[(int)seg]; }
|
|
|
|
|
|
- u8& gpr8(X86::RegisterIndex8 reg)
|
|
|
|
|
|
+ ValueAndShadowReference<u8> gpr8(X86::RegisterIndex8 reg)
|
|
{
|
|
{
|
|
switch (reg) {
|
|
switch (reg) {
|
|
case X86::RegisterAL:
|
|
case X86::RegisterAL:
|
|
- return m_gpr[X86::RegisterEAX].low_u8;
|
|
|
|
|
|
+ return { m_gpr[X86::RegisterEAX].low_u8, m_gpr_shadow[X86::RegisterEAX].low_u8 };
|
|
case X86::RegisterAH:
|
|
case X86::RegisterAH:
|
|
- return m_gpr[X86::RegisterEAX].high_u8;
|
|
|
|
|
|
+ return { m_gpr[X86::RegisterEAX].high_u8, m_gpr_shadow[X86::RegisterEAX].high_u8 };
|
|
case X86::RegisterBL:
|
|
case X86::RegisterBL:
|
|
- return m_gpr[X86::RegisterEBX].low_u8;
|
|
|
|
|
|
+ return { m_gpr[X86::RegisterEBX].low_u8, m_gpr_shadow[X86::RegisterEBX].low_u8 };
|
|
case X86::RegisterBH:
|
|
case X86::RegisterBH:
|
|
- return m_gpr[X86::RegisterEBX].high_u8;
|
|
|
|
|
|
+ return { m_gpr[X86::RegisterEBX].high_u8, m_gpr_shadow[X86::RegisterEBX].high_u8 };
|
|
case X86::RegisterCL:
|
|
case X86::RegisterCL:
|
|
- return m_gpr[X86::RegisterECX].low_u8;
|
|
|
|
|
|
+ return { m_gpr[X86::RegisterECX].low_u8, m_gpr_shadow[X86::RegisterECX].low_u8 };
|
|
case X86::RegisterCH:
|
|
case X86::RegisterCH:
|
|
- return m_gpr[X86::RegisterECX].high_u8;
|
|
|
|
|
|
+ return { m_gpr[X86::RegisterECX].high_u8, m_gpr_shadow[X86::RegisterECX].high_u8 };
|
|
case X86::RegisterDL:
|
|
case X86::RegisterDL:
|
|
- return m_gpr[X86::RegisterEDX].low_u8;
|
|
|
|
|
|
+ return { m_gpr[X86::RegisterEDX].low_u8, m_gpr_shadow[X86::RegisterEDX].low_u8 };
|
|
case X86::RegisterDH:
|
|
case X86::RegisterDH:
|
|
- return m_gpr[X86::RegisterEDX].high_u8;
|
|
|
|
|
|
+ return { m_gpr[X86::RegisterEDX].high_u8, m_gpr_shadow[X86::RegisterEDX].high_u8 };
|
|
}
|
|
}
|
|
ASSERT_NOT_REACHED();
|
|
ASSERT_NOT_REACHED();
|
|
}
|
|
}
|
|
|
|
|
|
- u8 gpr8(X86::RegisterIndex8 reg) const
|
|
|
|
|
|
+ ValueWithShadow<u8> const_gpr8(X86::RegisterIndex8 reg) const
|
|
{
|
|
{
|
|
switch (reg) {
|
|
switch (reg) {
|
|
case X86::RegisterAL:
|
|
case X86::RegisterAL:
|
|
- return m_gpr[X86::RegisterEAX].low_u8;
|
|
|
|
|
|
+ return { m_gpr[X86::RegisterEAX].low_u8, m_gpr_shadow[X86::RegisterEAX].low_u8 };
|
|
case X86::RegisterAH:
|
|
case X86::RegisterAH:
|
|
- return m_gpr[X86::RegisterEAX].high_u8;
|
|
|
|
|
|
+ return { m_gpr[X86::RegisterEAX].high_u8, m_gpr_shadow[X86::RegisterEAX].high_u8 };
|
|
case X86::RegisterBL:
|
|
case X86::RegisterBL:
|
|
- return m_gpr[X86::RegisterEBX].low_u8;
|
|
|
|
|
|
+ return { m_gpr[X86::RegisterEBX].low_u8, m_gpr_shadow[X86::RegisterEBX].low_u8 };
|
|
case X86::RegisterBH:
|
|
case X86::RegisterBH:
|
|
- return m_gpr[X86::RegisterEBX].high_u8;
|
|
|
|
|
|
+ return { m_gpr[X86::RegisterEBX].high_u8, m_gpr_shadow[X86::RegisterEBX].high_u8 };
|
|
case X86::RegisterCL:
|
|
case X86::RegisterCL:
|
|
- return m_gpr[X86::RegisterECX].low_u8;
|
|
|
|
|
|
+ return { m_gpr[X86::RegisterECX].low_u8, m_gpr_shadow[X86::RegisterECX].low_u8 };
|
|
case X86::RegisterCH:
|
|
case X86::RegisterCH:
|
|
- return m_gpr[X86::RegisterECX].high_u8;
|
|
|
|
|
|
+ return { m_gpr[X86::RegisterECX].high_u8, m_gpr_shadow[X86::RegisterECX].high_u8 };
|
|
case X86::RegisterDL:
|
|
case X86::RegisterDL:
|
|
- return m_gpr[X86::RegisterEDX].low_u8;
|
|
|
|
|
|
+ return { m_gpr[X86::RegisterEDX].low_u8, m_gpr_shadow[X86::RegisterEDX].low_u8 };
|
|
case X86::RegisterDH:
|
|
case X86::RegisterDH:
|
|
- return m_gpr[X86::RegisterEDX].high_u8;
|
|
|
|
|
|
+ return { m_gpr[X86::RegisterEDX].high_u8, m_gpr_shadow[X86::RegisterEDX].high_u8 };
|
|
}
|
|
}
|
|
ASSERT_NOT_REACHED();
|
|
ASSERT_NOT_REACHED();
|
|
}
|
|
}
|
|
|
|
|
|
- u16 gpr16(X86::RegisterIndex16 reg) const { return m_gpr[reg].low_u16; }
|
|
|
|
- u16& gpr16(X86::RegisterIndex16 reg) { return m_gpr[reg].low_u16; }
|
|
|
|
|
|
+ ValueWithShadow<u16> const_gpr16(X86::RegisterIndex16 reg) const
|
|
|
|
+ {
|
|
|
|
+ return { m_gpr[reg].low_u16, m_gpr_shadow[reg].low_u16 };
|
|
|
|
+ }
|
|
|
|
|
|
- u32 gpr32(X86::RegisterIndex32 reg) const { return m_gpr[reg].full_u32; }
|
|
|
|
- u32& gpr32(X86::RegisterIndex32 reg) { return m_gpr[reg].full_u32; }
|
|
|
|
|
|
+ ValueAndShadowReference<u16> gpr16(X86::RegisterIndex16 reg)
|
|
|
|
+ {
|
|
|
|
+ return { m_gpr[reg].low_u16, m_gpr_shadow[reg].low_u16 };
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ValueWithShadow<u32> const_gpr32(X86::RegisterIndex32 reg) const
|
|
|
|
+ {
|
|
|
|
+ return { m_gpr[reg].full_u32, m_gpr_shadow[reg].full_u32 };
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ValueAndShadowReference<u32> gpr32(X86::RegisterIndex32 reg)
|
|
|
|
+ {
|
|
|
|
+ return { m_gpr[reg].full_u32, m_gpr_shadow[reg].full_u32 };
|
|
|
|
+ }
|
|
|
|
|
|
template<typename T>
|
|
template<typename T>
|
|
- T gpr(unsigned register_index) const
|
|
|
|
|
|
+ ValueWithShadow<T> const_gpr(unsigned register_index) const
|
|
{
|
|
{
|
|
if constexpr (sizeof(T) == 1)
|
|
if constexpr (sizeof(T) == 1)
|
|
- return gpr8((X86::RegisterIndex8)register_index);
|
|
|
|
|
|
+ return const_gpr8((X86::RegisterIndex8)register_index);
|
|
if constexpr (sizeof(T) == 2)
|
|
if constexpr (sizeof(T) == 2)
|
|
- return gpr16((X86::RegisterIndex16)register_index);
|
|
|
|
|
|
+ return const_gpr16((X86::RegisterIndex16)register_index);
|
|
if constexpr (sizeof(T) == 4)
|
|
if constexpr (sizeof(T) == 4)
|
|
- return gpr32((X86::RegisterIndex32)register_index);
|
|
|
|
|
|
+ return const_gpr32((X86::RegisterIndex32)register_index);
|
|
}
|
|
}
|
|
|
|
|
|
template<typename T>
|
|
template<typename T>
|
|
- T& gpr(unsigned register_index)
|
|
|
|
|
|
+ ValueAndShadowReference<T> gpr(unsigned register_index)
|
|
{
|
|
{
|
|
if constexpr (sizeof(T) == 1)
|
|
if constexpr (sizeof(T) == 1)
|
|
return gpr8((X86::RegisterIndex8)register_index);
|
|
return gpr8((X86::RegisterIndex8)register_index);
|
|
@@ -162,49 +177,49 @@ public:
|
|
return gpr32((X86::RegisterIndex32)register_index);
|
|
return gpr32((X86::RegisterIndex32)register_index);
|
|
}
|
|
}
|
|
|
|
|
|
- u32 source_index(bool a32) const
|
|
|
|
|
|
+ ValueWithShadow<u32> source_index(bool a32) const
|
|
{
|
|
{
|
|
if (a32)
|
|
if (a32)
|
|
return esi();
|
|
return esi();
|
|
- return si();
|
|
|
|
|
|
+ return { si().value(), (u32)si().shadow() & 0xffff };
|
|
}
|
|
}
|
|
|
|
|
|
- u32 destination_index(bool a32) const
|
|
|
|
|
|
+ ValueWithShadow<u32> destination_index(bool a32) const
|
|
{
|
|
{
|
|
if (a32)
|
|
if (a32)
|
|
return edi();
|
|
return edi();
|
|
- return di();
|
|
|
|
|
|
+ return { di().value(), (u32)di().shadow() & 0xffff };
|
|
}
|
|
}
|
|
|
|
|
|
- u32 loop_index(bool a32) const
|
|
|
|
|
|
+ ValueWithShadow<u32> loop_index(bool a32) const
|
|
{
|
|
{
|
|
if (a32)
|
|
if (a32)
|
|
return ecx();
|
|
return ecx();
|
|
- return cx();
|
|
|
|
|
|
+ return { cx().value(), (u32)cx().shadow() & 0xffff };
|
|
}
|
|
}
|
|
|
|
|
|
bool decrement_loop_index(bool a32)
|
|
bool decrement_loop_index(bool a32)
|
|
{
|
|
{
|
|
if (a32) {
|
|
if (a32) {
|
|
- set_ecx(ecx() - 1);
|
|
|
|
- return ecx() == 0;
|
|
|
|
|
|
+ set_ecx({ ecx().value() - 1, ecx().shadow() });
|
|
|
|
+ return ecx().value() == 0;
|
|
}
|
|
}
|
|
- set_cx(cx() - 1);
|
|
|
|
- return cx() == 0;
|
|
|
|
|
|
+ set_cx(ValueWithShadow<u16>(cx().value() - 1, cx().shadow()));
|
|
|
|
+ return cx().value() == 0;
|
|
}
|
|
}
|
|
|
|
|
|
ALWAYS_INLINE void step_source_index(bool a32, u32 step)
|
|
ALWAYS_INLINE void step_source_index(bool a32, u32 step)
|
|
{
|
|
{
|
|
if (a32) {
|
|
if (a32) {
|
|
if (df())
|
|
if (df())
|
|
- set_esi(esi() - step);
|
|
|
|
|
|
+ set_esi({ esi().value() - step, esi().shadow() });
|
|
else
|
|
else
|
|
- set_esi(esi() + step);
|
|
|
|
|
|
+ set_esi({ esi().value() + step, esi().shadow() });
|
|
} else {
|
|
} else {
|
|
if (df())
|
|
if (df())
|
|
- set_si(si() - step);
|
|
|
|
|
|
+ set_si(ValueWithShadow<u16>(si().value() - step, si().shadow()));
|
|
else
|
|
else
|
|
- set_si(si() + step);
|
|
|
|
|
|
+ set_si(ValueWithShadow<u16>(si().value() + step, si().shadow()));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -212,71 +227,70 @@ public:
|
|
{
|
|
{
|
|
if (a32) {
|
|
if (a32) {
|
|
if (df())
|
|
if (df())
|
|
- set_edi(edi() - step);
|
|
|
|
|
|
+ set_edi({ edi().value() - step, edi().shadow() });
|
|
else
|
|
else
|
|
- set_edi(edi() + step);
|
|
|
|
|
|
+ set_edi({ edi().value() + step, edi().shadow() });
|
|
} else {
|
|
} else {
|
|
if (df())
|
|
if (df())
|
|
- set_di(di() - step);
|
|
|
|
|
|
+ set_di(ValueWithShadow<u16>(di().value() - step, di().shadow()));
|
|
else
|
|
else
|
|
- set_di(di() + step);
|
|
|
|
|
|
+ set_di(ValueWithShadow<u16>(di().value() + step, di().shadow()));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- u32 eax() const { return gpr32(X86::RegisterEAX); }
|
|
|
|
- u32 ebx() const { return gpr32(X86::RegisterEBX); }
|
|
|
|
- u32 ecx() const { return gpr32(X86::RegisterECX); }
|
|
|
|
- u32 edx() const { return gpr32(X86::RegisterEDX); }
|
|
|
|
- u32 esp() const { return gpr32(X86::RegisterESP); }
|
|
|
|
- u32 ebp() const { return gpr32(X86::RegisterEBP); }
|
|
|
|
- u32 esi() const { return gpr32(X86::RegisterESI); }
|
|
|
|
- u32 edi() const { return gpr32(X86::RegisterEDI); }
|
|
|
|
-
|
|
|
|
- u16 ax() const { return gpr16(X86::RegisterAX); }
|
|
|
|
- u16 bx() const { return gpr16(X86::RegisterBX); }
|
|
|
|
- u16 cx() const { return gpr16(X86::RegisterCX); }
|
|
|
|
- u16 dx() const { return gpr16(X86::RegisterDX); }
|
|
|
|
- u16 sp() const { return gpr16(X86::RegisterSP); }
|
|
|
|
- u16 bp() const { return gpr16(X86::RegisterBP); }
|
|
|
|
- u16 si() const { return gpr16(X86::RegisterSI); }
|
|
|
|
- u16 di() const { return gpr16(X86::RegisterDI); }
|
|
|
|
-
|
|
|
|
- u8 al() const { return gpr8(X86::RegisterAL); }
|
|
|
|
- u8 ah() const { return gpr8(X86::RegisterAH); }
|
|
|
|
- u8 bl() const { return gpr8(X86::RegisterBL); }
|
|
|
|
- u8 bh() const { return gpr8(X86::RegisterBH); }
|
|
|
|
- u8 cl() const { return gpr8(X86::RegisterCL); }
|
|
|
|
- u8 ch() const { return gpr8(X86::RegisterCH); }
|
|
|
|
- u8 dl() const { return gpr8(X86::RegisterDL); }
|
|
|
|
- u8 dh() const { return gpr8(X86::RegisterDH); }
|
|
|
|
-
|
|
|
|
- void set_eax(u32 value) { gpr32(X86::RegisterEAX) = value; }
|
|
|
|
- void set_ebx(u32 value) { gpr32(X86::RegisterEBX) = value; }
|
|
|
|
- void set_ecx(u32 value) { gpr32(X86::RegisterECX) = value; }
|
|
|
|
- void set_edx(u32 value) { gpr32(X86::RegisterEDX) = value; }
|
|
|
|
- void set_esp(u32 value) { gpr32(X86::RegisterESP) = value; }
|
|
|
|
- void set_ebp(u32 value) { gpr32(X86::RegisterEBP) = value; }
|
|
|
|
- void set_esi(u32 value) { gpr32(X86::RegisterESI) = value; }
|
|
|
|
- void set_edi(u32 value) { gpr32(X86::RegisterEDI) = value; }
|
|
|
|
-
|
|
|
|
- void set_ax(u16 value) { gpr16(X86::RegisterAX) = value; }
|
|
|
|
- void set_bx(u16 value) { gpr16(X86::RegisterBX) = value; }
|
|
|
|
- void set_cx(u16 value) { gpr16(X86::RegisterCX) = value; }
|
|
|
|
- void set_dx(u16 value) { gpr16(X86::RegisterDX) = value; }
|
|
|
|
- void set_sp(u16 value) { gpr16(X86::RegisterSP) = value; }
|
|
|
|
- void set_bp(u16 value) { gpr16(X86::RegisterBP) = value; }
|
|
|
|
- void set_si(u16 value) { gpr16(X86::RegisterSI) = value; }
|
|
|
|
- void set_di(u16 value) { gpr16(X86::RegisterDI) = value; }
|
|
|
|
-
|
|
|
|
- void set_al(u8 value) { gpr8(X86::RegisterAL) = value; }
|
|
|
|
- void set_ah(u8 value) { gpr8(X86::RegisterAH) = value; }
|
|
|
|
- void set_bl(u8 value) { gpr8(X86::RegisterBL) = value; }
|
|
|
|
- void set_bh(u8 value) { gpr8(X86::RegisterBH) = value; }
|
|
|
|
- void set_cl(u8 value) { gpr8(X86::RegisterCL) = value; }
|
|
|
|
- void set_ch(u8 value) { gpr8(X86::RegisterCH) = value; }
|
|
|
|
- void set_dl(u8 value) { gpr8(X86::RegisterDL) = value; }
|
|
|
|
- void set_dh(u8 value) { gpr8(X86::RegisterDH) = value; }
|
|
|
|
|
|
+ ValueWithShadow<u32> eax() const { return const_gpr32(X86::RegisterEAX); }
|
|
|
|
+ ValueWithShadow<u32> ebx() const { return const_gpr32(X86::RegisterEBX); }
|
|
|
|
+ ValueWithShadow<u32> ecx() const { return const_gpr32(X86::RegisterECX); }
|
|
|
|
+ ValueWithShadow<u32> edx() const { return const_gpr32(X86::RegisterEDX); }
|
|
|
|
+ ValueWithShadow<u32> esp() const { return const_gpr32(X86::RegisterESP); }
|
|
|
|
+ ValueWithShadow<u32> ebp() const { return const_gpr32(X86::RegisterEBP); }
|
|
|
|
+ ValueWithShadow<u32> esi() const { return const_gpr32(X86::RegisterESI); }
|
|
|
|
+ ValueWithShadow<u32> edi() const { return const_gpr32(X86::RegisterEDI); }
|
|
|
|
+
|
|
|
|
+ ValueWithShadow<u16> ax() const { return const_gpr16(X86::RegisterAX); }
|
|
|
|
+ ValueWithShadow<u16> bx() const { return const_gpr16(X86::RegisterBX); }
|
|
|
|
+ ValueWithShadow<u16> cx() const { return const_gpr16(X86::RegisterCX); }
|
|
|
|
+ ValueWithShadow<u16> dx() const { return const_gpr16(X86::RegisterDX); }
|
|
|
|
+ ValueWithShadow<u16> sp() const { return const_gpr16(X86::RegisterSP); }
|
|
|
|
+ ValueWithShadow<u16> bp() const { return const_gpr16(X86::RegisterBP); }
|
|
|
|
+ ValueWithShadow<u16> si() const { return const_gpr16(X86::RegisterSI); }
|
|
|
|
+ ValueWithShadow<u16> di() const { return const_gpr16(X86::RegisterDI); }
|
|
|
|
+
|
|
|
|
+ ValueWithShadow<u8> al() const { return const_gpr8(X86::RegisterAL); }
|
|
|
|
+ ValueWithShadow<u8> ah() const { return const_gpr8(X86::RegisterAH); }
|
|
|
|
+ ValueWithShadow<u8> bl() const { return const_gpr8(X86::RegisterBL); }
|
|
|
|
+ ValueWithShadow<u8> bh() const { return const_gpr8(X86::RegisterBH); }
|
|
|
|
+ ValueWithShadow<u8> cl() const { return const_gpr8(X86::RegisterCL); }
|
|
|
|
+ ValueWithShadow<u8> ch() const { return const_gpr8(X86::RegisterCH); }
|
|
|
|
+ ValueWithShadow<u8> dl() const { return const_gpr8(X86::RegisterDL); }
|
|
|
|
+ ValueWithShadow<u8> dh() const { return const_gpr8(X86::RegisterDH); }
|
|
|
|
+
|
|
|
|
+ void set_eax(ValueWithShadow<u32> value) { gpr32(X86::RegisterEAX) = value; }
|
|
|
|
+ void set_ebx(ValueWithShadow<u32> value) { gpr32(X86::RegisterEBX) = value; }
|
|
|
|
+ void set_ecx(ValueWithShadow<u32> value) { gpr32(X86::RegisterECX) = value; }
|
|
|
|
+ void set_edx(ValueWithShadow<u32> value) { gpr32(X86::RegisterEDX) = value; }
|
|
|
|
+ void set_esp(ValueWithShadow<u32> value) { gpr32(X86::RegisterESP) = value; }
|
|
|
|
+ void set_ebp(ValueWithShadow<u32> value) { gpr32(X86::RegisterEBP) = value; }
|
|
|
|
+ void set_esi(ValueWithShadow<u32> value) { gpr32(X86::RegisterESI) = value; }
|
|
|
|
+ void set_edi(ValueWithShadow<u32> value) { gpr32(X86::RegisterEDI) = value; }
|
|
|
|
+
|
|
|
|
+ void set_ax(ValueWithShadow<u16> value) { gpr16(X86::RegisterAX) = value; }
|
|
|
|
+ void set_bx(ValueWithShadow<u16> value) { gpr16(X86::RegisterBX) = value; }
|
|
|
|
+ void set_cx(ValueWithShadow<u16> value) { gpr16(X86::RegisterCX) = value; }
|
|
|
|
+ void set_dx(ValueWithShadow<u16> value) { gpr16(X86::RegisterDX) = value; }
|
|
|
|
+ void set_sp(ValueWithShadow<u16> value) { gpr16(X86::RegisterSP) = value; }
|
|
|
|
+ void set_bp(ValueWithShadow<u16> value) { gpr16(X86::RegisterBP) = value; }
|
|
|
|
+ void set_si(ValueWithShadow<u16> value) { gpr16(X86::RegisterSI) = value; }
|
|
|
|
+ void set_di(ValueWithShadow<u16> value) { gpr16(X86::RegisterDI) = value; }
|
|
|
|
+
|
|
|
|
+ void set_al(ValueWithShadow<u8> value) { gpr8(X86::RegisterAL) = value; }
|
|
|
|
+ void set_ah(ValueWithShadow<u8> value) { gpr8(X86::RegisterAH) = value; }
|
|
|
|
+ void set_bl(ValueWithShadow<u8> value) { gpr8(X86::RegisterBL) = value; }
|
|
|
|
+ void set_bh(ValueWithShadow<u8> value) { gpr8(X86::RegisterBH) = value; }
|
|
|
|
+ void set_cl(ValueWithShadow<u8> value) { gpr8(X86::RegisterCL) = value; }
|
|
|
|
+ void set_ch(ValueWithShadow<u8> value) { gpr8(X86::RegisterCH) = value; }
|
|
|
|
+ void set_dl(ValueWithShadow<u8> value) { gpr8(X86::RegisterDL) = value; }
|
|
|
|
+ void set_dh(ValueWithShadow<u8> value) { gpr8(X86::RegisterDH) = value; }
|
|
|
|
|
|
bool of() const { return m_eflags & Flags::OF; }
|
|
bool of() const { return m_eflags & Flags::OF; }
|
|
bool sf() const { return m_eflags & Flags::SF; }
|
|
bool sf() const { return m_eflags & Flags::SF; }
|
|
@@ -333,12 +347,12 @@ public:
|
|
u16 es() const { return m_segment[(int)X86::SegmentRegister::ES]; }
|
|
u16 es() const { return m_segment[(int)X86::SegmentRegister::ES]; }
|
|
u16 ss() const { return m_segment[(int)X86::SegmentRegister::SS]; }
|
|
u16 ss() const { return m_segment[(int)X86::SegmentRegister::SS]; }
|
|
|
|
|
|
- u8 read_memory8(X86::LogicalAddress);
|
|
|
|
- u16 read_memory16(X86::LogicalAddress);
|
|
|
|
- u32 read_memory32(X86::LogicalAddress);
|
|
|
|
|
|
+ ValueWithShadow<u8> read_memory8(X86::LogicalAddress);
|
|
|
|
+ ValueWithShadow<u16> read_memory16(X86::LogicalAddress);
|
|
|
|
+ ValueWithShadow<u32> read_memory32(X86::LogicalAddress);
|
|
|
|
|
|
template<typename T>
|
|
template<typename T>
|
|
- T read_memory(X86::LogicalAddress address)
|
|
|
|
|
|
+ ValueWithShadow<T> read_memory(X86::LogicalAddress address)
|
|
{
|
|
{
|
|
if constexpr (sizeof(T) == 1)
|
|
if constexpr (sizeof(T) == 1)
|
|
return read_memory8(address);
|
|
return read_memory8(address);
|
|
@@ -348,12 +362,12 @@ public:
|
|
return read_memory32(address);
|
|
return read_memory32(address);
|
|
}
|
|
}
|
|
|
|
|
|
- void write_memory8(X86::LogicalAddress, u8);
|
|
|
|
- void write_memory16(X86::LogicalAddress, u16);
|
|
|
|
- void write_memory32(X86::LogicalAddress, u32);
|
|
|
|
|
|
+ void write_memory8(X86::LogicalAddress, ValueWithShadow<u8>);
|
|
|
|
+ void write_memory16(X86::LogicalAddress, ValueWithShadow<u16>);
|
|
|
|
+ void write_memory32(X86::LogicalAddress, ValueWithShadow<u32>);
|
|
|
|
|
|
template<typename T>
|
|
template<typename T>
|
|
- void write_memory(X86::LogicalAddress address, T data)
|
|
|
|
|
|
+ void write_memory(X86::LogicalAddress address, ValueWithShadow<T> data)
|
|
{
|
|
{
|
|
if constexpr (sizeof(T) == 1)
|
|
if constexpr (sizeof(T) == 1)
|
|
return write_memory8(address, data);
|
|
return write_memory8(address, data);
|
|
@@ -896,12 +910,16 @@ private:
|
|
template<bool update_dest, typename Op>
|
|
template<bool update_dest, typename Op>
|
|
void generic_RM16_imm8(Op, const X86::Instruction&);
|
|
void generic_RM16_imm8(Op, const X86::Instruction&);
|
|
template<bool update_dest, typename Op>
|
|
template<bool update_dest, typename Op>
|
|
|
|
+ void generic_RM16_unsigned_imm8(Op, const X86::Instruction&);
|
|
|
|
+ template<bool update_dest, typename Op>
|
|
void generic_RM16_reg16(Op, const X86::Instruction&);
|
|
void generic_RM16_reg16(Op, const X86::Instruction&);
|
|
template<bool update_dest, typename Op>
|
|
template<bool update_dest, typename Op>
|
|
void generic_RM32_imm32(Op, const X86::Instruction&);
|
|
void generic_RM32_imm32(Op, const X86::Instruction&);
|
|
template<bool update_dest, typename Op>
|
|
template<bool update_dest, typename Op>
|
|
void generic_RM32_imm8(Op, const X86::Instruction&);
|
|
void generic_RM32_imm8(Op, const X86::Instruction&);
|
|
template<bool update_dest, typename Op>
|
|
template<bool update_dest, typename Op>
|
|
|
|
+ void generic_RM32_unsigned_imm8(Op, const X86::Instruction&);
|
|
|
|
+ template<bool update_dest, typename Op>
|
|
void generic_RM32_reg32(Op, const X86::Instruction&);
|
|
void generic_RM32_reg32(Op, const X86::Instruction&);
|
|
template<bool update_dest, typename Op>
|
|
template<bool update_dest, typename Op>
|
|
void generic_RM8_imm8(Op, const X86::Instruction&);
|
|
void generic_RM8_imm8(Op, const X86::Instruction&);
|
|
@@ -935,6 +953,8 @@ private:
|
|
Emulator& m_emulator;
|
|
Emulator& m_emulator;
|
|
|
|
|
|
PartAddressableRegister m_gpr[8];
|
|
PartAddressableRegister m_gpr[8];
|
|
|
|
+ PartAddressableRegister m_gpr_shadow[8];
|
|
|
|
+
|
|
u16 m_segment[8] { 0 };
|
|
u16 m_segment[8] { 0 };
|
|
u32 m_eflags { 0 };
|
|
u32 m_eflags { 0 };
|
|
|
|
|