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