mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
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. llvm-svn: 136287
This commit is contained in:
parent
b0bde240c1
commit
9adbbfffd0
@ -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;
|
||||
|
@ -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> {
|
||||
|
@ -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}"),
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -279,6 +279,7 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type,
|
||||
IMM("i16i8imm");
|
||||
IMM("i32imm");
|
||||
IMM("i32i8imm");
|
||||
IMM("u32u8imm");
|
||||
IMM("i64imm");
|
||||
IMM("i64i8imm");
|
||||
IMM("i64i32imm");
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user