<html><head><meta http-equiv="Content-Type" content="text/html charset=windows-1252"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">Hi Vladamir,<div><br></div><div>That helps, thanks.</div><div><br></div><div>It’s still unclear why splitting the types off into separate operands won’t work, as the ARM asm parser has dealt with these same issues, including multiple suffices on a single instruction. The more I think about it, though, I’m not sure that matters too much.</div><div><br></div><div>There is a bit of inconsistency in how the asm matcher tokenizes and how the generic asm parser tokenizes with respect to ‘.’ delimiters. I’m not sure of the historical reasons for the current behavior, but it makes sense to allow targets to opt-in to having the matcher not split the mnemonic on ‘.’ characters. That should be an AsmParser level distinction, though, not a per-instruction decision.</div><div><br></div><div>Also, please split the patch into two parts. First, the target-independent bits then the Mips backend bits which use the new functionality.</div><div><br></div><div>Regards,</div><div> Jim</div><div><br><div><div>On Jul 2, 2013, at 2:58 AM, Vladimir Medic <<a href="mailto:Vladimir.Medic@imgtec.com">Vladimir.Medic@imgtec.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div ocsi="0" fpstyle="1" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word;"><div style="direction: ltr; font-family: Tahoma; font-size: 10pt;">Hi Jim,<br>perhaps the subject was confusing making you think that my statement is that dot is not allowed in mnemonics at all.<span class="Apple-converted-space"> </span><br>The problem we are facing is in generated assembler matcher code (MipsGenAsmMatcher.inc), particularly MatchTable and OperandMatchTable . The code in tokenizeAsmString(AsmMatcherEmitter.cpp, ln 784) parses instruction mnemonic and when it meats '.' operand is sliced and added to a list of operands. Therefore, for example, string "add.s" (floating point addition, 32 bit register) is divided into "add" and "s" operands which are added into operands list with "add" as first operand treated as mnemonic. So, during the parsing we also have to split the token and add treat size modifier("s") as an operand. Now, size modifiers are important in Mips assembler as it determines the type of operand used in instruction. So far we used the approach of splitting the mnemonic and adding size modifiers into operands list, but this has proven to complicated in some cases as there are instructions that use two size modifiers and some don't use them at all. To simplify the parsing and solve these problems we have tried to introduce RegisterOperand instead of RegisterClass in instruction definition in order to call dedicated operand parsing class we face a problem. As the matcher uses only first part of the mnemonic in the tables to find the dedicated parser the "add.s" and "add.d" are treated in a same way as "add" which is CPU register addition. With a non-unique entries in table dedicated parser approach seems to lose the point. With the changes we propose the whole mnemonic including dots is used in matcher tables and operand parsing is more deterministic.<br><br>I hope this has cleared the reason behind the proposed changes.<br><br>Vladimir<br><div style="font-family: 'Times New Roman'; font-size: 16px;"><hr tabindex="-1"><div id="divRpF5352" style="direction: ltr;"><font face="Tahoma" size="2"><b>From:</b><span class="Apple-converted-space"> </span>Jim Grosbach [<a href="mailto:grosbach@apple.com">grosbach@apple.com</a>]<br><b>Sent:</b><span class="Apple-converted-space"> </span>Monday, July 01, 2013 7:27 PM<br><b>To:</b><span class="Apple-converted-space"> </span>Jack Carter<br><b>Cc:</b><span class="Apple-converted-space"> </span><a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a>; <a href="mailto:rafael.espindola@gmail.com">rafael.espindola@gmail.com</a>; <a href="mailto:echristo@gmail.com">echristo@gmail.com</a>; Vladimir Medic<br><b>Subject:</b><span class="Apple-converted-space"> </span>Re: [PATCH][TableGen][MC]Allow instruction mnemonic to contain dot character<br></font><br></div><div></div><div>Hi Jack,<div><br></div><div>I’m confused. Mnemonics with an embedded “.” should already work. ARM uses them all over the place and there’s dedicated code in the ARM asm parser to split them off into operands. What problems are you encountering?</div><div><br></div><div>-Jim</div><div><br></div><div><br><div><div>On Jun 28, 2013, at 4:23 PM, Jack Carter <<a href="mailto:Jack.Carter@imgtec.com" target="_blank">Jack.Carter@imgtec.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;"><div style="direction: ltr; font-family: Tahoma; font-size: 10pt;">I know this patch looks big, but the only non-Mips specific part of this patch is very small. An new bit field in Target.td.<span class="Apple-converted-space"> </span><br><br>This patch has been reviewed several times at Mips. Please give it look over so we can move forward.<br><br>Thanks,<br><br>Jack<br><br><br><br><div class="moz-text-html" lang="x-western"><div style="direction: ltr; font-family: Tahoma; font-size: 10pt;"><font face="Tahoma" size="2"><span dir="ltr" style="font-size: 10pt;">Mips FPU instructions have a size modifier that determines the size of the operand used. This modifier is introduced as a part of mnemonic marked with a dot character. For example, add.s means 32 bit FPU register addition, add.d uses 64 bit register, while add.l means that operators are fixed point registers. RegsiterOperand class is normally uset to resolve these kind of ambiguities, but currently llvm does not support dot character in mnemonic. This means that the add.s for example is in matcher tables treated as add which is integer addition, thus creating ambiguities when dedicated parser methods are called. In this patch we propose a solution to allow mnemonics in matcher tables to contain dot character. The bit field MnemonicContainsDot is added in class Instruction definition, defaulting to 0 so there is no change for targets that don't need this feature. The AsmMatcherEmitter.cpp code is modified to check for this field and allow matcher to emit dot as a part of mnemonic if set. The rest of the patch contains changes in Mips target definition files and MipsAsmParser.cpp which utilize this feature to parse FPU register operands.<br><br>I'm looking forward to your comments and remarks.<br><br>Vladimir</span></font></div></div><br><fieldset class="mimeAttachmentHeader" target="_blank"><legend class="mimeAttachmentHeaderName" target="_blank">DotInMnemonic.patch</legend></fieldset><br><div class="moz-text-plain" lang="x-western" style="font-size: 12px;"><pre>diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td
index a9644d4..2abe9f5 100644
--- a/include/llvm/Target/Target.td
+++ b/include/llvm/Target/Target.td
@@ -444,6 +444,9 @@ class Instruction {
/// constraint. For example, "$Rn = $Rd".
string TwoOperandAliasConstraint = "";
+ /// Does the instruction mnemonic allow '.'
+ bit MnemonicContainsDot = 0;
+
///@}
}
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 4d805a7..a4f3721 100644
--- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -78,15 +78,13 @@ class MipsAsmParser : public MCTargetAsmParser {
SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands);
- bool parseMathOperation(StringRef Name, SMLoc NameLoc,
- SmallVectorImpl<MCParsedAsmOperand*> &Operands);
-
bool ParseDirective(AsmToken DirectiveID);
MipsAsmParser::OperandMatchResultTy
parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
int RegKind);
- MipsAsmParser::OperandMatchResultTy
+
+ MipsAsmParser::OperandMatchResultTy
parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
MipsAsmParser::OperandMatchResultTy
@@ -1274,6 +1272,7 @@ MipsAsmParser::parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
}
return MatchOperand_NoMatch;
}
+
MipsAsmParser::OperandMatchResultTy
MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
@@ -1335,9 +1334,9 @@ bool MipsAsmParser::searchSymbolAlias(
APInt IntVal(32, -1);
if (!DefSymbol.substr(1).getAsInteger(10, IntVal))
RegNum = matchRegisterByNumber(IntVal.getZExtValue(),
- isMips64()
- ? Mips::CPU64RegsRegClassID
- : Mips::CPURegsRegClassID);
+ isMips64()
+ ? Mips::CPU64RegsRegClassID
+ : Mips::CPURegsRegClassID);
else {
// Lookup for the register with the corresponding name.
switch (Kind) {
@@ -1368,7 +1367,7 @@ bool MipsAsmParser::searchSymbolAlias(
Parser.Lex();
const MCConstantExpr <b class="moz-txt-star"><span class="moz-txt-tag">*</span>Const = static_cast<const MCConstantExpr<span class="moz-txt-tag">*</span></b>>(Expr);
MipsOperand *op = MipsOperand::CreateImm(Const, S,
- Parser.getTok().getLoc());
+ Parser.getTok().getLoc());
Operands.push_back(op);
return true;
}
@@ -1492,130 +1491,17 @@ MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
return VK;
}
-// Converts condition string to immediate operand value.
-static int ConvertCcString(StringRef CondString) {
- int CC = StringSwitch<unsigned>(CondString)
- .Case(".f", 0)
- .Case(".un", 1)
- .Case(".eq", 2)
- .Case(".ueq", 3)
- .Case(".olt", 4)
- .Case(".ult", 5)
- .Case(".ole", 6)
- .Case(".ule", 7)
- .Case(".sf", 8)
- .Case(".ngle", 9)
- .Case(".seq", 10)
- .Case(".ngl", 11)
- .Case(".lt", 12)
- .Case(".nge", 13)
- .Case(".le", 14)
- .Case(".ngt", 15)
- .Default(-1);
-
- return CC;
-}
-
-bool MipsAsmParser::
-parseMathOperation(StringRef Name, SMLoc NameLoc,
- SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
- // Split the format.
- size_t Start = Name.find('.'), Next = Name.rfind('.');
- StringRef Format1 = Name.slice(Start, Next);
- // Add the first format to the operands.
- Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
- // Now for the second format.
- StringRef Format2 = Name.slice(Next, StringRef::npos);
- Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
-
- // Set the format for the first register.
- setFpFormat(Format1);
-
- // Read the remaining operands.
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- // Read the first operand.
- if (ParseOperand(Operands, Name)) {
- SMLoc Loc = getLexer().getLoc();
- Parser.eatToEndOfStatement();
- return Error(Loc, "unexpected token in argument list");
- }
-
- if (getLexer().isNot(AsmToken::Comma)) {
- SMLoc Loc = getLexer().getLoc();
- Parser.eatToEndOfStatement();
- return Error(Loc, "unexpected token in argument list");
- }
- Parser.Lex(); // Eat the comma.
-
- // Set the format for the first register
- setFpFormat(Format2);
-
- // Parse and remember the operand.
- if (ParseOperand(Operands, Name)) {
- SMLoc Loc = getLexer().getLoc();
- Parser.eatToEndOfStatement();
- return Error(Loc, "unexpected token in argument list");
- }
- }
-
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- SMLoc Loc = getLexer().getLoc();
- Parser.eatToEndOfStatement();
- return Error(Loc, "unexpected token in argument list");
- }
-
- Parser.Lex(); // Consume the EndOfStatement.
- return false;
-}
bool MipsAsmParser::
ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
- StringRef Mnemonic;
-
- setDefaultFpFormat();
- // Create the leading tokens for the mnemonic, split by '.' characters.
- size_t Start = 0, Next = Name.find('.');
- Mnemonic = Name.slice(Start, Next);
-
- Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
-
- if (Next != StringRef::npos) {
- // There is a format token in mnemonic.
- size_t Dot = Name.find('.', Next + 1);
- StringRef Format = Name.slice(Next, Dot);
- if (Dot == StringRef::npos) // Only one '.' in a string, it's a format.
- Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
- else {
- if (Name.startswith("c.")) {
- // Floating point compare, add '.' and immediate represent for cc.
- Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
- int Cc = ConvertCcString(Format);
- if (Cc == -1) {
- return Error(NameLoc, "Invalid conditional code");
- }
- SMLoc E = SMLoc::getFromPointer(
- Parser.getTok().getLoc().getPointer() - 1);
- Operands.push_back(
- MipsOperand::CreateImm(MCConstantExpr::Create(Cc, getContext()),
- NameLoc, E));
- } else {
- // trunc, ceil, floor ...
- return parseMathOperation(Name, NameLoc, Operands);
- }
-
- // The rest is a format.
- Format = Name.slice(Dot, StringRef::npos);
- Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
- }
-
- setFpFormat(Format);
- }
+ // First operand in MCInst is instruction mnemonic.
+ Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
// Read the remaining operands.
if (getLexer().isNot(AsmToken::EndOfStatement)) {
// Read the first operand.
- if (ParseOperand(Operands, Mnemonic)) {
+ if (ParseOperand(Operands, Name)) {
SMLoc Loc = getLexer().getLoc();
Parser.eatToEndOfStatement();
return Error(Loc, "unexpected token in argument list");
@@ -1623,7 +1509,6 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
while (getLexer().is(AsmToken::Comma)) {
Parser.Lex(); // Eat the comma.
-
// Parse and remember the operand.
if (ParseOperand(Operands, Name)) {
SMLoc Loc = getLexer().getLoc();
@@ -1632,13 +1517,11 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
}
}
}
-
if (getLexer().isNot(AsmToken::EndOfStatement)) {
SMLoc Loc = getLexer().getLoc();
Parser.eatToEndOfStatement();
return Error(Loc, "unexpected token in argument list");
}
-
Parser.Lex(); // Consume the EndOfStatement.
return false;
}
diff --git a/lib/Target/Mips/MipsCondMov.td b/lib/Target/Mips/MipsCondMov.td
index 42e4c99..cb0112a 100644
--- a/lib/Target/Mips/MipsCondMov.td
+++ b/lib/Target/Mips/MipsCondMov.td
@@ -16,7 +16,7 @@
// MipsISelLowering::EmitInstrWithCustomInserter if target does not have
// conditional move instructions.
// cond:int, data:int
-class CMov_I_I_FT<string opstr, RegisterClass CRC, RegisterClass DRC,
+class CMov_I_I_FT<string opstr, RegisterOperand CRC, RegisterOperand DRC,
InstrItinClass Itin> :
InstSE<(outs DRC:$rd), (ins DRC:$rs, CRC:$rt, DRC:$F),
!strconcat(opstr, "\t$rd, $rs, $rt"), [], Itin, FrmFR> {
@@ -24,7 +24,7 @@ class CMov_I_I_FT<string opstr, RegisterClass CRC, RegisterClass DRC,
}
// cond:int, data:float
-class CMov_I_F_FT<string opstr, RegisterClass CRC, RegisterClass DRC,
+class CMov_I_F_FT<string opstr, RegisterOperand CRC, RegisterOperand DRC,
InstrItinClass Itin> :
InstSE<(outs DRC:$fd), (ins DRC:$fs, CRC:$rt, DRC:$F),
!strconcat(opstr, "\t$fd, $fs, $rt"), [], Itin, FrmFR> {
@@ -32,7 +32,7 @@ class CMov_I_F_FT<string opstr, RegisterClass CRC, RegisterClass DRC,
}
// cond:float, data:int
-class CMov_F_I_FT<string opstr, RegisterClass RC, InstrItinClass Itin,
+class CMov_F_I_FT<string opstr, RegisterOperand RC, InstrItinClass Itin,
SDPatternOperator OpNode = null_frag> :
InstSE<(outs RC:$rd), (ins RC:$rs, RC:$F),
!strconcat(opstr, "\t$rd, $rs, $$fcc0"),
@@ -103,82 +103,84 @@ multiclass MovnPats<RegisterClass CRC, RegisterClass DRC, Instruction MOVNInst,
}
// Instantiation of instructions.
-def MOVZ_I_I : CMov_I_I_FT<"movz", CPURegs, CPURegs, NoItinerary>,
+def MOVZ_I_I : CMov_I_I_FT<"movz", CPURegsOpnd, CPURegsOpnd, NoItinerary>,
ADD_FM<0, 0xa>;
let Predicates = [HasStdEnc],
DecoderNamespace = "Mips64" in {
- def MOVZ_I_I64 : CMov_I_I_FT<"movz", CPURegs, CPU64Regs, NoItinerary>,
- ADD_FM<0, 0xa>;
- def MOVZ_I64_I : CMov_I_I_FT<"movz", CPU64Regs, CPURegs, NoItinerary>,
- ADD_FM<0, 0xa> {
+ def MOVZ_I_I64 : CMov_I_I_FT<"movz", CPURegsOpnd, CPU64RegsOpnd,
+ NoItinerary>, ADD_FM<0, 0xa>;
+ def MOVZ_I64_I : CMov_I_I_FT<"movz", CPU64RegsOpnd, CPURegsOpnd,
+ NoItinerary>, ADD_FM<0, 0xa> {
let isCodeGenOnly = 1;
}
- def MOVZ_I64_I64 : CMov_I_I_FT<"movz", CPU64Regs, CPU64Regs, NoItinerary>,
- ADD_FM<0, 0xa> {
+ def MOVZ_I64_I64 : CMov_I_I_FT<"movz", CPU64RegsOpnd, CPU64RegsOpnd,
+ NoItinerary>, ADD_FM<0, 0xa> {
let isCodeGenOnly = 1;
}
}
-def MOVN_I_I : CMov_I_I_FT<"movn", CPURegs, CPURegs, NoItinerary>,
- ADD_FM<0, 0xb>;
+def MOVN_I_I : CMov_I_I_FT<"movn", CPURegsOpnd, CPURegsOpnd,
+ NoItinerary>, ADD_FM<0, 0xb>;
let Predicates = [HasStdEnc],
DecoderNamespace = "Mips64" in {
- def MOVN_I_I64 : CMov_I_I_FT<"movn", CPURegs, CPU64Regs, NoItinerary>,
- ADD_FM<0, 0xb>;
- def MOVN_I64_I : CMov_I_I_FT<"movn", CPU64Regs, CPURegs, NoItinerary>,
- ADD_FM<0, 0xb> {
+ def MOVN_I_I64 : CMov_I_I_FT<"movn", CPURegsOpnd, CPU64RegsOpnd,
+ NoItinerary>, ADD_FM<0, 0xb>;
+ def MOVN_I64_I : CMov_I_I_FT<"movn", CPU64RegsOpnd, CPURegsOpnd,
+ NoItinerary>, ADD_FM<0, 0xb> {
let isCodeGenOnly = 1;
}
- def MOVN_I64_I64 : CMov_I_I_FT<"movn", CPU64Regs, CPU64Regs, NoItinerary>,
- ADD_FM<0, 0xb> {
+ def MOVN_I64_I64 : CMov_I_I_FT<"movn", CPU64RegsOpnd, CPU64RegsOpnd,
+ NoItinerary>, ADD_FM<0, 0xb> {
let isCodeGenOnly = 1;
}
}
-def MOVZ_I_S : CMov_I_F_FT<"movz.s", CPURegs, FGR32, IIFmove>,
+def MOVZ_I_S : CMov_I_F_FT<"movz.s", CPURegsOpnd, FGR32RegsOpnd, IIFmove>,
CMov_I_F_FM<18, 16>;
-def MOVZ_I64_S : CMov_I_F_FT<"movz.s", CPU64Regs, FGR32, IIFmove>,
+def MOVZ_I64_S : CMov_I_F_FT<"movz.s", CPU64RegsOpnd, FGR32RegsOpnd, IIFmove>,
CMov_I_F_FM<18, 16>, Requires<[HasMips64, HasStdEnc]> {
let DecoderNamespace = "Mips64";
}
-def MOVN_I_S : CMov_I_F_FT<"movn.s", CPURegs, FGR32, IIFmove>,
+def MOVN_I_S : CMov_I_F_FT<"movn.s", CPURegsOpnd, FGR32RegsOpnd, IIFmove>,
CMov_I_F_FM<19, 16>;
-def MOVN_I64_S : CMov_I_F_FT<"movn.s", CPU64Regs, FGR32, IIFmove>,
+def MOVN_I64_S : CMov_I_F_FT<"movn.s", CPU64RegsOpnd, FGR32RegsOpnd, IIFmove>,
CMov_I_F_FM<19, 16>, Requires<[HasMips64, HasStdEnc]> {
let DecoderNamespace = "Mips64";
}
let Predicates = [NotFP64bit, HasStdEnc] in {
- def MOVZ_I_D32 : CMov_I_F_FT<"movz.d", CPURegs, AFGR64, IIFmove>,
+ def MOVZ_I_D32 : CMov_I_F_FT<"movz.d", CPURegsOpnd, AFGR64RegsOpnd, IIFmove>,
CMov_I_F_FM<18, 17>;
- def MOVN_I_D32 : CMov_I_F_FT<"movn.d", CPURegs, AFGR64, IIFmove>,
+ def MOVN_I_D32 : CMov_I_F_FT<"movn.d", CPURegsOpnd, AFGR64RegsOpnd, IIFmove>,
CMov_I_F_FM<19, 17>;
}
let Predicates = [IsFP64bit, HasStdEnc],
DecoderNamespace = "Mips64" in {
- def MOVZ_I_D64 : CMov_I_F_FT<"movz.d", CPURegs, FGR64, IIFmove>,
+ def MOVZ_I_D64 : CMov_I_F_FT<"movz.d", CPURegsOpnd, FGR64RegsOpnd, IIFmove>,
CMov_I_F_FM<18, 17>;
- def MOVZ_I64_D64 : CMov_I_F_FT<"movz.d", CPU64Regs, FGR64, IIFmove>,
- CMov_I_F_FM<18, 17> {
+ def MOVZ_I64_D64 : CMov_I_F_FT<"movz.d", CPU64RegsOpnd, FGR64RegsOpnd,
+ IIFmove>, CMov_I_F_FM<18, 17> {
let isCodeGenOnly = 1;
}
- def MOVN_I_D64 : CMov_I_F_FT<"movn.d", CPURegs, FGR64, IIFmove>,
+ def MOVN_I_D64 : CMov_I_F_FT<"movn.d", CPURegsOpnd, FGR64RegsOpnd, IIFmove>,
CMov_I_F_FM<19, 17>;
- def MOVN_I64_D64 : CMov_I_F_FT<"movn.d", CPU64Regs, FGR64, IIFmove>,
- CMov_I_F_FM<19, 17> {
+ def MOVN_I64_D64 : CMov_I_F_FT<"movn.d", CPU64RegsOpnd, FGR64RegsOpnd,
+ IIFmove>, CMov_I_F_FM<19, 17> {
let isCodeGenOnly = 1;
}
}
-def MOVT_I : CMov_F_I_FT<"movt", CPURegs, IIAlu, MipsCMovFP_T>, CMov_F_I_FM<1>;
-def MOVT_I64 : CMov_F_I_FT<"movt", CPU64Regs, IIAlu, MipsCMovFP_T>,
+def MOVT_I : CMov_F_I_FT<"movt", CPURegsOpnd, IIAlu, MipsCMovFP_T>,
+ CMov_F_I_FM<1>;
+def MOVT_I64 : CMov_F_I_FT<"movt", CPU64RegsOpnd, IIAlu, MipsCMovFP_T>,
CMov_F_I_FM<1>, Requires<[HasMips64, HasStdEnc]> {
let DecoderNamespace = "Mips64";
}
-def MOVF_I : CMov_F_I_FT<"movf", CPURegs, IIAlu, MipsCMovFP_F>, CMov_F_I_FM<0>;
-def MOVF_I64 : CMov_F_I_FT<"movf", CPU64Regs, IIAlu, MipsCMovFP_F>,
+def MOVF_I : CMov_F_I_FT<"movf", CPURegsOpnd, IIAlu, MipsCMovFP_F>,
+ CMov_F_I_FM<0>;
+def MOVF_I64 : CMov_F_I_FT<"movf", CPU64RegsOpnd, IIAlu, MipsCMovFP_F>,
CMov_F_I_FM<0>, Requires<[HasMips64, HasStdEnc]> {
let DecoderNamespace = "Mips64";
}
diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td
index 6b2b859..5c39ca6 100644
--- a/lib/Target/Mips/MipsInstrFPU.td
+++ b/lib/Target/Mips/MipsInstrFPU.td
@@ -88,7 +88,7 @@ def fpimm0neg : PatLeaf<(fpimm), [{
// Only S32 and D32 are supported right now.
//===----------------------------------------------------------------------===//
-class ADDS_FT<string opstr, RegisterClass RC, InstrItinClass Itin, bit IsComm,
+class ADDS_FT<string opstr, RegisterOperand RC, InstrItinClass Itin, bit IsComm,
SDPatternOperator OpNode= null_frag> :
InstSE<(outs RC:$fd), (ins RC:$fs, RC:$ft),
!strconcat(opstr, "\t$fd, $fs, $ft"),
@@ -98,15 +98,15 @@ class ADDS_FT<string opstr, RegisterClass RC, InstrItinClass Itin, bit IsComm,
multiclass ADDS_M<string opstr, InstrItinClass Itin, bit IsComm,
SDPatternOperator OpNode = null_frag> {
- def _D32 : ADDS_FT<opstr, AFGR64, Itin, IsComm, OpNode>,
+ def _D32 : ADDS_FT<opstr, AFGR64RegsOpnd, Itin, IsComm, OpNode>,
Requires<[NotFP64bit, HasStdEnc]>;
- def _D64 : ADDS_FT<opstr, FGR64, Itin, IsComm, OpNode>,
+ def _D64 : ADDS_FT<opstr, FGR64RegsOpnd, Itin, IsComm, OpNode>,
Requires<[IsFP64bit, HasStdEnc]> {
string DecoderNamespace = "Mips64";
}
}
-class ABSS_FT<string opstr, RegisterClass DstRC, RegisterClass SrcRC,
+class ABSS_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC,
InstrItinClass Itin, SDPatternOperator OpNode= null_frag> :
InstSE<(outs DstRC:$fd), (ins SrcRC:$fs), !strconcat(opstr, "\t$fd, $fs"),
[(set DstRC:$fd, (OpNode SrcRC:$fs))], Itin, FrmFR>,
@@ -114,39 +114,39 @@ class ABSS_FT<string opstr, RegisterClass DstRC, RegisterClass SrcRC,
multiclass ABSS_M<string opstr, InstrItinClass Itin,
SDPatternOperator OpNode= null_frag> {
- def _D32 : ABSS_FT<opstr, AFGR64, AFGR64, Itin, OpNode>,
+ def _D32 : ABSS_FT<opstr, AFGR64RegsOpnd, AFGR64RegsOpnd, Itin, OpNode>,
Requires<[NotFP64bit, HasStdEnc]>;
- def _D64 : ABSS_FT<opstr, FGR64, FGR64, Itin, OpNode>,
+ def _D64 : ABSS_FT<opstr, FGR64RegsOpnd, FGR64RegsOpnd, Itin, OpNode>,
Requires<[IsFP64bit, HasStdEnc]> {
string DecoderNamespace = "Mips64";
}
}
multiclass ROUND_M<string opstr, InstrItinClass Itin> {
- def _D32 : ABSS_FT<opstr, FGR32, AFGR64, Itin>,
+ def _D32 : ABSS_FT<opstr, FGR32RegsOpnd, AFGR64RegsOpnd, Itin>,
Requires<[NotFP64bit, HasStdEnc]>;
- def _D64 : ABSS_FT<opstr, FGR32, FGR64, Itin>,
+ def _D64 : ABSS_FT<opstr, FGR32RegsOpnd, FGR64RegsOpnd, Itin>,
Requires<[IsFP64bit, HasStdEnc]> {
let DecoderNamespace = "Mips64";
}
}
-class MFC1_FT<string opstr, RegisterClass DstRC, RegisterClass SrcRC,
+class MFC1_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC,
InstrItinClass Itin, SDPatternOperator OpNode= null_frag> :
InstSE<(outs DstRC:$rt), (ins SrcRC:$fs), !strconcat(opstr, "\t$rt, $fs"),
[(set DstRC:$rt, (OpNode SrcRC:$fs))], Itin, FrmFR>;
-class MTC1_FT<string opstr, RegisterClass DstRC, RegisterClass SrcRC,
+class MTC1_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC,
InstrItinClass Itin, SDPatternOperator OpNode= null_frag> :
InstSE<(outs DstRC:$fs), (ins SrcRC:$rt), !strconcat(opstr, "\t$rt, $fs"),
[(set DstRC:$fs, (OpNode SrcRC:$rt))], Itin, FrmFR>;
-class MFC1_FT_CCR<string opstr, RegisterClass DstRC, RegisterOperand SrcRC,
+class MFC1_FT_CCR<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC,
InstrItinClass Itin, SDPatternOperator OpNode= null_frag> :
InstSE<(outs DstRC:$rt), (ins SrcRC:$fs), !strconcat(opstr, "\t$rt, $fs"),
[(set DstRC:$rt, (OpNode SrcRC:$fs))], Itin, FrmFR>;
-class MTC1_FT_CCR<string opstr, RegisterOperand DstRC, RegisterClass SrcRC,
+class MTC1_FT_CCR<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC,
InstrItinClass Itin, SDPatternOperator OpNode= null_frag> :
InstSE<(outs DstRC:$fs), (ins SrcRC:$rt), !strconcat(opstr, "\t$rt, $fs"),
[(set DstRC:$fs, (OpNode SrcRC:$rt))], Itin, FrmFR>;
@@ -167,13 +167,13 @@ class SW_FT<string opstr, RegisterOperand RC, InstrItinClass Itin,
let mayStore = 1;
}
-class MADDS_FT<string opstr, RegisterClass RC, InstrItinClass Itin,
+class MADDS_FT<string opstr, RegisterOperand RC, InstrItinClass Itin,
SDPatternOperator OpNode = null_frag> :
InstSE<(outs RC:$fd), (ins RC:$fr, RC:$fs, RC:$ft),
!strconcat(opstr, "\t$fd, $fr, $fs, $ft"),
[(set RC:$fd, (OpNode (fmul RC:$fs, RC:$ft), RC:$fr))], Itin, FrmFR>;
-class NMADDS_FT<string opstr, RegisterClass RC, InstrItinClass Itin,
+class NMADDS_FT<string opstr, RegisterOperand RC, InstrItinClass Itin,
SDPatternOperator OpNode = null_frag> :
InstSE<(outs RC:$fd), (ins RC:$fr, RC:$fs, RC:$ft),
!strconcat(opstr, "\t$fd, $fr, $fs, $ft"),
@@ -213,16 +213,52 @@ class CEQS_FT<string typestr, RegisterClass RC, InstrItinClass Itin,
!strconcat("c.$cond.", typestr, "\t$fs, $ft"),
[(OpNode RC:$fs, RC:$ft, imm:$cond)], Itin, FrmFR> {
let Defs = [FCR31];
-}
+ let isCodeGenOnly = 1;
+}
+
+class C_COND_FT<string CondStr, string Typestr, RegisterOperand RC> :
+ InstSE<(outs), (ins RC:$fs, RC:$ft),
+ !strconcat("c.", CondStr, ".", Typestr, "\t$fs, $ft"), [], IIFcmp,
+ FrmFR>;
+
+multiclass C_COND_M<string TypeStr, RegisterOperand RC, bits<5> fmt> {
+ def C_F_#NAME : C_COND_FT<"f", TypeStr, RC>, C_COND_FM<fmt, 0>;
+ def C_UN_#NAME : C_COND_FT<"un", TypeStr, RC>, C_COND_FM<fmt, 1>;
+ def C_EQ_#NAME : C_COND_FT<"eq", TypeStr, RC>, C_COND_FM<fmt, 2>;
+ def C_UEQ_#NAME : C_COND_FT<"ueq", TypeStr, RC>, C_COND_FM<fmt, 3>;
+ def C_OLT_#NAME : C_COND_FT<"olt", TypeStr, RC>, C_COND_FM<fmt, 4>;
+ def C_ULT_#NAME : C_COND_FT<"ult", TypeStr, RC>, C_COND_FM<fmt, 5>;
+ def C_OLE_#NAME : C_COND_FT<"ole", TypeStr, RC>, C_COND_FM<fmt, 6>;
+ def C_ULE_#NAME : C_COND_FT<"ule", TypeStr, RC>, C_COND_FM<fmt, 7>;
+ def C_SF_#NAME : C_COND_FT<"sf", TypeStr, RC>, C_COND_FM<fmt, 8>;
+ def C_NGLE_#NAME : C_COND_FT<"ngle", TypeStr, RC>, C_COND_FM<fmt, 9>;
+ def C_SEQ_#NAME : C_COND_FT<"seq", TypeStr, RC>, C_COND_FM<fmt, 10>;
+ def C_NGL_#NAME : C_COND_FT<"ngl", TypeStr, RC>, C_COND_FM<fmt, 11>;
+ def C_LT_#NAME : C_COND_FT<"lt", TypeStr, RC>, C_COND_FM<fmt, 12>;
+ def C_NGE_#NAME : C_COND_FT<"nge", TypeStr, RC>, C_COND_FM<fmt, 13>;
+ def C_LE_#NAME : C_COND_FT<"le", TypeStr, RC>, C_COND_FM<fmt, 14>;
+ def C_NGT_#NAME : C_COND_FT<"ngt", TypeStr, RC>, C_COND_FM<fmt, 15>;
+}
+
+defm S : C_COND_M<"s", FGR32RegsOpnd, 16>;
+defm D32 : C_COND_M<"d", AFGR64RegsOpnd, 17>,
+ Requires<[NotFP64bit, HasStdEnc]>;
+let DecoderNamespace = "Mips64" in
+defm D64 : C_COND_M<"d", FGR64RegsOpnd, 17>, Requires<[IsFP64bit, HasStdEnc]>;
//===----------------------------------------------------------------------===//
// Floating Point Instructions
//===----------------------------------------------------------------------===//
-def ROUND_W_S : ABSS_FT<"round.w.s", FGR32, FGR32, IIFcvt>, ABSS_FM<0xc, 16>;
-def TRUNC_W_S : ABSS_FT<"trunc.w.s", FGR32, FGR32, IIFcvt>, ABSS_FM<0xd, 16>;
-def CEIL_W_S : ABSS_FT<"ceil.w.s", FGR32, FGR32, IIFcvt>, ABSS_FM<0xe, 16>;
-def FLOOR_W_S : ABSS_FT<"floor.w.s", FGR32, FGR32, IIFcvt>, ABSS_FM<0xf, 16>;
-def CVT_W_S : ABSS_FT<"cvt.w.s", FGR32, FGR32, IIFcvt>, ABSS_FM<0x24, 16>;
+def ROUND_W_S : ABSS_FT<"round.w.s", FGR32RegsOpnd, FGR32RegsOpnd, IIFcvt>,
+ ABSS_FM<0xc, 16>;
+def TRUNC_W_S : ABSS_FT<"trunc.w.s", FGR32RegsOpnd, FGR32RegsOpnd, IIFcvt>,
+ ABSS_FM<0xd, 16>;
+def CEIL_W_S : ABSS_FT<"ceil.w.s", FGR32RegsOpnd, FGR32RegsOpnd, IIFcvt>,
+ ABSS_FM<0xe, 16>;
+def FLOOR_W_S : ABSS_FT<"floor.w.s", FGR32RegsOpnd, FGR32RegsOpnd, IIFcvt>,
+ ABSS_FM<0xf, 16>;
+def CVT_W_S : ABSS_FT<"cvt.w.s", FGR32RegsOpnd, FGR32RegsOpnd, IIFcvt>,
+ ABSS_FM<0x24, 16>;
defm ROUND_W : ROUND_M<"round.w.d", IIFcvt>, ABSS_FM<0xc, 17>;
defm TRUNC_W : ROUND_M<"trunc.w.d", IIFcvt>, ABSS_FM<0xd, 17>;
@@ -231,54 +267,72 @@ defm FLOOR_W : ROUND_M<"floor.w.d", IIFcvt>, ABSS_FM<0xf, 17>;
defm CVT_W : ROUND_M<"cvt.w.d", IIFcvt>, ABSS_FM<0x24, 17>;
let Predicates = [IsFP64bit, HasStdEnc], DecoderNamespace = "Mips64" in {
- def ROUND_L_S : ABSS_FT<"round.l.s", FGR64, FGR32, IIFcvt>, ABSS_FM<0x8, 16>;
- def ROUND_L_D64 : ABSS_FT<"round.l.d", FGR64, FGR64, IIFcvt>,
+ def ROUND_L_S : ABSS_FT<"round.l.s", FGR64RegsOpnd, FGR32RegsOpnd, IIFcvt>,
+ ABSS_FM<0x8, 16>;
+ def ROUND_L_D64 : ABSS_FT<"round.l.d", FGR64RegsOpnd, FGR64RegsOpnd, IIFcvt>,
ABSS_FM<0x8, 17>;
- def TRUNC_L_S : ABSS_FT<"trunc.l.s", FGR64, FGR32, IIFcvt>, ABSS_FM<0x9, 16>;
- def TRUNC_L_D64 : ABSS_FT<"trunc.l.d", FGR64, FGR64, IIFcvt>,
+ def TRUNC_L_S : ABSS_FT<"trunc.l.s", FGR64RegsOpnd, FGR32RegsOpnd, IIFcvt>,
+ ABSS_FM<0x9, 16>;
+ def TRUNC_L_D64 : ABSS_FT<"trunc.l.d", FGR64RegsOpnd, FGR64RegsOpnd, IIFcvt>,
ABSS_FM<0x9, 17>;
- def CEIL_L_S : ABSS_FT<"ceil.l.s", FGR64, FGR32, IIFcvt>, ABSS_FM<0xa, 16>;
- def CEIL_L_D64 : ABSS_FT<"ceil.l.d", FGR64, FGR64, IIFcvt>, ABSS_FM<0xa, 17>;
- def FLOOR_L_S : ABSS_FT<"floor.l.s", FGR64, FGR32, IIFcvt>, ABSS_FM<0xb, 16>;
- def FLOOR_L_D64 : ABSS_FT<"floor.l.d", FGR64, FGR64, IIFcvt>,
+ def CEIL_L_S : ABSS_FT<"ceil.l.s", FGR64RegsOpnd, FGR32RegsOpnd, IIFcvt>,
+ ABSS_FM<0xa, 16>;
+ def CEIL_L_D64 : ABSS_FT<"ceil.l.d", FGR64RegsOpnd, FGR64RegsOpnd, IIFcvt>,
+ ABSS_FM<0xa, 17>;
+ def FLOOR_L_S : ABSS_FT<"floor.l.s", FGR64RegsOpnd, FGR32RegsOpnd, IIFcvt>,
+ ABSS_FM<0xb, 16>;
+ def FLOOR_L_D64 : ABSS_FT<"floor.l.d", FGR64RegsOpnd, FGR64RegsOpnd, IIFcvt>,
ABSS_FM<0xb, 17>;
}
-def CVT_S_W : ABSS_FT<"cvt.s.w", FGR32, FGR32, IIFcvt>, ABSS_FM<0x20, 20>;
-def CVT_L_S : ABSS_FT<"cvt.l.s", FGR64, FGR32, IIFcvt>, ABSS_FM<0x25, 16>;
-def CVT_L_D64: ABSS_FT<"cvt.l.d", FGR64, FGR64, IIFcvt>, ABSS_FM<0x25, 17>;
+def CVT_S_W : ABSS_FT<"cvt.s.w", FGR32RegsOpnd, FGR32RegsOpnd, IIFcvt>,
+ ABSS_FM<0x20, 20>;
+def CVT_L_S : ABSS_FT<"cvt.l.s", FGR64RegsOpnd, FGR32RegsOpnd, IIFcvt>,
+ ABSS_FM<0x25, 16>;
+def CVT_L_D64: ABSS_FT<"cvt.l.d", FGR64RegsOpnd, FGR64RegsOpnd, IIFcvt>,
+ ABSS_FM<0x25, 17>;
let Predicates = [NotFP64bit, HasStdEnc] in {
- def CVT_S_D32 : ABSS_FT<"cvt.s.d", FGR32, AFGR64, IIFcvt>, ABSS_FM<0x20, 17>;
- def CVT_D32_W : ABSS_FT<"cvt.d.w", AFGR64, FGR32, IIFcvt>, ABSS_FM<0x21, 20>;
- def CVT_D32_S : ABSS_FT<"cvt.d.s", AFGR64, FGR32, IIFcvt>, ABSS_FM<0x21, 16>;
+ def CVT_S_D32 : ABSS_FT<"cvt.s.d", FGR32RegsOpnd, AFGR64RegsOpnd, IIFcvt>,
+ ABSS_FM<0x20, 17>;
+ def CVT_D32_W : ABSS_FT<"cvt.d.w", AFGR64RegsOpnd, FGR32RegsOpnd, IIFcvt>,
+ ABSS_FM<0x21, 20>;
+ def CVT_D32_S : ABSS_FT<"cvt.d.s", AFGR64RegsOpnd, FGR32RegsOpnd, IIFcvt>,
+ ABSS_FM<0x21, 16>;
}
let Predicates = [IsFP64bit, HasStdEnc], DecoderNamespace = "Mips64" in {
- def CVT_S_D64 : ABSS_FT<"cvt.s.d", FGR32, FGR64, IIFcvt>, ABSS_FM<0x20, 17>;
- def CVT_S_L : ABSS_FT<"cvt.s.l", FGR32, FGR64, IIFcvt>, ABSS_FM<0x20, 21>;
- def CVT_D64_W : ABSS_FT<"cvt.d.w", FGR64, FGR32, IIFcvt>, ABSS_FM<0x21, 20>;
- def CVT_D64_S : ABSS_FT<"cvt.d.s", FGR64, FGR32, IIFcvt>, ABSS_FM<0x21, 16>;
- def CVT_D64_L : ABSS_FT<"cvt.d.l", FGR64, FGR64, IIFcvt>, ABSS_FM<0x21, 21>;
+ def CVT_S_D64 : ABSS_FT<"cvt.s.d", FGR32RegsOpnd, FGR64RegsOpnd, IIFcvt>,
+ ABSS_FM<0x20, 17>;
+ def CVT_S_L : ABSS_FT<"cvt.s.l", FGR32RegsOpnd, FGR64RegsOpnd, IIFcvt>,
+ ABSS_FM<0x20, 21>;
+ def CVT_D64_W : ABSS_FT<"cvt.d.w", FGR64RegsOpnd, FGR32RegsOpnd, IIFcvt>,
+ ABSS_FM<0x21, 20>;
+ def CVT_D64_S : ABSS_FT<"cvt.d.s", FGR64RegsOpnd, FGR32RegsOpnd, IIFcvt>,
+ ABSS_FM<0x21, 16>;
+ def CVT_D64_L : ABSS_FT<"cvt.d.l", FGR64RegsOpnd, FGR64RegsOpnd, IIFcvt>,
+ ABSS_FM<0x21, 21>;
}
let isPseudo = 1, isCodeGenOnly = 1 in {
- def PseudoCVT_S_W : ABSS_FT<"", FGR32, CPURegs, IIFcvt>;
- def PseudoCVT_D32_W : ABSS_FT<"", AFGR64, CPURegs, IIFcvt>;
- def PseudoCVT_S_L : ABSS_FT<"", FGR64, CPU64Regs, IIFcvt>;
- def PseudoCVT_D64_W : ABSS_FT<"", FGR64, CPURegs, IIFcvt>;
- def PseudoCVT_D64_L : ABSS_FT<"", FGR64, CPU64Regs, IIFcvt>;
+ def PseudoCVT_S_W : ABSS_FT<"", FGR32RegsOpnd, CPURegsOpnd, IIFcvt>;
+ def PseudoCVT_D32_W : ABSS_FT<"", AFGR64RegsOpnd, CPURegsOpnd, IIFcvt>;
+ def PseudoCVT_S_L : ABSS_FT<"", FGR64RegsOpnd, CPU64RegsOpnd, IIFcvt>;
+ def PseudoCVT_D64_W : ABSS_FT<"", FGR64RegsOpnd, CPURegsOpnd, IIFcvt>;
+ def PseudoCVT_D64_L : ABSS_FT<"", FGR64RegsOpnd, CPU64RegsOpnd, IIFcvt>;
}
let Predicates = [NoNaNsFPMath, HasStdEnc] in {
- def FABS_S : ABSS_FT<"abs.s", FGR32, FGR32, IIFcvt, fabs>, ABSS_FM<0x5, 16>;
- def FNEG_S : ABSS_FT<"neg.s", FGR32, FGR32, IIFcvt, fneg>, ABSS_FM<0x7, 16>;
+ def FABS_S : ABSS_FT<"abs.s", FGR32RegsOpnd, FGR32RegsOpnd, IIFcvt, fabs>,
+ ABSS_FM<0x5, 16>;
+ def FNEG_S : ABSS_FT<"neg.s", FGR32RegsOpnd, FGR32RegsOpnd, IIFcvt, fneg>,
+ ABSS_FM<0x7, 16>;
defm FABS : ABSS_M<"abs.d", IIFcvt, fabs>, ABSS_FM<0x5, 17>;
defm FNEG : ABSS_M<"neg.d", IIFcvt, fneg>, ABSS_FM<0x7, 17>;
}
-def FSQRT_S : ABSS_FT<"sqrt.s", FGR32, FGR32, IIFsqrtSingle, fsqrt>,
- ABSS_FM<0x4, 16>;
+def FSQRT_S : ABSS_FT<"sqrt.s", FGR32RegsOpnd, FGR32RegsOpnd, IIFsqrtSingle,
+ fsqrt>, ABSS_FM<0x4, 16>;
defm FSQRT : ABSS_M<"sqrt.d", IIFsqrtDouble, fsqrt>, ABSS_FM<0x4, 17>;
// The odd-numbered registers are only referenced when doing loads,
@@ -287,33 +341,39 @@ defm FSQRT : ABSS_M<"sqrt.d", IIFsqrtDouble, fsqrt>, ABSS_FM<0x4, 17>;
// regardless of register aliasing.
/// Move Control Registers From/To CPU Registers
-def CFC1 : MFC1_FT_CCR<"cfc1", CPURegs, CCROpnd, IIFmove>, MFC1_FM<2>;
-def CTC1 : MTC1_FT_CCR<"ctc1", CCROpnd, CPURegs, IIFmove>, MFC1_FM<6>;
-def MFC1 : MFC1_FT<"mfc1", CPURegs, FGR32, IIFmove, bitconvert>, MFC1_FM<0>;
-def MTC1 : MTC1_FT<"mtc1", FGR32, CPURegs, IIFmove, bitconvert>, MFC1_FM<4>;
-def DMFC1 : MFC1_FT<"dmfc1", CPU64Regs, FGR64, IIFmove, bitconvert>, MFC1_FM<1>;
-def DMTC1 : MTC1_FT<"dmtc1", FGR64, CPU64Regs, IIFmove, bitconvert>, MFC1_FM<5>;
-
-def FMOV_S : ABSS_FT<"mov.s", FGR32, FGR32, IIFmove>, ABSS_FM<0x6, 16>;
-def FMOV_D32 : ABSS_FT<"mov.d", AFGR64, AFGR64, IIFmove>, ABSS_FM<0x6, 17>,
- Requires<[NotFP64bit, HasStdEnc]>;
-def FMOV_D64 : ABSS_FT<"mov.d", FGR64, FGR64, IIFmove>, ABSS_FM<0x6, 17>,
- Requires<[IsFP64bit, HasStdEnc]> {
- let DecoderNamespace = "Mips64";
+def CFC1 : MFC1_FT_CCR<"cfc1", CPURegsOpnd, CCROpnd, IIFmove>, MFC1_FM<2>;
+def CTC1 : MTC1_FT_CCR<"ctc1", CCROpnd, CPURegsOpnd, IIFmove>, MFC1_FM<6>;
+def MFC1 : MFC1_FT<"mfc1", CPURegsOpnd, FGR32RegsOpnd, IIFmove, bitconvert>,
+ MFC1_FM<0>;
+def MTC1 : MTC1_FT<"mtc1", FGR32RegsOpnd, CPURegsOpnd, IIFmove, bitconvert>,
+ MFC1_FM<4>;
+def DMFC1 : MFC1_FT<"dmfc1", CPU64RegsOpnd, FGR64RegsOpnd, IIFmove, bitconvert>,
+ MFC1_FM<1>;
+def DMTC1 : MTC1_FT<"dmtc1", FGR64RegsOpnd, CPU64RegsOpnd, IIFmove, bitconvert>,
+ MFC1_FM<5>;
+
+def FMOV_S : ABSS_FT<"mov.s", FGR32RegsOpnd, FGR32RegsOpnd, IIFmove>,
+ ABSS_FM<0x6, 16>;
+def FMOV_D32 : ABSS_FT<"mov.d", AFGR64RegsOpnd, AFGR64RegsOpnd, IIFmove>,
+ ABSS_FM<0x6, 17>, Requires<[NotFP64bit, HasStdEnc]>;
+def FMOV_D64 : ABSS_FT<"mov.d", FGR64RegsOpnd, FGR64RegsOpnd, IIFmove>,
+ ABSS_FM<0x6, 17>, Requires<[IsFP64bit, HasStdEnc]> {
+ let DecoderNamespace = "Mips64";
}
/// Floating Point Memory Instructions
let Predicates = [IsN64, HasStdEnc], DecoderNamespace = "Mips64" in {
- def LWC1_P8 : LW_FT<"lwc1", FGR32RegsOpnd, IILoad, mem64, load>, LW_FM<0x31>;
+ def LWC1_P8 : LW_FT<"lwc1", FGR32RegsOpnd, IILoad, mem64, load>,
+ LW_FM<0x31>;
def SWC1_P8 : SW_FT<"swc1", FGR32RegsOpnd, IIStore, mem64, store>,
LW_FM<0x39>;
def LDC164_P8 : LW_FT<"ldc1", FGR64RegsOpnd, IILoad, mem64, load>,
LW_FM<0x35> {
- let isCodeGenOnly =1;
+ let isCodeGenOnly =1;
}
def SDC164_P8 : SW_FT<"sdc1", FGR64RegsOpnd, IIStore, mem64, store>,
LW_FM<0x3d> {
- let isCodeGenOnly =1;
+ let isCodeGenOnly =1;
}
}
@@ -364,11 +424,11 @@ let Predicates = [IsN64, HasStdEnc], isCodeGenOnly=1 in {
def LWXC1_P8 : LWXC1_FT<"lwxc1", FGR32RegsOpnd, CPU64RegsOpnd, IILoad, load>,
LWXC1_FM<0>;
def LDXC164_P8 : LWXC1_FT<"ldxc1", FGR64RegsOpnd, CPU64RegsOpnd, IILoad,
- load>, LWXC1_FM<1>;
+ load>, LWXC1_FM<1>;
def SWXC1_P8 : SWXC1_FT<"swxc1", FGR32RegsOpnd, CPU64RegsOpnd, IIStore,
- store>, SWXC1_FM<8>;
+ store>, SWXC1_FM<8>;
def SDXC164_P8 : SWXC1_FT<"sdxc1", FGR64RegsOpnd, CPU64RegsOpnd, IIStore,
- store>, SWXC1_FM<9>;
+ store>, SWXC1_FM<9>;
}
// Load/store doubleword indexed unaligned.
@@ -388,47 +448,59 @@ let Predicates = [HasMips64, HasStdEnc],
}
/// Floating-point Aritmetic
-def FADD_S : ADDS_FT<"add.s", FGR32, IIFadd, 1, fadd>, ADDS_FM<0x00, 16>;
-defm FADD : ADDS_M<"add.d", IIFadd, 1, fadd>, ADDS_FM<0x00, 17>;
-def FDIV_S : ADDS_FT<"div.s", FGR32, IIFdivSingle, 0, fdiv>, ADDS_FM<0x03, 16>;
-defm FDIV : ADDS_M<"div.d", IIFdivDouble, 0, fdiv>, ADDS_FM<0x03, 17>;
-def FMUL_S : ADDS_FT<"mul.s", FGR32, IIFmulSingle, 1, fmul>, ADDS_FM<0x02, 16>;
-defm FMUL : ADDS_M<"mul.d", IIFmulDouble, 1, fmul>, ADDS_FM<0x02, 17>;
-def FSUB_S : ADDS_FT<"sub.s", FGR32, IIFadd, 0, fsub>, ADDS_FM<0x01, 16>;
-defm FSUB : ADDS_M<"sub.d", IIFadd, 0, fsub>, ADDS_FM<0x01, 17>;
+def FADD_S : ADDS_FT<"add.s", FGR32RegsOpnd, IIFadd, 1, fadd>,
+ ADDS_FM<0x00, 16>;
+defm FADD : ADDS_M<"add.d", IIFadd, 1, fadd>, ADDS_FM<0x00, 17>;
+def FDIV_S : ADDS_FT<"div.s", FGR32RegsOpnd, IIFdivSingle, 0, fdiv>,
+ ADDS_FM<0x03, 16>;
+defm FDIV : ADDS_M<"div.d", IIFdivDouble, 0, fdiv>, ADDS_FM<0x03, 17>;
+def FMUL_S : ADDS_FT<"mul.s", FGR32RegsOpnd, IIFmulSingle, 1, fmul>,
+ ADDS_FM<0x02, 16>;
+defm FMUL : ADDS_M<"mul.d", IIFmulDouble, 1, fmul>, ADDS_FM<0x02, 17>;
+def FSUB_S : ADDS_FT<"sub.s", FGR32RegsOpnd, IIFadd, 0, fsub>,
+ ADDS_FM<0x01, 16>;
+defm FSUB : ADDS_M<"sub.d", IIFadd, 0, fsub>, ADDS_FM<0x01, 17>;
let Predicates = [HasMips32r2, HasStdEnc] in {
- def MADD_S : MADDS_FT<"madd.s", FGR32, IIFmulSingle, fadd>, MADDS_FM<4, 0>;
- def MSUB_S : MADDS_FT<"msub.s", FGR32, IIFmulSingle, fsub>, MADDS_FM<5, 0>;
+ def MADD_S : MADDS_FT<"madd.s", FGR32RegsOpnd, IIFmulSingle, fadd>,
+ MADDS_FM<4, 0>;
+ def MSUB_S : MADDS_FT<"msub.s", FGR32RegsOpnd, IIFmulSingle, fsub>,
+ MADDS_FM<5, 0>;
}
let Predicates = [HasMips32r2, NoNaNsFPMath, HasStdEnc] in {
- def NMADD_S : NMADDS_FT<"nmadd.s", FGR32, IIFmulSingle, fadd>, MADDS_FM<6, 0>;
- def NMSUB_S : NMADDS_FT<"nmsub.s", FGR32, IIFmulSingle, fsub>, MADDS_FM<7, 0>;
+ def NMADD_S : NMADDS_FT<"nmadd.s", FGR32RegsOpnd, IIFmulSingle, fadd>,
+ MADDS_FM<6, 0>;
+ def NMSUB_S : NMADDS_FT<"nmsub.s", FGR32RegsOpnd, IIFmulSingle, fsub>,
+ MADDS_FM<7, 0>;
}
let Predicates = [HasMips32r2, NotFP64bit, HasStdEnc] in {
- def MADD_D32 : MADDS_FT<"madd.d", AFGR64, IIFmulDouble, fadd>, MADDS_FM<4, 1>;
- def MSUB_D32 : MADDS_FT<"msub.d", AFGR64, IIFmulDouble, fsub>, MADDS_FM<5, 1>;
+ def MADD_D32 : MADDS_FT<"madd.d", AFGR64RegsOpnd, IIFmulDouble, fadd>,
+ MADDS_FM<4, 1>;
+ def MSUB_D32 : MADDS_FT<"msub.d", AFGR64RegsOpnd, IIFmulDouble, fsub>,
+ MADDS_FM<5, 1>;
}
let Predicates = [HasMips32r2, NotFP64bit, NoNaNsFPMath, HasStdEnc] in {
- def NMADD_D32 : NMADDS_FT<"nmadd.d", AFGR64, IIFmulDouble, fadd>,
+ def NMADD_D32 : NMADDS_FT<"nmadd.d", AFGR64RegsOpnd, IIFmulDouble, fadd>,
MADDS_FM<6, 1>;
- def NMSUB_D32 : NMADDS_FT<"nmsub.d", AFGR64, IIFmulDouble, fsub>,
+ def NMSUB_D32 : NMADDS_FT<"nmsub.d", AFGR64RegsOpnd, IIFmulDouble, fsub>,
MADDS_FM<7, 1>;
}
let Predicates = [HasMips32r2, IsFP64bit, HasStdEnc], isCodeGenOnly=1 in {
- def MADD_D64 : MADDS_FT<"madd.d", FGR64, IIFmulDouble, fadd>, MADDS_FM<4, 1>;
- def MSUB_D64 : MADDS_FT<"msub.d", FGR64, IIFmulDouble, fsub>, MADDS_FM<5, 1>;
+ def MADD_D64 : MADDS_FT<"madd.d", FGR64RegsOpnd, IIFmulDouble, fadd>,
+ MADDS_FM<4, 1>;
+ def MSUB_D64 : MADDS_FT<"msub.d", FGR64RegsOpnd, IIFmulDouble, fsub>,
+ MADDS_FM<5, 1>;
}
let Predicates = [HasMips32r2, IsFP64bit, NoNaNsFPMath, HasStdEnc],
isCodeGenOnly=1 in {
- def NMADD_D64 : NMADDS_FT<"nmadd.d", FGR64, IIFmulDouble, fadd>,
+ def NMADD_D64 : NMADDS_FT<"nmadd.d", FGR64RegsOpnd, IIFmulDouble, fadd>,
MADDS_FM<6, 1>;
- def NMSUB_D64 : NMADDS_FT<"nmsub.d", FGR64, IIFmulDouble, fsub>,
+ def NMSUB_D64 : NMADDS_FT<"nmsub.d", FGR64RegsOpnd, IIFmulDouble, fsub>,
MADDS_FM<7, 1>;
}
@@ -482,17 +554,19 @@ def MOVCCRToCCR : PseudoSE<(outs CCR:$dst), (ins CCROpnd:$src), []>;
// This pseudo instr gets expanded into 2 mtc1 instrs after register
// allocation.
def BuildPairF64 :
- PseudoSE<(outs AFGR64:$dst),
- (ins CPURegs:$lo, CPURegs:$hi),
- [(set AFGR64:$dst, (MipsBuildPairF64 CPURegs:$lo, CPURegs:$hi))]>;
+ PseudoSE<(outs AFGR64RegsOpnd:$dst),
+ (ins CPURegsOpnd:$lo, CPURegsOpnd:$hi),
+ [(set AFGR64RegsOpnd:$dst,
+ (MipsBuildPairF64 CPURegsOpnd:$lo, CPURegsOpnd:$hi))]>;
// This pseudo instr gets expanded into 2 mfc1 instrs after register
// allocation.
// if n is 0, lower part of src is extracted.
// if n is 1, higher part of src is extracted.
def ExtractElementF64 :
- PseudoSE<(outs CPURegs:$dst), (ins AFGR64:$src, i32imm:$n),
- [(set CPURegs:$dst, (MipsExtractElementF64 AFGR64:$src, imm:$n))]>;
+ PseudoSE<(outs CPURegsOpnd:$dst), (ins AFGR64RegsOpnd:$src, i32imm:$n),
+ [(set CPURegsOpnd:$dst,
+ (MipsExtractElementF64 AFGR64RegsOpnd:$src, imm:$n))]>;
//===----------------------------------------------------------------------===//
// Floating Point Patterns
@@ -500,34 +574,44 @@ def ExtractElementF64 :
def : MipsPat<(f32 fpimm0), (MTC1 ZERO)>;
def : MipsPat<(f32 fpimm0neg), (FNEG_S (MTC1 ZERO))>;
-def : MipsPat<(f32 (sint_to_fp CPURegs:$src)), (PseudoCVT_S_W CPURegs:$src)>;
-def : MipsPat<(MipsTruncIntFP FGR32:$src), (TRUNC_W_S FGR32:$src)>;
+def : MipsPat<(f32 (sint_to_fp CPURegsOpnd:$src)),
+ (PseudoCVT_S_W CPURegsOpnd:$src)>;
+def : MipsPat<(MipsTruncIntFP FGR32RegsOpnd:$src),
+ (TRUNC_W_S FGR32RegsOpnd:$src)>;
let Predicates = [NotFP64bit, HasStdEnc] in {
- def : MipsPat<(f64 (sint_to_fp CPURegs:$src)),
- (PseudoCVT_D32_W CPURegs:$src)>;
- def : MipsPat<(MipsTruncIntFP AFGR64:$src), (TRUNC_W_D32 AFGR64:$src)>;
- def : MipsPat<(f32 (fround AFGR64:$src)), (CVT_S_D32 AFGR64:$src)>;
- def : MipsPat<(f64 (fextend FGR32:$src)), (CVT_D32_S FGR32:$src)>;
+ def : MipsPat<(f64 (sint_to_fp CPURegsOpnd:$src)),
+ (PseudoCVT_D32_W CPURegsOpnd:$src)>;
+ def : MipsPat<(MipsTruncIntFP AFGR64RegsOpnd:$src),
+ (TRUNC_W_D32 AFGR64RegsOpnd:$src)>;
+ def : MipsPat<(f32 (fround AFGR64RegsOpnd:$src)),
+ (CVT_S_D32 AFGR64RegsOpnd:$src)>;
+ def : MipsPat<(f64 (fextend FGR32RegsOpnd:$src)),
+ (CVT_D32_S FGR32RegsOpnd:$src)>;
}
let Predicates = [IsFP64bit, HasStdEnc] in {
def : MipsPat<(f64 fpimm0), (DMTC1 ZERO_64)>;
def : MipsPat<(f64 fpimm0neg), (FNEG_D64 (DMTC1 ZERO_64))>;
- def : MipsPat<(f64 (sint_to_fp CPURegs:$src)),
- (PseudoCVT_D64_W CPURegs:$src)>;
- def : MipsPat<(f32 (sint_to_fp CPU64Regs:$src)),
- (EXTRACT_SUBREG (PseudoCVT_S_L CPU64Regs:$src), sub_32)>;
- def : MipsPat<(f64 (sint_to_fp CPU64Regs:$src)),
- (PseudoCVT_D64_L CPU64Regs:$src)>;
-
- def : MipsPat<(MipsTruncIntFP FGR64:$src), (TRUNC_W_D64 FGR64:$src)>;
- def : MipsPat<(MipsTruncIntFP FGR32:$src), (TRUNC_L_S FGR32:$src)>;
- def : MipsPat<(MipsTruncIntFP FGR64:$src), (TRUNC_L_D64 FGR64:$src)>;
-
- def : MipsPat<(f32 (fround FGR64:$src)), (CVT_S_D64 FGR64:$src)>;
- def : MipsPat<(f64 (fextend FGR32:$src)), (CVT_D64_S FGR32:$src)>;
+ def : MipsPat<(f64 (sint_to_fp CPURegsOpnd:$src)),
+ (PseudoCVT_D64_W CPURegsOpnd:$src)>;
+ def : MipsPat<(f32 (sint_to_fp CPU64RegsOpnd:$src)),
+ (EXTRACT_SUBREG (PseudoCVT_S_L CPU64RegsOpnd:$src), sub_32)>;
+ def : MipsPat<(f64 (sint_to_fp CPU64RegsOpnd:$src)),
+ (PseudoCVT_D64_L CPU64RegsOpnd:$src)>;
+
+ def : MipsPat<(MipsTruncIntFP FGR64RegsOpnd:$src),
+ (TRUNC_W_D64 FGR64RegsOpnd:$src)>;
+ def : MipsPat<(MipsTruncIntFP FGR32RegsOpnd:$src),
+ (TRUNC_L_S FGR32RegsOpnd:$src)>;
+ def : MipsPat<(MipsTruncIntFP FGR64RegsOpnd:$src),
+ (TRUNC_L_D64 FGR64RegsOpnd:$src)>;
+
+ def : MipsPat<(f32 (fround FGR64RegsOpnd:$src)),
+ (CVT_S_D64 FGR64RegsOpnd:$src)>;
+ def : MipsPat<(f64 (fextend FGR32RegsOpnd:$src)),
+ (CVT_D64_S FGR32RegsOpnd:$src)>;
}
// Patterns for loads/stores with a reg+imm operand.
diff --git a/lib/Target/Mips/MipsInstrFormats.td b/lib/Target/Mips/MipsInstrFormats.td
index 14cfcf9..c35c6cd 100644
--- a/lib/Target/Mips/MipsInstrFormats.td
+++ b/lib/Target/Mips/MipsInstrFormats.td
@@ -97,6 +97,7 @@ class InstSE<dag outs, dag ins, string asmstr, list<dag> pattern,
let Predicates = [HasStdEnc];
string BaseOpcode = opstr;
string Arch;
+ let MnemonicContainsDot = 1;
}
// Mips Pseudo Instructions Format
@@ -651,6 +652,10 @@ class CEQS_FM<bits<5> fmt> {
let Inst{3-0} = cond;
}
+class C_COND_FM<bits<5> fmt, bits<4> c> : CEQS_FM<fmt> {
+ let cond = c;
+}
+
class CMov_I_F_FM<bits<6> funct, bits<5> fmt> {
bits<5> fd;
bits<5> fs;
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index 218af21..db3050f 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -836,9 +836,12 @@ void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info) {
}
case '.':
- if (InTok)
- AsmOperands.push_back(AsmOperand(String.slice(Prev, i)));
- Prev = i;
+ if (!(TheDef->getValue("MnemonicContainsDot")) ||
+ !(TheDef->getValueAsBit("MnemonicContainsDot"))) {
+ if (InTok)
+ AsmOperands.push_back(AsmOperand(String.slice(Prev, i)));
+ Prev = i;
+ }
InTok = true;
break;
@@ -2303,7 +2306,7 @@ static void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info,
}
if (AliasesFromMnemonic.empty())
return;
-
+
// Process each alias a "from" mnemonic at a time, building the code executed
// by the string remapper.
std::vector<StringMatcher::StringPair> Cases;
</pre></div><br><fieldset class="mimeAttachmentHeader" target="_blank"></fieldset><br><div class="moz-text-plain" lang="x-western" style="font-size: 12px;"><pre>_______________________________________________
llvm-commits mailing list
<a class="moz-txt-link-abbreviated" href="mailto:llvm-commits-Tmj1lob9twqVc3sceRu5cw@public.gmane.org" target="_blank">llvm-commits-Tmj1lob9twqVc3sceRu5cw@public.gmane.org</a>
<a class="moz-txt-link-freetext" href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a></pre></div></div></div></blockquote></div></div></div></div></div></div></blockquote></div><br></div></body></html>