summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Enderby <enderby@apple.com>2011-07-27 23:01:50 +0000
committerKevin Enderby <enderby@apple.com>2011-07-27 23:01:50 +0000
commitc37d4bbf1f33c5e4b1c2f1bf1a6e2cae2ae5603a (patch)
treefcbda9c4873cb87eeb09ba0f65e1eaf73b3387bf
parentfc2eb31a3c054f9611a2e88238fbb5a8842064a6 (diff)
downloadllvm-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.cpp15
-rw-r--r--lib/Target/X86/X86InstrInfo.td16
-rw-r--r--lib/Target/X86/X86InstrSSE.td8
-rw-r--r--test/MC/X86/x86-32-avx.s22
-rw-r--r--test/MC/X86/x86-32-coverage.s17
-rw-r--r--utils/TableGen/EDEmitter.cpp1
-rw-r--r--utils/TableGen/X86RecognizableInstr.cpp2
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)