summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibX86
diff options
context:
space:
mode:
Diffstat (limited to 'Userland/Libraries/LibX86')
-rw-r--r--Userland/Libraries/LibX86/Disassembler.h6
-rw-r--r--Userland/Libraries/LibX86/Instruction.cpp71
-rw-r--r--Userland/Libraries/LibX86/Instruction.h23
3 files changed, 92 insertions, 8 deletions
diff --git a/Userland/Libraries/LibX86/Disassembler.h b/Userland/Libraries/LibX86/Disassembler.h
index 01cf39a075..1abd5d0ae3 100644
--- a/Userland/Libraries/LibX86/Disassembler.h
+++ b/Userland/Libraries/LibX86/Disassembler.h
@@ -25,8 +25,12 @@ public:
#if ARCH(I386)
return Instruction::from_stream(m_stream, OperandSize::Size32, AddressSize::Size32);
#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 {};
+# endif
#endif
}
diff --git a/Userland/Libraries/LibX86/Instruction.cpp b/Userland/Libraries/LibX86/Instruction.cpp
index f01468b89f..73cbe8e928 100644
--- a/Userland/Libraries/LibX86/Instruction.cpp
+++ b/Userland/Libraries/LibX86/Instruction.cpp
@@ -14,8 +14,8 @@
namespace X86 {
-InstructionDescriptor s_table[2][256];
-InstructionDescriptor s_0f_table[2][256];
+InstructionDescriptor s_table[3][256];
+InstructionDescriptor s_0f_table[3][256];
InstructionDescriptor s_sse_table_np[256];
InstructionDescriptor s_sse_table_66[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
{
switch (insn.address_size()) {
+ case AddressSize::Size64:
+ return to_string_a64();
case AddressSize::Size32:
return to_string_a32();
case AddressSize::Size16:
@@ -1455,6 +1457,65 @@ static String sib_to_string(u8 rm, u8 sib)
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
{
if (is_register())
@@ -1541,6 +1602,9 @@ String Instruction::to_string(u32 origin, SymbolProvider const* symbol_provider,
case AddressSize::Size32:
builder.append("a32"sv);
break;
+ case AddressSize::Size64:
+ builder.append("a64"sv);
+ break;
}
}
if (has_operand_size_override_prefix()) {
@@ -1551,6 +1615,9 @@ String Instruction::to_string(u32 origin, SymbolProvider const* symbol_provider,
case OperandSize::Size32:
builder.append("o32"sv);
break;
+ case OperandSize::Size64:
+ builder.append("o64"sv);
+ break;
}
}
if (has_lock_prefix())
diff --git a/Userland/Libraries/LibX86/Instruction.h b/Userland/Libraries/LibX86/Instruction.h
index 6c0903c92c..87a958d8ef 100644
--- a/Userland/Libraries/LibX86/Instruction.h
+++ b/Userland/Libraries/LibX86/Instruction.h
@@ -45,11 +45,13 @@ constexpr T sign_extended_to(U value)
enum class OperandSize : u8 {
Size16,
Size32,
+ Size64,
};
enum class AddressSize : u8 {
Size16,
Size32,
+ Size64,
};
enum IsLockPrefixAllowed {
@@ -228,6 +230,8 @@ struct InstructionDescriptor {
{
if (imm1_bytes == CurrentAddressSize) {
switch (size) {
+ case AddressSize::Size64:
+ return 8;
case AddressSize::Size32:
return 4;
case AddressSize::Size16:
@@ -242,6 +246,8 @@ struct InstructionDescriptor {
{
if (imm2_bytes == CurrentAddressSize) {
switch (size) {
+ case AddressSize::Size64:
+ return 8;
case AddressSize::Size32:
return 4;
case AddressSize::Size16:
@@ -255,8 +261,8 @@ struct InstructionDescriptor {
IsLockPrefixAllowed lock_prefix_allowed { LockPrefixNotAllowed };
};
-extern InstructionDescriptor s_table[2][256];
-extern InstructionDescriptor s_0f_table[2][256];
+extern InstructionDescriptor s_table[3][256];
+extern InstructionDescriptor s_0f_table[3][256];
extern InstructionDescriptor s_sse_table_np[256];
extern InstructionDescriptor s_sse_table_66[256];
extern InstructionDescriptor s_sse_table_f3[256];
@@ -489,6 +495,7 @@ private:
String to_string(Instruction const&) const;
String to_string_a16() const;
String to_string_a32() const;
+ String to_string_a64() const;
template<typename InstructionStreamType>
void decode(InstructionStreamType&, AddressSize);
@@ -553,15 +560,20 @@ public:
u8 imm8() const { return m_imm1; }
u16 imm16() const { return m_imm1; }
u32 imm32() const { return m_imm1; }
+ u64 imm64() const { return m_imm1; }
u8 imm8_1() const { return imm8(); }
u8 imm8_2() const { return m_imm2; }
u16 imm16_1() const { return imm16(); }
u16 imm16_2() const { return m_imm2; }
u32 imm32_1() const { return imm32(); }
u32 imm32_2() const { return m_imm2; }
+ u64 imm64_1() const { return imm64(); }
+ u64 imm64_2() const { return m_imm2; }
u32 imm_address() const
{
switch (m_address_size) {
+ case AddressSize::Size64:
+ return imm64();
case AddressSize::Size32:
return imm32();
case AddressSize::Size16:
@@ -603,8 +615,8 @@ private:
InstructionDescriptor* m_descriptor { nullptr };
mutable MemoryOrRegisterReference m_modrm;
- u32 m_imm1 { 0 };
- u32 m_imm2 { 0 };
+ u64 m_imm1 { 0 };
+ u64 m_imm2 { 0 };
u8 m_segment_prefix { 0xff };
u8 m_register_index { 0xff };
u8 m_op { 0 };
@@ -1137,8 +1149,9 @@ ALWAYS_INLINE LogicalAddress MemoryOrRegisterReference::resolve(const CPU& cpu,
return resolve16(cpu, insn.segment_prefix());
case AddressSize::Size32:
return resolve32(cpu, insn.segment_prefix());
+ default:
+ VERIFY_NOT_REACHED();
}
- VERIFY_NOT_REACHED();
}
}