1Pull in r198909 from upstream llvm trunk (by Venkatraman Govindaraju): 2 3 [Sparc] Add support for parsing jmpl instruction and make indirect call and jmp instructions as aliases to jmpl. 4 5Introduced here: http://svnweb.freebsd.org/changeset/base/262261 6 7Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp 8=================================================================== 9--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp 10+++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp 11@@ -453,6 +453,7 @@ parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand 12 switch (getLexer().getKind()) { 13 default: return MatchOperand_NoMatch; 14 15+ case AsmToken::Comma: 16 case AsmToken::RBrac: 17 case AsmToken::EndOfStatement: 18 Operands.push_back(SparcOperand::CreateMEMri(BaseReg, 0, S, E)); 19Index: lib/Target/Sparc/SparcInstrAliases.td 20=================================================================== 21--- lib/Target/Sparc/SparcInstrAliases.td 22+++ lib/Target/Sparc/SparcInstrAliases.td 23@@ -117,3 +117,14 @@ defm : fp_cond_alias<"uge", 0b1100>; 24 defm : fp_cond_alias<"le", 0b1101>; 25 defm : fp_cond_alias<"ule", 0b1110>; 26 defm : fp_cond_alias<"o", 0b1111>; 27+ 28+ 29+// Instruction aliases for JMPL. 30+ 31+// jmp addr -> jmpl addr, %g0 32+def : InstAlias<"jmp $addr", (JMPLrr G0, MEMrr:$addr)>; 33+def : InstAlias<"jmp $addr", (JMPLri G0, MEMri:$addr)>; 34+ 35+// call addr -> jmpl addr, %o7 36+def : InstAlias<"call $addr", (JMPLrr O7, MEMrr:$addr)>; 37+def : InstAlias<"call $addr", (JMPLri O7, MEMri:$addr)>; 38Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp 39=================================================================== 40--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp 41+++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp 42@@ -23,6 +23,7 @@ 43 using namespace llvm; 44 45 #define GET_INSTRUCTION_NAME 46+#define PRINT_ALIAS_INSTR 47 #include "SparcGenAsmWriter.inc" 48 49 void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const 50@@ -33,10 +34,34 @@ void SparcInstPrinter::printRegName(raw_ostream &O 51 void SparcInstPrinter::printInst(const MCInst *MI, raw_ostream &O, 52 StringRef Annot) 53 { 54- printInstruction(MI, O); 55+ if (!printAliasInstr(MI, O) && !printSparcAliasInstr(MI, O)) 56+ printInstruction(MI, O); 57 printAnnotation(O, Annot); 58 } 59 60+bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI, raw_ostream &O) 61+{ 62+ switch (MI->getOpcode()) { 63+ default: return false; 64+ case SP::JMPLrr: 65+ case SP::JMPLri: { 66+ if (MI->getNumOperands() != 3) 67+ return false; 68+ if (!MI->getOperand(0).isReg()) 69+ return false; 70+ switch (MI->getOperand(0).getReg()) { 71+ default: return false; 72+ case SP::G0: // jmp $addr 73+ O << "\tjmp "; printMemOperand(MI, 1, O); 74+ return true; 75+ case SP::O7: // call $addr 76+ O << "\tcall "; printMemOperand(MI, 1, O); 77+ return true; 78+ } 79+ } 80+ } 81+} 82+ 83 void SparcInstPrinter::printOperand(const MCInst *MI, int opNum, 84 raw_ostream &O) 85 { 86Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.h 87=================================================================== 88--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.h 89+++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.h 90@@ -29,9 +29,11 @@ class SparcInstPrinter : public MCInstPrinter { 91 92 virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; 93 virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot); 94+ bool printSparcAliasInstr(const MCInst *MI, raw_ostream &OS); 95 96 // Autogenerated by tblgen. 97 void printInstruction(const MCInst *MI, raw_ostream &O); 98+ bool printAliasInstr(const MCInst *MI, raw_ostream &O); 99 static const char *getRegisterName(unsigned RegNo); 100 101 void printOperand(const MCInst *MI, int opNum, raw_ostream &OS); 102Index: lib/Target/Sparc/SparcInstrInfo.td 103=================================================================== 104--- lib/Target/Sparc/SparcInstrInfo.td 105+++ lib/Target/Sparc/SparcInstrInfo.td 106@@ -362,10 +362,18 @@ let usesCustomInserter = 1, Uses = [FCC] in { 107 [(set f128:$dst, (SPselectfcc f128:$T, f128:$F, imm:$Cond))]>; 108 } 109 110+// JMPL Instruction. 111+let isTerminator = 1, hasDelaySlot = 1, isBarrier = 1 in { 112+ def JMPLrr: F3_1<2, 0b111000, (outs IntRegs:$dst), (ins MEMrr:$addr), 113+ "jmpl $addr, $dst", []>; 114+ def JMPLri: F3_2<2, 0b111000, (outs IntRegs:$dst), (ins MEMri:$addr), 115+ "jmpl $addr, $dst", []>; 116+} 117 118 // Section A.3 - Synthetic Instructions, p. 85 119 // special cases of JMPL: 120-let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1 in { 121+let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1, 122+ isCodeGenOnly = 1 in { 123 let rd = 0, rs1 = 15 in 124 def RETL: F3_2<2, 0b111000, (outs), (ins i32imm:$val), 125 "jmp %o7+$val", [(retflag simm13:$val)]>; 126@@ -519,9 +527,8 @@ class BranchSP<dag ins, string asmstr, list<dag> p 127 } 128 129 // Indirect branch instructions. 130-let isTerminator = 1, isBarrier = 1, 131- hasDelaySlot = 1, isBranch =1, 132- isIndirectBranch = 1, rd = 0 in { 133+let isTerminator = 1, isBarrier = 1, hasDelaySlot = 1, isBranch =1, 134+ isIndirectBranch = 1, rd = 0, isCodeGenOnly = 1 in { 135 def BINDrr : F3_1<2, 0b111000, 136 (outs), (ins MEMrr:$ptr), 137 "jmp $ptr", 138@@ -564,15 +571,17 @@ let Uses = [O6], 139 let Inst{29-0} = disp; 140 } 141 142- // indirect calls 143- def JMPLrr : F3_1<2, 0b111000, 144- (outs), (ins MEMrr:$ptr, variable_ops), 145- "call $ptr", 146- [(call ADDRrr:$ptr)]> { let rd = 15; } 147- def JMPLri : F3_2<2, 0b111000, 148- (outs), (ins MEMri:$ptr, variable_ops), 149- "call $ptr", 150- [(call ADDRri:$ptr)]> { let rd = 15; } 151+ // indirect calls: special cases of JMPL. 152+ let isCodeGenOnly = 1, rd = 15 in { 153+ def CALLrr : F3_1<2, 0b111000, 154+ (outs), (ins MEMrr:$ptr, variable_ops), 155+ "call $ptr", 156+ [(call ADDRrr:$ptr)]>; 157+ def CALLri : F3_2<2, 0b111000, 158+ (outs), (ins MEMri:$ptr, variable_ops), 159+ "call $ptr", 160+ [(call ADDRri:$ptr)]>; 161+ } 162 } 163 164 // Section B.28 - Read State Register Instructions 165Index: lib/Target/Sparc/DelaySlotFiller.cpp 166=================================================================== 167--- lib/Target/Sparc/DelaySlotFiller.cpp 168+++ lib/Target/Sparc/DelaySlotFiller.cpp 169@@ -278,19 +278,19 @@ void Filler::insertCallDefsUses(MachineBasicBlock: 170 switch(MI->getOpcode()) { 171 default: llvm_unreachable("Unknown opcode."); 172 case SP::CALL: break; 173- case SP::JMPLrr: 174- case SP::JMPLri: 175+ case SP::CALLrr: 176+ case SP::CALLri: 177 assert(MI->getNumOperands() >= 2); 178 const MachineOperand &Reg = MI->getOperand(0); 179- assert(Reg.isReg() && "JMPL first operand is not a register."); 180- assert(Reg.isUse() && "JMPL first operand is not a use."); 181+ assert(Reg.isReg() && "CALL first operand is not a register."); 182+ assert(Reg.isUse() && "CALL first operand is not a use."); 183 RegUses.insert(Reg.getReg()); 184 185 const MachineOperand &RegOrImm = MI->getOperand(1); 186 if (RegOrImm.isImm()) 187 break; 188- assert(RegOrImm.isReg() && "JMPLrr second operand is not a register."); 189- assert(RegOrImm.isUse() && "JMPLrr second operand is not a use."); 190+ assert(RegOrImm.isReg() && "CALLrr second operand is not a register."); 191+ assert(RegOrImm.isUse() && "CALLrr second operand is not a use."); 192 RegUses.insert(RegOrImm.getReg()); 193 break; 194 } 195@@ -353,8 +353,8 @@ bool Filler::needsUnimp(MachineBasicBlock::iterato 196 switch (I->getOpcode()) { 197 default: llvm_unreachable("Unknown call opcode."); 198 case SP::CALL: structSizeOpNum = 1; break; 199- case SP::JMPLrr: 200- case SP::JMPLri: structSizeOpNum = 2; break; 201+ case SP::CALLrr: 202+ case SP::CALLri: structSizeOpNum = 2; break; 203 case SP::TLS_CALL: return false; 204 } 205 206Index: test/MC/Sparc/sparc-ctrl-instructions.s 207=================================================================== 208--- test/MC/Sparc/sparc-ctrl-instructions.s 209+++ test/MC/Sparc/sparc-ctrl-instructions.s 210@@ -31,6 +31,19 @@ 211 ! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10 212 jmp %g1+%lo(sym) 213 214+ ! CHECK: jmpl %g1+%i2, %g2 ! encoding: [0x85,0xc0,0x40,0x1a] 215+ jmpl %g1 + %i2, %g2 216+ 217+ ! CHECK: jmpl %o1+8, %g2 ! encoding: [0x85,0xc2,0x60,0x08] 218+ jmpl %o1 + 8, %g2 219+ 220+ ! CHECK: jmpl %g1, %g2 ! encoding: [0x85,0xc0,0x60,0x00] 221+ jmpl %g1, %g2 222+ 223+ ! CHECK: jmpl %g1+%lo(sym), %g2 ! encoding: [0x85,0xc0,0b011000AA,A] 224+ ! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10 225+ jmpl %g1+%lo(sym), %g2 226+ 227 ! CHECK: ba .BB0 ! encoding: [0x10,0b10AAAAAA,A,A] 228 ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 229 ba .BB0 230