let PrintMethod = "printNEONModImmOperand";
let ParserMatchClass = nImmSplatI32AsmOperand;
}
+def nImmSplatNotI16AsmOperand : AsmOperandClass { let Name = "NEONi16splatNot"; }
+def nImmSplatNotI16 : Operand<i32> {
+ let ParserMatchClass = nImmSplatNotI16AsmOperand;
+}
+def nImmSplatNotI32AsmOperand : AsmOperandClass { let Name = "NEONi32splatNot"; }
+def nImmSplatNotI32 : Operand<i32> {
+ let ParserMatchClass = nImmSplatNotI32AsmOperand;
+}
def nImmVMOVI32AsmOperand : AsmOperandClass { let Name = "NEONi32vmov"; }
def nImmVMOVI32 : Operand<i32> {
let PrintMethod = "printNEONModImmOperand";
(VORRd DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
defm : NEONDTAnyInstAlias<"vorr${p}", "$Vdn, $Vm",
(VORRq QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
+// ... immediates
+def : NEONInstAlias<"vand${p}.i16 $Vd, $imm",
+ (VBICiv4i16 DPR:$Vd, nImmSplatNotI16:$imm, pred:$p)>;
+def : NEONInstAlias<"vand${p}.i32 $Vd, $imm",
+ (VBICiv2i32 DPR:$Vd, nImmSplatNotI32:$imm, pred:$p)>;
+def : NEONInstAlias<"vand${p}.i16 $Vd, $imm",
+ (VBICiv8i16 QPR:$Vd, nImmSplatNotI16:$imm, pred:$p)>;
+def : NEONInstAlias<"vand${p}.i32 $Vd, $imm",
+ (VBICiv4i32 QPR:$Vd, nImmSplatNotI32:$imm, pred:$p)>;
+
// VLD1 single-lane pseudo-instructions. These need special handling for
// the lane index that an InstAlias can't handle, so we use these instead.
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
// Must be a constant.
if (!CE) return false;
- int64_t Value = CE->getValue();
- // i16 value in the range [0,255] or [0x0100, 0xff00]
- return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
+ unsigned Value = CE->getValue();
+ return ARM_AM::isNEONi16splat(Value);
+ }
+
+ bool isNEONi16splatNot() const {
+ if (!isImm())
+ return false;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ // Must be a constant.
+ if (!CE) return false;
+ unsigned Value = CE->getValue();
+ return ARM_AM::isNEONi16splat(~Value & 0xffff);
}
bool isNEONi32splat() const {
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
// Must be a constant.
if (!CE) return false;
- int64_t Value = CE->getValue();
- // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
- return (Value >= 0 && Value < 256) ||
- (Value >= 0x0100 && Value <= 0xff00) ||
- (Value >= 0x010000 && Value <= 0xff0000) ||
- (Value >= 0x01000000 && Value <= 0xff000000);
+ unsigned Value = CE->getValue();
+ return ARM_AM::isNEONi32splat(Value);
+ }
+
+ bool isNEONi32splatNot() const {
+ if (!isImm())
+ return false;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ // Must be a constant.
+ if (!CE) return false;
+ unsigned Value = CE->getValue();
+ return ARM_AM::isNEONi32splat(~Value);
}
bool isNEONByteReplicate(unsigned NumBytes) const {
int64_t Value = CE->getValue();
// i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
// for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
+ // FIXME: This is probably wrong and a copy and paste from previous example
return (Value >= 0 && Value < 256) ||
(Value >= 0x0100 && Value <= 0xff00) ||
(Value >= 0x010000 && Value <= 0xff0000) ||
int64_t Value = ~CE->getValue();
// i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
// for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
+ // FIXME: This is probably wrong and a copy and paste from previous example
return (Value >= 0 && Value < 256) ||
(Value >= 0x0100 && Value <= 0xff00) ||
(Value >= 0x010000 && Value <= 0xff0000) ||
// The immediate encodes the type of constant as well as the value.
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
unsigned Value = CE->getValue();
- if (Value >= 256)
- Value = (Value >> 8) | 0xa00;
- else
- Value |= 0x800;
+ Value = ARM_AM::encodeNEONi16splat(Value);
+ Inst.addOperand(MCOperand::CreateImm(Value));
+ }
+
+ void addNEONi16splatNotOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ // The immediate encodes the type of constant as well as the value.
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ unsigned Value = CE->getValue();
+ Value = ARM_AM::encodeNEONi16splat(~Value & 0xffff);
Inst.addOperand(MCOperand::CreateImm(Value));
}
// The immediate encodes the type of constant as well as the value.
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
unsigned Value = CE->getValue();
- if (Value >= 256 && Value <= 0xff00)
- Value = (Value >> 8) | 0x200;
- else if (Value > 0xffff && Value <= 0xff0000)
- Value = (Value >> 16) | 0x400;
- else if (Value > 0xffffff)
- Value = (Value >> 24) | 0x600;
+ Value = ARM_AM::encodeNEONi32splat(Value);
+ Inst.addOperand(MCOperand::CreateImm(Value));
+ }
+
+ void addNEONi32splatNotOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ // The immediate encodes the type of constant as well as the value.
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ unsigned Value = CE->getValue();
+ Value = ARM_AM::encodeNEONi32splat(~Value);
Inst.addOperand(MCOperand::CreateImm(Value));
}
return Val;
}
+ // Generic validation for single-byte immediate (0X00, 00X0, etc).
+ static inline bool isNEONBytesplat(unsigned Value, unsigned Size) {
+ assert(Size >= 1 && Size <= 4 && "Invalid size");
+ unsigned count = 0;
+ for (unsigned i = 0; i < Size; ++i) {
+ if (Value & 0xff) count++;
+ Value >>= 8;
+ }
+ return count == 1;
+ }
+
+ /// Checks if Value is a correct immediate for instructions like VBIC/VORR.
+ static inline bool isNEONi16splat(unsigned Value) {
+ if (Value > 0xffff)
+ return false;
+ // i16 value with set bits only in one byte X0 or 0X.
+ return Value == 0 || isNEONBytesplat(Value, 2);
+ }
+
+ // Encode NEON 16 bits Splat immediate for instructions like VBIC/VORR
+ static inline unsigned encodeNEONi16splat(unsigned Value) {
+ assert(isNEONi16splat(Value) && "Invalid NEON splat value");
+ if (Value >= 0x100)
+ Value = (Value >> 8) | 0xa00;
+ else
+ Value |= 0x800;
+ return Value;
+ }
+
+ /// Checks if Value is a correct immediate for instructions like VBIC/VORR.
+ static inline bool isNEONi32splat(unsigned Value) {
+ // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
+ return Value == 0 || isNEONBytesplat(Value, 4);
+ }
+
+ /// Encode NEON 32 bits Splat immediate for instructions like VBIC/VORR.
+ static inline unsigned encodeNEONi32splat(unsigned Value) {
+ assert(isNEONi32splat(Value) && "Invalid NEON splat value");
+ if (Value >= 0x100 && Value <= 0xff00)
+ Value = (Value >> 8) | 0x200;
+ else if (Value > 0xffff && Value <= 0xff0000)
+ Value = (Value >> 16) | 0x400;
+ else if (Value > 0xffffff)
+ Value = (Value >> 24) | 0x600;
+ return Value;
+ }
+
AMSubMode getLoadStoreMultipleSubMode(int Opcode);
//===--------------------------------------------------------------------===//
vbic d16, d17, d16
vbic q8, q8, q9
+ vbic q10, q11
+ vbic d9, d1
+ vbic.i16 d16, #0xFF00
+ vbic.i16 q8, #0xFF00
+ vbic.i16 d16, #0x00FF
+ vbic.i16 q8, #0x00FF
vbic.i32 d16, #0xFF000000
- vbic.i32 q8, #0xFF000000
- vbic q10, q11
- vbic d9, d1
+ vbic.i32 q8, #0xFF000000
+ vbic.i32 d16, #0x00FF0000
+ vbic.i32 q8, #0x00FF0000
+ vbic.i32 d16, #0x0000FF00
+ vbic.i32 q8, #0x0000FF00
+ vbic.i32 d16, #0x000000FF
+ vbic.i32 q8, #0x000000FF
@ CHECK: vbic d16, d17, d16 @ encoding: [0xb0,0x01,0x51,0xf2]
@ CHECK: vbic q8, q8, q9 @ encoding: [0xf2,0x01,0x50,0xf2]
-@ CHECK: vbic.i32 d16, #0xff000000 @ encoding: [0x3f,0x07,0xc7,0xf3]
-@ CHECK: vbic.i32 q8, #0xff000000 @ encoding: [0x7f,0x07,0xc7,0xf3]
@ CHECK: vbic q10, q10, q11 @ encoding: [0xf6,0x41,0x54,0xf2]
@ CHECK: vbic d9, d9, d1 @ encoding: [0x11,0x91,0x19,0xf2]
-
+@ CHECK: vbic.i16 d16, #0xff00 @ encoding: [0x3f,0x0b,0xc7,0xf3]
+@ CHECK: vbic.i16 q8, #0xff00 @ encoding: [0x7f,0x0b,0xc7,0xf3]
+@ CHECK: vbic.i16 d16, #0xff @ encoding: [0x3f,0x09,0xc7,0xf3]
+@ CHECK: vbic.i16 q8, #0xff @ encoding: [0x7f,0x09,0xc7,0xf3]
+@ CHECK: vbic.i32 d16, #0xff000000 @ encoding: [0x3f,0x07,0xc7,0xf3]
+@ CHECK: vbic.i32 q8, #0xff000000 @ encoding: [0x7f,0x07,0xc7,0xf3]
+@ CHECK: vbic.i32 d16, #0xff0000 @ encoding: [0x3f,0x05,0xc7,0xf3]
+@ CHECK: vbic.i32 q8, #0xff0000 @ encoding: [0x7f,0x05,0xc7,0xf3]
+@ CHECK: vbic.i32 d16, #0xff00 @ encoding: [0x3f,0x03,0xc7,0xf3]
+@ CHECK: vbic.i32 q8, #0xff00 @ encoding: [0x7f,0x03,0xc7,0xf3]
+@ CHECK: vbic.i32 d16, #0xff @ encoding: [0x3f,0x01,0xc7,0xf3]
+@ CHECK: vbic.i32 q8, #0xff @ encoding: [0x7f,0x01,0xc7,0xf3]
+
+ vand.i16 d10, #0xff03
+ vand.i16 q10, #0xff03
+ vand.i16 d10, #0x03ff
+ vand.i16 q10, #0x03ff
+ vand.i32 d10, #0x03ffffff
+ vand.i32 q10, #0x03ffffff
+ vand.i32 d10, #0xff03ffff
+ vand.i32 q10, #0xff03ffff
+ vand.i32 d10, #0xffff03ff
+ vand.i32 q10, #0xffff03ff
+ vand.i32 d10, #0xffffff03
+ vand.i32 q10, #0xffffff03
+
+@ CHECK: vbic.i16 d10, #0xfc @ encoding: [0x3c,0xa9,0x87,0xf3]
+@ CHECK: vbic.i16 q10, #0xfc @ encoding: [0x7c,0x49,0xc7,0xf3]
+@ CHECK: vbic.i16 d10, #0xfc00 @ encoding: [0x3c,0xab,0x87,0xf3]
+@ CHECK: vbic.i16 q10, #0xfc00 @ encoding: [0x7c,0x4b,0xc7,0xf3]
+@ CHECK: vbic.i32 d10, #0xfc000000 @ encoding: [0x3c,0xa7,0x87,0xf3]
+@ CHECK: vbic.i32 q10, #0xfc000000 @ encoding: [0x7c,0x47,0xc7,0xf3]
+@ CHECK: vbic.i32 d10, #0xfc0000 @ encoding: [0x3c,0xa5,0x87,0xf3]
+@ CHECK: vbic.i32 q10, #0xfc0000 @ encoding: [0x7c,0x45,0xc7,0xf3]
+@ CHECK: vbic.i32 d10, #0xfc00 @ encoding: [0x3c,0xa3,0x87,0xf3]
+@ CHECK: vbic.i32 q10, #0xfc00 @ encoding: [0x7c,0x43,0xc7,0xf3]
+@ CHECK: vbic.i32 d10, #0xfc @ encoding: [0x3c,0xa1,0x87,0xf3]
+@ CHECK: vbic.i32 q10, #0xfc @ encoding: [0x7c,0x41,0xc7,0xf3]
vorn d16, d17, d16
vorn q8, q8, q9
@ RUN: not llvm-mc -triple=armv7-linux-gnueabi %s 2>&1 | FileCheck %s
.text
+ vorr.i32 d2, #0xffffffff
+ vorr.i32 q2, #0xffffffff
+ vorr.i32 d2, #0xabababab
+ vorr.i32 q2, #0xabababab
+ vorr.i16 q2, #0xabab
+ vorr.i16 q2, #0xabab
+
@ CHECK: error: invalid operand for instruction
@ CHECK: vorr.i32 d2, #0xffffffff
@ CHECK: error: invalid operand for instruction
@ CHECK: error: invalid operand for instruction
@ CHECK: vorr.i16 q2, #0xabab
+ vbic.i32 d2, #0xffffffff
+ vbic.i32 q2, #0xffffffff
+ vbic.i32 d2, #0xabababab
+ vbic.i32 q2, #0xabababab
+ vbic.i16 d2, #0xabab
+ vbic.i16 q2, #0xabab
+
@ CHECK: error: invalid operand for instruction
@ CHECK: vbic.i32 d2, #0xffffffff
@ CHECK: error: invalid operand for instruction
@ CHECK: error: invalid operand for instruction
@ CHECK: vbic.i16 q2, #0xabab
- vorr.i32 d2, #0xffffffff
- vorr.i32 q2, #0xffffffff
- vorr.i32 d2, #0xabababab
- vorr.i32 q2, #0xabababab
- vorr.i16 q2, #0xabab
- vorr.i16 q2, #0xabab
+ vbic.i32 d2, #0x03ffffff
+ vbic.i32 q2, #0x03ffff
+ vbic.i32 d2, #0x03ff
+ vbic.i32 d2, #0xff00ff
+ vbic.i16 d2, #0x03ff
+ vbic.i16 q2, #0xf0f0
+ vbic.i16 q2, #0xf0f0f0
- vbic.i32 d2, #0xffffffff
- vbic.i32 q2, #0xffffffff
- vbic.i32 d2, #0xabababab
- vbic.i32 q2, #0xabababab
- vbic.i16 d2, #0xabab
- vbic.i16 q2, #0xabab
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vbic.i32 d2, #0x03ffffff
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vbic.i32 q2, #0x03ffff
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vbic.i32 d2, #0x03ff
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vbic.i32 d2, #0xff00ff
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vbic.i16 d2, #0x03ff
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vbic.i16 q2, #0xf0f0
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vbic.i16 q2, #0xf0f0f0