diff options
author | Simon Wanner <skyrising@pvpctutorials.de> | 2022-03-25 00:08:40 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-11-26 12:50:38 +0100 |
commit | 06ece474e96df24d6126bab2fdac7822c267ff62 (patch) | |
tree | e9a9a05908e4ac41271de7b5519c541af04d3b23 /Userland/Libraries/LibX86 | |
parent | a7268c3c742191cbc13762f5a71af2ffe7e4b6bc (diff) | |
download | serenity-06ece474e96df24d6126bab2fdac7822c267ff62.zip |
LibX86: Add {Address,Operand}Size::Size64
For now the opcode tables for OperandSize::Size64 are empty
Diffstat (limited to 'Userland/Libraries/LibX86')
-rw-r--r-- | Userland/Libraries/LibX86/Disassembler.h | 6 | ||||
-rw-r--r-- | Userland/Libraries/LibX86/Instruction.cpp | 71 | ||||
-rw-r--r-- | Userland/Libraries/LibX86/Instruction.h | 23 |
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(); } } |