[Sparc] Add support for parsing jmpl instruction and make indirect call and jmp instructions as aliases to jmpl.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198909 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Venkatraman Govindaraju
2014-01-10 01:48:17 +00:00
parent 0f09c9f5ac
commit 8ce28c812b
7 changed files with 83 additions and 22 deletions

View File

@ -453,6 +453,7 @@ parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
switch (getLexer().getKind()) { switch (getLexer().getKind()) {
default: return MatchOperand_NoMatch; default: return MatchOperand_NoMatch;
case AsmToken::Comma:
case AsmToken::RBrac: case AsmToken::RBrac:
case AsmToken::EndOfStatement: case AsmToken::EndOfStatement:
Operands.push_back(SparcOperand::CreateMEMri(BaseReg, 0, S, E)); Operands.push_back(SparcOperand::CreateMEMri(BaseReg, 0, S, E));

View File

@ -278,19 +278,19 @@ void Filler::insertCallDefsUses(MachineBasicBlock::iterator MI,
switch(MI->getOpcode()) { switch(MI->getOpcode()) {
default: llvm_unreachable("Unknown opcode."); default: llvm_unreachable("Unknown opcode.");
case SP::CALL: break; case SP::CALL: break;
case SP::JMPLrr: case SP::CALLrr:
case SP::JMPLri: case SP::CALLri:
assert(MI->getNumOperands() >= 2); assert(MI->getNumOperands() >= 2);
const MachineOperand &Reg = MI->getOperand(0); const MachineOperand &Reg = MI->getOperand(0);
assert(Reg.isReg() && "JMPL first operand is not a register."); assert(Reg.isReg() && "CALL first operand is not a register.");
assert(Reg.isUse() && "JMPL first operand is not a use."); assert(Reg.isUse() && "CALL first operand is not a use.");
RegUses.insert(Reg.getReg()); RegUses.insert(Reg.getReg());
const MachineOperand &RegOrImm = MI->getOperand(1); const MachineOperand &RegOrImm = MI->getOperand(1);
if (RegOrImm.isImm()) if (RegOrImm.isImm())
break; break;
assert(RegOrImm.isReg() && "JMPLrr second operand is not a register."); assert(RegOrImm.isReg() && "CALLrr second operand is not a register.");
assert(RegOrImm.isUse() && "JMPLrr second operand is not a use."); assert(RegOrImm.isUse() && "CALLrr second operand is not a use.");
RegUses.insert(RegOrImm.getReg()); RegUses.insert(RegOrImm.getReg());
break; break;
} }
@ -353,8 +353,8 @@ bool Filler::needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize)
switch (I->getOpcode()) { switch (I->getOpcode()) {
default: llvm_unreachable("Unknown call opcode."); default: llvm_unreachable("Unknown call opcode.");
case SP::CALL: structSizeOpNum = 1; break; case SP::CALL: structSizeOpNum = 1; break;
case SP::JMPLrr: case SP::CALLrr:
case SP::JMPLri: structSizeOpNum = 2; break; case SP::CALLri: structSizeOpNum = 2; break;
case SP::TLS_CALL: return false; case SP::TLS_CALL: return false;
} }

View File

@ -22,6 +22,7 @@
using namespace llvm; using namespace llvm;
#define GET_INSTRUCTION_NAME #define GET_INSTRUCTION_NAME
#define PRINT_ALIAS_INSTR
#include "SparcGenAsmWriter.inc" #include "SparcGenAsmWriter.inc"
void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const
@ -32,10 +33,34 @@ void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const
void SparcInstPrinter::printInst(const MCInst *MI, raw_ostream &O, void SparcInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
StringRef Annot) StringRef Annot)
{ {
printInstruction(MI, O); if (!printAliasInstr(MI, O) && !printSparcAliasInstr(MI, O))
printInstruction(MI, O);
printAnnotation(O, Annot); printAnnotation(O, Annot);
} }
bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI, raw_ostream &O)
{
switch (MI->getOpcode()) {
default: return false;
case SP::JMPLrr:
case SP::JMPLri: {
if (MI->getNumOperands() != 3)
return false;
if (!MI->getOperand(0).isReg())
return false;
switch (MI->getOperand(0).getReg()) {
default: return false;
case SP::G0: // jmp $addr
O << "\tjmp "; printMemOperand(MI, 1, O);
return true;
case SP::O7: // call $addr
O << "\tcall "; printMemOperand(MI, 1, O);
return true;
}
}
}
}
void SparcInstPrinter::printOperand(const MCInst *MI, int opNum, void SparcInstPrinter::printOperand(const MCInst *MI, int opNum,
raw_ostream &O) raw_ostream &O)
{ {

View File

@ -29,9 +29,11 @@ public:
virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;
virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot); virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot);
bool printSparcAliasInstr(const MCInst *MI, raw_ostream &OS);
// Autogenerated by tblgen. // Autogenerated by tblgen.
void printInstruction(const MCInst *MI, raw_ostream &O); void printInstruction(const MCInst *MI, raw_ostream &O);
bool printAliasInstr(const MCInst *MI, raw_ostream &O);
static const char *getRegisterName(unsigned RegNo); static const char *getRegisterName(unsigned RegNo);
void printOperand(const MCInst *MI, int opNum, raw_ostream &OS); void printOperand(const MCInst *MI, int opNum, raw_ostream &OS);

