aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/Target/ARM/ARMInstrFormats.td1
-rw-r--r--lib/Target/ARM/ARMInstrNEON.td61
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp119
-rw-r--r--lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp5
-rw-r--r--lib/Target/ARM/InstPrinter/ARMInstPrinter.h1
-rw-r--r--test/MC/ARM/neont2-dup-encoding.s36
-rw-r--r--utils/TableGen/EDEmitter.cpp3
7 files changed, 200 insertions, 26 deletions
diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td
index 220091c..7cbc911 100644
--- a/lib/Target/ARM/ARMInstrFormats.td
+++ b/lib/Target/ARM/ARMInstrFormats.td
@@ -1951,7 +1951,6 @@ class NVDupLane<bits<4> op19_16, bit op6, dag oops, dag iops,
bits<5> Vd;
bits<5> Vm;
- bits<4> lane;
let Inst{22} = Vd{4};
let Inst{15-12} = Vd{3-0};
diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td
index e1f6656..7aad186 100644
--- a/lib/Target/ARM/ARMInstrNEON.td
+++ b/lib/Target/ARM/ARMInstrNEON.td
@@ -11,6 +11,35 @@
//
//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// NEON-specific Operands.
+//===----------------------------------------------------------------------===//
+def VectorIndex8Operand : AsmOperandClass { let Name = "VectorIndex8"; }
+def VectorIndex16Operand : AsmOperandClass { let Name = "VectorIndex16"; }
+def VectorIndex32Operand : AsmOperandClass { let Name = "VectorIndex32"; }
+def VectorIndex8 : Operand<i32>, ImmLeaf<i32, [{
+ return ((uint64_t)Imm) < 8;
+}]> {
+ let ParserMatchClass = VectorIndex8Operand;
+ let PrintMethod = "printVectorIndex";
+ let MIOperandInfo = (ops i32imm);
+}
+def VectorIndex16 : Operand<i32>, ImmLeaf<i32, [{
+ return ((uint64_t)Imm) < 4;
+}]> {
+ let ParserMatchClass = VectorIndex16Operand;
+ let PrintMethod = "printVectorIndex";
+ let MIOperandInfo = (ops i32imm);
+}
+def VectorIndex32 : Operand<i32>, ImmLeaf<i32, [{
+ return ((uint64_t)Imm) < 2;
+}]> {
+ let ParserMatchClass = VectorIndex32Operand;
+ let PrintMethod = "printVectorIndex";
+ let MIOperandInfo = (ops i32imm);
+}
+
//===----------------------------------------------------------------------===//
// NEON-specific DAG Nodes.
//===----------------------------------------------------------------------===//
@@ -4518,36 +4547,42 @@ def : Pat<(v4f32 (NEONvdup (f32 (bitconvert GPR:$R)))), (VDUP32q GPR:$R)>;
// VDUP : Vector Duplicate Lane (from scalar to all elements)
class VDUPLND<bits<4> op19_16, string OpcodeStr, string Dt,
- ValueType Ty>
- : NVDupLane<op19_16, 0, (outs DPR:$Vd), (ins DPR:$Vm, nohash_imm:$lane),
- IIC_VMOVD, OpcodeStr, Dt, "$Vd, $Vm[$lane]",
+ ValueType Ty, Operand IdxTy>
+ : NVDupLane<op19_16, 0, (outs DPR:$Vd), (ins DPR:$Vm, IdxTy:$lane),
+ IIC_VMOVD, OpcodeStr, Dt, "$Vd, $Vm$lane",
[(set DPR:$Vd, (Ty (NEONvduplane (Ty DPR:$Vm), imm:$lane)))]>;
class VDUPLNQ<bits<4> op19_16, string OpcodeStr, string Dt,
- ValueType ResTy, ValueType OpTy>
- : NVDupLane<op19_16, 1, (outs QPR:$Vd), (ins DPR:$Vm, nohash_imm:$lane),
- IIC_VMOVQ, OpcodeStr, Dt, "$Vd, $Vm[$lane]",
+ ValueType ResTy, ValueType OpTy, Operand IdxTy>
+ : NVDupLane<op19_16, 1, (outs QPR:$Vd), (ins DPR:$Vm, IdxTy:$lane),
+ IIC_VMOVQ, OpcodeStr, Dt, "$Vd, $Vm$lane",
[(set QPR:$Vd, (ResTy (NEONvduplane (OpTy DPR:$Vm),
- imm:$lane)))]>;
+ VectorIndex32:$lane)))]>;
// Inst{19-16} is partially specified depending on the element size.
-def VDUPLN8d : VDUPLND<{?,?,?,1}, "vdup", "8", v8i8> {
+def VDUPLN8d : VDUPLND<{?,?,?,1}, "vdup", "8", v8i8, VectorIndex8> {
+ bits<3> lane;
let Inst{19-17} = lane{2-0};
}
-def VDUPLN16d : VDUPLND<{?,?,1,0}, "vdup", "16", v4i16> {
+def VDUPLN16d : VDUPLND<{?,?,1,0}, "vdup", "16", v4i16, VectorIndex16> {
+ bits<2> lane;
let Inst{19-18} = lane{1-0};
}
-def VDUPLN32d : VDUPLND<{?,1,0,0}, "vdup", "32", v2i32> {
+def VDUPLN32d : VDUPLND<{?,1,0,0}, "vdup", "32", v2i32, VectorIndex32> {
+ bits<1> lane;
let Inst{19} = lane{0};
}
-def VDUPLN8q : VDUPLNQ<{?,?,?,1}, "vdup", "8", v16i8, v8i8> {
+def VDUPLN8q : VDUPLNQ<{?,?,?,1}, "vdup", "8", v16i8, v8i8, VectorIndex8> {
+ bits<3> lane;
let Inst{19-17} = lane{2-0};
}
-def VDUPLN16q : VDUPLNQ<{?,?,1,0}, "vdup", "16", v8i16, v4i16> {
+def VDUPLN16q : VDUPLNQ<{?,?,1,0}, "vdup", "16", v8i16, v4i16, VectorIndex16> {
+ bits<2> lane;
let Inst{19-18} = lane{1-0};
}
-def VDUPLN32q : VDUPLNQ<{?,1,0,0}, "vdup", "32", v4i32, v2i32> {
+def VDUPLN32q : VDUPLNQ<{?,1,0,0}, "vdup", "32", v4i32, v2i32, VectorIndex32> {
+ bits<1> lane;
let Inst{19} = lane{0};
}
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index f56f455..1d6a05c 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -254,6 +254,7 @@ class ARMOperand : public MCParsedAsmOperand {
k_PostIndexRegister,
k_MSRMask,
k_ProcIFlags,
+ k_VectorIndex,
k_Register,
k_RegisterList,
k_DPRRegisterList,
@@ -304,6 +305,10 @@ class ARMOperand : public MCParsedAsmOperand {
} Reg;
struct {
+ unsigned Val;
+ } VectorIndex;
+
+ struct {
const MCExpr *Val;
} Imm;
@@ -419,6 +424,9 @@ public:
case k_BitfieldDescriptor:
Bitfield = o.Bitfield;
break;
+ case k_VectorIndex:
+ VectorIndex = o.VectorIndex;
+ break;
}
}
@@ -463,6 +471,11 @@ public:
return FPImm.Val;
}
+ unsigned getVectorIndex() const {
+ assert(Kind == k_VectorIndex && "Invalid access!");
+ return VectorIndex.Val;
+ }
+
ARM_MB::MemBOpt getMemBarrierOpt() const {
assert(Kind == k_MemBarrierOpt && "Invalid access!");
return MBOpt.Val;
@@ -859,6 +872,21 @@ public:
bool isMSRMask() const { return Kind == k_MSRMask; }
bool isProcIFlags() const { return Kind == k_ProcIFlags; }
+ bool isVectorIndex8() const {
+ if (Kind != k_VectorIndex) return false;
+ return VectorIndex.Val < 8;
+ }
+ bool isVectorIndex16() const {
+ if (Kind != k_VectorIndex) return false;
+ return VectorIndex.Val < 4;
+ }
+ bool isVectorIndex32() const {
+ if (Kind != k_VectorIndex) return false;
+ return VectorIndex.Val < 2;
+ }
+
+
+
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
// Add as immediates when possible. Null MCExpr = 0.
if (Expr == 0)
@@ -1343,6 +1371,21 @@ public:
Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
}
+ void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
+ }
+
+ void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
+ }
+
+ void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
+ }
+
virtual void print(raw_ostream &OS) const;
static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
@@ -1479,6 +1522,15 @@ public:
return Op;
}
+ static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
+ MCContext &Ctx) {
+ ARMOperand *Op = new ARMOperand(k_VectorIndex);
+ Op->VectorIndex.Val = Idx;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
ARMOperand *Op = new ARMOperand(k_Immediate);
Op->Imm.Val = Val;
@@ -1659,6 +1711,9 @@ void ARMOperand::print(raw_ostream &OS) const {
case k_Token:
OS << "'" << getToken() << "'";
break;
+ case k_VectorIndex:
+ OS << "<vectorindex " << getVectorIndex() << ">";
+ break;
}
}
@@ -1700,6 +1755,39 @@ int ARMAsmParser::tryParseRegister() {
if (!RegNum) return -1;
Parser.Lex(); // Eat identifier token.
+
+#if 0
+ // Also check for an index operand. This is only legal for vector registers,
+ // but that'll get caught OK in operand matching, so we don't need to
+ // explicitly filter everything else out here.
+ if (Parser.getTok().is(AsmToken::LBrac)) {
+ SMLoc SIdx = Parser.getTok().getLoc();
+ Parser.Lex(); // Eat left bracket token.
+
+ const MCExpr *ImmVal;
+ SMLoc ExprLoc = Parser.getTok().getLoc();
+ if (getParser().ParseExpression(ImmVal))
+ return MatchOperand_ParseFail;
+ const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
+ if (!MCE) {
+ TokError("immediate value expected for vector index");
+ return MatchOperand_ParseFail;
+ }
+
+ SMLoc E = Parser.getTok().getLoc();
+ if (Parser.getTok().isNot(AsmToken::RBrac)) {
+ Error(E, "']' expected");
+ return MatchOperand_ParseFail;
+ }
+
+ Parser.Lex(); // Eat right bracket token.
+
+ Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
+ SIdx, E,
+ getContext()));
+ }
+#endif
+
return RegNum;
}
@@ -1815,6 +1903,37 @@ tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
ExclaimTok.getLoc()));
Parser.Lex(); // Eat exclaim token
+ return false;
+ }
+
+ // Also check for an index operand. This is only legal for vector registers,
+ // but that'll get caught OK in operand matching, so we don't need to
+ // explicitly filter everything else out here.
+ if (Parser.getTok().is(AsmToken::LBrac)) {
+ SMLoc SIdx = Parser.getTok().getLoc();
+ Parser.Lex(); // Eat left bracket token.
+
+ const MCExpr *ImmVal;
+ SMLoc ExprLoc = Parser.getTok().getLoc();
+ if (getParser().ParseExpression(ImmVal))
+ return MatchOperand_ParseFail;
+ const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
+ if (!MCE) {
+ TokError("immediate value expected for vector index");
+ return MatchOperand_ParseFail;
+ }
+
+ SMLoc E = Parser.getTok().getLoc();
+ if (Parser.getTok().isNot(AsmToken::RBrac)) {
+ Error(E, "']' expected");
+ return MatchOperand_ParseFail;
+ }
+
+ Parser.Lex(); // Eat right bracket token.
+
+ Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
+ SIdx, E,
+ getContext()));
}
return false;
diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
index 83cf58b..d637929 100644
--- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
+++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
@@ -981,3 +981,8 @@ void ARMInstPrinter::printRotImmOperand(const MCInst *MI, unsigned OpNum,
case 3: O << "24"; break;
}
}
+
+void ARMInstPrinter::printVectorIndex(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O) {
+ O << "[" << MI->getOperand(OpNum).getImm() << "]";
+}
diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
index 83a55ad..61b26e6 100644
--- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
+++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
@@ -127,6 +127,7 @@ public:
void printPCLabel(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printT2LdrLabelOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printVectorIndex(const MCInst *MI, unsigned OpNum, raw_ostream &O);
};
} // end namespace llvm
diff --git a/test/MC/ARM/neont2-dup-encoding.s b/test/MC/ARM/neont2-dup-encoding.s
index 5d2a005..bf25d70 100644
--- a/test/MC/ARM/neont2-dup-encoding.s
+++ b/test/MC/ARM/neont2-dup-encoding.s
@@ -16,16 +16,28 @@
@ CHECK: vdup.16 q8, r5 @ encoding: [0xa0,0xee,0xb0,0x5b]
@ CHECK: vdup.32 q7, r6 @ encoding: [0xae,0xee,0x10,0x6b]
-@ vdup.8 d16, d16[1]
-@ vdup.16 d16, d16[1]
-@ vdup.32 d16, d16[1]
-@ vdup.8 q8, d16[1]
-@ vdup.16 q8, d16[1]
-@ vdup.32 q8, d16[1]
+ vdup.8 d16, d11[0]
+ vdup.16 d17, d12[0]
+ vdup.32 d18, d13[0]
+ vdup.8 q3, d10[0]
+ vdup.16 q9, d9[0]
+ vdup.32 q8, d8[0]
+ vdup.8 d16, d11[1]
+ vdup.16 d17, d12[1]
+ vdup.32 d18, d13[1]
+ vdup.8 q3, d10[1]
+ vdup.16 q9, d9[1]
+ vdup.32 q8, d8[1]
-@ FIXME: vdup.8 d16, d16[1] @ encoding: [0x20,0x0c,0xf3,0xff]
-@ FIXME: vdup.16 d16, d16[1] @ encoding: [0x20,0x0c,0xf6,0xff]
-@ FIXME: vdup.32 d16, d16[1] @ encoding: [0x20,0x0c,0xfc,0xff]
-@ FIXME: vdup.8 q8, d16[1] @ encoding: [0x60,0x0c,0xf3,0xff]
-@ FIXME: vdup.16 q8, d16[1] @ encoding: [0x60,0x0c,0xf6,0xff]
-@ FIXME: vdup.32 q8, d16[1] @ encoding: [0x60,0x0c,0xfc,0xff]
+@ CHECK: vdup.8 d16, d11[0] @ encoding: [0xf1,0xff,0x0b,0x0c]
+@ CHECK: vdup.16 d17, d12[0] @ encoding: [0xf2,0xff,0x0c,0x1c]
+@ CHECK: vdup.32 d18, d13[0] @ encoding: [0xf4,0xff,0x0d,0x2c]
+@ CHECK: vdup.8 q3, d10[0] @ encoding: [0xb1,0xff,0x4a,0x6c]
+@ CHECK: vdup.16 q9, d9[0] @ encoding: [0xf2,0xff,0x49,0x2c]
+@ CHECK: vdup.32 q8, d8[0] @ encoding: [0xf4,0xff,0x48,0x0c]
+@ CHECK: vdup.8 d16, d11[1] @ encoding: [0xf3,0xff,0x0b,0x0c]
+@ CHECK: vdup.16 d17, d12[1] @ encoding: [0xf6,0xff,0x0c,0x1c]
+@ CHECK: vdup.32 d18, d13[1] @ encoding: [0xfc,0xff,0x0d,0x2c]
+@ CHECK: vdup.8 q3, d10[1] @ encoding: [0xb3,0xff,0x4a,0x6c]
+@ CHECK: vdup.16 q9, d9[1] @ encoding: [0xf6,0xff,0x49,0x2c]
+@ CHECK: vdup.32 q8, d8[1] @ encoding: [0xfc,0xff,0x48,0x0c]
diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp
index b5fe7e6..fa7058c 100644
--- a/utils/TableGen/EDEmitter.cpp
+++ b/utils/TableGen/EDEmitter.cpp
@@ -624,6 +624,9 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
IMM("postidx_imm8s4");
IMM("imm_sr");
IMM("imm1_31");
+ IMM("VectorIndex8");
+ IMM("VectorIndex16");
+ IMM("VectorIndex32");
MISC("brtarget", "kOperandTypeARMBranchTarget"); // ?
MISC("uncondbrtarget", "kOperandTypeARMBranchTarget"); // ?