1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 06:47:35 +00:00

LibX86: Use names closer to the spec for the Modrm

This gets rid of a lot of magic number shifts and ands.
This commit is contained in:
Hendiadyoin1 2021-07-08 17:46:13 +02:00 committed by Andreas Kling
parent 68193c365f
commit efa42c4d45
3 changed files with 58 additions and 53 deletions

View file

@ -1721,7 +1721,7 @@ void SoftCPU::FCMOVB(const X86::Instruction& insn)
{
VERIFY(insn.modrm().is_register());
if (cf())
fpu_set(0, fpu_get(insn.rm() & 7));
fpu_set(0, fpu_get(insn.modrm().rm()));
}
void SoftCPU::FIMUL_RM32(const X86::Instruction& insn)
@ -1736,7 +1736,7 @@ void SoftCPU::FCMOVE(const X86::Instruction& insn)
{
VERIFY(insn.modrm().is_register());
if (zf())
fpu_set(0, fpu_get(insn.rm() & 7));
fpu_set(0, fpu_get(insn.modrm().rm()));
}
void SoftCPU::FICOM_RM32(const X86::Instruction&) { TODO_INSN(); }
@ -1744,7 +1744,7 @@ void SoftCPU::FICOM_RM32(const X86::Instruction&) { TODO_INSN(); }
void SoftCPU::FCMOVBE(const X86::Instruction& insn)
{
if (evaluate_condition(6))
fpu_set(0, fpu_get(insn.rm() & 7));
fpu_set(0, fpu_get(insn.modrm().rm()));
}
void SoftCPU::FICOMP_RM32(const X86::Instruction&) { TODO_INSN(); }
@ -1832,7 +1832,7 @@ void SoftCPU::FIST_RM32(const X86::Instruction& insn)
void SoftCPU::FCMOVNBE(const X86::Instruction& insn)
{
if (evaluate_condition(7))
fpu_set(0, fpu_get(insn.rm() & 7));
fpu_set(0, fpu_get(insn.modrm().rm()));
}
void SoftCPU::FISTP_RM32(const X86::Instruction& insn)
@ -1869,7 +1869,7 @@ void SoftCPU::FLD_RM80(const X86::Instruction& insn)
void SoftCPU::FUCOMI(const X86::Instruction& insn)
{
auto i = insn.rm() & 7;
auto i = insn.modrm().rm();
// FIXME: Unordered comparison checks.
// FIXME: QNaN / exception handling.
// FIXME: Set C0, C2, C3 in FPU status word.
@ -1890,7 +1890,7 @@ void SoftCPU::FUCOMI(const X86::Instruction& insn)
void SoftCPU::FCOMI(const X86::Instruction& insn)
{
auto i = insn.rm() & 7;
auto i = insn.modrm().rm();
// FIXME: QNaN / exception handling.
// FIXME: Set C0, C2, C3 in FPU status word.
set_zf(fpu_get(0) == fpu_get(i));

View file

@ -1037,7 +1037,7 @@ String MemoryOrRegisterReference::to_string_a16() const
String base;
bool hasDisplacement = false;
switch (m_rm & 7) {
switch (rm()) {
case 0:
base = "bx+si";
break;
@ -1060,16 +1060,16 @@ String MemoryOrRegisterReference::to_string_a16() const
base = "bx";
break;
case 6:
if ((m_rm & 0xc0) == 0)
if (mod() == 0)
base = String::formatted("{:#04x}", m_displacement16);
else
base = "bp";
break;
}
switch (m_rm & 0xc0) {
case 0x40:
case 0x80:
switch (mod()) {
case 0b01:
case 0b10:
hasDisplacement = true;
}
@ -1178,16 +1178,16 @@ String MemoryOrRegisterReference::to_string_a32() const
return register_name(static_cast<RegisterIndex32>(m_register_index));
bool has_displacement = false;
switch (m_rm & 0xc0) {
case 0x40:
case 0x80:
switch (mod()) {
case 0b01:
case 0b10:
has_displacement = true;
}
if (m_has_sib && (m_sib & 7) == 5)
has_displacement = true;
String base;
switch (m_rm & 7) {
switch (rm()) {
case 0:
base = "eax";
break;
@ -1207,13 +1207,13 @@ String MemoryOrRegisterReference::to_string_a32() const
base = "edi";
break;
case 5:
if ((m_rm & 0xc0) == 0)
if (mod() == 0)
base = String::formatted("{:#08x}", m_displacement32);
else
base = "ebp";
break;
case 4:
base = sib_to_string(m_rm, m_sib);
base = sib_to_string(m_rm_byte, m_sib);
break;
}
@ -1766,7 +1766,7 @@ void Instruction::to_string_internal(StringBuilder& builder, u32 origin, const S
break;
case OP_reg32_CR:
append_mnemonic_space();
builder.append(register_name(static_cast<RegisterIndex32>(rm() & 7)));
builder.append(register_name(static_cast<RegisterIndex32>(modrm().rm())));
append(", ");
append_creg();
break;
@ -1774,11 +1774,11 @@ void Instruction::to_string_internal(StringBuilder& builder, u32 origin, const S
append_mnemonic_space();
append_creg();
append(", ");
builder.append(register_name(static_cast<RegisterIndex32>(rm() & 7)));
builder.append(register_name(static_cast<RegisterIndex32>(modrm().rm())));
break;
case OP_reg32_DR:
append_mnemonic_space();
builder.append(register_name(static_cast<RegisterIndex32>(rm() & 7)));
builder.append(register_name(static_cast<RegisterIndex32>(modrm().rm())));
append(", ");
append_dreg();
break;
@ -1786,7 +1786,7 @@ void Instruction::to_string_internal(StringBuilder& builder, u32 origin, const S
append_mnemonic_space();
append_dreg();
append(", ");
builder.append(register_name(static_cast<RegisterIndex32>(rm() & 7)));
builder.append(register_name(static_cast<RegisterIndex32>(modrm().rm())));
break;
case OP_short_imm8:
append_mnemonic_space();

View file

@ -374,6 +374,11 @@ public:
RegisterIndex8 reg8() const { return static_cast<RegisterIndex8>(register_index()); }
FpuRegisterIndex reg_fpu() const { return static_cast<FpuRegisterIndex>(register_index()); }
// helpers to get the parts by name as in the spec
u8 mod() const { return m_rm_byte >> 6; }
u8 reg() const { return m_rm_byte >> 3 & 0b111; }
u8 rm() const { return m_rm_byte & 0b111; }
template<typename CPU, typename T>
void write8(CPU&, const Instruction&, T);
template<typename CPU, typename T>
@ -429,7 +434,7 @@ private:
u16 m_displacement16;
};
u8 m_rm { 0 };
u8 m_rm_byte { 0 };
u8 m_sib { 0 };
u8 m_displacement_bytes { 0 };
u8 m_register_index : 7 { 0x7f };
@ -467,8 +472,8 @@ public:
String mnemonic() const;
u8 op() const { return m_op; }
u8 rm() const { return m_modrm.m_rm; }
u8 slash() const { return (rm() >> 3) & 7; }
u8 modrm_byte() const { return m_modrm.m_rm_byte; }
u8 slash() const { return (modrm_byte() >> 3) & 7; }
u8 imm8() const { return m_imm1; }
u16 imm16() const { return m_imm1; }
@ -535,7 +540,7 @@ ALWAYS_INLINE LogicalAddress MemoryOrRegisterReference::resolve16(const CPU& cpu
auto default_segment = SegmentRegister::DS;
u16 offset = 0;
switch (m_rm & 7) {
switch (rm()) {
case 0:
offset = cpu.bx().value() + cpu.si().value() + m_displacement16;
break;
@ -557,7 +562,7 @@ ALWAYS_INLINE LogicalAddress MemoryOrRegisterReference::resolve16(const CPU& cpu
offset = cpu.di().value() + m_displacement16;
break;
case 6:
if ((m_rm & 0xc0) == 0)
if (mod() == 0)
offset = m_displacement16;
else {
default_segment = SegmentRegister::SS;
@ -579,16 +584,16 @@ ALWAYS_INLINE LogicalAddress MemoryOrRegisterReference::resolve32(const CPU& cpu
auto default_segment = SegmentRegister::DS;
u32 offset = 0;
switch (m_rm & 0x07) {
switch (rm()) {
case 0 ... 3:
case 6 ... 7:
offset = cpu.const_gpr32((RegisterIndex32)(m_rm & 0x07)).value() + m_displacement32;
offset = cpu.const_gpr32((RegisterIndex32)(rm())).value() + m_displacement32;
break;
case 4:
offset = evaluate_sib(cpu, default_segment);
break;
default: // 5
if ((m_rm & 0xc0) == 0x00) {
if (mod() == 0) {
offset = m_displacement32;
break;
} else {
@ -628,7 +633,7 @@ ALWAYS_INLINE u32 MemoryOrRegisterReference::evaluate_sib(const CPU& cpu, Segmen
base += cpu.esp().value();
break;
default: // 5
switch ((m_rm >> 6) & 3) {
switch (mod()) {
case 0:
break;
case 1:
@ -846,7 +851,7 @@ ALWAYS_INLINE Instruction::Instruction(InstructionStreamType& stream, bool o32,
if (m_descriptor->has_rm) {
// Consume ModR/M (may include SIB and displacement.)
m_modrm.decode(stream, m_a32);
m_register_index = (m_modrm.m_rm >> 3) & 7;
m_register_index = m_modrm.reg();
} else {
if (has_sub_op())
m_register_index = m_sub_op & 7;
@ -857,8 +862,8 @@ ALWAYS_INLINE Instruction::Instruction(InstructionStreamType& stream, bool o32,
bool has_slash = m_descriptor->format == MultibyteWithSlash;
if (has_slash) {
m_descriptor = &m_descriptor->slashes[slash()];
if ((rm() & 0xc0) == 0xc0 && m_descriptor->slashes)
m_descriptor = &m_descriptor->slashes[rm() & 7];
if ((modrm_byte() & 0xc0) == 0xc0 && m_descriptor->slashes)
m_descriptor = &m_descriptor->slashes[modrm_byte() & 7];
}
if (!m_descriptor->mnemonic) {
@ -924,7 +929,7 @@ ALWAYS_INLINE Instruction::Instruction(InstructionStreamType& stream, bool o32,
template<typename InstructionStreamType>
ALWAYS_INLINE void MemoryOrRegisterReference::decode(InstructionStreamType& stream, bool a32)
{
m_rm = stream.read8();
m_rm_byte = stream.read8();
if (a32) {
decode32(stream);
@ -962,21 +967,21 @@ ALWAYS_INLINE void MemoryOrRegisterReference::decode(InstructionStreamType& stre
template<typename InstructionStreamType>
ALWAYS_INLINE void MemoryOrRegisterReference::decode16(InstructionStreamType&)
{
switch (m_rm & 0xc0) {
case 0:
if ((m_rm & 0x07) == 6)
switch (mod()) {
case 0b00:
if (rm() == 6)
m_displacement_bytes = 2;
else
VERIFY(m_displacement_bytes == 0);
break;
case 0x40:
case 0b01:
m_displacement_bytes = 1;
break;
case 0x80:
case 0b10:
m_displacement_bytes = 2;
break;
case 0xc0:
m_register_index = m_rm & 7;
case 0b11:
m_register_index = rm();
break;
}
}
@ -984,34 +989,34 @@ ALWAYS_INLINE void MemoryOrRegisterReference::decode16(InstructionStreamType&)
template<typename InstructionStreamType>
ALWAYS_INLINE void MemoryOrRegisterReference::decode32(InstructionStreamType& stream)
{
switch (m_rm & 0xc0) {
case 0:
if ((m_rm & 0x07) == 5)
switch (mod()) {
case 0b00:
if (rm() == 5)
m_displacement_bytes = 4;
break;
case 0x40:
case 0b01:
m_displacement_bytes = 1;
break;
case 0x80:
case 0b10:
m_displacement_bytes = 4;
break;
case 0xc0:
m_register_index = m_rm & 7;
case 0b11:
m_register_index = rm();
return;
}
m_has_sib = (m_rm & 0x07) == 4;
m_has_sib = rm() == 4;
if (m_has_sib) {
m_sib = stream.read8();
if ((m_sib & 0x07) == 5) {
switch ((m_rm >> 6) & 0x03) {
case 0:
switch (mod()) {
case 0b00:
m_displacement_bytes = 4;
break;
case 1:
case 0b01:
m_displacement_bytes = 1;
break;
case 2:
case 0b10:
m_displacement_bytes = 4;
break;
default: