forked from OSchip/llvm-project
[ARM] Convert more invalid NEON immediate loads
Summary: Currently the LLVM MC assembler is able to convert e.g. vmov.i32 d0, #0xabababab (which is technically invalid) into a valid instruction vmov.i8 d0, #0xab this patch adds support for vmov.i64 and for cases with the resulting load types other than i8, e.g.: vmov.i32 d0, #0xab00ab00 -> vmov.i16 d0, #0xab00 Reviewers: olista01, rengolin Reviewed By: rengolin Subscribers: rengolin, javed.absar, kristof.beyls, rogfer01, llvm-commits Differential Revision: https://reviews.llvm.org/D44467 llvm-svn: 327709
This commit is contained in:
parent
ce00978b10
commit
ed1c8bfec2
|
@ -48,46 +48,28 @@ def nImmVMOVI32 : Operand<i32> {
|
|||
let ParserMatchClass = nImmVMOVI32AsmOperand;
|
||||
}
|
||||
|
||||
def nImmVMOVI16AsmOperandByteReplicate :
|
||||
AsmOperandClass {
|
||||
let Name = "NEONi16vmovByteReplicate";
|
||||
let PredicateMethod = "isNEONi16ByteReplicate";
|
||||
let RenderMethod = "addNEONvmovByteReplicateOperands";
|
||||
}
|
||||
def nImmVMOVI32AsmOperandByteReplicate :
|
||||
AsmOperandClass {
|
||||
let Name = "NEONi32vmovByteReplicate";
|
||||
let PredicateMethod = "isNEONi32ByteReplicate";
|
||||
let RenderMethod = "addNEONvmovByteReplicateOperands";
|
||||
}
|
||||
def nImmVMVNI16AsmOperandByteReplicate :
|
||||
AsmOperandClass {
|
||||
let Name = "NEONi16invByteReplicate";
|
||||
let PredicateMethod = "isNEONi16ByteReplicate";
|
||||
let RenderMethod = "addNEONinvByteReplicateOperands";
|
||||
}
|
||||
def nImmVMVNI32AsmOperandByteReplicate :
|
||||
AsmOperandClass {
|
||||
let Name = "NEONi32invByteReplicate";
|
||||
let PredicateMethod = "isNEONi32ByteReplicate";
|
||||
let RenderMethod = "addNEONinvByteReplicateOperands";
|
||||
class nImmVMOVIAsmOperandReplicate<ValueType From, ValueType To>
|
||||
: AsmOperandClass {
|
||||
let Name = "NEONi" # To.Size # "vmovi" # From.Size # "Replicate";
|
||||
let PredicateMethod = "isNEONmovReplicate<" # From.Size # ", " # To.Size # ">";
|
||||
let RenderMethod = "addNEONvmovi" # From.Size # "ReplicateOperands";
|
||||
}
|
||||
|
||||
def nImmVMOVI16ByteReplicate : Operand<i32> {
|
||||
let PrintMethod = "printNEONModImmOperand";
|
||||
let ParserMatchClass = nImmVMOVI16AsmOperandByteReplicate;
|
||||
class nImmVINVIAsmOperandReplicate<ValueType From, ValueType To>
|
||||
: AsmOperandClass {
|
||||
let Name = "NEONi" # To.Size # "invi" # From.Size # "Replicate";
|
||||
let PredicateMethod = "isNEONinvReplicate<" # From.Size # ", " # To.Size # ">";
|
||||
let RenderMethod = "addNEONinvi" # From.Size # "ReplicateOperands";
|
||||
}
|
||||
def nImmVMOVI32ByteReplicate : Operand<i32> {
|
||||
|
||||
class nImmVMOVIReplicate<ValueType From, ValueType To> : Operand<i32> {
|
||||
let PrintMethod = "printNEONModImmOperand";
|
||||
let ParserMatchClass = nImmVMOVI32AsmOperandByteReplicate;
|
||||
let ParserMatchClass = nImmVMOVIAsmOperandReplicate<From, To>;
|
||||
}
|
||||
def nImmVMVNI16ByteReplicate : Operand<i32> {
|
||||
|
||||
class nImmVINVIReplicate<ValueType From, ValueType To> : Operand<i32> {
|
||||
let PrintMethod = "printNEONModImmOperand";
|
||||
let ParserMatchClass = nImmVMVNI16AsmOperandByteReplicate;
|
||||
}
|
||||
def nImmVMVNI32ByteReplicate : Operand<i32> {
|
||||
let PrintMethod = "printNEONModImmOperand";
|
||||
let ParserMatchClass = nImmVMVNI32AsmOperandByteReplicate;
|
||||
let ParserMatchClass = nImmVINVIAsmOperandReplicate<From, To>;
|
||||
}
|
||||
|
||||
def nImmVMOVI32NegAsmOperand : AsmOperandClass { let Name = "NEONi32vmovNeg"; }
|
||||
|
@ -5933,34 +5915,57 @@ def VMOVv4f32 : N1ModImm<1, 0b000, 0b1111, 0, 1, 0, 1, (outs QPR:$Vd),
|
|||
} // isReMaterializable, isAsCheapAsAMove
|
||||
|
||||
// Add support for bytes replication feature, so it could be GAS compatible.
|
||||
// E.g. instructions below:
|
||||
// "vmov.i32 d0, 0xffffffff"
|
||||
// "vmov.i32 d0, 0xabababab"
|
||||
// "vmov.i16 d0, 0xabab"
|
||||
// are incorrect, but we could deal with such cases.
|
||||
// For last two instructions, for example, it should emit:
|
||||
// "vmov.i8 d0, 0xab"
|
||||
def : NEONInstAlias<"vmov${p}.i16 $Vd, $Vm",
|
||||
(VMOVv8i8 DPR:$Vd, nImmVMOVI16ByteReplicate:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vmov${p}.i32 $Vd, $Vm",
|
||||
(VMOVv8i8 DPR:$Vd, nImmVMOVI32ByteReplicate:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vmov${p}.i16 $Vd, $Vm",
|
||||
(VMOVv16i8 QPR:$Vd, nImmVMOVI16ByteReplicate:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vmov${p}.i32 $Vd, $Vm",
|
||||
(VMOVv16i8 QPR:$Vd, nImmVMOVI32ByteReplicate:$Vm, pred:$p)>;
|
||||
multiclass NEONImmReplicateI8InstAlias<ValueType To> {
|
||||
// E.g. instructions below:
|
||||
// "vmov.i32 d0, #0xffffffff"
|
||||
// "vmov.i32 d0, #0xabababab"
|
||||
// "vmov.i16 d0, #0xabab"
|
||||
// are incorrect, but we could deal with such cases.
|
||||
// For last two instructions, for example, it should emit:
|
||||
// "vmov.i8 d0, #0xab"
|
||||
def : NEONInstAlias<"vmov${p}.i" # To.Size # " $Vd, $Vm",
|
||||
(VMOVv8i8 DPR:$Vd, nImmVMOVIReplicate<i8, To>:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vmov${p}.i" # To.Size # " $Vd, $Vm",
|
||||
(VMOVv16i8 QPR:$Vd, nImmVMOVIReplicate<i8, To>:$Vm, pred:$p)>;
|
||||
// Also add same support for VMVN instructions. So instruction:
|
||||
// "vmvn.i32 d0, #0xabababab"
|
||||
// actually means:
|
||||
// "vmov.i8 d0, #0x54"
|
||||
def : NEONInstAlias<"vmvn${p}.i" # To.Size # " $Vd, $Vm",
|
||||
(VMOVv8i8 DPR:$Vd, nImmVINVIReplicate<i8, To>:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vmvn${p}.i" # To.Size # " $Vd, $Vm",
|
||||
(VMOVv16i8 QPR:$Vd, nImmVINVIReplicate<i8, To>:$Vm, pred:$p)>;
|
||||
}
|
||||
|
||||
// Also add same support for VMVN instructions. So instruction:
|
||||
// "vmvn.i32 d0, 0xabababab"
|
||||
// actually means:
|
||||
// "vmov.i8 d0, 0x54"
|
||||
def : NEONInstAlias<"vmvn${p}.i16 $Vd, $Vm",
|
||||
(VMOVv8i8 DPR:$Vd, nImmVMVNI16ByteReplicate:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vmvn${p}.i32 $Vd, $Vm",
|
||||
(VMOVv8i8 DPR:$Vd, nImmVMVNI32ByteReplicate:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vmvn${p}.i16 $Vd, $Vm",
|
||||
(VMOVv16i8 QPR:$Vd, nImmVMVNI16ByteReplicate:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vmvn${p}.i32 $Vd, $Vm",
|
||||
(VMOVv16i8 QPR:$Vd, nImmVMVNI32ByteReplicate:$Vm, pred:$p)>;
|
||||
defm : NEONImmReplicateI8InstAlias<i16>;
|
||||
defm : NEONImmReplicateI8InstAlias<i32>;
|
||||
defm : NEONImmReplicateI8InstAlias<i64>;
|
||||
|
||||
// Similar to above for types other than i8, e.g.:
|
||||
// "vmov.i32 d0, #0xab00ab00" -> "vmov.i16 d0, #0xab00"
|
||||
// "vmvn.i64 q0, #0xab000000ab000000" -> "vmvn.i32 q0, #0xab000000"
|
||||
// In this case we do not canonicalize VMVN to VMOV
|
||||
multiclass NEONImmReplicateInstAlias<ValueType From, NeonI V8, NeonI V16,
|
||||
NeonI NV8, NeonI NV16, ValueType To> {
|
||||
def : NEONInstAlias<"vmov${p}.i" # To.Size # " $Vd, $Vm",
|
||||
(V8 DPR:$Vd, nImmVMOVIReplicate<From, To>:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vmov${p}.i" # To.Size # " $Vd, $Vm",
|
||||
(V16 QPR:$Vd, nImmVMOVIReplicate<From, To>:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vmvn${p}.i" # To.Size # " $Vd, $Vm",
|
||||
(NV8 DPR:$Vd, nImmVMOVIReplicate<From, To>:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vmvn${p}.i" # To.Size # " $Vd, $Vm",
|
||||
(NV16 QPR:$Vd, nImmVMOVIReplicate<From, To>:$Vm, pred:$p)>;
|
||||
}
|
||||
|
||||
defm : NEONImmReplicateInstAlias<i16, VMOVv4i16, VMOVv8i16,
|
||||
VMVNv4i16, VMVNv8i16, i32>;
|
||||
defm : NEONImmReplicateInstAlias<i16, VMOVv4i16, VMOVv8i16,
|
||||
VMVNv4i16, VMVNv8i16, i64>;
|
||||
defm : NEONImmReplicateInstAlias<i32, VMOVv2i32, VMOVv4i32,
|
||||
VMVNv2i32, VMVNv4i32, i64>;
|
||||
// TODO: add "VMOV <-> VMVN" conversion for cases like
|
||||
// "vmov.i32 d0, #0xffaaffaa" -> "vmvn.i16 d0, #0x55"
|
||||
// "vmvn.i32 d0, #0xaaffaaff" -> "vmov.i16 d0, #0xff00"
|
||||
|
||||
// On some CPUs the two instructions "vmov.i32 dD, #0" and "vmov.i32 qD, #0"
|
||||
// require zero cycles to execute so they should be used wherever possible for
|
||||
|
|
|
@ -1857,29 +1857,6 @@ public:
|
|||
return ARM_AM::isNEONi32splat(~Value);
|
||||
}
|
||||
|
||||
bool isNEONByteReplicate(unsigned NumBytes) const {
|
||||
if (!isImm())
|
||||
return false;
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||
// Must be a constant.
|
||||
if (!CE)
|
||||
return false;
|
||||
int64_t Value = CE->getValue();
|
||||
if (!Value)
|
||||
return false; // Don't bother with zero.
|
||||
|
||||
unsigned char B = Value & 0xff;
|
||||
for (unsigned i = 1; i < NumBytes; ++i) {
|
||||
Value >>= 8;
|
||||
if ((Value & 0xff) != B)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isNEONi16ByteReplicate() const { return isNEONByteReplicate(2); }
|
||||
bool isNEONi32ByteReplicate() const { return isNEONByteReplicate(4); }
|
||||
|
||||
static bool isValidNEONi32vmovImm(int64_t Value) {
|
||||
// i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
|
||||
// for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
|
||||
|
@ -1891,6 +1868,63 @@ public:
|
|||
((Value & 0xffffffffff00ffff) == 0xffff);
|
||||
}
|
||||
|
||||
bool isNEONReplicate(unsigned Width, unsigned NumElems, bool Inv,
|
||||
bool AllowMinusOne) const {
|
||||
assert(Width == 8 || Width == 16 || Width == 32 && "Invalid element width");
|
||||
assert(NumElems * Width <= 64 && "Invalid result width");
|
||||
|
||||
if (!isImm())
|
||||
return false;
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||
// Must be a constant.
|
||||
if (!CE)
|
||||
return false;
|
||||
int64_t Value = CE->getValue();
|
||||
if (!Value)
|
||||
return false; // Don't bother with zero.
|
||||
if (Inv)
|
||||
Value = ~Value;
|
||||
|
||||
uint64_t Mask = (1ull << Width) - 1;
|
||||
uint64_t Elem = Value & Mask;
|
||||
if (!AllowMinusOne && Elem == Mask)
|
||||
return false;
|
||||
if (Width == 16 && (Elem & 0x00ff) != 0 && (Elem & 0xff00) != 0)
|
||||
return false;
|
||||
if (Width == 32 && !isValidNEONi32vmovImm(Elem))
|
||||
return false;
|
||||
|
||||
for (unsigned i = 1; i < NumElems; ++i) {
|
||||
Value >>= Width;
|
||||
if ((Value & Mask) != Elem)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isNEONByteReplicate(unsigned NumBytes) const {
|
||||
return isNEONReplicate(8, NumBytes, false, true);
|
||||
}
|
||||
|
||||
static void checkNeonReplicateArgs(unsigned FromW, unsigned ToW) {
|
||||
assert(FromW == 8 || FromW == 16 || FromW == 32 && "Invalid source width");
|
||||
assert(ToW == 16 || ToW == 32 || ToW == 64 && "Invalid destination width");
|
||||
assert(FromW < ToW && "ToW is not less than FromW");
|
||||
}
|
||||
|
||||
template<unsigned FromW, unsigned ToW>
|
||||
bool isNEONmovReplicate() const {
|
||||
checkNeonReplicateArgs(FromW, ToW);
|
||||
bool AllowMinusOne = ToW != 64;
|
||||
return isNEONReplicate(FromW, ToW / FromW, false, AllowMinusOne);
|
||||
}
|
||||
|
||||
template<unsigned FromW, unsigned ToW>
|
||||
bool isNEONinvReplicate() const {
|
||||
checkNeonReplicateArgs(FromW, ToW);
|
||||
return isNEONReplicate(FromW, ToW / FromW, true, true);
|
||||
}
|
||||
|
||||
bool isNEONi32vmov() const {
|
||||
if (isNEONByteReplicate(4))
|
||||
return false; // Let it to be classified as byte-replicate case.
|
||||
|
@ -2726,62 +2760,87 @@ public:
|
|||
Inst.addOperand(MCOperand::createImm(Value));
|
||||
}
|
||||
|
||||
void addNEONinvByteReplicateOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
void addNEONi8ReplicateOperands(MCInst &Inst, bool Inv) const {
|
||||
// The immediate encodes the type of constant as well as the value.
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||
unsigned Value = CE->getValue();
|
||||
assert((Inst.getOpcode() == ARM::VMOVv8i8 ||
|
||||
Inst.getOpcode() == ARM::VMOVv16i8) &&
|
||||
"All vmvn instructions that wants to replicate non-zero byte "
|
||||
"always must be replaced with VMOVv8i8 or VMOVv16i8.");
|
||||
unsigned B = ((~Value) & 0xff);
|
||||
"All instructions that wants to replicate non-zero byte "
|
||||
"always must be replaced with VMOVv8i8 or VMOVv16i8.");
|
||||
unsigned Value = CE->getValue();
|
||||
if (Inv)
|
||||
Value = ~Value;
|
||||
unsigned B = Value & 0xff;
|
||||
B |= 0xe00; // cmode = 0b1110
|
||||
Inst.addOperand(MCOperand::createImm(B));
|
||||
}
|
||||
|
||||
void addNEONinvi8ReplicateOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
addNEONi8ReplicateOperands(Inst, true);
|
||||
}
|
||||
|
||||
static unsigned encodeNeonVMOVImmediate(unsigned Value) {
|
||||
if (Value >= 256 && Value <= 0xffff)
|
||||
Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
|
||||
else if (Value > 0xffff && Value <= 0xffffff)
|
||||
Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
|
||||
else if (Value > 0xffffff)
|
||||
Value = (Value >> 24) | 0x600;
|
||||
return Value;
|
||||
}
|
||||
|
||||
void addNEONi32vmovOperands(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();
|
||||
if (Value >= 256 && Value <= 0xffff)
|
||||
Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
|
||||
else if (Value > 0xffff && Value <= 0xffffff)
|
||||
Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
|
||||
else if (Value > 0xffffff)
|
||||
Value = (Value >> 24) | 0x600;
|
||||
unsigned Value = encodeNeonVMOVImmediate(CE->getValue());
|
||||
Inst.addOperand(MCOperand::createImm(Value));
|
||||
}
|
||||
|
||||
void addNEONvmovByteReplicateOperands(MCInst &Inst, unsigned N) const {
|
||||
void addNEONvmovi8ReplicateOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
addNEONi8ReplicateOperands(Inst, false);
|
||||
}
|
||||
|
||||
void addNEONvmovi16ReplicateOperands(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();
|
||||
assert((Inst.getOpcode() == ARM::VMOVv8i8 ||
|
||||
Inst.getOpcode() == ARM::VMOVv16i8) &&
|
||||
"All instructions that wants to replicate non-zero byte "
|
||||
"always must be replaced with VMOVv8i8 or VMOVv16i8.");
|
||||
unsigned B = Value & 0xff;
|
||||
B |= 0xe00; // cmode = 0b1110
|
||||
Inst.addOperand(MCOperand::createImm(B));
|
||||
assert((Inst.getOpcode() == ARM::VMOVv4i16 ||
|
||||
Inst.getOpcode() == ARM::VMOVv8i16 ||
|
||||
Inst.getOpcode() == ARM::VMVNv4i16 ||
|
||||
Inst.getOpcode() == ARM::VMVNv8i16) &&
|
||||
"All instructions that want to replicate non-zero half-word "
|
||||
"always must be replaced with V{MOV,MVN}v{4,8}i16.");
|
||||
uint64_t Value = CE->getValue();
|
||||
unsigned Elem = Value & 0xffff;
|
||||
if (Elem >= 256)
|
||||
Elem = (Elem >> 8) | 0x200;
|
||||
Inst.addOperand(MCOperand::createImm(Elem));
|
||||
}
|
||||
|
||||
void addNEONi32vmovNegOperands(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();
|
||||
if (Value >= 256 && Value <= 0xffff)
|
||||
Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
|
||||
else if (Value > 0xffff && Value <= 0xffffff)
|
||||
Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
|
||||
else if (Value > 0xffffff)
|
||||
Value = (Value >> 24) | 0x600;
|
||||
unsigned Value = encodeNeonVMOVImmediate(~CE->getValue());
|
||||
Inst.addOperand(MCOperand::createImm(Value));
|
||||
}
|
||||
|
||||
void addNEONvmovi32ReplicateOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||
assert((Inst.getOpcode() == ARM::VMOVv2i32 ||
|
||||
Inst.getOpcode() == ARM::VMOVv4i32 ||
|
||||
Inst.getOpcode() == ARM::VMVNv2i32 ||
|
||||
Inst.getOpcode() == ARM::VMVNv4i32) &&
|
||||
"All instructions that want to replicate non-zero word "
|
||||
"always must be replaced with V{MOV,MVN}v{2,4}i32.");
|
||||
uint64_t Value = CE->getValue();
|
||||
unsigned Elem = encodeNeonVMOVImmediate(Value & 0xffffffff);
|
||||
Inst.addOperand(MCOperand::createImm(Elem));
|
||||
}
|
||||
|
||||
void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
// The immediate encodes the type of constant as well as the value.
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
@ PR18921, "vmov" part.
|
||||
@ RUN: llvm-mc -triple=armv7-linux-gnueabi -show-encoding < %s | FileCheck %s
|
||||
.text
|
||||
|
||||
@ CHECK: vmov.i8 d2, #0xff @ encoding: [0x1f,0x2e,0x87,0xf3]
|
||||
@ CHECK: vmov.i8 q2, #0xff @ encoding: [0x5f,0x4e,0x87,0xf3]
|
||||
@ CHECK: vmov.i8 d2, #0xab @ encoding: [0x1b,0x2e,0x82,0xf3]
|
||||
@ CHECK: vmov.i8 q2, #0xab @ encoding: [0x5b,0x4e,0x82,0xf3]
|
||||
@ CHECK: vmov.i8 q2, #0xab @ encoding: [0x5b,0x4e,0x82,0xf3]
|
||||
@ CHECK: vmov.i8 q2, #0xab @ encoding: [0x5b,0x4e,0x82,0xf3]
|
||||
|
||||
@ CHECK: vmov.i8 d2, #0x0 @ encoding: [0x10,0x2e,0x80,0xf2]
|
||||
@ CHECK: vmov.i8 q2, #0x0 @ encoding: [0x50,0x4e,0x80,0xf2]
|
||||
@ CHECK: vmov.i8 d2, #0x54 @ encoding: [0x14,0x2e,0x85,0xf2]
|
||||
@ CHECK: vmov.i8 q2, #0x54 @ encoding: [0x54,0x4e,0x85,0xf2]
|
||||
@ CHECK: vmov.i8 d2, #0x54 @ encoding: [0x14,0x2e,0x85,0xf2]
|
||||
@ CHECK: vmov.i8 q2, #0x54 @ encoding: [0x54,0x4e,0x85,0xf2]
|
||||
|
||||
vmov.i32 d2, #0xffffffff
|
||||
vmov.i32 q2, #0xffffffff
|
||||
vmov.i32 d2, #0xabababab
|
||||
vmov.i32 q2, #0xabababab
|
||||
vmov.i16 q2, #0xabab
|
||||
vmov.i16 q2, #0xabab
|
||||
|
||||
vmvn.i32 d2, #0xffffffff
|
||||
vmvn.i32 q2, #0xffffffff
|
||||
vmvn.i32 d2, #0xabababab
|
||||
vmvn.i32 q2, #0xabababab
|
||||
vmvn.i16 d2, #0xabab
|
||||
vmvn.i16 q2, #0xabab
|
|
@ -0,0 +1,102 @@
|
|||
@ PR18921, "vmov" part.
|
||||
@ RUN: llvm-mc -triple=armv7-linux-gnueabi -show-encoding < %s | FileCheck %s
|
||||
.text
|
||||
vmov.i64 d2, #0xffffffffffffffff
|
||||
vmov.i64 q2, #0xffffffffffffffff
|
||||
vmov.i32 d2, #0xffffffff
|
||||
vmov.i32 q2, #0xffffffff
|
||||
vmov.i64 d2, #0xabababababababab
|
||||
vmov.i64 q2, #0xabababababababab
|
||||
vmov.i32 d2, #0xabababab
|
||||
vmov.i32 q2, #0xabababab
|
||||
vmov.i16 q2, #0xabab
|
||||
vmov.i16 q2, #0xabab
|
||||
|
||||
@ CHECK: vmov.i64 d2, #0xffffffffffffffff @ encoding: [0x3f,0x2e,0x87,0xf3]
|
||||
@ CHECK: vmov.i64 q2, #0xffffffffffffffff @ encoding: [0x7f,0x4e,0x87,0xf3]
|
||||
@ CHECK: vmov.i8 d2, #0xff @ encoding: [0x1f,0x2e,0x87,0xf3]
|
||||
@ CHECK: vmov.i8 q2, #0xff @ encoding: [0x5f,0x4e,0x87,0xf3]
|
||||
@ CHECK: vmov.i8 d2, #0xab @ encoding: [0x1b,0x2e,0x82,0xf3]
|
||||
@ CHECK: vmov.i8 q2, #0xab @ encoding: [0x5b,0x4e,0x82,0xf3]
|
||||
@ CHECK: vmov.i8 d2, #0xab @ encoding: [0x1b,0x2e,0x82,0xf3]
|
||||
@ CHECK: vmov.i8 q2, #0xab @ encoding: [0x5b,0x4e,0x82,0xf3]
|
||||
@ CHECK: vmov.i8 q2, #0xab @ encoding: [0x5b,0x4e,0x82,0xf3]
|
||||
@ CHECK: vmov.i8 q2, #0xab @ encoding: [0x5b,0x4e,0x82,0xf3]
|
||||
|
||||
vmov.i64 d2, #0x00a500a500a500a5
|
||||
vmov.i64 q2, #0x00a500a500a500a5
|
||||
vmov.i32 d2, #0x00a500a5
|
||||
vmov.i32 q2, #0x00a500a5
|
||||
vmov.i64 d2, #0xa500a500a500a500
|
||||
vmov.i64 q2, #0xa500a500a500a500
|
||||
vmov.i32 d2, #0xa500a500
|
||||
vmov.i32 q2, #0xa500a500
|
||||
|
||||
@ CHECK: vmov.i16 d2, #0xa5 @ encoding: [0x15,0x28,0x82,0xf3]
|
||||
@ CHECK: vmov.i16 q2, #0xa5 @ encoding: [0x55,0x48,0x82,0xf3]
|
||||
@ CHECK: vmov.i16 d2, #0xa5 @ encoding: [0x15,0x28,0x82,0xf3]
|
||||
@ CHECK: vmov.i16 q2, #0xa5 @ encoding: [0x55,0x48,0x82,0xf3]
|
||||
@ CHECK: vmov.i16 d2, #0xa500 @ encoding: [0x15,0x2a,0x82,0xf3]
|
||||
@ CHECK: vmov.i16 q2, #0xa500 @ encoding: [0x55,0x4a,0x82,0xf3]
|
||||
@ CHECK: vmov.i16 d2, #0xa500 @ encoding: [0x15,0x2a,0x82,0xf3]
|
||||
@ CHECK: vmov.i16 q2, #0xa500 @ encoding: [0x55,0x4a,0x82,0xf3]
|
||||
|
||||
vmov.i64 d2, #0x000000a5000000a5
|
||||
vmov.i64 q2, #0x000000a5000000a5
|
||||
vmov.i64 d2, #0x00a5ffff00a5ffff
|
||||
vmov.i64 q2, #0x00a5ffff00a5ffff
|
||||
|
||||
@ CHECK: vmov.i32 d2, #0xa5 @ encoding: [0x15,0x20,0x82,0xf3]
|
||||
@ CHECK: vmov.i32 q2, #0xa5 @ encoding: [0x55,0x40,0x82,0xf3]
|
||||
@ CHECK: vmov.i32 d2, #0xa5ffff @ encoding: [0x15,0x2d,0x82,0xf3]
|
||||
@ CHECK: vmov.i32 q2, #0xa5ffff @ encoding: [0x55,0x4d,0x82,0xf3]
|
||||
|
||||
vmvn.i64 d2, #0xffffffffffffffff
|
||||
vmvn.i64 q2, #0xffffffffffffffff
|
||||
vmvn.i32 d2, #0xffffffff
|
||||
vmvn.i32 q2, #0xffffffff
|
||||
vmvn.i64 d2, #0xabababababababab
|
||||
vmvn.i64 q2, #0xabababababababab
|
||||
vmvn.i32 d2, #0xabababab
|
||||
vmvn.i32 q2, #0xabababab
|
||||
vmvn.i16 d2, #0xabab
|
||||
vmvn.i16 q2, #0xabab
|
||||
|
||||
@ CHECK: vmov.i8 d2, #0x0 @ encoding: [0x10,0x2e,0x80,0xf2]
|
||||
@ CHECK: vmov.i8 q2, #0x0 @ encoding: [0x50,0x4e,0x80,0xf2]
|
||||
@ CHECK: vmov.i8 d2, #0x0 @ encoding: [0x10,0x2e,0x80,0xf2]
|
||||
@ CHECK: vmov.i8 q2, #0x0 @ encoding: [0x50,0x4e,0x80,0xf2]
|
||||
@ CHECK: vmov.i8 d2, #0x54 @ encoding: [0x14,0x2e,0x85,0xf2]
|
||||
@ CHECK: vmov.i8 q2, #0x54 @ encoding: [0x54,0x4e,0x85,0xf2]
|
||||
@ CHECK: vmov.i8 d2, #0x54 @ encoding: [0x14,0x2e,0x85,0xf2]
|
||||
@ CHECK: vmov.i8 q2, #0x54 @ encoding: [0x54,0x4e,0x85,0xf2]
|
||||
@ CHECK: vmov.i8 d2, #0x54 @ encoding: [0x14,0x2e,0x85,0xf2]
|
||||
@ CHECK: vmov.i8 q2, #0x54 @ encoding: [0x54,0x4e,0x85,0xf2]
|
||||
|
||||
vmvn.i64 d2, #0x00a500a500a500a5
|
||||
vmvn.i64 q2, #0x00a500a500a500a5
|
||||
vmvn.i32 d2, #0x00a500a5
|
||||
vmvn.i32 q2, #0x00a500a5
|
||||
vmvn.i64 d2, #0xa500a500a500a500
|
||||
vmvn.i64 q2, #0xa500a500a500a500
|
||||
vmvn.i32 d2, #0xa500a500
|
||||
vmvn.i32 q2, #0xa500a500
|
||||
|
||||
@ CHECK: vmvn.i16 d2, #0xa5 @ encoding: [0x35,0x28,0x82,0xf3]
|
||||
@ CHECK: vmvn.i16 q2, #0xa5 @ encoding: [0x75,0x48,0x82,0xf3]
|
||||
@ CHECK: vmvn.i16 d2, #0xa5 @ encoding: [0x35,0x28,0x82,0xf3]
|
||||
@ CHECK: vmvn.i16 q2, #0xa5 @ encoding: [0x75,0x48,0x82,0xf3]
|
||||
@ CHECK: vmvn.i16 d2, #0xa500 @ encoding: [0x35,0x2a,0x82,0xf3]
|
||||
@ CHECK: vmvn.i16 q2, #0xa500 @ encoding: [0x75,0x4a,0x82,0xf3]
|
||||
@ CHECK: vmvn.i16 d2, #0xa500 @ encoding: [0x35,0x2a,0x82,0xf3]
|
||||
@ CHECK: vmvn.i16 q2, #0xa500 @ encoding: [0x75,0x4a,0x82,0xf3]
|
||||
|
||||
vmvn.i64 d2, #0x000000a5000000a5
|
||||
vmvn.i64 q2, #0x000000a5000000a5
|
||||
vmvn.i64 d2, #0x00a5ffff00a5ffff
|
||||
vmvn.i64 q2, #0x00a5ffff00a5ffff
|
||||
|
||||
@ CHECK: vmvn.i32 d2, #0xa5 @ encoding: [0x35,0x20,0x82,0xf3]
|
||||
@ CHECK: vmvn.i32 q2, #0xa5 @ encoding: [0x75,0x40,0x82,0xf3]
|
||||
@ CHECK: vmvn.i32 d2, #0xa5ffff @ encoding: [0x35,0x2d,0x82,0xf3]
|
||||
@ CHECK: vmvn.i32 q2, #0xa5ffff @ encoding: [0x75,0x4d,0x82,0xf3]
|
Loading…
Reference in New Issue