1 Pull in r198909 from upstream llvm trunk (by Venkatraman Govindaraju):
3 [Sparc] Add support for parsing jmpl instruction and make indirect call and jmp instructions as aliases to jmpl.
5 Introduced here: http://svnweb.freebsd.org/changeset/base/262261
7 Index: 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;
15 + case AsmToken::Comma:
17 case AsmToken::EndOfStatement:
18 Operands.push_back(SparcOperand::CreateMEMri(BaseReg, 0, S, E));
19 Index: 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>;
29 +// Instruction aliases for JMPL.
31 +// jmp addr -> jmpl addr, %g0
32 +def : InstAlias<"jmp $addr", (JMPLrr G0, MEMrr:$addr)>;
33 +def : InstAlias<"jmp $addr", (JMPLri G0, MEMri:$addr)>;
35 +// call addr -> jmpl addr, %o7
36 +def : InstAlias<"call $addr", (JMPLrr O7, MEMrr:$addr)>;
37 +def : InstAlias<"call $addr", (JMPLri O7, MEMri:$addr)>;
38 Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
39 ===================================================================
40 --- lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
41 +++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
45 #define GET_INSTRUCTION_NAME
46 +#define PRINT_ALIAS_INSTR
47 #include "SparcGenAsmWriter.inc"
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,
54 - printInstruction(MI, O);
55 + if (!printAliasInstr(MI, O) && !printSparcAliasInstr(MI, O))
56 + printInstruction(MI, O);
57 printAnnotation(O, Annot);
60 +bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI, raw_ostream &O)
62 + switch (MI->getOpcode()) {
63 + default: return false;
66 + if (MI->getNumOperands() != 3)
68 + if (!MI->getOperand(0).isReg())
70 + switch (MI->getOperand(0).getReg()) {
71 + default: return false;
72 + case SP::G0: // jmp $addr
73 + O << "\tjmp "; printMemOperand(MI, 1, O);
75 + case SP::O7: // call $addr
76 + O << "\tcall "; printMemOperand(MI, 1, O);
83 void SparcInstPrinter::printOperand(const MCInst *MI, int opNum,
86 Index: 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 {
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);
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);
101 void printOperand(const MCInst *MI, int opNum, raw_ostream &OS);
102 Index: 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))]>;
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", []>;
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
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),
138 @@ -564,15 +571,17 @@ let Uses = [O6],
139 let Inst{29-0} = disp;
143 - def JMPLrr : F3_1<2, 0b111000,
144 - (outs), (ins MEMrr:$ptr, variable_ops),
146 - [(call ADDRrr:$ptr)]> { let rd = 15; }
147 - def JMPLri : F3_2<2, 0b111000,
148 - (outs), (ins MEMri:$ptr, variable_ops),
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),
156 + [(call ADDRrr:$ptr)]>;
157 + def CALLri : F3_2<2, 0b111000,
158 + (outs), (ins MEMri:$ptr, variable_ops),
160 + [(call ADDRri:$ptr)]>;
164 // Section B.28 - Read State Register Instructions
165 Index: 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;
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());
185 const MachineOperand &RegOrImm = MI->getOperand(1);
186 if (RegOrImm.isImm())
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());
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;
200 - case SP::JMPLri: structSizeOpNum = 2; break;
202 + case SP::CALLri: structSizeOpNum = 2; break;
203 case SP::TLS_CALL: return false;
206 Index: test/MC/Sparc/sparc-ctrl-instructions.s
207 ===================================================================
208 --- test/MC/Sparc/sparc-ctrl-instructions.s
209 +++ test/MC/Sparc/sparc-ctrl-instructions.s
211 ! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10
214 + ! CHECK: jmpl %g1+%i2, %g2 ! encoding: [0x85,0xc0,0x40,0x1a]
215 + jmpl %g1 + %i2, %g2
217 + ! CHECK: jmpl %o1+8, %g2 ! encoding: [0x85,0xc2,0x60,0x08]
220 + ! CHECK: jmpl %g1, %g2 ! encoding: [0x85,0xc0,0x60,0x00]
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
227 ! CHECK: ba .BB0 ! encoding: [0x10,0b10AAAAAA,A,A]
228 ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22