230 lines
8.8 KiB
Diff
230 lines
8.8 KiB
Diff
Pull in r198909 from upstream llvm trunk (by Venkatraman Govindaraju):
|
|
|
|
[Sparc] Add support for parsing jmpl instruction and make indirect call and jmp instructions as aliases to jmpl.
|
|
|
|
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
|
|
|
Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
|
===================================================================
|
|
--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
|
+++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
|
@@ -453,6 +453,7 @@ parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand
|
|
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));
|
|
Index: lib/Target/Sparc/SparcInstrAliases.td
|
|
===================================================================
|
|
--- lib/Target/Sparc/SparcInstrAliases.td
|
|
+++ lib/Target/Sparc/SparcInstrAliases.td
|
|
@@ -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)>;
|
|
Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
|
|
===================================================================
|
|
--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
|
|
+++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
|
|
@@ -23,6 +23,7 @@
|
|
using namespace llvm;
|
|
|
|
#define GET_INSTRUCTION_NAME
|
|
+#define PRINT_ALIAS_INSTR
|
|
#include "SparcGenAsmWriter.inc"
|
|
|
|
void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const
|
|
@@ -33,10 +34,34 @@ void SparcInstPrinter::printRegName(raw_ostream &O
|
|
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)
|
|
{
|
|
Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.h
|
|
===================================================================
|
|
--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.h
|
|
+++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.h
|
|
@@ -29,9 +29,11 @@ class SparcInstPrinter : public MCInstPrinter {
|
|
|
|
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);
|
|
Index: lib/Target/Sparc/SparcInstrInfo.td
|
|
===================================================================
|
|
--- lib/Target/Sparc/SparcInstrInfo.td
|
|
+++ lib/Target/Sparc/SparcInstrInfo.td
|
|
@@ -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> p
|
|
}
|
|
|
|
// 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
|
|
Index: lib/Target/Sparc/DelaySlotFiller.cpp
|
|
===================================================================
|
|
--- lib/Target/Sparc/DelaySlotFiller.cpp
|
|
+++ lib/Target/Sparc/DelaySlotFiller.cpp
|
|
@@ -278,19 +278,19 @@ void Filler::insertCallDefsUses(MachineBasicBlock:
|
|
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::iterato
|
|
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;
|
|
}
|
|
|
|
Index: test/MC/Sparc/sparc-ctrl-instructions.s
|
|
===================================================================
|
|
--- test/MC/Sparc/sparc-ctrl-instructions.s
|
|
+++ test/MC/Sparc/sparc-ctrl-instructions.s
|
|
@@ -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
|