View File

@ -117,3 +117,14 @@ defm : fp_cond_alias<"uge", 0b1100>;
defm : fp_cond_alias<"le", 0b1101>; defm : fp_cond_alias<"le", 0b1101>;
defm : fp_cond_alias<"ule", 0b1110>; defm : fp_cond_alias<"ule", 0b1110>;
defm : fp_cond_alias<"o", 0b1111>; defm : fp_cond_alias<"o", 0b1111>;
// Instruction aliases for JMPL.
// jmp addr -> jmpl addr, %g0
def : InstAlias<"jmp $addr", (JMPLrr G0, MEMrr:$addr)>;
def : InstAlias<"jmp $addr", (JMPLri G0, MEMri:$addr)>;
// call addr -> jmpl addr, %o7
def : InstAlias<"call $addr", (JMPLrr O7, MEMrr:$addr)>;
def : InstAlias<"call $addr", (JMPLri O7, MEMri:$addr)>;

View File

@ -362,10 +362,18 @@ let usesCustomInserter = 1, Uses = [FCC] in {
[(set f128:$dst, (SPselectfcc f128:$T, f128:$F, imm:$Cond))]>; [(set f128:$dst, (SPselectfcc f128:$T, f128:$F, imm:$Cond))]>;
} }
// JMPL Instruction.
let isTerminator = 1, hasDelaySlot = 1, isBarrier = 1 in {
def JMPLrr: F3_1<2, 0b111000, (outs IntRegs:$dst), (ins MEMrr:$addr),
"jmpl $addr, $dst", []>;
def JMPLri: F3_2<2, 0b111000, (outs IntRegs:$dst), (ins MEMri:$addr),
"jmpl $addr, $dst", []>;
}
// Section A.3 - Synthetic Instructions, p. 85 // Section A.3 - Synthetic Instructions, p. 85
// special cases of JMPL: // special cases of JMPL:
let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1 in { let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1,
isCodeGenOnly = 1 in {
let rd = 0, rs1 = 15 in let rd = 0, rs1 = 15 in
def RETL: F3_2<2, 0b111000, (outs), (ins i32imm:$val), def RETL: F3_2<2, 0b111000, (outs), (ins i32imm:$val),
"jmp %o7+$val", [(retflag simm13:$val)]>; "jmp %o7+$val", [(retflag simm13:$val)]>;
@ -519,9 +527,8 @@ class BranchSP<dag ins, string asmstr, list<dag> pattern>
} }
// Indirect branch instructions. // Indirect branch instructions.
let isTerminator = 1, isBarrier = 1, let isTerminator = 1, isBarrier = 1, hasDelaySlot = 1, isBranch =1,
hasDelaySlot = 1, isBranch =1, isIndirectBranch = 1, rd = 0, isCodeGenOnly = 1 in {
isIndirectBranch = 1, rd = 0 in {
def BINDrr : F3_1<2, 0b111000, def BINDrr : F3_1<2, 0b111000,
(outs), (ins MEMrr:$ptr), (outs), (ins MEMrr:$ptr),
"jmp $ptr", "jmp $ptr",
@ -564,15 +571,17 @@ let Uses = [O6],
let Inst{29-0} = disp; let Inst{29-0} = disp;
} }
// indirect calls // indirect calls: special cases of JMPL.
def JMPLrr : F3_1<2, 0b111000, let isCodeGenOnly = 1, rd = 15 in {
(outs), (ins MEMrr:$ptr, variable_ops), def CALLrr : F3_1<2, 0b111000,
"call $ptr", (outs), (ins MEMrr:$ptr, variable_ops),
[(call ADDRrr:$ptr)]> { let rd = 15; } "call $ptr",
def JMPLri : F3_2<2, 0b111000, [(call ADDRrr:$ptr)]>;
(outs), (ins MEMri:$ptr, variable_ops), def CALLri : F3_2<2, 0b111000,
"call $ptr", (outs), (ins MEMri:$ptr, variable_ops),
[(call ADDRri:$ptr)]> { let rd = 15; } "call $ptr",
[(call ADDRri:$ptr)]>;
}
} }
// Section B.28 - Read State Register Instructions // Section B.28 - Read State Register Instructions

View File

@ -31,6 +31,19 @@
! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10 ! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10
jmp %g1+%lo(sym) jmp %g1+%lo(sym)
! CHECK: jmpl %g1+%i2, %g2 ! encoding: [0x85,0xc0,0x40,0x1a]
jmpl %g1 + %i2, %g2
! CHECK: jmpl %o1+8, %g2 ! encoding: [0x85,0xc2,0x60,0x08]
jmpl %o1 + 8, %g2
! CHECK: jmpl %g1, %g2 ! encoding: [0x85,0xc0,0x60,0x00]
jmpl %g1, %g2
! CHECK: jmpl %g1+%lo(sym), %g2 ! encoding: [0x85,0xc0,0b011000AA,A]
! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10
jmpl %g1+%lo(sym), %g2
! CHECK: ba .BB0 ! encoding: [0x10,0b10AAAAAA,A,A] ! CHECK: ba .BB0 ! encoding: [0x10,0b10AAAAAA,A,A]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
ba .BB0 ba .BB0