[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()) {
default: return MatchOperand_NoMatch;
case AsmToken::Comma:
case AsmToken::RBrac:
case AsmToken::EndOfStatement:
Operands.push_back(SparcOperand::CreateMEMri(BaseReg, 0, S, E));

View File

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

View File

@ -22,6 +22,7 @@
using namespace llvm;
#define GET_INSTRUCTION_NAME
#define PRINT_ALIAS_INSTR
#include "SparcGenAsmWriter.inc"
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,
StringRef Annot)
{
printInstruction(MI, O);
if (!printAliasInstr(MI, O) && !printSparcAliasInstr(MI, O))
printInstruction(MI, O);
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,
raw_ostream &O)
{

View File

@ -29,9 +29,11 @@ public:
virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;
virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot);
bool printSparcAliasInstr(const MCInst *MI, raw_ostream &OS);
// Autogenerated by tblgen.
void printInstruction(const MCInst *MI, raw_ostream &O);
bool printAliasInstr(const MCInst *MI, raw_ostream &O);
static const char *getRegisterName(unsigned RegNo);
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<"ule", 0b1110>;
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))]>;
}
// 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
// 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
def RETL: F3_2<2, 0b111000, (outs), (ins i32imm:$val),
"jmp %o7+$val", [(retflag simm13:$val)]>;
@ -519,9 +527,8 @@ class BranchSP<dag ins, string asmstr, list<dag> pattern>
}
// Indirect branch instructions.
let isTerminator = 1, isBarrier = 1,
hasDelaySlot = 1, isBranch =1,
isIndirectBranch = 1, rd = 0 in {
let isTerminator = 1, isBarrier = 1, hasDelaySlot = 1, isBranch =1,
isIndirectBranch = 1, rd = 0, isCodeGenOnly = 1 in {
def BINDrr : F3_1<2, 0b111000,
(outs), (ins MEMrr:$ptr),
"jmp $ptr",
@ -564,15 +571,17 @@ let Uses = [O6],
let Inst{29-0} = disp;
}
// indirect calls
def JMPLrr : F3_1<2, 0b111000,
(outs), (ins MEMrr:$ptr, variable_ops),
"call $ptr",
[(call ADDRrr:$ptr)]> { let rd = 15; }
def JMPLri : F3_2<2, 0b111000,
(outs), (ins MEMri:$ptr, variable_ops),
"call $ptr",
[(call ADDRri:$ptr)]> { let rd = 15; }
// indirect calls: special cases of JMPL.
let isCodeGenOnly = 1, rd = 15 in {
def CALLrr : F3_1<2, 0b111000,
(outs), (ins MEMrr:$ptr, variable_ops),
"call $ptr",
[(call ADDRrr:$ptr)]>;
def CALLri : F3_2<2, 0b111000,
(outs), (ins MEMri:$ptr, variable_ops),
"call $ptr",
[(call ADDRri:$ptr)]>;
}
}
// 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
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-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
ba .BB0