From e1b4a1a07ec79440536e4535721f15de3893cd13 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sat, 1 Oct 2011 19:54:56 +0000 Subject: [PATCH] Fix disassembler handling of CRC32 which is an odd instruction that uses 0xf2 as an opcode extension and allows the opsize prefix. This necessitated adding IC_XD_OPSIZE and IC_64BIT_XD_OPSIZE contexts. Unfortunately, this increases the size of the disassembler tables. Fixes PR10702. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@140954 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Disassembler/X86DisassemblerDecoderCommon.h | 3 +++ test/MC/Disassembler/X86/simple-tests.txt | 12 ++++++++++++ test/MC/Disassembler/X86/x86-32.txt | 3 +++ utils/TableGen/X86DisassemblerTables.cpp | 9 +++++++++ utils/TableGen/X86RecognizableInstr.cpp | 15 +++++++++------ 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h b/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h index 70315ed572b..b1eef6c1a91 100644 --- a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h +++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h @@ -81,12 +81,15 @@ enum attributeBits { "but not the operands") \ ENUM_ENTRY(IC_XS, 2, "may say something about the opcode " \ "but not the operands") \ + ENUM_ENTRY(IC_XD_OPSIZE, 3, "requires an OPSIZE prefix, so " \ + "operands change width") \ ENUM_ENTRY(IC_64BIT_REXW, 4, "requires a REX.W prefix, so operands "\ "change width; overrides IC_OPSIZE") \ ENUM_ENTRY(IC_64BIT_OPSIZE, 3, "Just as meaningful as IC_OPSIZE") \ ENUM_ENTRY(IC_64BIT_XD, 5, "XD instructions are SSE; REX.W is " \ "secondary") \ ENUM_ENTRY(IC_64BIT_XS, 5, "Just as meaningful as IC_64BIT_XD") \ + ENUM_ENTRY(IC_64BIT_XD_OPSIZE, 3, "Just as meaningful as IC_XD_OPSIZE") \ ENUM_ENTRY(IC_64BIT_REXW_XS, 6, "OPSIZE could mean a different " \ "opcode") \ ENUM_ENTRY(IC_64BIT_REXW_XD, 6, "Just as meaningful as " \ diff --git a/test/MC/Disassembler/X86/simple-tests.txt b/test/MC/Disassembler/X86/simple-tests.txt index 55ac9ab168c..4f88caa4b5c 100644 --- a/test/MC/Disassembler/X86/simple-tests.txt +++ b/test/MC/Disassembler/X86/simple-tests.txt @@ -290,3 +290,15 @@ # CHECK: vroundsd $0, %xmm0, %xmm0, %xmm0 0xc4 0xe3 0x79 0x0b 0xc0 0x00 + +# CHECK: crc32b %al, %eax +0xf2 0x0f 0x38 0xf0 0xc0 + +# CHECK: crc32w %ax, %eax +0x66 0xf2 0x0f 0x38 0xf1 0xc0 + +# CHECK: crc32l %eax, %eax +0xf2 0x0f 0x38 0xf1 0xc0 + +# CHECK: crc32q %rax, %rax +0xf2 0x48 0x0f 0x38 0xf1 0xc0 diff --git a/test/MC/Disassembler/X86/x86-32.txt b/test/MC/Disassembler/X86/x86-32.txt index 5c2a95d078d..7df29546e8a 100644 --- a/test/MC/Disassembler/X86/x86-32.txt +++ b/test/MC/Disassembler/X86/x86-32.txt @@ -31,6 +31,9 @@ # CHECK: crc32w %ax, %eax 0x66 0xf2 0x0f 0x38 0xf1 0xc0 +# CHECK: crc32l %eax, %eax +0xf2 0x0f 0x38 0xf1 0xc0 + # CHECK: int $33 0xCD 0x21 diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index e7b608306c8..14de3682a51 100644 --- a/utils/TableGen/X86DisassemblerTables.cpp +++ b/utils/TableGen/X86DisassemblerTables.cpp @@ -51,8 +51,11 @@ static inline bool inheritsFrom(InstructionContext child, return inheritsFrom(child, IC_64BIT_OPSIZE); case IC_XD: return inheritsFrom(child, IC_64BIT_XD); + inheritsFrom(child, IC_XD_OPSIZE); case IC_XS: return inheritsFrom(child, IC_64BIT_XS); + case IC_XD_OPSIZE: + return inheritsFrom(child, IC_64BIT_XD_OPSIZE); case IC_64BIT_REXW: return(inheritsFrom(child, IC_64BIT_REXW_XS) || inheritsFrom(child, IC_64BIT_REXW_XD) || @@ -63,6 +66,8 @@ static inline bool inheritsFrom(InstructionContext child, return(inheritsFrom(child, IC_64BIT_REXW_XD)); case IC_64BIT_XS: return(inheritsFrom(child, IC_64BIT_REXW_XS)); + case IC_64BIT_XD_OPSIZE: + return false; case IC_64BIT_REXW_XD: return false; case IC_64BIT_REXW_XS: @@ -521,6 +526,8 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, uint32_t &i) const { else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) o << "IC_64BIT_REXW_OPSIZE"; + else if ((index & ATTR_64BIT) && (index & ATTR_XD) && (index & ATTR_OPSIZE)) + o << "IC_64BIT_XD_OPSIZE"; else if ((index & ATTR_64BIT) && (index & ATTR_XS)) o << "IC_64BIT_XS"; else if ((index & ATTR_64BIT) && (index & ATTR_XD)) @@ -531,6 +538,8 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, uint32_t &i) const { o << "IC_64BIT_REXW"; else if ((index & ATTR_64BIT)) o << "IC_64BIT"; + else if ((index & ATTR_XD) && (index & ATTR_OPSIZE)) + o << "IC_XD_OPSIZE"; else if (index & ATTR_XS) o << "IC_XS"; else if (index & ATTR_XD) diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index 4118293ae56..532e7307050 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -309,13 +309,15 @@ InstructionContext RecognizableInstr::insnContext() const { } else if (Is64Bit || HasREX_WPrefix) { if (HasREX_WPrefix && HasOpSizePrefix) insnContext = IC_64BIT_REXW_OPSIZE; + else if (HasOpSizePrefix && (Prefix == X86Local::XD || Prefix == X86Local::TF)) + insnContext = IC_64BIT_XD_OPSIZE; else if (HasOpSizePrefix) insnContext = IC_64BIT_OPSIZE; else if (HasREX_WPrefix && Prefix == X86Local::XS) insnContext = IC_64BIT_REXW_XS; - else if (HasREX_WPrefix && Prefix == X86Local::XD) + else if (HasREX_WPrefix && (Prefix == X86Local::XD || Prefix == X86Local::TF)) insnContext = IC_64BIT_REXW_XD; - else if (Prefix == X86Local::XD) + else if (Prefix == X86Local::XD || Prefix == X86Local::TF) insnContext = IC_64BIT_XD; else if (Prefix == X86Local::XS) insnContext = IC_64BIT_XS; @@ -324,11 +326,12 @@ InstructionContext RecognizableInstr::insnContext() const { else insnContext = IC_64BIT; } else { - if (HasOpSizePrefix && Prefix == X86Local::TF) - insnContext = IC_XD; + if (HasOpSizePrefix && + (Prefix == X86Local::XD || Prefix == X86Local::TF)) + insnContext = IC_XD_OPSIZE; else if (HasOpSizePrefix) insnContext = IC_OPSIZE; - else if (Prefix == X86Local::XD) + else if (Prefix == X86Local::XD || Prefix == X86Local::TF) insnContext = IC_XD; else if (Prefix == X86Local::XS || Prefix == X86Local::REP) insnContext = IC_XS; @@ -402,7 +405,7 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const { // Filter out alternate forms of AVX instructions if (Name.find("_alt") != Name.npos || Name.find("XrYr") != Name.npos || - Name.find("r64r") != Name.npos || + (Name.find("r64r") != Name.npos && Name.find("r64r64") == Name.npos) || Name.find("_64mr") != Name.npos || Name.find("Xrr") != Name.npos || Name.find("rr64") != Name.npos) -- 2.34.1