summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-04-11 13:41:51 +0200
committerAndreas Kling <kling@serenityos.org>2020-04-11 13:42:18 +0200
commit2ce38d4699a92ef75f9a0770d4dafdd9fa516e72 (patch)
treeddd7748a63c6f07aa169b90dbc79d2f6f3958587
parente5cde0082a64ae375615d94c69a4c4554dc1e0ad (diff)
downloadserenity-2ce38d4699a92ef75f9a0770d4dafdd9fa516e72.zip
LibX86: Support decoding basic MMX instructions like MOVQ
-rw-r--r--Libraries/LibX86/Instruction.cpp56
-rw-r--r--Libraries/LibX86/Instruction.h12
2 files changed, 67 insertions, 1 deletions
diff --git a/Libraries/LibX86/Instruction.cpp b/Libraries/LibX86/Instruction.cpp
index 01b7313cea..78eed2f201 100644
--- a/Libraries/LibX86/Instruction.cpp
+++ b/Libraries/LibX86/Instruction.cpp
@@ -24,8 +24,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <LibX86/Instruction.h>
#include <AK/StringBuilder.h>
+#include <LibX86/Instruction.h>
#include <stdio.h>
namespace X86 {
@@ -85,6 +85,8 @@ enum InstructionFormat {
OP_RM32_reg32_imm8,
OP_RM16_reg16_CL,
OP_RM32_reg32_CL,
+ OP_mm1_mm2m64,
+ OP_mm1m64_mm2,
__EndFormatsWithRMByte,
OP_reg32_imm32,
@@ -283,6 +285,8 @@ static void build(InstructionDescriptor* table, u8 op, const char* mnemonic, Ins
case OP_CR_reg32:
case OP_reg16_RM8:
case OP_reg32_RM8:
+ case OP_mm1_mm2m64:
+ case OP_mm1m64_mm2:
case __EndFormatsWithRMByte:
case OP_CS:
case OP_DS:
@@ -760,6 +764,10 @@ void build_opcode_tables_if_needed()
build0F(0x4E, "CMOVNG", OP_reg16_RM16, OP_reg32_RM32);
build0F(0x4F, "CMOVG", OP_reg16_RM16, OP_reg32_RM32);
+ build0F(0x6F, "MOVQ", OP_mm1_mm2m64);
+ build0F(0x77, "EMMS", OP);
+ build0F(0x7F, "MOVQ", OP_mm1m64_mm2);
+
build0F(0x80, "JO", OP_NEAR_imm);
build0F(0x81, "JNO", OP_NEAR_imm);
build0F(0x82, "JC", OP_NEAR_imm);
@@ -975,6 +983,7 @@ static const char* register_name(RegisterIndex8);
static const char* register_name(RegisterIndex16);
static const char* register_name(RegisterIndex32);
static const char* register_name(SegmentRegister);
+static const char* register_name(MMXRegisterIndex);
const char* Instruction::reg8_name() const
{
@@ -1012,6 +1021,13 @@ String MemoryOrRegisterReference::to_string_o32() const
return String::format("[%s]", to_string().characters());
}
+String MemoryOrRegisterReference::to_string_mm() const
+{
+ if (is_register())
+ return register_name(static_cast<MMXRegisterIndex>(m_register_index));
+ return String::format("[%s]", to_string().characters());
+}
+
String MemoryOrRegisterReference::to_string() const
{
if (m_a32)
@@ -1291,6 +1307,10 @@ String Instruction::to_string_internal(u32 origin, bool x32) const
auto append_relative_imm8 = [&] { builder.append(relative_address(origin + 2, x32, i8(imm8()))); };
auto append_relative_imm16 = [&] { builder.append(relative_address(origin + 3, x32, i16(imm16()))); };
auto append_relative_imm32 = [&] { builder.append(relative_address(origin + 5, x32, i32(imm32()))); };
+
+ auto append_mm = [&] { builder.appendf("mm%u", register_index()); };
+ auto append_mmrm64 = [&] { builder.append(m_modrm.to_string_mm()); };
+
auto append = [&](auto& content) { builder.append(content); };
auto append_moff = [&] {
builder.append('[');
@@ -1686,6 +1706,16 @@ String Instruction::to_string_internal(u32 origin, bool x32) const
append_reg32();
append(", cl");
break;
+ case OP_mm1_mm2m64:
+ append_mm();
+ append(", ");
+ append_mmrm64();
+ break;
+ case OP_mm1m64_mm2:
+ append_mm();
+ append(", ");
+ append_mmrm64();
+ break;
case InstructionPrefix:
return mnemonic;
case InvalidFormat:
@@ -1799,6 +1829,30 @@ const char* register_name(RegisterIndex32 register_index)
return nullptr;
}
+const char* register_name(MMXRegisterIndex register_index)
+{
+ switch (register_index) {
+ case RegisterMM0:
+ return "mm0";
+ case RegisterMM1:
+ return "mm1";
+ case RegisterMM2:
+ return "mm2";
+ case RegisterMM3:
+ return "mm3";
+ case RegisterMM4:
+ return "mm4";
+ case RegisterMM5:
+ return "mm5";
+ case RegisterMM6:
+ return "mm6";
+ case RegisterMM7:
+ return "mm7";
+ }
+ ASSERT_NOT_REACHED();
+ return nullptr;
+}
+
void MemoryOrRegisterReference::decode(InstructionStream& stream, bool a32)
{
m_a32 = a32;
diff --git a/Libraries/LibX86/Instruction.h b/Libraries/LibX86/Instruction.h
index 10eddac2bc..7e65dbed53 100644
--- a/Libraries/LibX86/Instruction.h
+++ b/Libraries/LibX86/Instruction.h
@@ -124,6 +124,17 @@ enum RegisterIndex32 {
RegisterEDI
};
+enum MMXRegisterIndex {
+ RegisterMM0 = 0,
+ RegisterMM1,
+ RegisterMM2,
+ RegisterMM3,
+ RegisterMM4,
+ RegisterMM5,
+ RegisterMM6,
+ RegisterMM7
+};
+
class LogicalAddress {
public:
LogicalAddress() {}
@@ -197,6 +208,7 @@ public:
String to_string_o8() const;
String to_string_o16() const;
String to_string_o32() const;
+ String to_string_mm() const;
bool is_register() const { return m_register_index != 0xffffffff; }
SegmentRegister segment() const