a1f8ad145e
applied to our copy of llvm/clang. These can be applied in alphabetical order to a pristine llvm/clang 3.4 release source tree, to result in the same version used in FreeBSD. This is intended to clearly document all the changes until now, which mostly consist of cherry pickings from the respective upstream trunks, plus a number of hand-written FreeBSD-specific ones. Hopefully those can eventually be cleaned up and sent upstream too. MFC after: 1 week X-MFC-With: r263313
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://svn.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
|