mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 04:57:45 +00:00
LibX86: Add {Address,Operand}Size::Size64
For now the opcode tables for OperandSize::Size64 are empty
This commit is contained in:
parent
a7268c3c74
commit
06ece474e9
4 changed files with 98 additions and 11 deletions
|
@ -106,9 +106,10 @@ public:
|
||||||
return m_gpr[X86::RegisterEDX].reference_to<&PartAddressableRegister::low_u8>();
|
return m_gpr[X86::RegisterEDX].reference_to<&PartAddressableRegister::low_u8>();
|
||||||
case X86::RegisterDH:
|
case X86::RegisterDH:
|
||||||
return m_gpr[X86::RegisterEDX].reference_to<&PartAddressableRegister::high_u8>();
|
return m_gpr[X86::RegisterEDX].reference_to<&PartAddressableRegister::high_u8>();
|
||||||
}
|
default:
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ValueWithShadow<u8> const_gpr8(X86::RegisterIndex8 reg) const
|
ValueWithShadow<u8> const_gpr8(X86::RegisterIndex8 reg) const
|
||||||
{
|
{
|
||||||
|
@ -129,9 +130,10 @@ public:
|
||||||
return m_gpr[X86::RegisterEDX].slice<&PartAddressableRegister::low_u8>();
|
return m_gpr[X86::RegisterEDX].slice<&PartAddressableRegister::low_u8>();
|
||||||
case X86::RegisterDH:
|
case X86::RegisterDH:
|
||||||
return m_gpr[X86::RegisterEDX].slice<&PartAddressableRegister::high_u8>();
|
return m_gpr[X86::RegisterEDX].slice<&PartAddressableRegister::high_u8>();
|
||||||
}
|
default:
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ValueWithShadow<u16> const_gpr16(X86::RegisterIndex16 reg) const
|
ValueWithShadow<u16> const_gpr16(X86::RegisterIndex16 reg) const
|
||||||
{
|
{
|
||||||
|
@ -211,9 +213,10 @@ public:
|
||||||
case X86::AddressSize::Size16:
|
case X86::AddressSize::Size16:
|
||||||
set_cx(ValueWithShadow<u16>(cx().value() - 1, cx().shadow()));
|
set_cx(ValueWithShadow<u16>(cx().value() - 1, cx().shadow()));
|
||||||
return cx().value() == 0;
|
return cx().value() == 0;
|
||||||
}
|
default:
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE void step_source_index(X86::AddressSize address_size, u32 step)
|
ALWAYS_INLINE void step_source_index(X86::AddressSize address_size, u32 step)
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,8 +25,12 @@ public:
|
||||||
#if ARCH(I386)
|
#if ARCH(I386)
|
||||||
return Instruction::from_stream(m_stream, OperandSize::Size32, AddressSize::Size32);
|
return Instruction::from_stream(m_stream, OperandSize::Size32, AddressSize::Size32);
|
||||||
#else
|
#else
|
||||||
dbgln("FIXME: Implement disassembly support for x86_64");
|
# if ARCH(X86_64)
|
||||||
|
return Instruction::from_stream(m_stream, OperandSize::Size64, AddressSize::Size64);
|
||||||
|
# else
|
||||||
|
dbgln("Unsupported platform");
|
||||||
return {};
|
return {};
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
|
|
||||||
namespace X86 {
|
namespace X86 {
|
||||||
|
|
||||||
InstructionDescriptor s_table[2][256];
|
InstructionDescriptor s_table[3][256];
|
||||||
InstructionDescriptor s_0f_table[2][256];
|
InstructionDescriptor s_0f_table[3][256];
|
||||||
InstructionDescriptor s_sse_table_np[256];
|
InstructionDescriptor s_sse_table_np[256];
|
||||||
InstructionDescriptor s_sse_table_66[256];
|
InstructionDescriptor s_sse_table_66[256];
|
||||||
InstructionDescriptor s_sse_table_f3[256];
|
InstructionDescriptor s_sse_table_f3[256];
|
||||||
|
@ -1307,6 +1307,8 @@ String MemoryOrRegisterReference::to_string_xmm(Instruction const& insn) const
|
||||||
String MemoryOrRegisterReference::to_string(Instruction const& insn) const
|
String MemoryOrRegisterReference::to_string(Instruction const& insn) const
|
||||||
{
|
{
|
||||||
switch (insn.address_size()) {
|
switch (insn.address_size()) {
|
||||||
|
case AddressSize::Size64:
|
||||||
|
return to_string_a64();
|
||||||
case AddressSize::Size32:
|
case AddressSize::Size32:
|
||||||
return to_string_a32();
|
return to_string_a32();
|
||||||
case AddressSize::Size16:
|
case AddressSize::Size16:
|
||||||
|
@ -1455,6 +1457,65 @@ static String sib_to_string(u8 rm, u8 sib)
|
||||||
return builder.to_string();
|
return builder.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String MemoryOrRegisterReference::to_string_a64() const
|
||||||
|
{
|
||||||
|
if (is_register())
|
||||||
|
return register_name(static_cast<RegisterIndex32>(m_register_index));
|
||||||
|
|
||||||
|
bool has_displacement = false;
|
||||||
|
switch (mod()) {
|
||||||
|
case 0b00:
|
||||||
|
has_displacement = rm() == 5;
|
||||||
|
break;
|
||||||
|
case 0b01:
|
||||||
|
case 0b10:
|
||||||
|
has_displacement = true;
|
||||||
|
}
|
||||||
|
if (m_has_sib && (m_sib & 7) == 5)
|
||||||
|
has_displacement = true;
|
||||||
|
|
||||||
|
String base;
|
||||||
|
switch (rm()) {
|
||||||
|
case 0:
|
||||||
|
base = "rax";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
base = "rcx";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
base = "rdx";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
base = "rbx";
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
base = "rsi";
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
base = "rdi";
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
if (mod() == 0)
|
||||||
|
base = String::formatted("{:#08x}", m_displacement32);
|
||||||
|
else
|
||||||
|
base = "rbp";
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
base = sib_to_string(m_rm_byte, m_sib);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!has_displacement)
|
||||||
|
return base;
|
||||||
|
|
||||||
|
String displacement_string;
|
||||||
|
if ((i32)m_displacement32 < 0)
|
||||||
|
displacement_string = String::formatted("-{:#x}", -(i32)m_displacement32);
|
||||||
|
else
|
||||||
|
displacement_string = String::formatted("+{:#x}", m_displacement32);
|
||||||
|
return String::formatted("{}{}", base, displacement_string);
|
||||||
|
}
|
||||||
|
|
||||||
String MemoryOrRegisterReference::to_string_a32() const
|
String MemoryOrRegisterReference::to_string_a32() const
|
||||||
{
|
{
|
||||||
if (is_register())
|
if (is_register())
|
||||||
|
@ -1541,6 +1602,9 @@ String Instruction::to_string(u32 origin, SymbolProvider const* symbol_provider,
|
||||||
case AddressSize::Size32:
|
case AddressSize::Size32:
|
||||||
builder.append("a32"sv);
|
builder.append("a32"sv);
|
||||||
break;
|
break;
|
||||||
|
case AddressSize::Size64:
|
||||||
|
builder.append("a64"sv);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (has_operand_size_override_prefix()) {
|
if (has_operand_size_override_prefix()) {
|
||||||
|
@ -1551,6 +1615,9 @@ String Instruction::to_string(u32 origin, SymbolProvider const* symbol_provider,
|
||||||
case OperandSize::Size32:
|
case OperandSize::Size32:
|
||||||
builder.append("o32"sv);
|
builder.append("o32"sv);
|
||||||
break;
|
break;
|
||||||
|
case OperandSize::Size64:
|
||||||
|
builder.append("o64"sv);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (has_lock_prefix())
|
if (has_lock_prefix())
|
||||||
|
|
|
@ -45,11 +45,13 @@ constexpr T sign_extended_to(U value)
|
||||||
enum class OperandSize : u8 {
|
enum class OperandSize : u8 {
|
||||||
Size16,
|
Size16,
|
||||||
Size32,
|
Size32,
|
||||||
|
Size64,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class AddressSize : u8 {
|
enum class AddressSize : u8 {
|
||||||
Size16,
|
Size16,
|
||||||
Size32,
|
Size32,
|
||||||
|
Size64,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum IsLockPrefixAllowed {
|
enum IsLockPrefixAllowed {
|
||||||
|
@ -228,6 +230,8 @@ struct InstructionDescriptor {
|
||||||
{
|
{
|
||||||
if (imm1_bytes == CurrentAddressSize) {
|
if (imm1_bytes == CurrentAddressSize) {
|
||||||
switch (size) {
|
switch (size) {
|
||||||
|
case AddressSize::Size64:
|
||||||
|
return 8;
|
||||||
case AddressSize::Size32:
|
case AddressSize::Size32:
|
||||||
return 4;
|
return 4;
|
||||||
case AddressSize::Size16:
|
case AddressSize::Size16:
|
||||||
|
@ -242,6 +246,8 @@ struct InstructionDescriptor {
|
||||||
{
|
{
|
||||||
if (imm2_bytes == CurrentAddressSize) {
|
if (imm2_bytes == CurrentAddressSize) {
|
||||||
switch (size) {
|
switch (size) {
|
||||||
|
case AddressSize::Size64:
|
||||||
|
return 8;
|
||||||
case AddressSize::Size32:
|
case AddressSize::Size32:
|
||||||
return 4;
|
return 4;
|
||||||
case AddressSize::Size16:
|
case AddressSize::Size16:
|
||||||
|
@ -255,8 +261,8 @@ struct InstructionDescriptor {
|
||||||
IsLockPrefixAllowed lock_prefix_allowed { LockPrefixNotAllowed };
|
IsLockPrefixAllowed lock_prefix_allowed { LockPrefixNotAllowed };
|
||||||
};
|
};
|
||||||
|
|
||||||
extern InstructionDescriptor s_table[2][256];
|
extern InstructionDescriptor s_table[3][256];
|
||||||
extern InstructionDescriptor s_0f_table[2][256];
|
extern InstructionDescriptor s_0f_table[3][256];
|
||||||
extern InstructionDescriptor s_sse_table_np[256];
|
extern InstructionDescriptor s_sse_table_np[256];
|
||||||
extern InstructionDescriptor s_sse_table_66[256];
|
extern InstructionDescriptor s_sse_table_66[256];
|
||||||
extern InstructionDescriptor s_sse_table_f3[256];
|
extern InstructionDescriptor s_sse_table_f3[256];
|
||||||
|
@ -489,6 +495,7 @@ private:
|
||||||
String to_string(Instruction const&) const;
|
String to_string(Instruction const&) const;
|
||||||
String to_string_a16() const;
|
String to_string_a16() const;
|
||||||
String to_string_a32() const;
|
String to_string_a32() const;
|
||||||
|
String to_string_a64() const;
|
||||||
|
|
||||||
template<typename InstructionStreamType>
|
template<typename InstructionStreamType>
|
||||||
void decode(InstructionStreamType&, AddressSize);
|
void decode(InstructionStreamType&, AddressSize);
|
||||||
|
@ -553,15 +560,20 @@ public:
|
||||||
u8 imm8() const { return m_imm1; }
|
u8 imm8() const { return m_imm1; }
|
||||||
u16 imm16() const { return m_imm1; }
|
u16 imm16() const { return m_imm1; }
|
||||||
u32 imm32() const { return m_imm1; }
|
u32 imm32() const { return m_imm1; }
|
||||||
|
u64 imm64() const { return m_imm1; }
|
||||||
u8 imm8_1() const { return imm8(); }
|
u8 imm8_1() const { return imm8(); }
|
||||||
u8 imm8_2() const { return m_imm2; }
|
u8 imm8_2() const { return m_imm2; }
|
||||||
u16 imm16_1() const { return imm16(); }
|
u16 imm16_1() const { return imm16(); }
|
||||||
u16 imm16_2() const { return m_imm2; }
|
u16 imm16_2() const { return m_imm2; }
|
||||||
u32 imm32_1() const { return imm32(); }
|
u32 imm32_1() const { return imm32(); }
|
||||||
u32 imm32_2() const { return m_imm2; }
|
u32 imm32_2() const { return m_imm2; }
|
||||||
|
u64 imm64_1() const { return imm64(); }
|
||||||
|
u64 imm64_2() const { return m_imm2; }
|
||||||
u32 imm_address() const
|
u32 imm_address() const
|
||||||
{
|
{
|
||||||
switch (m_address_size) {
|
switch (m_address_size) {
|
||||||
|
case AddressSize::Size64:
|
||||||
|
return imm64();
|
||||||
case AddressSize::Size32:
|
case AddressSize::Size32:
|
||||||
return imm32();
|
return imm32();
|
||||||
case AddressSize::Size16:
|
case AddressSize::Size16:
|
||||||
|
@ -603,8 +615,8 @@ private:
|
||||||
|
|
||||||
InstructionDescriptor* m_descriptor { nullptr };
|
InstructionDescriptor* m_descriptor { nullptr };
|
||||||
mutable MemoryOrRegisterReference m_modrm;
|
mutable MemoryOrRegisterReference m_modrm;
|
||||||
u32 m_imm1 { 0 };
|
u64 m_imm1 { 0 };
|
||||||
u32 m_imm2 { 0 };
|
u64 m_imm2 { 0 };
|
||||||
u8 m_segment_prefix { 0xff };
|
u8 m_segment_prefix { 0xff };
|
||||||
u8 m_register_index { 0xff };
|
u8 m_register_index { 0xff };
|
||||||
u8 m_op { 0 };
|
u8 m_op { 0 };
|
||||||
|
@ -1137,8 +1149,9 @@ ALWAYS_INLINE LogicalAddress MemoryOrRegisterReference::resolve(const CPU& cpu,
|
||||||
return resolve16(cpu, insn.segment_prefix());
|
return resolve16(cpu, insn.segment_prefix());
|
||||||
case AddressSize::Size32:
|
case AddressSize::Size32:
|
||||||
return resolve32(cpu, insn.segment_prefix());
|
return resolve32(cpu, insn.segment_prefix());
|
||||||
}
|
default:
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue