summaryrefslogtreecommitdiff
path: root/lib/Target/ARM
diff options
context:
space:
mode:
authorJoey Gouly <joey.gouly@arm.com>2013-07-19 16:34:16 +0000
committerJoey Gouly <joey.gouly@arm.com>2013-07-19 16:34:16 +0000
commit6fec715a1a662ce3b560f85c710875cfeeb1fb98 (patch)
treef39f45ee8a071b4846106f9a07cea2e6f8eb8d2f /lib/Target/ARM
parent70d3e71f2e44250594f1b6edd7bbbf8b945a4452 (diff)
downloadllvm-6fec715a1a662ce3b560f85c710875cfeeb1fb98.tar.gz
llvm-6fec715a1a662ce3b560f85c710875cfeeb1fb98.tar.bz2
llvm-6fec715a1a662ce3b560f85c710875cfeeb1fb98.tar.xz
[ARMv8] Implement the NEON instructions VRINT{N, X, A, Z, M, P}.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186688 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM')
-rw-r--r--lib/Target/ARM/ARMInstrNEON.td28
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp30
2 files changed, 58 insertions, 0 deletions
diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td
index 0836700415..3e2ab0698d 100644
--- a/lib/Target/ARM/ARMInstrNEON.td
+++ b/lib/Target/ARM/ARMInstrNEON.td
@@ -5738,6 +5738,34 @@ def VTBX4Pseudo
IIC_VTBX4, "$orig = $dst", []>;
} // DecoderMethod = "DecodeTBLInstruction"
+// VRINT : Vector Rounding
+multiclass VRINT_FPI<string op, bits<3> op9_7, SDPatternOperator Int> {
+ let PostEncoderMethod = "NEONThumb2V8PostEncoder", DecoderNamespace = "v8NEON" in {
+ def D : N2VDIntnp<0b10, 0b100, 0, NoItinerary,
+ !strconcat("vrint", op), "f32",
+ v2f32, v2f32, Int>, Requires<[HasV8, HasNEON]> {
+ let Inst{9-7} = op9_7;
+ }
+ def Q : N2VQIntnp<0b10, 0b100, 0, NoItinerary,
+ !strconcat("vrint", op), "f32",
+ v4f32, v4f32, Int>, Requires<[HasV8, HasNEON]> {
+ let Inst{9-7} = op9_7;
+ }
+ }
+
+ def : InstAlias<!strconcat("vrint", op, ".f32.f32\t$Dd, $Dm"),
+ (!cast<Instruction>(NAME#"D") DPR:$Dd, DPR:$Dm)>;
+ def : InstAlias<!strconcat("vrint", op, ".f32.f32\t$Qd, $Qm"),
+ (!cast<Instruction>(NAME#"Q") QPR:$Qd, QPR:$Qm)>;
+}
+
+defm VRINTNN : VRINT_FPI<"n", 0b000, int_arm_neon_vrintn>;
+defm VRINTXN : VRINT_FPI<"x", 0b001, int_arm_neon_vrintx>;
+defm VRINTAN : VRINT_FPI<"a", 0b010, int_arm_neon_vrinta>;
+defm VRINTZN : VRINT_FPI<"z", 0b011, int_arm_neon_vrintz>;
+defm VRINTMN : VRINT_FPI<"m", 0b101, int_arm_neon_vrintm>;
+defm VRINTPN : VRINT_FPI<"p", 0b111, int_arm_neon_vrintp>;
+
//===----------------------------------------------------------------------===//
// NEON instructions for single-precision FP math
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index f114b7a26d..7061ede4e2 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -263,6 +263,8 @@ class ARMAsmParser : public MCTargetAsmParser {
const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
bool shouldOmitCCOutOperand(StringRef Mnemonic,
SmallVectorImpl<MCParsedAsmOperand*> &Operands);
+ bool shouldOmitPredicateOperand(StringRef Mnemonic,
+ SmallVectorImpl<MCParsedAsmOperand*> &Operands);
public:
enum ARMMatchResultTy {
@@ -5157,6 +5159,25 @@ bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
return false;
}
+bool ARMAsmParser::shouldOmitPredicateOperand(
+ StringRef Mnemonic, SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+ // VRINT{Z, R, X} have a predicate operand in VFP, but not in NEON
+ unsigned RegIdx = 3;
+ if ((Mnemonic == "vrintz" || Mnemonic == "vrintx" || Mnemonic == "vrintr") &&
+ static_cast<ARMOperand *>(Operands[2])->getToken() == ".f32") {
+ if (static_cast<ARMOperand *>(Operands[3])->isToken() &&
+ static_cast<ARMOperand *>(Operands[3])->getToken() == ".f32")
+ RegIdx = 4;
+
+ if (static_cast<ARMOperand *>(Operands[RegIdx])->isReg() &&
+ (ARMMCRegisterClasses[ARM::DPRRegClassID]
+ .contains(static_cast<ARMOperand *>(Operands[RegIdx])->getReg()) ||
+ ARMMCRegisterClasses[ARM::QPRRegClassID]
+ .contains(static_cast<ARMOperand *>(Operands[RegIdx])->getReg())))
+ return true;
+ }
+}
+
static bool isDataTypeToken(StringRef Tok) {
return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
@@ -5359,6 +5380,15 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
delete Op;
}
+ // Some instructions have the same mnemonic, but don't always
+ // have a predicate. Distinguish them here and delete the
+ // predicate if needed.
+ if (shouldOmitPredicateOperand(Mnemonic, Operands)) {
+ ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
+ Operands.erase(Operands.begin() + 1);
+ delete Op;
+ }
+
// ARM mode 'blx' need special handling, as the register operand version
// is predicable, but the label operand version is not. So, we can't rely
// on the Mnemonic based checking to correctly figure out when to put