From c37d4bbf1f33c5e4b1c2f1bf1a6e2cae2ae5603a Mon Sep 17 00:00:00 2001 From: Kevin Enderby Date: Wed, 27 Jul 2011 23:01:50 +0000 Subject: [PATCH] Fix llvm-mc handing of x86 instructions that take 8-bit unsigned immediates. llvm-mc gives an "invalid operand" error for instructions that take an unsigned immediate which have the high bit set such as: pblendw $0xc5, %xmm2, %xmm1 llvm-mc treats all x86 immediates as signed values and range checks them. A small number of x86 instructions use the imm8 field as a set of bits. This change only changes those instructions and where the high bit is not ignored. The others remain unchanged. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136287 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/AsmParser/X86AsmParser.cpp | 15 +++++++++++++++ lib/Target/X86/X86InstrInfo.td | 16 ++++++++++++++++ lib/Target/X86/X86InstrSSE.td | 8 ++++---- test/MC/X86/x86-32-avx.s | 22 ++++++++++++++++++++++ test/MC/X86/x86-32-coverage.s | 17 +++++++++++++++++ utils/TableGen/EDEmitter.cpp | 1 + utils/TableGen/X86RecognizableInstr.cpp | 2 ++ 7 files changed, 77 insertions(+), 4 deletions(-) diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index e4adff6f9fb..efa8a6e1547 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -226,6 +226,21 @@ struct X86Operand : public MCParsedAsmOperand { (0x00000000FFFFFF80ULL <= Value && Value <= 0x00000000FFFFFFFFULL)|| (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL)); } + bool isImmZExtu32u8() const { + if (!isImm()) + return false; + + // If this isn't a constant expr, just assume it fits and let relaxation + // handle it. + const MCConstantExpr *CE = dyn_cast(getImm()); + if (!CE) + return true; + + // Otherwise, check the value is in a range that makes sense for this + // extension. + uint64_t Value = CE->getValue(); + return (Value <= 0x00000000000000FFULL); + } bool isImmSExti64i8() const { if (!isImm()) return false; diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 7eb07b0a97b..612a3f97469 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -331,6 +331,11 @@ class ImmSExtAsmOperandClass : AsmOperandClass { let RenderMethod = "addImmOperands"; } +class ImmZExtAsmOperandClass : AsmOperandClass { + let SuperClasses = [ImmAsmOperand]; + let RenderMethod = "addImmOperands"; +} + // Sign-extended immediate classes. We don't need to define the full lattice // here because there is no instruction with an ambiguity between ImmSExti64i32 // and ImmSExti32i8. @@ -358,6 +363,12 @@ def ImmSExti32i8AsmOperand : ImmSExtAsmOperandClass { let Name = "ImmSExti32i8"; } +// [0, 0x000000FF] +def ImmZExtu32u8AsmOperand : ImmZExtAsmOperandClass { + let Name = "ImmZExtu32u8"; +} + + // [0, 0x0000007F] | // [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] def ImmSExti64i8AsmOperand : ImmSExtAsmOperandClass { @@ -377,6 +388,11 @@ def i32i8imm : Operand { let ParserMatchClass = ImmSExti32i8AsmOperand; let OperandType = "OPERAND_IMMEDIATE"; } +// 32-bits but only 8 bits are significant, and those 8 bits are unsigned. +def u32u8imm : Operand { + let ParserMatchClass = ImmZExtu32u8AsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; +} // 64-bits but only 32 bits are significant. def i64i32imm : Operand { diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td index 1594d822374..84f53298caf 100644 --- a/lib/Target/X86/X86InstrSSE.td +++ b/lib/Target/X86/X86InstrSSE.td @@ -4298,7 +4298,7 @@ let Constraints = "$src1 = $dst" in // in the target vector. multiclass SS41I_insertf32 opc, string asm, bit Is2Addr = 1> { def rr : SS4AIi8 opc, string asm, bit Is2Addr = 1> { (X86insrtps VR128:$src1, VR128:$src2, imm:$src3))]>, OpSize; def rm : SS4AIi8 opc, string OpcodeStr, X86MemOperand x86memop, bit Is2Addr = 1> { let isCommutable = 1 in def rri : SS4AIi8 opc, string OpcodeStr, [(set RC:$dst, (IntId RC:$src1, RC:$src2, imm:$src3))]>, OpSize; def rmi : SS4AIi8