From 29480fd798dc6452948f63825ff41c66f09c2493 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 11 Oct 2011 04:34:23 +0000 Subject: [PATCH] Fix disassembling of popcntw. Also remove some code that says it accounts for 64BIT_REXW_XD not existing, but it does exist. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141642 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../X86/Disassembler/X86DisassemblerDecoder.c | 68 ------------------- .../X86DisassemblerDecoderCommon.h | 3 + test/MC/Disassembler/X86/simple-tests.txt | 9 +++ test/MC/Disassembler/X86/x86-32.txt | 6 ++ utils/TableGen/X86DisassemblerTables.cpp | 7 ++ utils/TableGen/X86RecognizableInstr.cpp | 10 ++- 6 files changed, 33 insertions(+), 70 deletions(-) diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c index 9ad8532d400..f9b0fe5d51b 100644 --- a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c +++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c @@ -703,34 +703,6 @@ static BOOL is16BitEquvalent(const char* orig, const char* equiv) { } } -/* - * is64BitEquivalent - Determines whether two instruction names refer to - * equivalent instructions but one is 64-bit whereas the other is not. - * - * @param orig - The instruction that is not 64-bit - * @param equiv - The instruction that is 64-bit - */ -static BOOL is64BitEquivalent(const char* orig, const char* equiv) { - off_t i; - - for (i = 0;; i++) { - if (orig[i] == '\0' && equiv[i] == '\0') - return TRUE; - if (orig[i] == '\0' || equiv[i] == '\0') - return FALSE; - if (orig[i] != equiv[i]) { - if ((orig[i] == 'W' || orig[i] == 'L') && equiv[i] == 'Q') - continue; - if ((orig[i] == '1' || orig[i] == '3') && equiv[i] == '6') - continue; - if ((orig[i] == '6' || orig[i] == '2') && equiv[i] == '4') - continue; - return FALSE; - } - } -} - - /* * getID - Determines the ID of an instruction, consuming the ModR/M byte as * appropriate for extended and escape opcodes. Determines the attributes and @@ -840,46 +812,6 @@ static int getID(struct InternalInstruction* insn) { return 0; } - if ((attrMask & ATTR_XD) && (attrMask & ATTR_REXW)) { - /* - * Although for SSE instructions it is usually necessary to treat REX.W+F2 - * as F2 for decode (in the absence of a 64BIT_REXW_XD category) there is - * an occasional instruction where F2 is incidental and REX.W is the more - * significant. If the decoded instruction is 32-bit and adding REX.W - * instead of F2 changes a 32 to a 64, we adopt the new encoding. - */ - - const struct InstructionSpecifier *spec; - uint16_t instructionIDWithREXw; - const struct InstructionSpecifier *specWithREXw; - - spec = specifierForUID(instructionID); - - if (getIDWithAttrMask(&instructionIDWithREXw, - insn, - attrMask & (~ATTR_XD))) { - /* - * Decoding with REX.w would yield nothing; give up and return original - * decode. - */ - - insn->instructionID = instructionID; - insn->spec = spec; - return 0; - } - - specWithREXw = specifierForUID(instructionIDWithREXw); - - if (is64BitEquivalent(spec->name, specWithREXw->name)) { - insn->instructionID = instructionIDWithREXw; - insn->spec = specWithREXw; - } else { - insn->instructionID = instructionID; - insn->spec = spec; - } - return 0; - } - if (insn->prefixPresent[0x66] && !(attrMask & ATTR_OPSIZE)) { /* * The instruction tables make no distinction between instructions that diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h b/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h index 651ce9e4592..8b7933545a5 100644 --- a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h +++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h @@ -83,6 +83,8 @@ enum attributeBits { "but not the operands") \ ENUM_ENTRY(IC_XD_OPSIZE, 3, "requires an OPSIZE prefix, so " \ "operands change width") \ + ENUM_ENTRY(IC_XS_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") \ @@ -90,6 +92,7 @@ enum attributeBits { "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_XS_OPSIZE, 3, "Just as meaningful as IC_XS_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 0b0085842af..d1d60ef6d04 100644 --- a/test/MC/Disassembler/X86/simple-tests.txt +++ b/test/MC/Disassembler/X86/simple-tests.txt @@ -479,3 +479,12 @@ # CHECK: vcvtps2ph $0, %ymm0, (%rax) 0xc4 0xe3 0x7d 0x1d 0x00 0x00 + +# CHECK: popcntl %eax, %eax +0xf3 0x0f 0xb8 0xc0 + +# CHECK: popcntw %ax, %ax +0x66 0xf3 0x0f 0xb8 0xc0 + +# CHECK: popcntq %rax, %rax +0xf3 0x48 0x0f 0xb8 0xc0 diff --git a/test/MC/Disassembler/X86/x86-32.txt b/test/MC/Disassembler/X86/x86-32.txt index d0b24d2ebe7..f8944da9eed 100644 --- a/test/MC/Disassembler/X86/x86-32.txt +++ b/test/MC/Disassembler/X86/x86-32.txt @@ -465,3 +465,9 @@ # CHECK: vcvtps2ph $0, %ymm0, (%eax) 0xc4 0xe3 0x7d 0x1d 0x00 0x00 + +# CHECK: popcntl %eax, %eax +0xf3 0x0f 0xb8 0xc0 + +# CHECK: popcntw %ax, %ax +0x66 0xf3 0x0f 0xb8 0xc0 diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index f42119c0740..e8c9a489732 100644 --- a/utils/TableGen/X86DisassemblerTables.cpp +++ b/utils/TableGen/X86DisassemblerTables.cpp @@ -56,6 +56,8 @@ static inline bool inheritsFrom(InstructionContext child, return inheritsFrom(child, IC_64BIT_XS); case IC_XD_OPSIZE: return inheritsFrom(child, IC_64BIT_XD_OPSIZE); + case IC_XS_OPSIZE: + return inheritsFrom(child, IC_64BIT_XS_OPSIZE); case IC_64BIT_REXW: return(inheritsFrom(child, IC_64BIT_REXW_XS) || inheritsFrom(child, IC_64BIT_REXW_XD) || @@ -67,6 +69,7 @@ static inline bool inheritsFrom(InstructionContext child, case IC_64BIT_XS: return(inheritsFrom(child, IC_64BIT_REXW_XS)); case IC_64BIT_XD_OPSIZE: + case IC_64BIT_XS_OPSIZE: return false; case IC_64BIT_REXW_XD: case IC_64BIT_REXW_XS: @@ -524,6 +527,8 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, uint32_t &i) const { 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) && (index & ATTR_OPSIZE)) + o << "IC_64BIT_XS_OPSIZE"; else if ((index & ATTR_64BIT) && (index & ATTR_XS)) o << "IC_64BIT_XS"; else if ((index & ATTR_64BIT) && (index & ATTR_XD)) @@ -534,6 +539,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_XS) && (index & ATTR_OPSIZE)) + o << "IC_XS_OPSIZE"; else if ((index & ATTR_XD) && (index & ATTR_OPSIZE)) o << "IC_XD_OPSIZE"; else if (index & ATTR_XS) diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index ee9deb3628c..e7092c762c4 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -314,13 +314,17 @@ 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)) + else if (HasOpSizePrefix && + (Prefix == X86Local::XD || Prefix == X86Local::TF)) insnContext = IC_64BIT_XD_OPSIZE; + else if (HasOpSizePrefix && Prefix == X86Local::XS) + insnContext = IC_64BIT_XS_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 || Prefix == X86Local::TF)) + else if (HasREX_WPrefix && + (Prefix == X86Local::XD || Prefix == X86Local::TF)) insnContext = IC_64BIT_REXW_XD; else if (Prefix == X86Local::XD || Prefix == X86Local::TF) insnContext = IC_64BIT_XD; @@ -334,6 +338,8 @@ InstructionContext RecognizableInstr::insnContext() const { if (HasOpSizePrefix && (Prefix == X86Local::XD || Prefix == X86Local::TF)) insnContext = IC_XD_OPSIZE; + else if (HasOpSizePrefix && Prefix == X86Local::XS) + insnContext = IC_XS_OPSIZE; else if (HasOpSizePrefix) insnContext = IC_OPSIZE; else if (Prefix == X86Local::XD || Prefix == X86Local::TF)