aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
diff options
context:
space:
mode:
authorMatheus Almeida <matheus.almeida@imgtec.com>2013-10-11 13:29:36 +0000
committerMatheus Almeida <matheus.almeida@imgtec.com>2013-10-11 13:29:36 +0000
commit6f36ea5c4778ac0519d821798b94aaac92ec1389 (patch)
tree452cbbce020a2ae25674c19220ffed8754cc53b0 /lib/Target/Mips/AsmParser/MipsAsmParser.cpp
parent71e7893757d4f43de7c060153b2e5e8c53dd2e31 (diff)
downloadexternal_llvm-6f36ea5c4778ac0519d821798b94aaac92ec1389.zip
external_llvm-6f36ea5c4778ac0519d821798b94aaac92ec1389.tar.gz
external_llvm-6f36ea5c4778ac0519d821798b94aaac92ec1389.tar.bz2
[mips][msa] Direct Object Emission of INSERT.{B,H,W} instruction.
INSERT is the first type of MSA instruction that requires a change to the way MSA registers are parsed. This happens because MSA registers may be suffixed by an index in the form of an immediate or a general purpose register. The changes to parseMSARegs reflect that requirement. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@192447 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/Mips/AsmParser/MipsAsmParser.cpp')
-rw-r--r--lib/Target/Mips/AsmParser/MipsAsmParser.cpp121
1 files changed, 121 insertions, 0 deletions
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index ae9d276..41399c5 100644
--- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -236,6 +236,12 @@ class MipsAsmParser : public MCTargetAsmParser {
bool processInstruction(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions);
+
+ // Helper function that checks if the value of a vector index is within the
+ // boundaries of accepted values for each RegisterKind
+ // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
+ bool validateMSAIndex(int Val, int RegKind);
+
public:
MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
const MCInstrInfo &MII)
@@ -1547,6 +1553,26 @@ MipsAsmParser::parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
return MatchOperand_NoMatch;
}
+bool MipsAsmParser::validateMSAIndex(int Val, int RegKind) {
+ MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
+
+ if (Val < 0)
+ return false;
+
+ switch (Kind) {
+ default:
+ return false;
+ case MipsOperand::Kind_MSA128BRegs:
+ return Val < 16;
+ case MipsOperand::Kind_MSA128HRegs:
+ return Val < 8;
+ case MipsOperand::Kind_MSA128WRegs:
+ return Val < 4;
+ case MipsOperand::Kind_MSA128DRegs:
+ return Val < 2;
+ }
+}
+
MipsAsmParser::OperandMatchResultTy
MipsAsmParser::parseMSARegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
int RegKind) {
@@ -1589,6 +1615,101 @@ MipsAsmParser::parseMSARegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Parser.Lex(); // Eat the register identifier.
+ // MSA registers may be suffixed with an index in the form of:
+ // 1) Immediate expression.
+ // 2) General Purpose Register.
+ // Examples:
+ // 1) copy_s.b $29,$w0[0]
+ // 2) sld.b $w0,$w1[$1]
+
+ if (Parser.getTok().isNot(AsmToken::LBrac))
+ return MatchOperand_Success;
+
+ MipsOperand *Mnemonic = static_cast<MipsOperand *>(Operands[0]);
+
+ Operands.push_back(MipsOperand::CreateToken("[", Parser.getTok().getLoc()));
+ Parser.Lex(); // Parse the '[' token.
+
+ if (Parser.getTok().is(AsmToken::Dollar)) {
+ // This must be a GPR.
+ MipsOperand *RegOp;
+ SMLoc VIdx = Parser.getTok().getLoc();
+ Parser.Lex(); // Parse the '$' token.
+
+ // GPR have aliases and we must account for that. Example: $30 == $fp
+ if (getLexer().getKind() == AsmToken::Integer) {
+ unsigned RegNum = Parser.getTok().getIntVal();
+ int Reg = matchRegisterByNumber(
+ RegNum, regKindToRegClass(MipsOperand::Kind_GPR32));
+ if (Reg == -1) {
+ Error(VIdx, "invalid general purpose register");
+ return MatchOperand_ParseFail;
+ }
+
+ RegOp = MipsOperand::CreateReg(Reg, VIdx, Parser.getTok().getLoc());
+ } else if (getLexer().getKind() == AsmToken::Identifier) {
+ int RegNum = -1;
+ std::string RegName = Parser.getTok().getString().lower();
+
+ RegNum = matchCPURegisterName(RegName);
+ if (RegNum == -1) {
+ Error(VIdx, "general purpose register expected");
+ return MatchOperand_ParseFail;
+ }
+ RegNum = getReg(regKindToRegClass(MipsOperand::Kind_GPR32), RegNum);
+ RegOp = MipsOperand::CreateReg(RegNum, VIdx, Parser.getTok().getLoc());
+ }
+
+ RegOp->setRegKind(MipsOperand::Kind_GPR32);
+ Operands.push_back(RegOp);
+ Parser.Lex(); // Eat the register identifier.
+
+ if (Parser.getTok().isNot(AsmToken::RBrac))
+ return MatchOperand_ParseFail;
+
+ Operands.push_back(MipsOperand::CreateToken("]", Parser.getTok().getLoc()));
+ Parser.Lex(); // Parse the ']' token.
+
+ return MatchOperand_Success;
+ }
+
+ // The index must be a constant expression then.
+ SMLoc VIdx = Parser.getTok().getLoc();
+ const MCExpr *ImmVal;
+
+ if (getParser().parseExpression(ImmVal))
+ return MatchOperand_ParseFail;
+
+ const MCConstantExpr *expr = dyn_cast<MCConstantExpr>(ImmVal);
+ if (!expr || !validateMSAIndex((int)expr->getValue(), Kind)) {
+ Error(VIdx, "invalid immediate value");
+ return MatchOperand_ParseFail;
+ }
+
+ SMLoc E = Parser.getTok().getEndLoc();
+
+ if (Parser.getTok().isNot(AsmToken::RBrac))
+ return MatchOperand_ParseFail;
+
+ bool insve = Mnemonic->getToken() == "insve.b" ||
+ Mnemonic->getToken() == "insve.h" ||
+ Mnemonic->getToken() == "insve.w" ||
+ Mnemonic->getToken() == "insve.d";
+
+ // The second vector index of insve instructions is always 0.
+ if (insve && Operands.size() > 6) {
+ if (expr->getValue() != 0) {
+ Error(VIdx, "immediate value must be 0");
+ return MatchOperand_ParseFail;
+ }
+ Operands.push_back(MipsOperand::CreateToken("0", VIdx));
+ } else
+ Operands.push_back(MipsOperand::CreateImm(expr, VIdx, E));
+
+ Operands.push_back(MipsOperand::CreateToken("]", Parser.getTok().getLoc()));
+
+ Parser.Lex(); // Parse the ']' token.
+
return MatchOperand_Success;
}