summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Sparc
diff options
context:
space:
mode:
authorVenkatraman Govindaraju <venkatra@cs.wisc.edu>2014-03-01 20:08:48 +0000
committerVenkatraman Govindaraju <venkatra@cs.wisc.edu>2014-03-01 20:08:48 +0000
commit228687411979c3047fb58fd5f4ed999abddd4cb4 (patch)
tree584aef90f85a0c1955317d6a7bd9959f03082ef8 /llvm/lib/Target/Sparc
parente0c5bff720b2ad211c7cffa91be14b64618e69eb (diff)
downloadbcm5719-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.cpp31
-rw-r--r--llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp1
-rw-r--r--llvm/lib/Target/Sparc/Sparc.h12
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrAliases.td8
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrFormats.td4
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrInfo.cpp4
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrInfo.td33
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
OpenPOWER on IntegriCloud