From 92b45819531966f2d1365ab3564342a561f3b949 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 30 Sep 2013 02:46:36 +0000 Subject: [PATCH] Various x86 disassembler fixes. Add VEX_LIG to scalar FMA4 instructions. Use VEX_LIG in some of the inheriting checks in disassembler table generator. Make use of VEX_L_W, VEX_L_W_XS, VEX_L_W_XD contexts. Don't let VEX_L_W, VEX_L_W_XS, VEX_L_W_XD, VEX_L_W_OPSIZE inherit from their non-L forms unless VEX_LIG is set. Let VEX_L_W, VEX_L_W_XS, VEX_L_W_XD, VEX_L_W_OPSIZE inherit from all of their non-L or non-W cases. Increase ranking on VEX_L_W, VEX_L_W_XS, VEX_L_W_XD, VEX_L_W_OPSIZE so they get chosen over non-L/non-W forms. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191649 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../X86/Disassembler/X86DisassemblerDecoder.c | 36 ---------------------- .../Disassembler/X86DisassemblerDecoderCommon.h | 8 ++--- lib/Target/X86/X86InstrFMA.td | 15 ++++----- test/MC/Disassembler/X86/simple-tests.txt | 36 ++++++++++++++++++++++ utils/TableGen/X86DisassemblerTables.cpp | 24 +++++++++++---- 5 files changed, 66 insertions(+), 53 deletions(-) diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c index 20e61daf39e..70d3163a502 100644 --- a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c +++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c @@ -828,42 +828,6 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) { /* The following clauses compensate for limitations of the tables. */ - if ((attrMask & ATTR_VEXL) && (attrMask & ATTR_REXW) && - !(attrMask & ATTR_OPSIZE)) { - /* - * Some VEX instructions ignore the L-bit, but use the W-bit. Normally L-bit - * has precedence since there are no L-bit with W-bit entries in the tables. - * So if the L-bit isn't significant we should use the W-bit instead. - * We only need to do this if the instruction doesn't specify OpSize since - * there is a VEX_L_W_OPSIZE table. - */ - - const struct InstructionSpecifier *spec; - uint16_t instructionIDWithWBit; - const struct InstructionSpecifier *specWithWBit; - - spec = specifierForUID(instructionID); - - if (getIDWithAttrMask(&instructionIDWithWBit, - insn, - (attrMask & (~ATTR_VEXL)) | ATTR_REXW)) { - insn->instructionID = instructionID; - insn->spec = spec; - return 0; - } - - specWithWBit = specifierForUID(instructionIDWithWBit); - - if (instructionID != instructionIDWithWBit) { - insn->instructionID = instructionIDWithWBit; - insn->spec = specWithWBit; - } 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 d291441aaf4..b2f053b172c 100644 --- a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h +++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h @@ -116,10 +116,10 @@ enum attributeBits { ENUM_ENTRY(IC_VEX_L_XS, 4, "requires VEX and the L and XS prefix")\ ENUM_ENTRY(IC_VEX_L_XD, 4, "requires VEX and the L and XD prefix")\ ENUM_ENTRY(IC_VEX_L_OPSIZE, 4, "requires VEX, L, and OpSize") \ - ENUM_ENTRY(IC_VEX_L_W, 3, "requires VEX, L and W") \ - ENUM_ENTRY(IC_VEX_L_W_XS, 4, "requires VEX, L, W and XS prefix") \ - ENUM_ENTRY(IC_VEX_L_W_XD, 4, "requires VEX, L, W and XD prefix") \ - ENUM_ENTRY(IC_VEX_L_W_OPSIZE, 4, "requires VEX, L, W and OpSize") \ + ENUM_ENTRY(IC_VEX_L_W, 4, "requires VEX, L and W") \ + ENUM_ENTRY(IC_VEX_L_W_XS, 5, "requires VEX, L, W and XS prefix") \ + ENUM_ENTRY(IC_VEX_L_W_XD, 5, "requires VEX, L, W and XD prefix") \ + ENUM_ENTRY(IC_VEX_L_W_OPSIZE, 5, "requires VEX, L, W and OpSize") \ ENUM_ENTRY(IC_EVEX, 1, "requires an EVEX prefix") \ ENUM_ENTRY(IC_EVEX_XS, 2, "requires EVEX and the XS prefix") \ ENUM_ENTRY(IC_EVEX_XD, 2, "requires EVEX and the XD prefix") \ diff --git a/lib/Target/X86/X86InstrFMA.td b/lib/Target/X86/X86InstrFMA.td index 79fa7a05ac5..69cd5a568ba 100644 --- a/lib/Target/X86/X86InstrFMA.td +++ b/lib/Target/X86/X86InstrFMA.td @@ -206,25 +206,26 @@ multiclass fma4s opc, string OpcodeStr, RegisterClass RC, !strconcat(OpcodeStr, "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"), [(set RC:$dst, - (OpVT (OpNode RC:$src1, RC:$src2, RC:$src3)))]>, VEX_W, MemOp4; + (OpVT (OpNode RC:$src1, RC:$src2, RC:$src3)))]>, VEX_W, VEX_LIG, MemOp4; def rm : FMA4, VEX_W, MemOp4; + (mem_frag addr:$src3)))]>, VEX_W, VEX_LIG, MemOp4; def mr : FMA4; + (OpNode RC:$src1, (mem_frag addr:$src2), RC:$src3))]>, VEX_LIG; // For disassembler let isCodeGenOnly = 1, hasSideEffects = 0 in def rr_REV : FMA4; + "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"), []>, + VEX_LIG; } multiclass fma4s_int opc, string OpcodeStr, Operand memop, @@ -235,19 +236,19 @@ multiclass fma4s_int opc, string OpcodeStr, Operand memop, !strconcat(OpcodeStr, "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"), [(set VR128:$dst, - (Int VR128:$src1, VR128:$src2, VR128:$src3))]>, VEX_W, MemOp4; + (Int VR128:$src1, VR128:$src2, VR128:$src3))]>, VEX_W, VEX_LIG, MemOp4; def rm_Int : FMA4, VEX_W, MemOp4; + mem_cpat:$src3))]>, VEX_W, VEX_LIG, MemOp4; def mr_Int : FMA4; + (Int VR128:$src1, mem_cpat:$src2, VR128:$src3))]>, VEX_LIG; } multiclass fma4p opc, string OpcodeStr, SDNode OpNode, diff --git a/test/MC/Disassembler/X86/simple-tests.txt b/test/MC/Disassembler/X86/simple-tests.txt index 940b1f7b8f8..a29ae5c3cd3 100644 --- a/test/MC/Disassembler/X86/simple-tests.txt +++ b/test/MC/Disassembler/X86/simple-tests.txt @@ -129,6 +129,9 @@ # CHECK: vcvtsd2si %xmm0, %rax 0xc4 0xe1 0xfb 0x2d 0xc0 +# CHECK: vcvtsd2si %xmm0, %rax +0xc4 0xe1 0xff 0x2d 0xc0 + # CHECK: vmaskmovpd %xmm0, %xmm1, (%rax) 0xc4 0xe2 0x71 0x2f 0x00 @@ -260,6 +263,9 @@ # CHECK: vmovups %ymm0, %ymm1 0xc5 0xfc 0x11 0xc1 +# CHECK: vmovups %ymm0, %ymm1 +0xc4 0xe1 0xfc 0x11 0xc1 + # CHECK: vmovaps %ymm1, %ymm0 0xc5 0xfc 0x28 0xc1 @@ -722,6 +728,36 @@ # CHECK: vfmaddss %xmm1, (%rcx), %xmm0, %xmm0 0xc4 0xe3 0x79 0x6a 0x01 0x10 +# CHECK: vfmaddss (%rcx), %xmm1, %xmm0, %xmm0 +0xc4 0xe3 0xfd 0x6a 0x01 0x10 + +# CHECK: vfmaddss %xmm1, (%rcx), %xmm0, %xmm0 +0xc4 0xe3 0x7d 0x6a 0x01 0x10 + +# CHECK: vfmaddss %xmm2, %xmm1, %xmm0, %xmm0 +0xc4 0xe3 0xf9 0x6a 0xc2 0x10 + +# CHECK: vfmaddss %xmm1, %xmm2, %xmm0, %xmm0 +0xc4 0xe3 0x79 0x6a 0xc2 0x10 + +# CHECK: vfmaddss %xmm2, %xmm1, %xmm0, %xmm0 +0xc4 0xe3 0xfd 0x6a 0xc2 0x10 + +# CHECK: vfmaddss %xmm1, %xmm2, %xmm0, %xmm0 +0xc4 0xe3 0x7d 0x6a 0xc2 0x10 + +# CHECK: vfmaddps (%rcx), %xmm1, %xmm0, %xmm0 +0xc4 0xe3 0xf9 0x68 0x01 0x10 + +# CHECK: vfmaddps %xmm1, (%rcx), %xmm0, %xmm0 +0xc4 0xe3 0x79 0x68 0x01 0x10 + +# CHECK: vfmaddps %xmm1, %xmm2, %xmm0, %xmm0 +0xc4 0xe3 0x79 0x68 0xc2 0x10 + +# CHECK: vfmaddps %xmm2, %xmm1, %xmm0, %xmm0 +0xc4 0xe3 0xf9 0x68 0xc2 0x10 + # CHECK: vpermil2ps $1, 4(%rax), %xmm2, %xmm3, %xmm0 0xc4 0xe3 0xe1 0x48 0x40 0x04 0x21 diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index 0838ac412ee..db0964f8bf6 100644 --- a/utils/TableGen/X86DisassemblerTables.cpp +++ b/utils/TableGen/X86DisassemblerTables.cpp @@ -81,31 +81,37 @@ static inline bool inheritsFrom(InstructionContext child, case IC_64BIT_REXW_OPSIZE: return false; case IC_VEX: - return inheritsFrom(child, IC_VEX_L_W) || + return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W)) || inheritsFrom(child, IC_VEX_W) || (VEX_LIG && inheritsFrom(child, IC_VEX_L)); case IC_VEX_XS: - return inheritsFrom(child, IC_VEX_L_W_XS) || + return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XS)) || inheritsFrom(child, IC_VEX_W_XS) || (VEX_LIG && inheritsFrom(child, IC_VEX_L_XS)); case IC_VEX_XD: - return inheritsFrom(child, IC_VEX_L_W_XD) || + return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XD)) || inheritsFrom(child, IC_VEX_W_XD) || (VEX_LIG && inheritsFrom(child, IC_VEX_L_XD)); case IC_VEX_OPSIZE: - return inheritsFrom(child, IC_VEX_L_W_OPSIZE) || + return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W_OPSIZE)) || inheritsFrom(child, IC_VEX_W_OPSIZE) || (VEX_LIG && inheritsFrom(child, IC_VEX_L_OPSIZE)); case IC_VEX_W: + return VEX_LIG && inheritsFrom(child, IC_VEX_L_W); case IC_VEX_W_XS: + return VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XS); case IC_VEX_W_XD: + return VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XD); case IC_VEX_W_OPSIZE: - return false; + return VEX_LIG && inheritsFrom(child, IC_VEX_L_W_OPSIZE); case IC_VEX_L: + return inheritsFrom(child, IC_VEX_L_W); case IC_VEX_L_XS: + return inheritsFrom(child, IC_VEX_L_W_XS); case IC_VEX_L_XD: + return inheritsFrom(child, IC_VEX_L_W_XD); case IC_VEX_L_OPSIZE: - return false; + return inheritsFrom(child, IC_VEX_L_W_OPSIZE); case IC_VEX_L_W: case IC_VEX_L_W_XS: case IC_VEX_L_W_XD: @@ -622,6 +628,12 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const { if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) o << "IC_VEX_L_W_OPSIZE"; + else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XD)) + o << "IC_VEX_L_W_XD"; + else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XS)) + o << "IC_VEX_L_W_XS"; + else if ((index & ATTR_VEXL) && (index & ATTR_REXW)) + o << "IC_VEX_L_W"; else if ((index & ATTR_VEXL) && (index & ATTR_OPSIZE)) o << "IC_VEX_L_OPSIZE"; else if ((index & ATTR_VEXL) && (index & ATTR_XD)) -- 2.11.0