[x86] Add assembly parser bounds checking to the immediate value for cmpss/cmpsd/cmpps/cmppd.

llvm-svn: 226642
This commit is contained in:
Craig Topper 2015-01-21 06:07:53 +00:00
parent 53afae49ee
commit f38dea1cfa
7 changed files with 60 additions and 14 deletions

View File

@ -34,6 +34,11 @@ inline bool isImmSExti64i32Value(uint64_t Value) {
(0xFFFFFFFF80000000ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
}
inline bool isImmUnsignedi8Value(uint64_t Value) {
return (( Value <= 0x00000000000000FFULL)||
(0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
}
} // End of namespace llvm
#endif

View File

@ -187,6 +187,13 @@ struct X86Operand : public MCParsedAsmOperand {
return isImmSExti64i32Value(CE->getValue());
}
bool isImmUnsignedi8() const {
if (!isImm()) return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
return isImmUnsignedi8Value(CE->getValue());
}
bool isOffsetOf() const override {
return OffsetOfLoc.getPointer();
}

View File

@ -1210,11 +1210,11 @@ multiclass avx512_cmp_scalar<RegisterClass RC, X86MemOperand x86memop,
(ld_frag addr:$src2), imm:$cc))], IIC_SSE_ALU_F32P_RM>, EVEX_4V;
let isAsmParserOnly = 1, hasSideEffects = 0 in {
def rri_alt : AVX512Ii8<0xC2, MRMSrcReg,
(outs VK1:$dst), (ins RC:$src1, RC:$src2, i8imm:$cc),
(outs VK1:$dst), (ins RC:$src1, RC:$src2, u8imm:$cc),
asm_alt, [], IIC_SSE_ALU_F32S_RR>, EVEX_4V;
let mayLoad = 1 in
def rmi_alt : AVX512Ii8<0xC2, MRMSrcMem,
(outs VK1:$dst), (ins RC:$src1, x86memop:$src2, i8imm:$cc),
(outs VK1:$dst), (ins RC:$src1, x86memop:$src2, u8imm:$cc),
asm_alt, [], IIC_SSE_ALU_F32P_RM>, EVEX_4V;
}
}
@ -1545,12 +1545,12 @@ multiclass avx512_cmp_packed<RegisterClass KRC, RegisterClass RC,
// Accept explicit immediate argument form instead of comparison code.
let isAsmParserOnly = 1, hasSideEffects = 0 in {
def rri_alt : AVX512PIi8<0xC2, MRMSrcReg,
(outs KRC:$dst), (ins RC:$src1, RC:$src2, i8imm:$cc),
(outs KRC:$dst), (ins RC:$src1, RC:$src2, u8imm:$cc),
!strconcat("vcmp", suffix,
"\t{$cc, $src2, $src1, $dst|$dst, $src1, $src2, $cc}"), [], d>;
let mayLoad = 1 in
def rmi_alt : AVX512PIi8<0xC2, MRMSrcMem,
(outs KRC:$dst), (ins RC:$src1, x86memop:$src2, i8imm:$cc),
(outs KRC:$dst), (ins RC:$src1, x86memop:$src2, u8imm:$cc),
!strconcat("vcmp", suffix,
"\t{$cc, $src2, $src1, $dst|$dst, $src1, $src2, $cc}"), [], d>;
}

View File

