diff options
author | Venkatraman Govindaraju <venkatra@cs.wisc.edu> | 2014-03-01 20:08:48 +0000 |
---|---|---|
committer | Venkatraman Govindaraju <venkatra@cs.wisc.edu> | 2014-03-01 20:08:48 +0000 |
commit | 228687411979c3047fb58fd5f4ed999abddd4cb4 (patch) | |
tree | 584aef90f85a0c1955317d6a7bd9959f03082ef8 /llvm/lib/Target/Sparc | |
parent | e0c5bff720b2ad211c7cffa91be14b64618e69eb (diff) | |
download | bcm5719-llvm-228687411979c3047fb58fd5f4ed999abddd4cb4.tar.gz bcm5719-llvm-228687411979c3047fb58fd5f4ed999abddd4cb4.zip |
[Sparc] Add support for parsing annulled branch instructions.
llvm-svn: 202599
Diffstat (limited to 'llvm/lib/Target/Sparc')
-rw-r--r-- | llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp | 31 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/Sparc.h | 12 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/SparcInstrAliases.td | 8 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/SparcInstrFormats.td | 4 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/SparcInstrInfo.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/SparcInstrInfo.td | 33 |
7 files changed, 80 insertions, 13 deletions
diff --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp index d00456e9990..0aba1f28cd1 100644 --- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -70,6 +70,9 @@ class SparcAsmParser : public MCTargetAsmParser { OperandMatchResultTy parseSparcAsmOperand(SparcOperand *&Operand, bool isCall = false); + OperandMatchResultTy + parseBranchModifiers(SmallVectorImpl<MCParsedAsmOperand*> &Operands); + // returns true if Tok is matched to a register and returns register in RegNo. bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, unsigned &RegKind); @@ -454,6 +457,13 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, if (getLexer().isNot(AsmToken::EndOfStatement)) { // Read the first operand. + if (getLexer().is(AsmToken::Comma)) { + if (parseBranchModifiers(Operands) != MatchOperand_Success) { + SMLoc Loc = getLexer().getLoc(); + Parser.eatToEndOfStatement(); + return Error(Loc, "unexpected token"); + } + } if (parseOperand(Operands, Name) != MatchOperand_Success) { SMLoc Loc = getLexer().getLoc(); Parser.eatToEndOfStatement(); @@ -705,6 +715,27 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op, bool isCall) return (Op) ? MatchOperand_Success : MatchOperand_ParseFail; } +SparcAsmParser::OperandMatchResultTy SparcAsmParser:: +parseBranchModifiers(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { + + // parse (,a|,pn|,pt)+ + + while (getLexer().is(AsmToken::Comma)) { + + Parser.Lex(); // Eat the comma + + if (!getLexer().is(AsmToken::Identifier)) + return MatchOperand_ParseFail; + StringRef modName = Parser.getTok().getString(); + if (modName == "a" || modName == "pn" || modName == "pt") { + Operands.push_back(SparcOperand::CreateToken(modName, + Parser.getTok().getLoc())); + Parser.Lex(); // eat the identifier. + } + } + return MatchOperand_Success; +} + bool SparcAsmParser::matchRegisterName(const AsmToken &Tok, unsigned &RegNo, unsigned &RegKind) diff --git a/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp b/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp index 239d4ef9958..41db5798724 100644 --- a/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp +++ b/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp @@ -117,6 +117,7 @@ void SparcInstPrinter::printCCOperand(const MCInst *MI, int opNum, switch (MI->getOpcode()) { default: break; case SP::FBCOND: + case SP::FBCONDA: case SP::MOVFCCrr: case SP::MOVFCCri: case SP::FMOVS_FCC: diff --git a/llvm/lib/Target/Sparc/Sparc.h b/llvm/lib/Target/Sparc/Sparc.h index 8d46c60255e..de20aaa5db5 100644 --- a/llvm/lib/Target/Sparc/Sparc.h +++ b/llvm/lib/Target/Sparc/Sparc.h @@ -42,8 +42,8 @@ namespace llvm { // values must be kept in sync with the ones in the .td file. namespace SPCC { enum CondCodes { - //ICC_A = 8 , // Always - //ICC_N = 0 , // Never + ICC_A = 8 , // Always + ICC_N = 0 , // Never ICC_NE = 9 , // Not Equal ICC_E = 1 , // Equal ICC_G = 10 , // Greater @@ -59,8 +59,8 @@ namespace llvm { ICC_VC = 15 , // Overflow Clear ICC_VS = 7 , // Overflow Set - //FCC_A = 8+16, // Always - //FCC_N = 0+16, // Never + FCC_A = 8+16, // Always + FCC_N = 0+16, // Never FCC_U = 7+16, // Unordered FCC_G = 6+16, // Greater FCC_UG = 5+16, // Unordered or Greater @@ -80,6 +80,8 @@ namespace llvm { inline static const char *SPARCCondCodeToString(SPCC::CondCodes CC) { switch (CC) { + case SPCC::ICC_A: return "a"; + case SPCC::ICC_N: return "n"; case SPCC::ICC_NE: return "ne"; case SPCC::ICC_E: return "e"; case SPCC::ICC_G: return "g"; @@ -94,6 +96,8 @@ namespace llvm { case SPCC::ICC_NEG: return "neg"; case SPCC::ICC_VC: return "vc"; case SPCC::ICC_VS: return "vs"; + case SPCC::FCC_A: return "a"; + case SPCC::FCC_N: return "n"; case SPCC::FCC_U: return "u"; case SPCC::FCC_G: return "g"; case SPCC::FCC_UG: return "ug"; diff --git a/llvm/lib/Target/Sparc/SparcInstrAliases.td b/llvm/lib/Target/Sparc/SparcInstrAliases.td index 624a5a3de8c..cee1c04a05c 100644 --- a/llvm/lib/Target/Sparc/SparcInstrAliases.td +++ b/llvm/lib/Target/Sparc/SparcInstrAliases.td @@ -46,6 +46,10 @@ multiclass int_cond_alias<string cond, int condVal> { def : InstAlias<!strconcat(!strconcat("b", cond), " $imm"), (BCOND brtarget:$imm, condVal)>; + // b<cond>,a $imm + def : InstAlias<!strconcat(!strconcat("b", cond), ",a $imm"), + (BCONDA brtarget:$imm, condVal)>; + // b<cond> %xcc, $imm def : InstAlias<!strconcat(!strconcat("b", cond), " %xcc, $imm"), (BPXCC brtarget:$imm, condVal)>, Requires<[Is64Bit]>; @@ -76,6 +80,10 @@ multiclass fp_cond_alias<string cond, int condVal> { def : InstAlias<!strconcat(!strconcat("fb", cond), " $imm"), (FBCOND brtarget:$imm, condVal), 0>; + // fb<cond>,a $imm + def : InstAlias<!strconcat(!strconcat("fb", cond), ",a $imm"), + (FBCONDA brtarget:$imm, condVal), 0>; + defm : cond_mov_alias<cond, condVal, " %fcc0", MOVFCCrr, MOVFCCri, FMOVS_FCC, FMOVD_FCC>, Requires<[HasV9]>; diff --git a/llvm/lib/Target/Sparc/SparcInstrFormats.td b/llvm/lib/Target/Sparc/SparcInstrFormats.td index b38a663bd3c..97b6498c947 100644 --- a/llvm/lib/Target/Sparc/SparcInstrFormats.td +++ b/llvm/lib/Target/Sparc/SparcInstrFormats.td @@ -51,11 +51,9 @@ class F2_1<bits<3> op2Val, dag outs, dag ins, string asmstr, list<dag> pattern> let Inst{29-25} = rd; } -class F2_2<bits<3> op2Val, dag outs, dag ins, string asmstr, +class F2_2<bits<3> op2Val, bit annul, dag outs, dag ins, string asmstr, list<dag> pattern> : F2<outs, ins, asmstr, pattern> { bits<4> cond; - bit annul = 0; // currently unused - let op2 = op2Val; let Inst{29} = annul; diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp index 6ecf81de836..b0aa25b255f 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp @@ -89,6 +89,8 @@ static bool IsIntegerCC(unsigned CC) static SPCC::CondCodes GetOppositeBranchCondition(SPCC::CondCodes CC) { switch(CC) { + case SPCC::ICC_A: return SPCC::ICC_N; + case SPCC::ICC_N: return SPCC::ICC_A; case SPCC::ICC_NE: return SPCC::ICC_E; case SPCC::ICC_E: return SPCC::ICC_NE; case SPCC::ICC_G: return SPCC::ICC_LE; @@ -104,6 +106,8 @@ static SPCC::CondCodes GetOppositeBranchCondition(SPCC::CondCodes CC) case SPCC::ICC_VC: return SPCC::ICC_VS; case SPCC::ICC_VS: return SPCC::ICC_VC; + case SPCC::FCC_A: return SPCC::FCC_N; + case SPCC::FCC_N: return SPCC::FCC_A; case SPCC::FCC_U: return SPCC::FCC_O; case SPCC::FCC_O: return SPCC::FCC_U; case SPCC::FCC_G: return SPCC::FCC_ULE; diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td index 9bf7be9e8f7..da1dfb5bde8 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.td +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td @@ -552,7 +552,7 @@ defm RESTORE : F3_12np<"restore", 0b111101>; // unconditional branch class. class BranchAlways<dag ins, string asmstr, list<dag> pattern> - : F2_2<0b010, (outs), ins, asmstr, pattern> { + : F2_2<0b010, 0, (outs), ins, asmstr, pattern> { let isBranch = 1; let isTerminator = 1; let hasDelaySlot = 1; @@ -564,7 +564,15 @@ let cond = 8 in // conditional branch class: class BranchSP<dag ins, string asmstr, list<dag> pattern> - : F2_2<0b010, (outs), ins, asmstr, pattern> { + : F2_2<0b010, 0, (outs), ins, asmstr, pattern> { + let isBranch = 1; + let isTerminator = 1; + let hasDelaySlot = 1; +} + +// conditional branch with annul class: +class BranchSPA<dag ins, string asmstr, list<dag> pattern> + : F2_2<0b010, 1, (outs), ins, asmstr, pattern> { let isBranch = 1; let isTerminator = 1; let hasDelaySlot = 1; @@ -583,26 +591,39 @@ let isTerminator = 1, isBarrier = 1, hasDelaySlot = 1, isBranch =1, [(brind ADDRri:$ptr)]>; } -let Uses = [ICC] in +let Uses = [ICC] in { def BCOND : BranchSP<(ins brtarget:$imm22, CCOp:$cond), "b$cond $imm22", [(SPbricc bb:$imm22, imm:$cond)]>; + def BCONDA : BranchSPA<(ins brtarget:$imm22, CCOp:$cond), + "b$cond,a $imm22", []>; +} // Section B.22 - Branch on Floating-point Condition Codes Instructions, p. 121 // floating-point conditional branch class: class FPBranchSP<dag ins, string asmstr, list<dag> pattern> - : F2_2<0b110, (outs), ins, asmstr, pattern> { + : F2_2<0b110, 0, (outs), ins, asmstr, pattern> { let isBranch = 1; let isTerminator = 1; let hasDelaySlot = 1; } -let Uses = [FCC] in +// floating-point conditional branch with annul class: +class FPBranchSPA<dag ins, string asmstr, list<dag> pattern> + : F2_2<0b110, 1, (outs), ins, asmstr, pattern> { + let isBranch = 1; + let isTerminator = 1; + let hasDelaySlot = 1; +} + +let Uses = [FCC] in { def FBCOND : FPBranchSP<(ins brtarget:$imm22, CCOp:$cond), "fb$cond $imm22", [(SPbrfcc bb:$imm22, imm:$cond)]>; - + def FBCONDA : FPBranchSPA<(ins brtarget:$imm22, CCOp:$cond), + "fb$cond,a $imm22", []>; +} // Section B.24 - Call and Link Instruction, p. 125 // This is the only Format 1 instruction |