aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Grosbach <grosbach@apple.com>2011-12-19 23:51:07 +0000
committerJim Grosbach <grosbach@apple.com>2011-12-19 23:51:07 +0000
commit9b0878512fb57ee4b0bc483509e4d9f4f0b9e426 (patch)
treea612ce11b7654b6c605e708689c8acddcebed15b
parent26118cfaa03619ff12bdc5c9f848afa3d3289f9e (diff)
downloadexternal_llvm-9b0878512fb57ee4b0bc483509e4d9f4f0b9e426.zip
external_llvm-9b0878512fb57ee4b0bc483509e4d9f4f0b9e426.tar.gz
external_llvm-9b0878512fb57ee4b0bc483509e4d9f4f0b9e426.tar.bz2
ARM NEON assembly aliases for VMOV<-->VMVN for i32 immediates.
e.g., "vmov.i32 d4, #-118" can be assembled as "vmvn.i32 d4, #117" rdar://10603913 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146925 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMInstrNEON.td15
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp30
2 files changed, 45 insertions, 0 deletions
diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td
index ef987d2..cd10dde 100644
--- a/lib/Target/ARM/ARMInstrNEON.td
+++ b/lib/Target/ARM/ARMInstrNEON.td
@@ -39,6 +39,11 @@ def nImmVMOVI32 : Operand<i32> {
let PrintMethod = "printNEONModImmOperand";
let ParserMatchClass = nImmVMOVI32AsmOperand;
}
+def nImmVMOVI32NegAsmOperand : AsmOperandClass { let Name = "NEONi32vmovNeg"; }
+def nImmVMOVI32Neg : Operand<i32> {
+ let PrintMethod = "printNEONModImmOperand";
+ let ParserMatchClass = nImmVMOVI32NegAsmOperand;
+}
def nImmVMOVF32 : Operand<i32> {
let PrintMethod = "printFPImmOperand";
let ParserMatchClass = FPImmOperand;
@@ -5949,6 +5954,16 @@ def : NEONInstAlias<"vpadd${p}.i32 $Vdn, $Vm",
def : NEONInstAlias<"vpadd${p}.f32 $Vdn, $Vm",
(VPADDf DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
+// "vmov Rd, #-imm" can be handled via "vmvn".
+def : NEONInstAlias<"vmov${p}.i32 $Vd, $imm",
+ (VMVNv2i32 DPR:$Vd, nImmVMOVI32Neg:$imm, pred:$p)>;
+def : NEONInstAlias<"vmov${p}.i32 $Vd, $imm",
+ (VMVNv4i32 QPR:$Vd, nImmVMOVI32Neg:$imm, pred:$p)>;
+def : NEONInstAlias<"vmvn${p}.i32 $Vd, $imm",
+ (VMOVv2i32 DPR:$Vd, nImmVMOVI32Neg:$imm, pred:$p)>;
+def : NEONInstAlias<"vmvn${p}.i32 $Vd, $imm",
+ (VMOVv4i32 QPR:$Vd, nImmVMOVI32Neg:$imm, pred:$p)>;
+
// 'gas' compatibility aliases for quad-word instructions. Strictly speaking,
// these should restrict to just the Q register variants, but the register
// classes are enough to match correctly regardless, so we keep it simple
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 1c109f0..9852cc8 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -1222,6 +1222,22 @@ public:
(Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
(Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
}
+ bool isNEONi32vmovNeg() const {
+ if (Kind != k_Immediate)
+ return false;
+ 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,
+ // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
+ return (Value >= 0 && Value < 256) ||
+ (Value >= 0x0100 && Value <= 0xff00) ||
+ (Value >= 0x010000 && Value <= 0xff0000) ||
+ (Value >= 0x01000000 && Value <= 0xff000000) ||
+ (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
+ (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
+ }
bool isNEONi64splat() const {
if (Kind != k_Immediate)
@@ -1825,6 +1841,20 @@ public:
Inst.addOperand(MCOperand::CreateImm(Value));
}
+ 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;
+ Inst.addOperand(MCOperand::CreateImm(Value));
+ }
+
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.