mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
ARM parsing aliases for VLD1 single register all lanes.
llvm-svn: 145464
This commit is contained in:
parent
c5fa9f413a
commit
693ce8291c
@ -812,6 +812,9 @@ def addrmode6dup : Operand<i32>,
|
|||||||
let PrintMethod = "printAddrMode6Operand";
|
let PrintMethod = "printAddrMode6Operand";
|
||||||
let MIOperandInfo = (ops GPR:$addr, i32imm);
|
let MIOperandInfo = (ops GPR:$addr, i32imm);
|
||||||
let EncoderMethod = "getAddrMode6DupAddressOpValue";
|
let EncoderMethod = "getAddrMode6DupAddressOpValue";
|
||||||
|
// FIXME: This is close, but not quite right. The alignment specifier is
|
||||||
|
// different.
|
||||||
|
let ParserMatchClass = AddrMode6AsmOperand;
|
||||||
}
|
}
|
||||||
|
|
||||||
// addrmodepc := pc + reg
|
// addrmodepc := pc + reg
|
||||||
|
@ -120,6 +120,16 @@ def VecListTwoQ : RegisterOperand<DPR, "printVectorListTwo"> {
|
|||||||
let ParserMatchClass = VecListTwoQAsmOperand;
|
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.
|
// NEON-specific DAG Nodes.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -1003,9 +1013,11 @@ def VLD4LNq32Pseudo_UPD : VLDQQQQLNWBPseudo<IIC_VLD4lnu>;
|
|||||||
|
|
||||||
// VLD1DUP : Vector Load (single element to all lanes)
|
// VLD1DUP : Vector Load (single element to all lanes)
|
||||||
class VLD1DUP<bits<4> op7_4, string Dt, ValueType Ty, PatFrag LoadOp>
|
class VLD1DUP<bits<4> op7_4, string Dt, ValueType Ty, PatFrag LoadOp>
|
||||||
: NLdSt<1, 0b10, 0b1100, op7_4, (outs DPR:$Vd), (ins addrmode6dup:$Rn),
|
: NLdSt<1, 0b10, 0b1100, op7_4, (outs VecListOneDAllLanes:$Vd),
|
||||||
IIC_VLD1dup, "vld1", Dt, "\\{$Vd[]\\}, $Rn", "",
|
(ins addrmode6dup:$Rn),
|
||||||
[(set DPR:$Vd, (Ty (NEONvdup (i32 (LoadOp addrmode6dup:$Rn)))))]> {
|
IIC_VLD1dup, "vld1", Dt, "$Vd, $Rn", "",
|
||||||
|
[(set VecListOneDAllLanes:$Vd,
|
||||||
|
(Ty (NEONvdup (i32 (LoadOp addrmode6dup:$Rn)))))]> {
|
||||||
let Rm = 0b1111;
|
let Rm = 0b1111;
|
||||||
let Inst{4} = Rn{4};
|
let Inst{4} = Rn{4};
|
||||||
let DecoderMethod = "DecodeVLD1DupInstruction";
|
let DecoderMethod = "DecodeVLD1DupInstruction";
|
||||||
|
@ -39,6 +39,8 @@ namespace {
|
|||||||
|
|
||||||
class ARMOperand;
|
class ARMOperand;
|
||||||
|
|
||||||
|
enum VectorLaneTy { NoLanes, AllLanes };
|
||||||
|
|
||||||
class ARMAsmParser : public MCTargetAsmParser {
|
class ARMAsmParser : public MCTargetAsmParser {
|
||||||
MCSubtargetInfo &STI;
|
MCSubtargetInfo &STI;
|
||||||
MCAsmParser &Parser;
|
MCAsmParser &Parser;
|
||||||
@ -161,6 +163,7 @@ class ARMAsmParser : public MCTargetAsmParser {
|
|||||||
OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
|
OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||||
OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
|
OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||||
OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
|
OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||||
|
OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind);
|
||||||
|
|
||||||
// Asm Match Converter Methods
|
// Asm Match Converter Methods
|
||||||
bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
|
bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
|
||||||
@ -271,6 +274,7 @@ class ARMOperand : public MCParsedAsmOperand {
|
|||||||
k_DPRRegisterList,
|
k_DPRRegisterList,
|
||||||
k_SPRRegisterList,
|
k_SPRRegisterList,
|
||||||
k_VectorList,
|
k_VectorList,
|
||||||
|
k_VectorListAllLanes,
|
||||||
k_ShiftedRegister,
|
k_ShiftedRegister,
|
||||||
k_ShiftedImmediate,
|
k_ShiftedImmediate,
|
||||||
k_ShifterImmediate,
|
k_ShifterImmediate,
|
||||||
@ -409,6 +413,7 @@ public:
|
|||||||
Registers = o.Registers;
|
Registers = o.Registers;
|
||||||
break;
|
break;
|
||||||
case k_VectorList:
|
case k_VectorList:
|
||||||
|
case k_VectorListAllLanes:
|
||||||
VectorList = o.VectorList;
|
VectorList = o.VectorList;
|
||||||
break;
|
break;
|
||||||
case k_CoprocNum:
|
case k_CoprocNum:
|
||||||
@ -967,6 +972,11 @@ public:
|
|||||||
return VectorList.Count == 2 && false;
|
return VectorList.Count == 2 && false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isVecListOneDAllLanes() const {
|
||||||
|
if (Kind != k_VectorListAllLanes) return false;
|
||||||
|
return VectorList.Count == 1;
|
||||||
|
}
|
||||||
|
|
||||||
bool isVectorIndex8() const {
|
bool isVectorIndex8() const {
|
||||||
if (Kind != k_VectorIndex) return false;
|
if (Kind != k_VectorIndex) return false;
|
||||||
return VectorIndex.Val < 8;
|
return VectorIndex.Val < 8;
|
||||||
@ -1761,6 +1771,16 @@ public:
|
|||||||
return Op;
|
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,
|
static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
|
||||||
MCContext &Ctx) {
|
MCContext &Ctx) {
|
||||||
ARMOperand *Op = new ARMOperand(k_VectorIndex);
|
ARMOperand *Op = new ARMOperand(k_VectorIndex);
|
||||||
@ -1954,6 +1974,10 @@ void ARMOperand::print(raw_ostream &OS) const {
|
|||||||
OS << "<vector_list " << VectorList.Count << " * "
|
OS << "<vector_list " << VectorList.Count << " * "
|
||||||
<< VectorList.RegNum << ">";
|
<< VectorList.RegNum << ">";
|
||||||
break;
|
break;
|
||||||
|
case k_VectorListAllLanes:
|
||||||
|
OS << "<vector_list(all lanes) " << VectorList.Count << " * "
|
||||||
|
<< VectorList.RegNum << ">";
|
||||||
|
break;
|
||||||
case k_Token:
|
case k_Token:
|
||||||
OS << "'" << getToken() << "'";
|
OS << "'" << getToken() << "'";
|
||||||
break;
|
break;
|
||||||
@ -2453,9 +2477,29 @@ parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
|||||||
return false;
|
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
|
// parse a vector register list
|
||||||
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
|
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
|
||||||
parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||||
|
VectorLaneTy LaneKind;
|
||||||
SMLoc S = Parser.getTok().getLoc();
|
SMLoc S = Parser.getTok().getLoc();
|
||||||
// As an extension (to match gas), support a plain D register or Q register
|
// 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,
|
// (without encosing curly braces) as a single or double entry list,
|
||||||
@ -2466,12 +2510,40 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
|||||||
return MatchOperand_NoMatch;
|
return MatchOperand_NoMatch;
|
||||||
SMLoc E = Parser.getTok().getLoc();
|
SMLoc E = Parser.getTok().getLoc();
|
||||||
if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
|
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;
|
return MatchOperand_Success;
|
||||||
}
|
}
|
||||||
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
|
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
|
||||||
Reg = getDRegFromQReg(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;
|
return MatchOperand_Success;
|
||||||
}
|
}
|
||||||
Error(S, "vector register expected");
|
Error(S, "vector register expected");
|
||||||
@ -2498,6 +2570,8 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
|||||||
++Reg;
|
++Reg;
|
||||||
++Count;
|
++Count;
|
||||||
}
|
}
|
||||||
|
if (parseVectorLane(LaneKind) != MatchOperand_Success)
|
||||||
|
return MatchOperand_ParseFail;
|
||||||
|
|
||||||
while (Parser.getTok().is(AsmToken::Comma) ||
|
while (Parser.getTok().is(AsmToken::Comma) ||
|
||||||
Parser.getTok().is(AsmToken::Minus)) {
|
Parser.getTok().is(AsmToken::Minus)) {
|
||||||
@ -2526,6 +2600,15 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
|||||||
Error(EndLoc, "bad range in register list");
|
Error(EndLoc, "bad range in register list");
|
||||||
return MatchOperand_ParseFail;
|
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.
|
// Add all the registers in the range to the register list.
|
||||||
Count += EndReg - Reg;
|
Count += EndReg - Reg;
|
||||||
@ -2554,6 +2637,15 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
|||||||
}
|
}
|
||||||
++Reg;
|
++Reg;
|
||||||
Count += 2;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
// Normal D register. Just check that it's contiguous and keep going.
|
// Normal D register. Just check that it's contiguous and keep going.
|
||||||
@ -2562,6 +2654,15 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
|||||||
return MatchOperand_ParseFail;
|
return MatchOperand_ParseFail;
|
||||||
}
|
}
|
||||||
++Count;
|
++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();
|
SMLoc E = Parser.getTok().getLoc();
|
||||||
@ -2571,7 +2672,17 @@ parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
|||||||
}
|
}
|
||||||
Parser.Lex(); // Eat '}' token.
|
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;
|
return MatchOperand_Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1029,3 +1029,10 @@ void ARMInstPrinter::printVectorListFour(const MCInst *MI, unsigned OpNum,
|
|||||||
<< getRegisterName(MI->getOperand(OpNum).getReg() + 2) << ", "
|
<< getRegisterName(MI->getOperand(OpNum).getReg() + 2) << ", "
|
||||||
<< getRegisterName(MI->getOperand(OpNum).getReg() + 3) << "}";
|
<< getRegisterName(MI->getOperand(OpNum).getReg() + 3) << "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ARMInstPrinter::printVectorListOneAllLanes(const MCInst *MI,
|
||||||
|
unsigned OpNum,
|
||||||
|
raw_ostream &O) {
|
||||||
|
O << "{" << getRegisterName(MI->getOperand(OpNum).getReg()) << "[]}";
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -133,6 +133,8 @@ public:
|
|||||||
void printVectorListTwo(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
void printVectorListTwo(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||||
void printVectorListThree(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 printVectorListFour(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||||
|
void printVectorListOneAllLanes(const MCInst *MI, unsigned OpNum,
|
||||||
|
raw_ostream &O);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
@ -576,6 +576,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
|
|||||||
REG("VecListThreeD");
|
REG("VecListThreeD");
|
||||||
REG("VecListFourD");
|
REG("VecListFourD");
|
||||||
REG("VecListTwoQ");
|
REG("VecListTwoQ");
|
||||||
|
REG("VecListOneDAllLanes");
|
||||||
|
|
||||||
IMM("i32imm");
|
IMM("i32imm");
|
||||||
IMM("i32imm_hilo16");
|
IMM("i32imm_hilo16");
|
||||||
|
Loading…
Reference in New Issue
Block a user