mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 17:07:35 +00:00
LibX86+UserspaceEmulator: Don't store a32 in MemoryOrRegisterReference
The a32 bit tells us whether a memory address is 32-bit or not. We already have this information in Instruction, so just plumb that around instead of double-caching the bit.
This commit is contained in:
parent
bc66221ee3
commit
6a926a8c61
3 changed files with 38 additions and 45 deletions
|
@ -1026,12 +1026,12 @@ void SoftCPU::LEAVE32(const X86::Instruction&)
|
||||||
|
|
||||||
void SoftCPU::LEA_reg16_mem16(const X86::Instruction& insn)
|
void SoftCPU::LEA_reg16_mem16(const X86::Instruction& insn)
|
||||||
{
|
{
|
||||||
gpr16(insn.reg16()) = insn.modrm().resolve(*this, insn.segment_prefix()).offset();
|
gpr16(insn.reg16()) = insn.modrm().resolve(*this, insn).offset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftCPU::LEA_reg32_mem32(const X86::Instruction& insn)
|
void SoftCPU::LEA_reg32_mem32(const X86::Instruction& insn)
|
||||||
{
|
{
|
||||||
gpr32(insn.reg32()) = insn.modrm().resolve(*this, insn.segment_prefix()).offset();
|
gpr32(insn.reg32()) = insn.modrm().resolve(*this, insn).offset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftCPU::LES_reg16_mem16(const X86::Instruction&) { TODO(); }
|
void SoftCPU::LES_reg16_mem16(const X86::Instruction&) { TODO(); }
|
||||||
|
|
|
@ -725,37 +725,37 @@ const char* Instruction::reg32_name() const
|
||||||
return register_name(static_cast<RegisterIndex32>(register_index()));
|
return register_name(static_cast<RegisterIndex32>(register_index()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String MemoryOrRegisterReference::to_string_o8() const
|
String MemoryOrRegisterReference::to_string_o8(const Instruction& insn) const
|
||||||
{
|
{
|
||||||
if (is_register())
|
if (is_register())
|
||||||
return register_name(static_cast<RegisterIndex8>(m_register_index));
|
return register_name(static_cast<RegisterIndex8>(m_register_index));
|
||||||
return String::format("[%s]", to_string().characters());
|
return String::format("[%s]", to_string(insn).characters());
|
||||||
}
|
}
|
||||||
|
|
||||||
String MemoryOrRegisterReference::to_string_o16() const
|
String MemoryOrRegisterReference::to_string_o16(const Instruction& insn) const
|
||||||
{
|
{
|
||||||
if (is_register())
|
if (is_register())
|
||||||
return register_name(static_cast<RegisterIndex16>(m_register_index));
|
return register_name(static_cast<RegisterIndex16>(m_register_index));
|
||||||
return String::format("[%s]", to_string().characters());
|
return String::format("[%s]", to_string(insn).characters());
|
||||||
}
|
}
|
||||||
|
|
||||||
String MemoryOrRegisterReference::to_string_o32() const
|
String MemoryOrRegisterReference::to_string_o32(const Instruction& insn) const
|
||||||
{
|
{
|
||||||
if (is_register())
|
if (is_register())
|
||||||
return register_name(static_cast<RegisterIndex32>(m_register_index));
|
return register_name(static_cast<RegisterIndex32>(m_register_index));
|
||||||
return String::format("[%s]", to_string().characters());
|
return String::format("[%s]", to_string(insn).characters());
|
||||||
}
|
}
|
||||||
|
|
||||||
String MemoryOrRegisterReference::to_string_mm() const
|
String MemoryOrRegisterReference::to_string_mm(const Instruction& insn) const
|
||||||
{
|
{
|
||||||
if (is_register())
|
if (is_register())
|
||||||
return register_name(static_cast<MMXRegisterIndex>(m_register_index));
|
return register_name(static_cast<MMXRegisterIndex>(m_register_index));
|
||||||
return String::format("[%s]", to_string().characters());
|
return String::format("[%s]", to_string(insn).characters());
|
||||||
}
|
}
|
||||||
|
|
||||||
String MemoryOrRegisterReference::to_string() const
|
String MemoryOrRegisterReference::to_string(const Instruction& insn) const
|
||||||
{
|
{
|
||||||
if (m_a32)
|
if (insn.a32())
|
||||||
return to_string_a32();
|
return to_string_a32();
|
||||||
return to_string_a16();
|
return to_string_a16();
|
||||||
}
|
}
|
||||||
|
@ -1032,9 +1032,9 @@ String Instruction::to_string_internal(u32 origin, const SymbolProvider* symbol_
|
||||||
return builder.to_string();
|
return builder.to_string();
|
||||||
};
|
};
|
||||||
|
|
||||||
auto append_rm8 = [&] { builder.append(m_modrm.to_string_o8()); };
|
auto append_rm8 = [&] { builder.append(m_modrm.to_string_o8(*this)); };
|
||||||
auto append_rm16 = [&] { builder.append(m_modrm.to_string_o16()); };
|
auto append_rm16 = [&] { builder.append(m_modrm.to_string_o16(*this)); };
|
||||||
auto append_rm32 = [&] { builder.append(m_modrm.to_string_o32()); };
|
auto append_rm32 = [&] { builder.append(m_modrm.to_string_o32(*this)); };
|
||||||
auto append_imm8 = [&] { builder.appendf("%#02x", imm8()); };
|
auto append_imm8 = [&] { builder.appendf("%#02x", imm8()); };
|
||||||
auto append_imm8_2 = [&] { builder.appendf("%#02x", imm8_2()); };
|
auto append_imm8_2 = [&] { builder.appendf("%#02x", imm8_2()); };
|
||||||
auto append_imm16 = [&] { builder.appendf("%#04x", imm16()); };
|
auto append_imm16 = [&] { builder.appendf("%#04x", imm16()); };
|
||||||
|
@ -1054,7 +1054,7 @@ String Instruction::to_string_internal(u32 origin, const SymbolProvider* symbol_
|
||||||
auto append_relative_imm32 = [&] { builder.append(formatted_address(origin + 5, x32, i32(imm32()))); };
|
auto append_relative_imm32 = [&] { builder.append(formatted_address(origin + 5, x32, i32(imm32()))); };
|
||||||
|
|
||||||
auto append_mm = [&] { builder.appendf("mm%u", register_index()); };
|
auto append_mm = [&] { builder.appendf("mm%u", register_index()); };
|
||||||
auto append_mmrm64 = [&] { builder.append(m_modrm.to_string_mm()); };
|
auto append_mmrm64 = [&] { builder.append(m_modrm.to_string_mm(*this)); };
|
||||||
|
|
||||||
auto append = [&](auto& content) { builder.append(content); };
|
auto append = [&](auto& content) { builder.append(content); };
|
||||||
auto append_moff = [&] {
|
auto append_moff = [&] {
|
||||||
|
|
|
@ -336,10 +336,10 @@ class MemoryOrRegisterReference {
|
||||||
friend class Instruction;
|
friend class Instruction;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
String to_string_o8() const;
|
String to_string_o8(const Instruction&) const;
|
||||||
String to_string_o16() const;
|
String to_string_o16(const Instruction&) const;
|
||||||
String to_string_o32() const;
|
String to_string_o32(const Instruction&) const;
|
||||||
String to_string_mm() const;
|
String to_string_mm(const Instruction&) const;
|
||||||
|
|
||||||
bool is_register() const { return m_register_index != 0xffffffff; }
|
bool is_register() const { return m_register_index != 0xffffffff; }
|
||||||
|
|
||||||
|
@ -363,17 +363,12 @@ public:
|
||||||
u32 read32(CPU&, const Instruction&);
|
u32 read32(CPU&, const Instruction&);
|
||||||
|
|
||||||
template<typename CPU>
|
template<typename CPU>
|
||||||
ALWAYS_INLINE LogicalAddress resolve(const CPU& cpu, Optional<SegmentRegister> segment_prefix)
|
LogicalAddress resolve(const CPU&, const Instruction&);
|
||||||
{
|
|
||||||
if (m_a32)
|
|
||||||
return resolve32(cpu, segment_prefix);
|
|
||||||
return resolve16(cpu, segment_prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MemoryOrRegisterReference() { }
|
MemoryOrRegisterReference() { }
|
||||||
|
|
||||||
String to_string() const;
|
String to_string(const Instruction&) const;
|
||||||
String to_string_a16() const;
|
String to_string_a16() const;
|
||||||
String to_string_a32() const;
|
String to_string_a32() const;
|
||||||
|
|
||||||
|
@ -399,8 +394,6 @@ private:
|
||||||
u16 m_offset16;
|
u16 m_offset16;
|
||||||
};
|
};
|
||||||
|
|
||||||
u8 m_a32 { false };
|
|
||||||
|
|
||||||
u8 m_rm { 0 };
|
u8 m_rm { 0 };
|
||||||
u8 m_sib { 0 };
|
u8 m_sib { 0 };
|
||||||
u8 m_displacement_bytes { 0 };
|
u8 m_displacement_bytes { 0 };
|
||||||
|
@ -477,6 +470,8 @@ public:
|
||||||
|
|
||||||
u8 cc() const { return m_has_sub_op ? m_sub_op & 0xf : m_op & 0xf; }
|
u8 cc() const { return m_has_sub_op ? m_sub_op & 0xf : m_op & 0xf; }
|
||||||
|
|
||||||
|
bool a32() const { return m_a32; }
|
||||||
|
|
||||||
String to_string(u32 origin, const SymbolProvider* = nullptr, bool x32 = true) const;
|
String to_string(u32 origin, const SymbolProvider* = nullptr, bool x32 = true) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -517,8 +512,6 @@ private:
|
||||||
template<typename CPU>
|
template<typename CPU>
|
||||||
ALWAYS_INLINE LogicalAddress MemoryOrRegisterReference::resolve16(const CPU& cpu, Optional<SegmentRegister> segment_prefix)
|
ALWAYS_INLINE LogicalAddress MemoryOrRegisterReference::resolve16(const CPU& cpu, Optional<SegmentRegister> segment_prefix)
|
||||||
{
|
{
|
||||||
ASSERT(!m_a32);
|
|
||||||
|
|
||||||
auto default_segment = SegmentRegister::DS;
|
auto default_segment = SegmentRegister::DS;
|
||||||
u16 offset = 0;
|
u16 offset = 0;
|
||||||
|
|
||||||
|
@ -563,8 +556,6 @@ ALWAYS_INLINE LogicalAddress MemoryOrRegisterReference::resolve16(const CPU& cpu
|
||||||
template<typename CPU>
|
template<typename CPU>
|
||||||
ALWAYS_INLINE LogicalAddress MemoryOrRegisterReference::resolve32(const CPU& cpu, Optional<SegmentRegister> segment_prefix)
|
ALWAYS_INLINE LogicalAddress MemoryOrRegisterReference::resolve32(const CPU& cpu, Optional<SegmentRegister> segment_prefix)
|
||||||
{
|
{
|
||||||
ASSERT(m_a32);
|
|
||||||
|
|
||||||
auto default_segment = SegmentRegister::DS;
|
auto default_segment = SegmentRegister::DS;
|
||||||
u32 offset = 0;
|
u32 offset = 0;
|
||||||
|
|
||||||
|
@ -702,7 +693,7 @@ ALWAYS_INLINE void MemoryOrRegisterReference::write8(CPU& cpu, const Instruction
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto address = resolve(cpu, insn.segment_prefix());
|
auto address = resolve(cpu, insn);
|
||||||
cpu.write_memory8(address, value);
|
cpu.write_memory8(address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -714,7 +705,7 @@ ALWAYS_INLINE void MemoryOrRegisterReference::write16(CPU& cpu, const Instructio
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto address = resolve(cpu, insn.segment_prefix());
|
auto address = resolve(cpu, insn);
|
||||||
cpu.write_memory16(address, value);
|
cpu.write_memory16(address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,7 +717,7 @@ ALWAYS_INLINE void MemoryOrRegisterReference::write32(CPU& cpu, const Instructio
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto address = resolve(cpu, insn.segment_prefix());
|
auto address = resolve(cpu, insn);
|
||||||
cpu.write_memory32(address, value);
|
cpu.write_memory32(address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -736,7 +727,7 @@ ALWAYS_INLINE u8 MemoryOrRegisterReference::read8(CPU& cpu, const Instruction& i
|
||||||
if (is_register())
|
if (is_register())
|
||||||
return cpu.gpr8(reg8());
|
return cpu.gpr8(reg8());
|
||||||
|
|
||||||
auto address = resolve(cpu, insn.segment_prefix());
|
auto address = resolve(cpu, insn);
|
||||||
return cpu.read_memory8(address);
|
return cpu.read_memory8(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -746,7 +737,7 @@ ALWAYS_INLINE u16 MemoryOrRegisterReference::read16(CPU& cpu, const Instruction&
|
||||||
if (is_register())
|
if (is_register())
|
||||||
return cpu.gpr16(reg16());
|
return cpu.gpr16(reg16());
|
||||||
|
|
||||||
auto address = resolve(cpu, insn.segment_prefix());
|
auto address = resolve(cpu, insn);
|
||||||
return cpu.read_memory16(address);
|
return cpu.read_memory16(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,7 +747,7 @@ ALWAYS_INLINE u32 MemoryOrRegisterReference::read32(CPU& cpu, const Instruction&
|
||||||
if (is_register())
|
if (is_register())
|
||||||
return cpu.gpr32(reg32());
|
return cpu.gpr32(reg32());
|
||||||
|
|
||||||
auto address = resolve(cpu, insn.segment_prefix());
|
auto address = resolve(cpu, insn);
|
||||||
return cpu.read_memory32(address);
|
return cpu.read_memory32(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -919,10 +910,9 @@ ALWAYS_INLINE Instruction::Instruction(InstructionStreamType& stream, bool o32,
|
||||||
template<typename InstructionStreamType>
|
template<typename InstructionStreamType>
|
||||||
ALWAYS_INLINE void MemoryOrRegisterReference::decode(InstructionStreamType& stream, bool a32)
|
ALWAYS_INLINE void MemoryOrRegisterReference::decode(InstructionStreamType& stream, bool a32)
|
||||||
{
|
{
|
||||||
m_a32 = a32;
|
|
||||||
m_rm = stream.read8();
|
m_rm = stream.read8();
|
||||||
|
|
||||||
if (m_a32) {
|
if (a32) {
|
||||||
decode32(stream);
|
decode32(stream);
|
||||||
switch (m_displacement_bytes) {
|
switch (m_displacement_bytes) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -958,8 +948,6 @@ ALWAYS_INLINE void MemoryOrRegisterReference::decode(InstructionStreamType& stre
|
||||||
template<typename InstructionStreamType>
|
template<typename InstructionStreamType>
|
||||||
ALWAYS_INLINE void MemoryOrRegisterReference::decode16(InstructionStreamType&)
|
ALWAYS_INLINE void MemoryOrRegisterReference::decode16(InstructionStreamType&)
|
||||||
{
|
{
|
||||||
ASSERT(!m_a32);
|
|
||||||
|
|
||||||
switch (m_rm & 0xc0) {
|
switch (m_rm & 0xc0) {
|
||||||
case 0:
|
case 0:
|
||||||
if ((m_rm & 0x07) == 6)
|
if ((m_rm & 0x07) == 6)
|
||||||
|
@ -982,8 +970,6 @@ ALWAYS_INLINE void MemoryOrRegisterReference::decode16(InstructionStreamType&)
|
||||||
template<typename InstructionStreamType>
|
template<typename InstructionStreamType>
|
||||||
ALWAYS_INLINE void MemoryOrRegisterReference::decode32(InstructionStreamType& stream)
|
ALWAYS_INLINE void MemoryOrRegisterReference::decode32(InstructionStreamType& stream)
|
||||||
{
|
{
|
||||||
ASSERT(m_a32);
|
|
||||||
|
|
||||||
switch (m_rm & 0xc0) {
|
switch (m_rm & 0xc0) {
|
||||||
case 0:
|
case 0:
|
||||||
if ((m_rm & 0x07) == 5)
|
if ((m_rm & 0x07) == 5)
|
||||||
|
@ -1025,5 +1011,12 @@ ALWAYS_INLINE void MemoryOrRegisterReference::decode32(InstructionStreamType& st
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CPU>
|
||||||
|
ALWAYS_INLINE LogicalAddress MemoryOrRegisterReference::resolve(const CPU& cpu, const Instruction& insn)
|
||||||
|
{
|
||||||
|
if (insn.a32())
|
||||||
|
return resolve32(cpu, insn.segment_prefix());
|
||||||
|
return resolve16(cpu, insn.segment_prefix());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue