ARM parsing aliases for VLD1 single register all lanes.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@145464 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jim Grosbach 2011-11-30 01:09:44 +00:00
parent 3d925d24e8
commit 98b05a57b6
6 changed files with 142 additions and 6 deletions

View File

@ -812,6 +812,9 @@ def addrmode6dup : Operand<i32>,
let PrintMethod = "printAddrMode6Operand";
let MIOperandInfo = (ops GPR:$addr, i32imm);
let EncoderMethod = "getAddrMode6DupAddressOpValue";
// FIXME: This is close, but not quite right. The alignment specifier is
// different.
let ParserMatchClass = AddrMode6AsmOperand;
}
// addrmodepc := pc + reg

View File

@ -120,6 +120,16 @@ def VecListTwoQ : RegisterOperand<DPR, "printVectorListTwo"> {
let ParserMatchClass = VecListTwoQAsmOperand;
}
// Register list of one D register, with "all lanes" subscripting.
def VecListOneDAllLanesAsmOperand : AsmOperandClass {
let Name = "VecListOneDAllLanes";
let ParserMethod = "parseVectorList";
let RenderMethod = "addVecListOperands";
}
def VecListOneDAllLanes : RegisterOperand<DPR, "printVectorListOneAllLanes"> {
let ParserMatchClass = VecListOneDAllLanesAsmOperand;
}
//===----------------------------------------------------------------------===//
// NEON-specific DAG Nodes.
//===----------------------------------------------------------------------===//
@ -1003,9 +1013,11 @@ def VLD4LNq32Pseudo_UPD : VLDQQQQLNWBPseudo<IIC_VLD4lnu>;
// VLD1DUP : Vector Load (single element to all lanes)
class VLD1DUP<bits<4> op7_4, string Dt, ValueType Ty, PatFrag LoadOp>
: NLdSt<1, 0b10, 0b1100, op7_4, (outs DPR:$Vd), (ins addrmode6dup:$Rn),
IIC_VLD1dup, "vld1", Dt, "\\{$Vd[]\\}, $Rn", "",
[(set DPR:$Vd, (Ty (NEONvdup (i32 (LoadOp addrmode6dup:$Rn)))))]> {
: NLdSt<1, 0b10, 0b1100, op7_4, (outs VecListOneDAllLanes:$Vd),
(ins addrmode6dup:$Rn),
IIC_VLD1dup, "vld1", Dt, "$Vd, $Rn", "",
[(set VecListOneDAllLanes:$Vd,
(Ty (NEONvdup (i32 (LoadOp addrmode6dup:$Rn)))))]> {
let Rm = 0b1111;
let Inst{4} = Rn{4};
let DecoderMethod = "DecodeVLD1DupInstruction";

View File

@ -39,6 +39,8 @@ namespace {
class ARMOperand;
enum VectorLaneTy { NoLanes, AllLanes };
class ARMAsmParser : public MCTargetAsmParser {
MCSubtargetInfo &STI;
MCAsmParser &Parser;
@ -161,6 +163,7 @@ class ARMAsmParser : public MCTargetAsmParser {
OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind);
// Asm Match Converter Methods
bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
@ -271,6 +274,7 @@ class ARMOperand : public MCParsedAsmOperand {
k_DPRRegisterList,
k_SPRRegisterList,
k_VectorList,
k_VectorListAllLanes,
k_ShiftedRegister,
k_ShiftedImmediate,
k_ShifterImmediate,
@ -409,6 +413,7 @@ public:
Registers = o.Registers;
break;
case k_VectorList:
case k_VectorListAllLanes:
VectorList = o.VectorList;
break;
case k_CoprocNum:
@ -967,6 +972,11 @@ public:
return VectorList.Count == 2 && false;
}
bool isVecListOneDAllLanes() const {
if (Kind != k_VectorListAllLanes) return false;
return VectorList.Count == 1;
}
bool isVectorIndex8() const {
if (Kind != k_VectorIndex) return false;
return VectorIndex.Val < 8;
@ -1761,6 +1771,16 @@ public:
return Op;
}
static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
SMLoc S, SMLoc E) {
ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
Op->VectorList.RegNum = RegNum;
Op->VectorList.Count = Count;
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);
@ -1954,6 +1974,10 @@ void ARMOperand::print(raw_ostream &OS) const {
OS << "<vector_list " << VectorList.Count << " * "
<< VectorList.RegNum << ">";
break;
case k_VectorListAllLanes:
OS << "<vector_list(all lanes) " << VectorList.Count << " * "
<< VectorList.RegNum << ">";
break;
case k_Token:
OS << "'" << getToken() << "'";
break;
@ -2453,9 +2477,29 @@ parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return false;
}
// Helper function to parse the lane index for vector lists.
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
parseVectorLane(VectorLaneTy &LaneKind) {
if (Parser.getTok().is(AsmToken::LBrac)) {
Parser.Lex(); // Eat the '['.
if (Parser.getTok().is(AsmToken::RBrac)) {
// "Dn[]" is the 'all lanes' syntax.
LaneKind = AllLanes;
Parser.Lex(); // Eat the ']'.
return MatchOperand_Success;
}
// FIXME: Other lane kinds as we add them.
Error(Parser.getTok().getLoc(), "FIXME: Unexpected lane kind.");
return MatchOperand_ParseFail;
}
LaneKind = NoLanes;
return MatchOperand_Success;
}
// parse a vector register list
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
VectorLaneTy LaneKind;
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,
@ -2466,12 +2510,40 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_NoMatch;
SMLoc E = Parser.getTok().getLoc();
if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E));
OperandMatchResultTy Res = parseVectorLane(LaneKind);
if (Res != MatchOperand_Success)
return Res;
switch (LaneKind) {
default:
assert(0 && "unexpected lane kind!");
case NoLanes:
E = Parser.getTok().getLoc();
Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E));
break;
case AllLanes:
E = Parser.getTok().getLoc();
Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
break;
}
return MatchOperand_Success;
}
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Reg = getDRegFromQReg(Reg);
Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E));
OperandMatchResultTy Res = parseVectorLane(LaneKind);
if (Res != MatchOperand_Success)
return Res;
switch (LaneKind) {
default:
assert(0 && "unexpected lane kind!");
case NoLanes:
E = Parser.getTok().getLoc();
Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E));
break;
case AllLanes:
E = Parser.getTok().getLoc();
Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
break;
}
return MatchOperand_Success;
}
Error(S, "vector register expected");
@ -2498,6 +2570,8 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
++Reg;
++Count;
}
if (parseVectorLane(LaneKind) != MatchOperand_Success)
return MatchOperand_ParseFail;
while (Parser.getTok().is(AsmToken::Comma) ||
Parser.getTok().is(AsmToken::Minus)) {
@ -2526,6 +2600,15 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Error(EndLoc, "bad range in register list");
return MatchOperand_ParseFail;
}
// Parse the lane specifier if present.
VectorLaneTy NextLaneKind;
if (parseVectorLane(NextLaneKind) != MatchOperand_Success)
return MatchOperand_ParseFail;
if (NextLaneKind != LaneKind) {
Error(EndLoc, "mismatched lane index in register list");
return MatchOperand_ParseFail;
}
EndLoc = Parser.getTok().getLoc();
// Add all the registers in the range to the register list.
Count += EndReg - Reg;
@ -2554,6 +2637,15 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
}
++Reg;
Count += 2;
// Parse the lane specifier if present.
VectorLaneTy NextLaneKind;
SMLoc EndLoc = Parser.getTok().getLoc();
if (parseVectorLane(NextLaneKind) != MatchOperand_Success)
return MatchOperand_ParseFail;
if (NextLaneKind != LaneKind) {
Error(EndLoc, "mismatched lane index in register list");
return MatchOperand_ParseFail;
}
continue;
}
// Normal D register. Just check that it's contiguous and keep going.
@ -2562,6 +2654,15 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_ParseFail;
}
++Count;
// Parse the lane specifier if present.
VectorLaneTy NextLaneKind;
SMLoc EndLoc = Parser.getTok().getLoc();
if (parseVectorLane(NextLaneKind) != MatchOperand_Success)
return MatchOperand_ParseFail;
if (NextLaneKind != LaneKind) {
Error(EndLoc, "mismatched lane index in register list");
return MatchOperand_ParseFail;
}
}
SMLoc E = Parser.getTok().getLoc();
@ -2571,7 +2672,17 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
}
Parser.Lex(); // Eat '}' token.
Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
switch (LaneKind) {
default:
assert(0 && "unexpected lane kind in register list.");
case NoLanes:
Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
break;
case AllLanes:
Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
S, E));
break;
}
return MatchOperand_Success;
}

View File

@ -1029,3 +1029,10 @@ void ARMInstPrinter::printVectorListFour(const MCInst *MI, unsigned OpNum,
<< getRegisterName(MI->getOperand(OpNum).getReg() + 2) << ", "
<< getRegisterName(MI->getOperand(OpNum).getReg() + 3) << "}";
}
void ARMInstPrinter::printVectorListOneAllLanes(const MCInst *MI,
unsigned OpNum,
raw_ostream &O) {
O << "{" << getRegisterName(MI->getOperand(OpNum).getReg()) << "[]}";
}

View File

@ -133,6 +133,8 @@ public:
void printVectorListTwo(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printVectorListThree(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printVectorListFour(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printVectorListOneAllLanes(const MCInst *MI, unsigned OpNum,
raw_ostream &O);
};
} // end namespace llvm

View File

@ -576,6 +576,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
REG("VecListThreeD");
REG("VecListFourD");
REG("VecListTwoQ");
REG("VecListOneDAllLanes");
IMM("i32imm");
IMM("i32imm_hilo16");