summaryrefslogtreecommitdiff
path: root/Libraries/LibX86/Instruction.h
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-07-10 17:18:49 +0200
committerAndreas Kling <kling@serenityos.org>2020-07-10 20:20:27 +0200
commit0cf7fd5268582eca705158f71541013ef340738d (patch)
tree3541d1fd69c521e8912d9d322611c75ebd6173a4 /Libraries/LibX86/Instruction.h
parent9955819d92438a06465927b3b4eadb8fc1c383e1 (diff)
downloadserenity-0cf7fd5268582eca705158f71541013ef340738d.zip
UserspaceEmulator+LibX86: Implement all the forms of XOR
And they're all generic, which will make it easy to support more ops.
Diffstat (limited to 'Libraries/LibX86/Instruction.h')
-rw-r--r--Libraries/LibX86/Instruction.h64
1 files changed, 62 insertions, 2 deletions
diff --git a/Libraries/LibX86/Instruction.h b/Libraries/LibX86/Instruction.h
index ea928ee3eb..17208a829b 100644
--- a/Libraries/LibX86/Instruction.h
+++ b/Libraries/LibX86/Instruction.h
@@ -205,9 +205,17 @@ public:
RegisterIndex8 reg8() const { return static_cast<RegisterIndex8>(register_index()); }
template<typename CPU>
+ void write8(CPU&, const Instruction&, u8);
+ template<typename CPU>
+ void write16(CPU&, const Instruction&, u16);
+ template<typename CPU>
void write32(CPU&, const Instruction&, u32);
template<typename CPU>
+ u8 read8(CPU&, const Instruction&);
+ template<typename CPU>
+ u16 read16(CPU&, const Instruction&);
+ template<typename CPU>
u32 read32(CPU&, const Instruction&);
private:
@@ -227,6 +235,14 @@ private:
LogicalAddress resolve32(const CPU&, Optional<SegmentRegister>);
template<typename CPU>
+ LogicalAddress resolve(const CPU& cpu, Optional<SegmentRegister> segment_prefix)
+ {
+ if (m_a32)
+ return resolve32(cpu, segment_prefix);
+ return resolve16(cpu, segment_prefix);
+ }
+
+ template<typename CPU>
u32 evaluate_sib(const CPU&, SegmentRegister& default_segment) const;
unsigned m_register_index { 0xffffffff };
@@ -560,6 +576,30 @@ inline u32 MemoryOrRegisterReference::evaluate_sib(const CPU& cpu, SegmentRegist
}
template<typename CPU>
+inline void MemoryOrRegisterReference::write8(CPU& cpu, const Instruction& insn, u8 value)
+{
+ if (is_register()) {
+ cpu.gpr8(reg8()) = value;
+ return;
+ }
+
+ auto address = resolve(cpu, insn.segment_prefix());
+ cpu.write_memory8(address, value);
+}
+
+template<typename CPU>
+inline void MemoryOrRegisterReference::write16(CPU& cpu, const Instruction& insn, u16 value)
+{
+ if (is_register()) {
+ cpu.gpr16(reg16()) = value;
+ return;
+ }
+
+ auto address = resolve(cpu, insn.segment_prefix());
+ cpu.write_memory16(address, value);
+}
+
+template<typename CPU>
inline void MemoryOrRegisterReference::write32(CPU& cpu, const Instruction& insn, u32 value)
{
if (is_register()) {
@@ -567,17 +607,37 @@ inline void MemoryOrRegisterReference::write32(CPU& cpu, const Instruction& insn
return;
}
- auto address = resolve32(cpu, insn.segment_prefix());
+ auto address = resolve(cpu, insn.segment_prefix());
cpu.write_memory32(address, value);
}
template<typename CPU>
+inline u8 MemoryOrRegisterReference::read8(CPU& cpu, const Instruction& insn)
+{
+ if (is_register())
+ return cpu.gpr8(reg8());
+
+ auto address = resolve(cpu, insn.segment_prefix());
+ return cpu.read_memory8(address);
+}
+
+template<typename CPU>
+inline u16 MemoryOrRegisterReference::read16(CPU& cpu, const Instruction& insn)
+{
+ if (is_register())
+ return cpu.gpr16(reg16());
+
+ auto address = resolve(cpu, insn.segment_prefix());
+ return cpu.read_memory16(address);
+}
+
+template<typename CPU>
inline u32 MemoryOrRegisterReference::read32(CPU& cpu, const Instruction& insn)
{
if (is_register())
return cpu.gpr32(reg32());
- auto address = resolve32(cpu, insn.segment_prefix());
+ auto address = resolve(cpu, insn.segment_prefix());
return cpu.read_memory32(address);
}