aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Target/ARM/ARMInstrNEON.td18
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp111
2 files changed, 115 insertions, 14 deletions
diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td
index 406f163f89..12efea242b 100644
--- a/lib/Target/ARM/ARMInstrNEON.td
+++ b/lib/Target/ARM/ARMInstrNEON.td
@@ -139,6 +139,17 @@ def VecListTwoDAllLanes : RegisterOperand<DPR, "printVectorListTwoAllLanes"> {
let ParserMatchClass = VecListTwoDAllLanesAsmOperand;
}
+// Register list of one D register, with byte lane subscripting.
+def VecListOneDByteIndexAsmOperand : AsmOperandClass {
+ let Name = "VecListOneDByteIndexed";
+ let ParserMethod = "parseVectorList";
+ let RenderMethod = "addVecListIndexedOperands";
+}
+def VecListOneDByteIndexed : Operand<i32> {
+ let ParserMatchClass = VecListOneDByteIndexAsmOperand;
+ let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx);
+}
+
//===----------------------------------------------------------------------===//
// NEON-specific DAG Nodes.
//===----------------------------------------------------------------------===//
@@ -754,6 +765,13 @@ def VLD1LNd32 : VLD1LN32<0b1000, {?,0,?,?}, "32", v2i32, load> {
let Inst{4} = Rn{4};
}
+// FIXME: Proof of concept pseudos. We want to parameterize these for all
+// the suffices we have to support.
+def VLD1LNd8asm : NEONAsmPseudo<"vld1${p}.8 $list, $addr",
+ (ins VecListOneDByteIndexed:$list, addrmode6:$addr, pred:$p)>;
+def VLD1LNdf32asm : NEONAsmPseudo<"vld1${p}.f32 $list, $addr",
+ (ins VecListOneDByteIndexed:$list, addrmode6:$addr, pred:$p)>;
+
def VLD1LNq8Pseudo : VLD1QLNPseudo<v16i8, extloadi8>;
def VLD1LNq16Pseudo : VLD1QLNPseudo<v8i16, extloadi16>;
def VLD1LNq32Pseudo : VLD1QLNPseudo<v4i32, load>;
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index c24335ca35..59dec0edfa 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -39,7 +39,7 @@ namespace {
class ARMOperand;
-enum VectorLaneTy { NoLanes, AllLanes };
+enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
class ARMAsmParser : public MCTargetAsmParser {
MCSubtargetInfo &STI;
@@ -163,7 +163,7 @@ class ARMAsmParser : public MCTargetAsmParser {
OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
- OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind);
+ OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
// Asm Match Converter Methods
bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
@@ -275,6 +275,7 @@ class ARMOperand : public MCParsedAsmOperand {
k_SPRRegisterList,
k_VectorList,
k_VectorListAllLanes,
+ k_VectorListIndexed,
k_ShiftedRegister,
k_ShiftedImmediate,
k_ShifterImmediate,
@@ -328,6 +329,7 @@ class ARMOperand : public MCParsedAsmOperand {
struct {
unsigned RegNum;
unsigned Count;
+ unsigned LaneIndex;
} VectorList;
struct {
@@ -414,6 +416,7 @@ public:
break;
case k_VectorList:
case k_VectorListAllLanes:
+ case k_VectorListIndexed:
VectorList = o.VectorList;
break;
case k_CoprocNum:
@@ -982,6 +985,11 @@ public:
return VectorList.Count == 2;
}
+ bool isVecListOneDByteIndexed() const {
+ if (Kind != k_VectorListIndexed) return false;
+ return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
+ }
+
bool isVectorIndex8() const {
if (Kind != k_VectorIndex) return false;
return VectorIndex.Val < 8;
@@ -1547,6 +1555,12 @@ public:
Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
}
+ void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
+ Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
+ }
+
void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
@@ -1786,6 +1800,17 @@ public:
return Op;
}
+ static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
+ unsigned Index, SMLoc S, SMLoc E) {
+ ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
+ Op->VectorList.RegNum = RegNum;
+ Op->VectorList.Count = Count;
+ Op->VectorList.LaneIndex = Index;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
MCContext &Ctx) {
ARMOperand *Op = new ARMOperand(k_VectorIndex);
@@ -1983,6 +2008,10 @@ void ARMOperand::print(raw_ostream &OS) const {
OS << "<vector_list(all lanes) " << VectorList.Count << " * "
<< VectorList.RegNum << ">";
break;
+ case k_VectorListIndexed:
+ OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
+ << VectorList.Count << " * " << VectorList.RegNum << ">";
+ break;
case k_Token:
OS << "'" << getToken() << "'";
break;
@@ -2484,7 +2513,8 @@ parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
// Helper function to parse the lane index for vector lists.
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
-parseVectorLane(VectorLaneTy &LaneKind) {
+parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
+ Index = 0; // Always return a defined index value.
if (Parser.getTok().is(AsmToken::LBrac)) {
Parser.Lex(); // Eat the '['.
if (Parser.getTok().is(AsmToken::RBrac)) {
@@ -2493,8 +2523,20 @@ parseVectorLane(VectorLaneTy &LaneKind) {
Parser.Lex(); // Eat the ']'.
return MatchOperand_Success;
}
- // FIXME: Other lane kinds as we add them.
- Error(Parser.getTok().getLoc(), "FIXME: Unexpected lane kind.");
+ if (Parser.getTok().is(AsmToken::Integer)) {
+ int64_t Val = Parser.getTok().getIntVal();
+ // Make this range check context sensitive for .8, .16, .32.
+ if (Val < 0 && Val > 7)
+ Error(Parser.getTok().getLoc(), "lane index out of range");
+ Index = Val;
+ LaneKind = IndexedLane;
+ Parser.Lex(); // Eat the token;
+ if (Parser.getTok().isNot(AsmToken::RBrac))
+ Error(Parser.getTok().getLoc(), "']' expected");
+ Parser.Lex(); // Eat the ']'.
+ return MatchOperand_Success;
+ }
+ Error(Parser.getTok().getLoc(), "lane index must be empty or an integer");
return MatchOperand_ParseFail;
}
LaneKind = NoLanes;
@@ -2505,6 +2547,7 @@ parseVectorLane(VectorLaneTy &LaneKind) {
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
VectorLaneTy LaneKind;
+ unsigned LaneIndex;
SMLoc S = Parser.getTok().getLoc();
// As an extension (to match gas), support a plain D register or Q register
// (without encosing curly braces) as a single or double entry list,
@@ -2515,7 +2558,7 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_NoMatch;
SMLoc E = Parser.getTok().getLoc();
if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
- OperandMatchResultTy Res = parseVectorLane(LaneKind);
+ OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
if (Res != MatchOperand_Success)
return Res;
switch (LaneKind) {
@@ -2529,12 +2572,16 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
E = Parser.getTok().getLoc();
Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
break;
+ case IndexedLane:
+ Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
+ LaneIndex, S,E));
+ break;
}
return MatchOperand_Success;
}
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Reg = getDRegFromQReg(Reg);
- OperandMatchResultTy Res = parseVectorLane(LaneKind);
+ OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
if (Res != MatchOperand_Success)
return Res;
switch (LaneKind) {
@@ -2548,6 +2595,10 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
E = Parser.getTok().getLoc();
Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
break;
+ case IndexedLane:
+ Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
+ LaneIndex, S,E));
+ break;
}
return MatchOperand_Success;
}
@@ -2575,7 +2626,7 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
++Reg;
++Count;
}
- if (parseVectorLane(LaneKind) != MatchOperand_Success)
+ if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
return MatchOperand_ParseFail;
while (Parser.getTok().is(AsmToken::Comma) ||
@@ -2607,9 +2658,10 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
}
// Parse the lane specifier if present.
VectorLaneTy NextLaneKind;
- if (parseVectorLane(NextLaneKind) != MatchOperand_Success)
+ unsigned NextLaneIndex;
+ if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
return MatchOperand_ParseFail;
- if (NextLaneKind != LaneKind) {
+ if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Error(EndLoc, "mismatched lane index in register list");
return MatchOperand_ParseFail;
}
@@ -2644,10 +2696,11 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Count += 2;
// Parse the lane specifier if present.
VectorLaneTy NextLaneKind;
+ unsigned NextLaneIndex;
SMLoc EndLoc = Parser.getTok().getLoc();
- if (parseVectorLane(NextLaneKind) != MatchOperand_Success)
+ if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
return MatchOperand_ParseFail;
- if (NextLaneKind != LaneKind) {
+ if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Error(EndLoc, "mismatched lane index in register list");
return MatchOperand_ParseFail;
}
@@ -2661,10 +2714,11 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
++Count;
// Parse the lane specifier if present.
VectorLaneTy NextLaneKind;
+ unsigned NextLaneIndex;
SMLoc EndLoc = Parser.getTok().getLoc();
- if (parseVectorLane(NextLaneKind) != MatchOperand_Success)
+ if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
return MatchOperand_ParseFail;
- if (NextLaneKind != LaneKind) {
+ if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Error(EndLoc, "mismatched lane index in register list");
return MatchOperand_ParseFail;
}
@@ -2687,6 +2741,10 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
S, E));
break;
+ case IndexedLane:
+ Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
+ LaneIndex, S, E));
+ break;
}
return MatchOperand_Success;
}
@@ -4693,10 +4751,35 @@ validateInstruction(MCInst &Inst,
return false;
}
+static unsigned getRealVLDNOpcode(unsigned Opc) {
+ switch(Opc) {
+ default: assert(0 && "unexpected opcode!");
+ case ARM::VLD1LNd8asm: return ARM::VLD1LNd8;
+ case ARM::VLD1LNdf32asm: return ARM::VLD1LNd32;
+ }
+}
+
bool ARMAsmParser::
processInstruction(MCInst &Inst,
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
switch (Inst.getOpcode()) {
+ // Handle NEON VLD1 complex aliases.
+ case ARM::VLD1LNd8asm:
+ case ARM::VLD1LNdf32asm: {
+ MCInst TmpInst;
+ // Shuffle the operands around so the lane index operand is in the
+ // right place.
+ TmpInst.setOpcode(getRealVLDNOpcode(Inst.getOpcode()));
+ TmpInst.addOperand(Inst.getOperand(0)); // Vd
+ TmpInst.addOperand(Inst.getOperand(2)); // Rn
+ TmpInst.addOperand(Inst.getOperand(3)); // alignment
+ TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
+ TmpInst.addOperand(Inst.getOperand(1)); // lane
+ TmpInst.addOperand(Inst.getOperand(4)); // CondCode
+ TmpInst.addOperand(Inst.getOperand(5));
+ Inst = TmpInst;
+ return true;
+ }
// Handle the MOV complex aliases.
case ARM::ASRr:
case ARM::LSRr: