mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
[Sparc] Add support for parsing annulled branch instructions.
llvm-svn: 202599
This commit is contained in:
parent
30d1614f94
commit
44a4d4b894
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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";
|
||||
|
@ -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]>;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user