@ -609,6 +609,14 @@ def ImmSExti64i8AsmOperand : ImmSExtAsmOperandClass {
ImmSExti64i32AsmOperand];
}
// Unsigned immediate used by SSE/AVX instructions
// [0, 0xFF]
// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF]
def ImmUnsignedi8AsmOperand : AsmOperandClass {
let Name = "ImmUnsignedi8";
let RenderMethod = "addImmOperands";
}
// A couple of more descriptive operand definitions.
// 16-bits but only 8 bits are significant.
def i16i8imm : Operand<i16> {
@ -627,6 +635,18 @@ def i64i32imm : Operand<i64> {
let OperandType = "OPERAND_IMMEDIATE";
}
// 64-bits but only 8 bits are significant.
def i64i8imm : Operand<i64> {
let ParserMatchClass = ImmSExti64i8AsmOperand;
let OperandType = "OPERAND_IMMEDIATE";
}
// Unsigned 8-bit immediate used by SSE/AVX instructions.
def u8imm : Operand<i8> {
let ParserMatchClass = ImmUnsignedi8AsmOperand;
let OperandType = "OPERAND_IMMEDIATE";
}
// 64-bits but only 32 bits are significant, and those bits are treated as being
// pc relative.
def i64i32imm_pcrel : Operand<i64> {
@ -635,12 +655,6 @@ def i64i32imm_pcrel : Operand<i64> {
let OperandType = "OPERAND_PCREL";
}
// 64-bits but only 8 bits are significant.
def i64i8imm : Operand<i64> {
let ParserMatchClass = ImmSExti64i8AsmOperand;
let OperandType = "OPERAND_IMMEDIATE";
}
def lea64_32mem : Operand<i32> {
let PrintMethod = "printanymem";
let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm, i8imm);

View File

@ -2348,11 +2348,11 @@ multiclass sse12_cmp_scalar<RegisterClass RC, X86MemOperand x86memop,
// Accept explicit immediate argument form instead of comparison code.
let isAsmParserOnly = 1, hasSideEffects = 0 in {
def rr_alt : SIi8<0xC2, MRMSrcReg, (outs RC:$dst),
(ins RC:$src1, RC:$src2, i8imm:$cc), asm_alt, [],
(ins RC:$src1, RC:$src2, u8imm:$cc), asm_alt, [],
IIC_SSE_ALU_F32S_RR>, Sched<[itins.Sched]>;
let mayLoad = 1 in
def rm_alt : SIi8<0xC2, MRMSrcMem, (outs RC:$dst),
(ins RC:$src1, x86memop:$src2, i8imm:$cc), asm_alt, [],
(ins RC:$src1, x86memop:$src2, u8imm:$cc), asm_alt, [],
IIC_SSE_ALU_F32S_RM>,
Sched<[itins.Sched.Folded, ReadAfterLd]>;
}
@ -2502,11 +2502,11 @@ multiclass sse12_cmp_packed<RegisterClass RC, X86MemOperand x86memop,
// Accept explicit immediate argument form instead of comparison code.
let isAsmParserOnly = 1, hasSideEffects = 0 in {
def rri_alt : PIi8<0xC2, MRMSrcReg,
(outs RC:$dst), (ins RC:$src1, RC:$src2, i8imm:$cc),
(outs RC:$dst), (ins RC:$src1, RC:$src2, u8imm:$cc),
asm_alt, [], itins.rr, d>, Sched<[WriteFAdd]>;
let mayLoad = 1 in
def rmi_alt : PIi8<0xC2, MRMSrcMem,
(outs RC:$dst), (ins RC:$src1, x86memop:$src2, i8imm:$cc),
(outs RC:$dst), (ins RC:$src1, x86memop:$src2, u8imm:$cc),
asm_alt, [], itins.rm, d>,
Sched<[WriteFAddLd, ReadAfterLd]>;
}

View File

@ -3351,3 +3351,15 @@
vdppd $0x81, %xmm2, %xmm5, %xmm1
// CHECK: vinsertps $129, %xmm3, %xmm2, %xmm1
vinsertps $0x81, %xmm3, %xmm2, %xmm1
// CHECK: vcmpps $-128, %xmm2, %xmm1, %xmm0
// CHECK: encoding: [0xc5,0xf0,0xc2,0xc2,0x80]
vcmpps $-128, %xmm2, %xmm1, %xmm0
// CHECK: vcmpps $128, %xmm2, %xmm1, %xmm0
// CHECK: encoding: [0xc5,0xf0,0xc2,0xc2,0x80]
vcmpps $128, %xmm2, %xmm1, %xmm0
// CHECK: vcmpps $255, %xmm2, %xmm1, %xmm0
// CHECK: encoding: [0xc5,0xf0,0xc2,0xc2,0xff]
vcmpps $255, %xmm2, %xmm1, %xmm0

View File

@ -50,3 +50,11 @@ outb al, 4
// 32: error: invalid segment register
// 64: error: invalid segment register
movl %eax:0x00, %ebx
// 32: error: invalid operand for instruction
// 64: error: invalid operand for instruction
cmpps $-129, %xmm0, %xmm0
// 32: error: invalid operand for instruction
// 64: error: invalid operand for instruction
cmppd $256, %xmm0, %xmm0