diff options
author | Kevin Enderby <enderby@apple.com> | 2011-07-27 23:01:50 +0000 |
---|---|---|
committer | Kevin Enderby <enderby@apple.com> | 2011-07-27 23:01:50 +0000 |
commit | c37d4bbf1f33c5e4b1c2f1bf1a6e2cae2ae5603a (patch) | |
tree | fcbda9c4873cb87eeb09ba0f65e1eaf73b3387bf | |
parent | fc2eb31a3c054f9611a2e88238fbb5a8842064a6 (diff) | |
download | llvm-c37d4bbf1f33c5e4b1c2f1bf1a6e2cae2ae5603a.tar.gz llvm-c37d4bbf1f33c5e4b1c2f1bf1a6e2cae2ae5603a.tar.bz2 llvm-c37d4bbf1f33c5e4b1c2f1bf1a6e2cae2ae5603a.tar.xz |
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
-rw-r--r-- | lib/Target/X86/AsmParser/X86AsmParser.cpp | 15 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrInfo.td | 16 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrSSE.td | 8 | ||||
-rw-r--r-- | test/MC/X86/x86-32-avx.s | 22 | ||||
-rw-r--r-- | test/MC/X86/x86-32-coverage.s | 17 | ||||
-rw-r--r-- | utils/TableGen/EDEmitter.cpp | 1 | ||||
-rw-r--r-- | 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 e4adff6f9f..efa8a6e154 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<MCConstantExpr>(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 7eb07b0a97..612a3f9746 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<i32> { let ParserMatchClass = ImmSExti32i8AsmOperand; let OperandType = "OPERAND_IMMEDIATE"; } +// 32-bits but only 8 bits are significant, and those 8 bits are unsigned. +def u32u8imm : Operand<i32> { + let ParserMatchClass = ImmZExtu32u8AsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; +} // 64-bits but only 32 bits are significant. def i64i32imm : Operand<i64> { diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td index 1594d82237..84f53298ca 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<bits<8> opc, string asm, bit Is2Addr = 1> { def rr : SS4AIi8<opc, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src2, i32i8imm:$src3), + (ins VR128:$src1, VR128:$src2, u32u8imm:$src3), !if(Is2Addr, !strconcat(asm, "\t{$src3, $src2, $dst|$dst, $src2, $src3}"), !strconcat(asm, @@ -4307,7 +4307,7 @@ multiclass SS41I_insertf32<bits<8> opc, string asm, bit Is2Addr = 1> { (X86insrtps VR128:$src1, VR128:$src2, imm:$src3))]>, OpSize; def rm : SS4AIi8<opc, MRMSrcMem, (outs VR128:$dst), - (ins VR128:$src1, f32mem:$src2, i32i8imm:$src3), + (ins VR128:$src1, f32mem:$src2, u32u8imm:$src3), !if(Is2Addr, !strconcat(asm, "\t{$src3, $src2, $dst|$dst, $src2, $src3}"), !strconcat(asm, @@ -4721,7 +4721,7 @@ multiclass SS41I_binop_rmi_int<bits<8> opc, string OpcodeStr, X86MemOperand x86memop, bit Is2Addr = 1> { let isCommutable = 1 in def rri : SS4AIi8<opc, MRMSrcReg, (outs RC:$dst), - (ins RC:$src1, RC:$src2, i32i8imm:$src3), + (ins RC:$src1, RC:$src2, u32u8imm:$src3), !if(Is2Addr, !strconcat(OpcodeStr, "\t{$src3, $src2, $dst|$dst, $src2, $src3}"), @@ -4730,7 +4730,7 @@ multiclass SS41I_binop_rmi_int<bits<8> opc, string OpcodeStr, [(set RC:$dst, (IntId RC:$src1, RC:$src2, imm:$src3))]>, OpSize; def rmi : SS4AIi8<opc, MRMSrcMem, (outs RC:$dst), - (ins RC:$src1, x86memop:$src2, i32i8imm:$src3), + (ins RC:$src1, x86memop:$src2, u32u8imm:$src3), !if(Is2Addr, !strconcat(OpcodeStr, "\t{$src3, $src2, $dst|$dst, $src2, $src3}"), diff --git a/test/MC/X86/x86-32-avx.s b/test/MC/X86/x86-32-avx.s index 1927e4e7a6..f56d5763ad 100644 --- a/test/MC/X86/x86-32-avx.s +++ b/test/MC/X86/x86-32-avx.s @@ -3281,3 +3281,25 @@ // CHECK: encoding: [0xc4,0xe3,0x51,0x44,0x18,0x11] vpclmulqdq $17, (%eax), %xmm5, %xmm3 +// rdar://9795008 +// These instructions take a mask not an 8-bit sign extended value. +// CHECK: vblendps $129, %ymm2, %ymm5, %ymm1 + vblendps $0x81, %ymm2, %ymm5, %ymm1 +// CHECK: vblendps $129, (%eax), %ymm5, %ymm1 + vblendps $0x81, (%eax), %ymm5, %ymm1 +// CHECK: vblendpd $129, %ymm2, %ymm5, %ymm1 + vblendpd $0x81, %ymm2, %ymm5, %ymm1 +// CHECK: vblendpd $129, (%eax), %ymm5, %ymm1 + vblendpd $0x81, (%eax), %ymm5, %ymm1 +// CHECK: vpblendw $129, %xmm2, %xmm5, %xmm1 + vpblendw $0x81, %xmm2, %xmm5, %xmm1 +// CHECK: vmpsadbw $129, %xmm2, %xmm5, %xmm1 + vmpsadbw $0x81, %xmm2, %xmm5, %xmm1 +// CHECK: vdpps $129, %ymm2, %ymm5, %ymm1 + vdpps $0x81, %ymm2, %ymm5, %ymm1 +// CHECK: vdpps $129, (%eax), %ymm5, %ymm1 + vdpps $0x81, (%eax), %ymm5, %ymm1 +// CHECK: vdppd $129, %xmm2, %xmm5, %xmm1 + vdppd $0x81, %xmm2, %xmm5, %xmm1 +// CHECK: vinsertps $129, %xmm3, %xmm2, %xmm1 + vinsertps $0x81, %xmm3, %xmm2, %xmm1 diff --git a/test/MC/X86/x86-32-coverage.s b/test/MC/X86/x86-32-coverage.s index bdc54a60e3..d2d42c209d 100644 --- a/test/MC/X86/x86-32-coverage.s +++ b/test/MC/X86/x86-32-coverage.s @@ -19575,3 +19575,20 @@ blendvps (%rax), %xmm1 // CHECK: blendvps %xmm2, %xmm1 # encoding: [0x66,0x0f,0x38,0x14,0xca] blendvps %xmm2, %xmm1 + +// rdar://9795008 +// These instructions take a mask not an 8-bit sign extended value. +// CHECK: blendps $129, %xmm2, %xmm1 + blendps $0x81, %xmm2, %xmm1 +// CHECK: blendpd $129, %xmm2, %xmm1 + blendpd $0x81, %xmm2, %xmm1 +// CHECK: pblendw $129, %xmm2, %xmm1 + pblendw $0x81, %xmm2, %xmm1 +// CHECK: mpsadbw $129, %xmm2, %xmm1 + mpsadbw $0x81, %xmm2, %xmm1 +// CHECK: dpps $129, %xmm2, %xmm1 + dpps $0x81, %xmm2, %xmm1 +// CHECK: dppd $129, %xmm2, %xmm1 + dppd $0x81, %xmm2, %xmm1 +// CHECK: insertps $129, %xmm2, %xmm1 + insertps $0x81, %xmm2, %xmm1 diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index db1b67f451..ce01e9c028 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -279,6 +279,7 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type, IMM("i16i8imm"); IMM("i32imm"); IMM("i32i8imm"); + IMM("u32u8imm"); IMM("i64imm"); IMM("i64i8imm"); IMM("i64i32imm"); diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index ea3bb700b2..3071d8e274 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -984,6 +984,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("i32mem", TYPE_Mv) TYPE("i32imm", TYPE_IMMv) TYPE("i32i8imm", TYPE_IMM32) + TYPE("u32u8imm", TYPE_IMM32) TYPE("GR32", TYPE_Rv) TYPE("i64mem", TYPE_Mv) TYPE("i64i32imm", TYPE_IMM64) @@ -1044,6 +1045,7 @@ OperandEncoding RecognizableInstr::immediateEncodingFromString ENCODING("i16imm", ENCODING_IW) } ENCODING("i32i8imm", ENCODING_IB) + ENCODING("u32u8imm", ENCODING_IB) ENCODING("SSECC", ENCODING_IB) ENCODING("i16imm", ENCODING_Iv) ENCODING("i16i8imm", ENCODING_IB) |