forked from OSchip/llvm-project
[Sparc] Add support for parsing jmpl instruction and make indirect call and jmp instructions as aliases to jmpl.
llvm-svn: 198909
This commit is contained in:
parent
15ed5ebfc5
commit
0d288d3105
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)>;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue