From 44a4d4b8946d4ed3d18705a8fc1b82bb9f909f01 Mon Sep 17 00:00:00 2001 From: Venkatraman Govindaraju Date: Sat, 1 Mar 2014 20:08:48 +0000 Subject: [PATCH] [Sparc] Add support for parsing annulled branch instructions. llvm-svn: 202599 --- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp | 31 +++++ .../Sparc/InstPrinter/SparcInstPrinter.cpp | 1 + lib/Target/Sparc/Sparc.h | 12 +- lib/Target/Sparc/SparcInstrAliases.td | 8 ++ lib/Target/Sparc/SparcInstrFormats.td | 4 +- lib/Target/Sparc/SparcInstrInfo.cpp | 4 + lib/Target/Sparc/SparcInstrInfo.td | 33 ++++- test/MC/Sparc/sparc-ctrl-instructions.s | 116 ++++++++++++++++++ 8 files changed, 196 insertions(+), 13 deletions(-) diff --git a/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp index d00456e9990..0aba1f28cd1 100644 --- a/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ b/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -70,6 +70,9 @@ class SparcAsmParser : public MCTargetAsmParser { OperandMatchResultTy parseSparcAsmOperand(SparcOperand *&Operand, bool isCall = false); + OperandMatchResultTy + parseBranchModifiers(SmallVectorImpl &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 &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/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp b/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp index 239d4ef9958..41db5798724 100644 --- a/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp +++ b/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/lib/Target/Sparc/Sparc.h b/lib/Target/Sparc/Sparc.h index 8d46c60255e..de20aaa5db5 100644 --- a/lib/Target/Sparc/Sparc.h +++ b/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/lib/Target/Sparc/SparcInstrAliases.td b/lib/Target/Sparc/SparcInstrAliases.td index 624a5a3de8c..cee1c04a05c 100644 --- a/lib/Target/Sparc/SparcInstrAliases.td +++ b/lib/Target/Sparc/SparcInstrAliases.td @@ -46,6 +46,10 @@ multiclass int_cond_alias { def : InstAlias; + // b,a $imm + def : InstAlias; + // b %xcc, $imm def : InstAlias, Requires<[Is64Bit]>; @@ -76,6 +80,10 @@ multiclass fp_cond_alias { def : InstAlias; + // fb,a $imm + def : InstAlias; + defm : cond_mov_alias, Requires<[HasV9]>; diff --git a/lib/Target/Sparc/SparcInstrFormats.td b/lib/Target/Sparc/SparcInstrFormats.td index b38a663bd3c..97b6498c947 100644 --- a/lib/Target/Sparc/SparcInstrFormats.td +++ b/lib/Target/Sparc/SparcInstrFormats.td @@ -51,11 +51,9 @@ class F2_1 op2Val, dag outs, dag ins, string asmstr, list pattern> let Inst{29-25} = rd; } -class F2_2 op2Val, dag outs, dag ins, string asmstr, +class F2_2 op2Val, bit annul, dag outs, dag ins, string asmstr, list pattern> : F2 { bits<4> cond; - bit annul = 0; // currently unused - let op2 = op2Val; let Inst{29} = annul; diff --git a/lib/Target/Sparc/SparcInstrInfo.cpp b/lib/Target/Sparc/SparcInstrInfo.cpp index 6ecf81de836..b0aa25b255f 100644 --- a/lib/Target/Sparc/SparcInstrInfo.cpp +++ b/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/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td index 9bf7be9e8f7..da1dfb5bde8 100644 --- a/lib/Target/Sparc/SparcInstrInfo.td +++ b/lib/Target/Sparc/SparcInstrInfo.td @@ -552,7 +552,7 @@ defm RESTORE : F3_12np<"restore", 0b111101>; // unconditional branch class. class BranchAlways 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 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 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 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 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 diff --git a/test/MC/Sparc/sparc-ctrl-instructions.s b/test/MC/Sparc/sparc-ctrl-instructions.s index f713276747b..ac4ead1ee04 100644 --- a/test/MC/Sparc/sparc-ctrl-instructions.s +++ b/test/MC/Sparc/sparc-ctrl-instructions.s @@ -158,3 +158,119 @@ ! CHECK: fbo .BB0 ! encoding: [0x1f,0b10AAAAAA,A,A] ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 fbo .BB0 + + ! CHECK: ba,a .BB0 ! encoding: [0x30,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + ba,a .BB0 + + ! CHECK: bne,a .BB0 ! encoding: [0x32,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + bne,a .BB0 + + ! CHECK: be,a .BB0 ! encoding: [0x22,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + be,a .BB0 + + ! CHECK: bg,a .BB0 ! encoding: [0x34,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + bg,a .BB0 + + ! CHECK: ble,a .BB0 ! encoding: [0x24,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + ble,a .BB0 + + ! CHECK: bge,a .BB0 ! encoding: [0x36,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + bge,a .BB0 + + ! CHECK: bl,a .BB0 ! encoding: [0x26,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + bl,a .BB0 + + ! CHECK: bgu,a .BB0 ! encoding: [0x38,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + bgu,a .BB0 + + ! CHECK: bleu,a .BB0 ! encoding: [0x28,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + bleu,a .BB0 + + ! CHECK: bcc,a .BB0 ! encoding: [0x3a,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + bcc,a .BB0 + + ! CHECK: bcs,a .BB0 ! encoding: [0x2a,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + bcs,a .BB0 + + ! CHECK: bpos,a .BB0 ! encoding: [0x3c,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + bpos,a .BB0 + + ! CHECK: bneg,a .BB0 ! encoding: [0x2c,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + bneg,a .BB0 + + ! CHECK: bvc,a .BB0 ! encoding: [0x3e,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + bvc,a .BB0 + + ! CHECK: bvs,a .BB0 ! encoding: [0x2e,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + bvs,a .BB0 + + ! CHECK: fbu,a .BB0 ! encoding: [0x2f,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + fbu,a .BB0 + + ! CHECK: fbg,a .BB0 ! encoding: [0x2d,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + fbg,a .BB0 + ! CHECK: fbug,a .BB0 ! encoding: [0x2b,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + fbug,a .BB0 + + ! CHECK: fbl,a .BB0 ! encoding: [0x29,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + fbl,a .BB0 + + ! CHECK: fbul,a .BB0 ! encoding: [0x27,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + fbul,a .BB0 + + ! CHECK: fblg,a .BB0 ! encoding: [0x25,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + fblg,a .BB0 + + ! CHECK: fbne,a .BB0 ! encoding: [0x23,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + fbne,a .BB0 + + ! CHECK: fbe,a .BB0 ! encoding: [0x33,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + fbe,a .BB0 + + ! CHECK: fbue,a .BB0 ! encoding: [0x35,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + fbue,a .BB0 + + ! CHECK: fbge,a .BB0 ! encoding: [0x37,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + fbge,a .BB0 + + ! CHECK: fbuge,a .BB0 ! encoding: [0x39,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + fbuge,a .BB0 + + ! CHECK: fble,a .BB0 ! encoding: [0x3b,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + fble,a .BB0 + + ! CHECK: fbule,a .BB0 ! encoding: [0x3d,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + fbule,a .BB0 + + ! CHECK: fbo,a .BB0 ! encoding: [0x3f,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + fbo,a .BB0 +