1263320SdimPull in r198909 from upstream llvm trunk (by Venkatraman Govindaraju): 2263320Sdim 3263320Sdim [Sparc] Add support for parsing jmpl instruction and make indirect call and jmp instructions as aliases to jmpl. 4263320Sdim 5269012SemasteIntroduced here: http://svnweb.freebsd.org/changeset/base/262261 6263320Sdim 7263320SdimIndex: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp 8263320Sdim=================================================================== 9263320Sdim--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp 10263320Sdim+++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp 11263320Sdim@@ -453,6 +453,7 @@ parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand 12263320Sdim switch (getLexer().getKind()) { 13263320Sdim default: return MatchOperand_NoMatch; 14263320Sdim 15263320Sdim+ case AsmToken::Comma: 16263320Sdim case AsmToken::RBrac: 17263320Sdim case AsmToken::EndOfStatement: 18263320Sdim Operands.push_back(SparcOperand::CreateMEMri(BaseReg, 0, S, E)); 19263320SdimIndex: lib/Target/Sparc/SparcInstrAliases.td 20263320Sdim=================================================================== 21263320Sdim--- lib/Target/Sparc/SparcInstrAliases.td 22263320Sdim+++ lib/Target/Sparc/SparcInstrAliases.td 23263320Sdim@@ -117,3 +117,14 @@ defm : fp_cond_alias<"uge", 0b1100>; 24263320Sdim defm : fp_cond_alias<"le", 0b1101>; 25263320Sdim defm : fp_cond_alias<"ule", 0b1110>; 26263320Sdim defm : fp_cond_alias<"o", 0b1111>; 27263320Sdim+ 28263320Sdim+ 29263320Sdim+// Instruction aliases for JMPL. 30263320Sdim+ 31263320Sdim+// jmp addr -> jmpl addr, %g0 32263320Sdim+def : InstAlias<"jmp $addr", (JMPLrr G0, MEMrr:$addr)>; 33263320Sdim+def : InstAlias<"jmp $addr", (JMPLri G0, MEMri:$addr)>; 34263320Sdim+ 35263320Sdim+// call addr -> jmpl addr, %o7 36263320Sdim+def : InstAlias<"call $addr", (JMPLrr O7, MEMrr:$addr)>; 37263320Sdim+def : InstAlias<"call $addr", (JMPLri O7, MEMri:$addr)>; 38263320SdimIndex: lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp 39263320Sdim=================================================================== 40263320Sdim--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp 41263320Sdim+++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp 42263320Sdim@@ -23,6 +23,7 @@ 43263320Sdim using namespace llvm; 44263320Sdim 45263320Sdim #define GET_INSTRUCTION_NAME 46263320Sdim+#define PRINT_ALIAS_INSTR 47263320Sdim #include "SparcGenAsmWriter.inc" 48263320Sdim 49263320Sdim void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const 50263320Sdim@@ -33,10 +34,34 @@ void SparcInstPrinter::printRegName(raw_ostream &O 51263320Sdim void SparcInstPrinter::printInst(const MCInst *MI, raw_ostream &O, 52263320Sdim StringRef Annot) 53263320Sdim { 54263320Sdim- printInstruction(MI, O); 55263320Sdim+ if (!printAliasInstr(MI, O) && !printSparcAliasInstr(MI, O)) 56263320Sdim+ printInstruction(MI, O); 57263320Sdim printAnnotation(O, Annot); 58263320Sdim } 59263320Sdim 60263320Sdim+bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI, raw_ostream &O) 61263320Sdim+{ 62263320Sdim+ switch (MI->getOpcode()) { 63263320Sdim+ default: return false; 64263320Sdim+ case SP::JMPLrr: 65263320Sdim+ case SP::JMPLri: { 66263320Sdim+ if (MI->getNumOperands() != 3) 67263320Sdim+ return false; 68263320Sdim+ if (!MI->getOperand(0).isReg()) 69263320Sdim+ return false; 70263320Sdim+ switch (MI->getOperand(0).getReg()) { 71263320Sdim+ default: return false; 72263320Sdim+ case SP::G0: // jmp $addr 73263320Sdim+ O << "\tjmp "; printMemOperand(MI, 1, O); 74263320Sdim+ return true; 75263320Sdim+ case SP::O7: // call $addr 76263320Sdim+ O << "\tcall "; printMemOperand(MI, 1, O); 77263320Sdim+ return true; 78263320Sdim+ } 79263320Sdim+ } 80263320Sdim+ } 81263320Sdim+} 82263320Sdim+ 83263320Sdim void SparcInstPrinter::printOperand(const MCInst *MI, int opNum, 84263320Sdim raw_ostream &O) 85263320Sdim { 86263320SdimIndex: lib/Target/Sparc/InstPrinter/SparcInstPrinter.h 87263320Sdim=================================================================== 88263320Sdim--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.h 89263320Sdim+++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.h 90263320Sdim@@ -29,9 +29,11 @@ class SparcInstPrinter : public MCInstPrinter { 91263320Sdim 92263320Sdim virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; 93263320Sdim virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot); 94263320Sdim+ bool printSparcAliasInstr(const MCInst *MI, raw_ostream &OS); 95263320Sdim 96263320Sdim // Autogenerated by tblgen. 97263320Sdim void printInstruction(const MCInst *MI, raw_ostream &O); 98263320Sdim+ bool printAliasInstr(const MCInst *MI, raw_ostream &O); 99263320Sdim static const char *getRegisterName(unsigned RegNo); 100263320Sdim 101263320Sdim void printOperand(const MCInst *MI, int opNum, raw_ostream &OS); 102263320SdimIndex: lib/Target/Sparc/SparcInstrInfo.td 103263320Sdim=================================================================== 104263320Sdim--- lib/Target/Sparc/SparcInstrInfo.td 105263320Sdim+++ lib/Target/Sparc/SparcInstrInfo.td 106263320Sdim@@ -362,10 +362,18 @@ let usesCustomInserter = 1, Uses = [FCC] in { 107263320Sdim [(set f128:$dst, (SPselectfcc f128:$T, f128:$F, imm:$Cond))]>; 108263320Sdim } 109263320Sdim 110263320Sdim+// JMPL Instruction. 111263320Sdim+let isTerminator = 1, hasDelaySlot = 1, isBarrier = 1 in { 112263320Sdim+ def JMPLrr: F3_1<2, 0b111000, (outs IntRegs:$dst), (ins MEMrr:$addr), 113263320Sdim+ "jmpl $addr, $dst", []>; 114263320Sdim+ def JMPLri: F3_2<2, 0b111000, (outs IntRegs:$dst), (ins MEMri:$addr), 115263320Sdim+ "jmpl $addr, $dst", []>; 116263320Sdim+} 117263320Sdim 118263320Sdim // Section A.3 - Synthetic Instructions, p. 85 119263320Sdim // special cases of JMPL: 120263320Sdim-let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1 in { 121263320Sdim+let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1, 122263320Sdim+ isCodeGenOnly = 1 in { 123263320Sdim let rd = 0, rs1 = 15 in 124263320Sdim def RETL: F3_2<2, 0b111000, (outs), (ins i32imm:$val), 125263320Sdim "jmp %o7+$val", [(retflag simm13:$val)]>; 126263320Sdim@@ -519,9 +527,8 @@ class BranchSP<dag ins, string asmstr, list<dag> p 127263320Sdim } 128263320Sdim 129263320Sdim // Indirect branch instructions. 130263320Sdim-let isTerminator = 1, isBarrier = 1, 131263320Sdim- hasDelaySlot = 1, isBranch =1, 132263320Sdim- isIndirectBranch = 1, rd = 0 in { 133263320Sdim+let isTerminator = 1, isBarrier = 1, hasDelaySlot = 1, isBranch =1, 134263320Sdim+ isIndirectBranch = 1, rd = 0, isCodeGenOnly = 1 in { 135263320Sdim def BINDrr : F3_1<2, 0b111000, 136263320Sdim (outs), (ins MEMrr:$ptr), 137263320Sdim "jmp $ptr", 138263320Sdim@@ -564,15 +571,17 @@ let Uses = [O6], 139263320Sdim let Inst{29-0} = disp; 140263320Sdim } 141263320Sdim 142263320Sdim- // indirect calls 143263320Sdim- def JMPLrr : F3_1<2, 0b111000, 144263320Sdim- (outs), (ins MEMrr:$ptr, variable_ops), 145263320Sdim- "call $ptr", 146263320Sdim- [(call ADDRrr:$ptr)]> { let rd = 15; } 147263320Sdim- def JMPLri : F3_2<2, 0b111000, 148263320Sdim- (outs), (ins MEMri:$ptr, variable_ops), 149263320Sdim- "call $ptr", 150263320Sdim- [(call ADDRri:$ptr)]> { let rd = 15; } 151263320Sdim+ // indirect calls: special cases of JMPL. 152263320Sdim+ let isCodeGenOnly = 1, rd = 15 in { 153263320Sdim+ def CALLrr : F3_1<2, 0b111000, 154263320Sdim+ (outs), (ins MEMrr:$ptr, variable_ops), 155263320Sdim+ "call $ptr", 156263320Sdim+ [(call ADDRrr:$ptr)]>; 157263320Sdim+ def CALLri : F3_2<2, 0b111000, 158263320Sdim+ (outs), (ins MEMri:$ptr, variable_ops), 159263320Sdim+ "call $ptr", 160263320Sdim+ [(call ADDRri:$ptr)]>; 161263320Sdim+ } 162263320Sdim } 163263320Sdim 164263320Sdim // Section B.28 - Read State Register Instructions 165263320SdimIndex: lib/Target/Sparc/DelaySlotFiller.cpp 166263320Sdim=================================================================== 167263320Sdim--- lib/Target/Sparc/DelaySlotFiller.cpp 168263320Sdim+++ lib/Target/Sparc/DelaySlotFiller.cpp 169263320Sdim@@ -278,19 +278,19 @@ void Filler::insertCallDefsUses(MachineBasicBlock: 170263320Sdim switch(MI->getOpcode()) { 171263320Sdim default: llvm_unreachable("Unknown opcode."); 172263320Sdim case SP::CALL: break; 173263320Sdim- case SP::JMPLrr: 174263320Sdim- case SP::JMPLri: 175263320Sdim+ case SP::CALLrr: 176263320Sdim+ case SP::CALLri: 177263320Sdim assert(MI->getNumOperands() >= 2); 178263320Sdim const MachineOperand &Reg = MI->getOperand(0); 179263320Sdim- assert(Reg.isReg() && "JMPL first operand is not a register."); 180263320Sdim- assert(Reg.isUse() && "JMPL first operand is not a use."); 181263320Sdim+ assert(Reg.isReg() && "CALL first operand is not a register."); 182263320Sdim+ assert(Reg.isUse() && "CALL first operand is not a use."); 183263320Sdim RegUses.insert(Reg.getReg()); 184263320Sdim 185263320Sdim const MachineOperand &RegOrImm = MI->getOperand(1); 186263320Sdim if (RegOrImm.isImm()) 187263320Sdim break; 188263320Sdim- assert(RegOrImm.isReg() && "JMPLrr second operand is not a register."); 189263320Sdim- assert(RegOrImm.isUse() && "JMPLrr second operand is not a use."); 190263320Sdim+ assert(RegOrImm.isReg() && "CALLrr second operand is not a register."); 191263320Sdim+ assert(RegOrImm.isUse() && "CALLrr second operand is not a use."); 192263320Sdim RegUses.insert(RegOrImm.getReg()); 193263320Sdim break; 194263320Sdim } 195263320Sdim@@ -353,8 +353,8 @@ bool Filler::needsUnimp(MachineBasicBlock::iterato 196263320Sdim switch (I->getOpcode()) { 197263320Sdim default: llvm_unreachable("Unknown call opcode."); 198263320Sdim case SP::CALL: structSizeOpNum = 1; break; 199263320Sdim- case SP::JMPLrr: 200263320Sdim- case SP::JMPLri: structSizeOpNum = 2; break; 201263320Sdim+ case SP::CALLrr: 202263320Sdim+ case SP::CALLri: structSizeOpNum = 2; break; 203263320Sdim case SP::TLS_CALL: return false; 204263320Sdim } 205263320Sdim 206263320SdimIndex: test/MC/Sparc/sparc-ctrl-instructions.s 207263320Sdim=================================================================== 208263320Sdim--- test/MC/Sparc/sparc-ctrl-instructions.s 209263320Sdim+++ test/MC/Sparc/sparc-ctrl-instructions.s 210263320Sdim@@ -31,6 +31,19 @@ 211263320Sdim ! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10 212263320Sdim jmp %g1+%lo(sym) 213263320Sdim 214263320Sdim+ ! CHECK: jmpl %g1+%i2, %g2 ! encoding: [0x85,0xc0,0x40,0x1a] 215263320Sdim+ jmpl %g1 + %i2, %g2 216263320Sdim+ 217263320Sdim+ ! CHECK: jmpl %o1+8, %g2 ! encoding: [0x85,0xc2,0x60,0x08] 218263320Sdim+ jmpl %o1 + 8, %g2 219263320Sdim+ 220263320Sdim+ ! CHECK: jmpl %g1, %g2 ! encoding: [0x85,0xc0,0x60,0x00] 221263320Sdim+ jmpl %g1, %g2 222263320Sdim+ 223263320Sdim+ ! CHECK: jmpl %g1+%lo(sym), %g2 ! encoding: [0x85,0xc0,0b011000AA,A] 224263320Sdim+ ! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10 225263320Sdim+ jmpl %g1+%lo(sym), %g2 226263320Sdim+ 227263320Sdim ! CHECK: ba .BB0 ! encoding: [0x10,0b10AAAAAA,A,A] 228263320Sdim ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 229263320Sdim ba .BB0 230