ARM NEON two-register double spaced register list parsing support.

llvm-svn: 146685
This commit is contained in:
Jim Grosbach 2011-12-15 21:44:33 +00:00
parent 75ed9dcbc6
commit 2f50e92f40
1 changed files with 49 additions and 14 deletions

View File

@ -336,6 +336,7 @@ class ARMOperand : public MCParsedAsmOperand {
unsigned RegNum; unsigned RegNum;
unsigned Count; unsigned Count;
unsigned LaneIndex; unsigned LaneIndex;
bool isDoubleSpaced;
} VectorList; } VectorList;
struct { struct {
@ -1074,31 +1075,35 @@ public:
bool isProcIFlags() const { return Kind == k_ProcIFlags; } bool isProcIFlags() const { return Kind == k_ProcIFlags; }
// NEON operands. // NEON operands.
bool isSingleSpacedVectorList() const {
return Kind == k_VectorList && !VectorList.isDoubleSpaced;
}
bool isDoubleSpacedVectorList() const {
return Kind == k_VectorList && VectorList.isDoubleSpaced;
}
bool isVecListOneD() const { bool isVecListOneD() const {
if (Kind != k_VectorList) return false; if (!isSingleSpacedVectorList()) return false;
return VectorList.Count == 1; return VectorList.Count == 1;
} }
bool isVecListTwoD() const { bool isVecListTwoD() const {
if (Kind != k_VectorList) return false; if (!isSingleSpacedVectorList()) return false;
return VectorList.Count == 2; return VectorList.Count == 2;
} }
bool isVecListThreeD() const { bool isVecListThreeD() const {
if (Kind != k_VectorList) return false; if (!isSingleSpacedVectorList()) return false;
return VectorList.Count == 3; return VectorList.Count == 3;
} }
bool isVecListFourD() const { bool isVecListFourD() const {
if (Kind != k_VectorList) return false; if (!isSingleSpacedVectorList()) return false;
return VectorList.Count == 4; return VectorList.Count == 4;
} }
bool isVecListTwoQ() const { bool isVecListTwoQ() const {
if (Kind != k_VectorList) return false; if (!isDoubleSpacedVectorList()) return false;
//FIXME: We haven't taught the parser to handle by-two register lists return VectorList.Count == 2;
// yet, so don't pretend to know one.
return VectorList.Count == 2 && false;
} }
bool isVecListOneDAllLanes() const { bool isVecListOneDAllLanes() const {
@ -1948,10 +1953,11 @@ public:
} }
static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count, static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
SMLoc S, SMLoc E) { bool isDoubleSpaced, SMLoc S, SMLoc E) {
ARMOperand *Op = new ARMOperand(k_VectorList); ARMOperand *Op = new ARMOperand(k_VectorList);
Op->VectorList.RegNum = RegNum; Op->VectorList.RegNum = RegNum;
Op->VectorList.Count = Count; Op->VectorList.Count = Count;
Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Op->StartLoc = S; Op->StartLoc = S;
Op->EndLoc = E; Op->EndLoc = E;
return Op; return Op;
@ -2774,7 +2780,7 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
assert(0 && "unexpected lane kind!"); assert(0 && "unexpected lane kind!");
case NoLanes: case NoLanes:
E = Parser.getTok().getLoc(); E = Parser.getTok().getLoc();
Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E)); Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
break; break;
case AllLanes: case AllLanes:
E = Parser.getTok().getLoc(); E = Parser.getTok().getLoc();
@ -2797,7 +2803,7 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
assert(0 && "unexpected lane kind!"); assert(0 && "unexpected lane kind!");
case NoLanes: case NoLanes:
E = Parser.getTok().getLoc(); E = Parser.getTok().getLoc();
Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E)); Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
break; break;
case AllLanes: case AllLanes:
E = Parser.getTok().getLoc(); E = Parser.getTok().getLoc();
@ -2826,11 +2832,14 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_ParseFail; return MatchOperand_ParseFail;
} }
unsigned Count = 1; unsigned Count = 1;
unsigned Spacing = 0;
unsigned FirstReg = Reg; unsigned FirstReg = Reg;
// The list is of D registers, but we also allow Q regs and just interpret // The list is of D registers, but we also allow Q regs and just interpret
// them as the two D sub-registers. // them as the two D sub-registers.
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
FirstReg = Reg = getDRegFromQReg(Reg); FirstReg = Reg = getDRegFromQReg(Reg);
Spacing = 1; // double-spacing requires explicit D registers, otherwise
// it's ambiguous with four-register single spaced.
++Reg; ++Reg;
++Count; ++Count;
} }
@ -2840,6 +2849,13 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
while (Parser.getTok().is(AsmToken::Comma) || while (Parser.getTok().is(AsmToken::Comma) ||
Parser.getTok().is(AsmToken::Minus)) { Parser.getTok().is(AsmToken::Minus)) {
if (Parser.getTok().is(AsmToken::Minus)) { if (Parser.getTok().is(AsmToken::Minus)) {
if (!Spacing)
Spacing = 1; // Register range implies a single spaced list.
else if (Spacing == 2) {
Error(Parser.getTok().getLoc(),
"sequential registers in double spaced list");
return MatchOperand_ParseFail;
}
Parser.Lex(); // Eat the minus. Parser.Lex(); // Eat the minus.
SMLoc EndLoc = Parser.getTok().getLoc(); SMLoc EndLoc = Parser.getTok().getLoc();
int EndReg = tryParseRegister(); int EndReg = tryParseRegister();
@ -2895,6 +2911,13 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
// The list is of D registers, but we also allow Q regs and just interpret // The list is of D registers, but we also allow Q regs and just interpret
// them as the two D sub-registers. // them as the two D sub-registers.
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
if (!Spacing)
Spacing = 1; // Register range implies a single spaced list.
else if (Spacing == 2) {
Error(RegLoc,
"invalid register in double-spaced list (must be 'D' register')");
return MatchOperand_ParseFail;
}
Reg = getDRegFromQReg(Reg); Reg = getDRegFromQReg(Reg);
if (Reg != OldReg + 1) { if (Reg != OldReg + 1) {
Error(RegLoc, "non-contiguous register range"); Error(RegLoc, "non-contiguous register range");
@ -2914,8 +2937,14 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
} }
continue; continue;
} }
// Normal D register. Just check that it's contiguous and keep going. // Normal D register.
if (Reg != OldReg + 1) { // Figure out the register spacing (single or double) of the list if
// we don't know it already.
if (!Spacing)
Spacing = 1 + (Reg == OldReg + 2);
// Just check that it's contiguous and keep going.
if (Reg != OldReg + Spacing) {
Error(RegLoc, "non-contiguous register range"); Error(RegLoc, "non-contiguous register range");
return MatchOperand_ParseFail; return MatchOperand_ParseFail;
} }
@ -2930,6 +2959,11 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Error(EndLoc, "mismatched lane index in register list"); Error(EndLoc, "mismatched lane index in register list");
return MatchOperand_ParseFail; return MatchOperand_ParseFail;
} }
if (Spacing == 2 && LaneKind != NoLanes) {
Error(EndLoc,
"lane index specfier invalid in double spaced register list");
return MatchOperand_ParseFail;
}
} }
SMLoc E = Parser.getTok().getLoc(); SMLoc E = Parser.getTok().getLoc();
@ -2943,7 +2977,8 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
default: default:
assert(0 && "unexpected lane kind in register list."); assert(0 && "unexpected lane kind in register list.");
case NoLanes: case NoLanes:
Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E)); Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
(Spacing == 2), S, E));
break; break;
case AllLanes: case AllLanes:
Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count, Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,