xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/VE/VEAsmPrinter.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
1480093f4SDimitry Andric //===-- VEAsmPrinter.cpp - VE LLVM assembly writer ------------------------===//
2480093f4SDimitry Andric //
3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6480093f4SDimitry Andric //
7480093f4SDimitry Andric //===----------------------------------------------------------------------===//
8480093f4SDimitry Andric //
9480093f4SDimitry Andric // This file contains a printer that converts from our internal representation
10480093f4SDimitry Andric // of machine-dependent LLVM code to GAS-format VE assembly language.
11480093f4SDimitry Andric //
12480093f4SDimitry Andric //===----------------------------------------------------------------------===//
13480093f4SDimitry Andric 
14*5ffd83dbSDimitry Andric #include "MCTargetDesc/VEInstPrinter.h"
15*5ffd83dbSDimitry Andric #include "MCTargetDesc/VEMCExpr.h"
16480093f4SDimitry Andric #include "MCTargetDesc/VETargetStreamer.h"
17*5ffd83dbSDimitry Andric #include "TargetInfo/VETargetInfo.h"
18480093f4SDimitry Andric #include "VE.h"
19480093f4SDimitry Andric #include "VEInstrInfo.h"
20480093f4SDimitry Andric #include "VETargetMachine.h"
21480093f4SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h"
22480093f4SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
23480093f4SDimitry Andric #include "llvm/CodeGen/MachineModuleInfoImpls.h"
24480093f4SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
25480093f4SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
26480093f4SDimitry Andric #include "llvm/IR/Mangler.h"
27480093f4SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
28480093f4SDimitry Andric #include "llvm/MC/MCContext.h"
29480093f4SDimitry Andric #include "llvm/MC/MCInst.h"
30480093f4SDimitry Andric #include "llvm/MC/MCInstBuilder.h"
31480093f4SDimitry Andric #include "llvm/MC/MCStreamer.h"
32480093f4SDimitry Andric #include "llvm/MC/MCSymbol.h"
33480093f4SDimitry Andric #include "llvm/Support/TargetRegistry.h"
34480093f4SDimitry Andric #include "llvm/Support/raw_ostream.h"
35480093f4SDimitry Andric using namespace llvm;
36480093f4SDimitry Andric 
37480093f4SDimitry Andric #define DEBUG_TYPE "ve-asmprinter"
38480093f4SDimitry Andric 
39480093f4SDimitry Andric namespace {
40480093f4SDimitry Andric class VEAsmPrinter : public AsmPrinter {
41480093f4SDimitry Andric   VETargetStreamer &getTargetStreamer() {
42480093f4SDimitry Andric     return static_cast<VETargetStreamer &>(*OutStreamer->getTargetStreamer());
43480093f4SDimitry Andric   }
44480093f4SDimitry Andric 
45480093f4SDimitry Andric public:
46480093f4SDimitry Andric   explicit VEAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
47480093f4SDimitry Andric       : AsmPrinter(TM, std::move(Streamer)) {}
48480093f4SDimitry Andric 
49480093f4SDimitry Andric   StringRef getPassName() const override { return "VE Assembly Printer"; }
50480093f4SDimitry Andric 
51*5ffd83dbSDimitry Andric   void lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,
52*5ffd83dbSDimitry Andric                                  const MCSubtargetInfo &STI);
53*5ffd83dbSDimitry Andric   void lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,
54*5ffd83dbSDimitry Andric                                     const MCSubtargetInfo &STI);
55*5ffd83dbSDimitry Andric   void lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,
56*5ffd83dbSDimitry Andric                                      const MCSubtargetInfo &STI);
57*5ffd83dbSDimitry Andric 
58*5ffd83dbSDimitry Andric   void emitInstruction(const MachineInstr *MI) override;
59480093f4SDimitry Andric 
60480093f4SDimitry Andric   static const char *getRegisterName(unsigned RegNo) {
61480093f4SDimitry Andric     return VEInstPrinter::getRegisterName(RegNo);
62480093f4SDimitry Andric   }
63480093f4SDimitry Andric };
64480093f4SDimitry Andric } // end of anonymous namespace
65480093f4SDimitry Andric 
66*5ffd83dbSDimitry Andric static MCOperand createVEMCOperand(VEMCExpr::VariantKind Kind, MCSymbol *Sym,
67*5ffd83dbSDimitry Andric                                    MCContext &OutContext) {
68*5ffd83dbSDimitry Andric   const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym, OutContext);
69*5ffd83dbSDimitry Andric   const VEMCExpr *expr = VEMCExpr::create(Kind, MCSym, OutContext);
70*5ffd83dbSDimitry Andric   return MCOperand::createExpr(expr);
71*5ffd83dbSDimitry Andric }
72*5ffd83dbSDimitry Andric 
73*5ffd83dbSDimitry Andric static MCOperand createGOTRelExprOp(VEMCExpr::VariantKind Kind,
74*5ffd83dbSDimitry Andric                                     MCSymbol *GOTLabel, MCContext &OutContext) {
75*5ffd83dbSDimitry Andric   const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext);
76*5ffd83dbSDimitry Andric   const VEMCExpr *expr = VEMCExpr::create(Kind, GOT, OutContext);
77*5ffd83dbSDimitry Andric   return MCOperand::createExpr(expr);
78*5ffd83dbSDimitry Andric }
79*5ffd83dbSDimitry Andric 
80*5ffd83dbSDimitry Andric static void emitSIC(MCStreamer &OutStreamer, MCOperand &RD,
81*5ffd83dbSDimitry Andric                     const MCSubtargetInfo &STI) {
82*5ffd83dbSDimitry Andric   MCInst SICInst;
83*5ffd83dbSDimitry Andric   SICInst.setOpcode(VE::SIC);
84*5ffd83dbSDimitry Andric   SICInst.addOperand(RD);
85*5ffd83dbSDimitry Andric   OutStreamer.emitInstruction(SICInst, STI);
86*5ffd83dbSDimitry Andric }
87*5ffd83dbSDimitry Andric 
88*5ffd83dbSDimitry Andric static void emitBSIC(MCStreamer &OutStreamer, MCOperand &R1, MCOperand &R2,
89*5ffd83dbSDimitry Andric                      const MCSubtargetInfo &STI) {
90*5ffd83dbSDimitry Andric   MCInst BSICInst;
91*5ffd83dbSDimitry Andric   BSICInst.setOpcode(VE::BSICrii);
92*5ffd83dbSDimitry Andric   BSICInst.addOperand(R1);
93*5ffd83dbSDimitry Andric   BSICInst.addOperand(R2);
94*5ffd83dbSDimitry Andric   MCOperand czero = MCOperand::createImm(0);
95*5ffd83dbSDimitry Andric   BSICInst.addOperand(czero);
96*5ffd83dbSDimitry Andric   BSICInst.addOperand(czero);
97*5ffd83dbSDimitry Andric   OutStreamer.emitInstruction(BSICInst, STI);
98*5ffd83dbSDimitry Andric }
99*5ffd83dbSDimitry Andric 
100*5ffd83dbSDimitry Andric static void emitLEAzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
101*5ffd83dbSDimitry Andric                        const MCSubtargetInfo &STI) {
102*5ffd83dbSDimitry Andric   MCInst LEAInst;
103*5ffd83dbSDimitry Andric   LEAInst.setOpcode(VE::LEAzii);
104*5ffd83dbSDimitry Andric   LEAInst.addOperand(RD);
105*5ffd83dbSDimitry Andric   MCOperand CZero = MCOperand::createImm(0);
106*5ffd83dbSDimitry Andric   LEAInst.addOperand(CZero);
107*5ffd83dbSDimitry Andric   LEAInst.addOperand(CZero);
108*5ffd83dbSDimitry Andric   LEAInst.addOperand(Imm);
109*5ffd83dbSDimitry Andric   OutStreamer.emitInstruction(LEAInst, STI);
110*5ffd83dbSDimitry Andric }
111*5ffd83dbSDimitry Andric 
112*5ffd83dbSDimitry Andric static void emitLEASLzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
113*5ffd83dbSDimitry Andric                          const MCSubtargetInfo &STI) {
114*5ffd83dbSDimitry Andric   MCInst LEASLInst;
115*5ffd83dbSDimitry Andric   LEASLInst.setOpcode(VE::LEASLzii);
116*5ffd83dbSDimitry Andric   LEASLInst.addOperand(RD);
117*5ffd83dbSDimitry Andric   MCOperand CZero = MCOperand::createImm(0);
118*5ffd83dbSDimitry Andric   LEASLInst.addOperand(CZero);
119*5ffd83dbSDimitry Andric   LEASLInst.addOperand(CZero);
120*5ffd83dbSDimitry Andric   LEASLInst.addOperand(Imm);
121*5ffd83dbSDimitry Andric   OutStreamer.emitInstruction(LEASLInst, STI);
122*5ffd83dbSDimitry Andric }
123*5ffd83dbSDimitry Andric 
124*5ffd83dbSDimitry Andric static void emitLEAzii(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,
125*5ffd83dbSDimitry Andric                        MCOperand &RD, const MCSubtargetInfo &STI) {
126*5ffd83dbSDimitry Andric   MCInst LEAInst;
127*5ffd83dbSDimitry Andric   LEAInst.setOpcode(VE::LEAzii);
128*5ffd83dbSDimitry Andric   LEAInst.addOperand(RD);
129*5ffd83dbSDimitry Andric   MCOperand CZero = MCOperand::createImm(0);
130*5ffd83dbSDimitry Andric   LEAInst.addOperand(CZero);
131*5ffd83dbSDimitry Andric   LEAInst.addOperand(RS1);
132*5ffd83dbSDimitry Andric   LEAInst.addOperand(Imm);
133*5ffd83dbSDimitry Andric   OutStreamer.emitInstruction(LEAInst, STI);
134*5ffd83dbSDimitry Andric }
135*5ffd83dbSDimitry Andric 
136*5ffd83dbSDimitry Andric static void emitLEASLrri(MCStreamer &OutStreamer, MCOperand &RS1,
137*5ffd83dbSDimitry Andric                          MCOperand &RS2, MCOperand &Imm, MCOperand &RD,
138*5ffd83dbSDimitry Andric                          const MCSubtargetInfo &STI) {
139*5ffd83dbSDimitry Andric   MCInst LEASLInst;
140*5ffd83dbSDimitry Andric   LEASLInst.setOpcode(VE::LEASLrri);
141*5ffd83dbSDimitry Andric   LEASLInst.addOperand(RD);
142*5ffd83dbSDimitry Andric   LEASLInst.addOperand(RS1);
143*5ffd83dbSDimitry Andric   LEASLInst.addOperand(RS2);
144*5ffd83dbSDimitry Andric   LEASLInst.addOperand(Imm);
145*5ffd83dbSDimitry Andric   OutStreamer.emitInstruction(LEASLInst, STI);
146*5ffd83dbSDimitry Andric }
147*5ffd83dbSDimitry Andric 
148*5ffd83dbSDimitry Andric static void emitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1,
149*5ffd83dbSDimitry Andric                        MCOperand &Src2, MCOperand &RD,
150*5ffd83dbSDimitry Andric                        const MCSubtargetInfo &STI) {
151*5ffd83dbSDimitry Andric   MCInst Inst;
152*5ffd83dbSDimitry Andric   Inst.setOpcode(Opcode);
153*5ffd83dbSDimitry Andric   Inst.addOperand(RD);
154*5ffd83dbSDimitry Andric   Inst.addOperand(RS1);
155*5ffd83dbSDimitry Andric   Inst.addOperand(Src2);
156*5ffd83dbSDimitry Andric   OutStreamer.emitInstruction(Inst, STI);
157*5ffd83dbSDimitry Andric }
158*5ffd83dbSDimitry Andric 
159*5ffd83dbSDimitry Andric static void emitANDrm(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,
160*5ffd83dbSDimitry Andric                       MCOperand &RD, const MCSubtargetInfo &STI) {
161*5ffd83dbSDimitry Andric   emitBinary(OutStreamer, VE::ANDrm, RS1, Imm, RD, STI);
162*5ffd83dbSDimitry Andric }
163*5ffd83dbSDimitry Andric 
164*5ffd83dbSDimitry Andric static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym,
165*5ffd83dbSDimitry Andric                      VEMCExpr::VariantKind HiKind, VEMCExpr::VariantKind LoKind,
166*5ffd83dbSDimitry Andric                      MCOperand &RD, MCContext &OutContext,
167*5ffd83dbSDimitry Andric                      const MCSubtargetInfo &STI) {
168*5ffd83dbSDimitry Andric 
169*5ffd83dbSDimitry Andric   MCOperand hi = createVEMCOperand(HiKind, GOTSym, OutContext);
170*5ffd83dbSDimitry Andric   MCOperand lo = createVEMCOperand(LoKind, GOTSym, OutContext);
171*5ffd83dbSDimitry Andric   emitLEAzzi(OutStreamer, lo, RD, STI);
172*5ffd83dbSDimitry Andric   MCOperand M032 = MCOperand::createImm(M0(32));
173*5ffd83dbSDimitry Andric   emitANDrm(OutStreamer, RD, M032, RD, STI);
174*5ffd83dbSDimitry Andric   emitLEASLzzi(OutStreamer, hi, RD, STI);
175*5ffd83dbSDimitry Andric }
176*5ffd83dbSDimitry Andric 
177*5ffd83dbSDimitry Andric void VEAsmPrinter::lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,
178*5ffd83dbSDimitry Andric                                              const MCSubtargetInfo &STI) {
179*5ffd83dbSDimitry Andric   MCSymbol *GOTLabel =
180*5ffd83dbSDimitry Andric       OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
181*5ffd83dbSDimitry Andric 
182*5ffd83dbSDimitry Andric   const MachineOperand &MO = MI->getOperand(0);
183*5ffd83dbSDimitry Andric   MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
184*5ffd83dbSDimitry Andric 
185*5ffd83dbSDimitry Andric   if (!isPositionIndependent()) {
186*5ffd83dbSDimitry Andric     // Just load the address of GOT to MCRegOP.
187*5ffd83dbSDimitry Andric     switch (TM.getCodeModel()) {
188*5ffd83dbSDimitry Andric     default:
189*5ffd83dbSDimitry Andric       llvm_unreachable("Unsupported absolute code model");
190*5ffd83dbSDimitry Andric     case CodeModel::Small:
191*5ffd83dbSDimitry Andric     case CodeModel::Medium:
192*5ffd83dbSDimitry Andric     case CodeModel::Large:
193*5ffd83dbSDimitry Andric       emitHiLo(*OutStreamer, GOTLabel, VEMCExpr::VK_VE_HI32,
194*5ffd83dbSDimitry Andric                VEMCExpr::VK_VE_LO32, MCRegOP, OutContext, STI);
195*5ffd83dbSDimitry Andric       break;
196*5ffd83dbSDimitry Andric     }
197*5ffd83dbSDimitry Andric     return;
198*5ffd83dbSDimitry Andric   }
199*5ffd83dbSDimitry Andric 
200*5ffd83dbSDimitry Andric   MCOperand RegGOT = MCOperand::createReg(VE::SX15); // GOT
201*5ffd83dbSDimitry Andric   MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
202*5ffd83dbSDimitry Andric 
203*5ffd83dbSDimitry Andric   // lea %got, _GLOBAL_OFFSET_TABLE_@PC_LO(-24)
204*5ffd83dbSDimitry Andric   // and %got, %got, (32)0
205*5ffd83dbSDimitry Andric   // sic %plt
206*5ffd83dbSDimitry Andric   // lea.sl %got, _GLOBAL_OFFSET_TABLE_@PC_HI(%got, %plt)
207*5ffd83dbSDimitry Andric   MCOperand cim24 = MCOperand::createImm(-24);
208*5ffd83dbSDimitry Andric   MCOperand loImm =
209*5ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_PC_LO32, GOTLabel, OutContext);
210*5ffd83dbSDimitry Andric   emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);
211*5ffd83dbSDimitry Andric   MCOperand M032 = MCOperand::createImm(M0(32));
212*5ffd83dbSDimitry Andric   emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);
213*5ffd83dbSDimitry Andric   emitSIC(*OutStreamer, RegPLT, STI);
214*5ffd83dbSDimitry Andric   MCOperand hiImm =
215*5ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_PC_HI32, GOTLabel, OutContext);
216*5ffd83dbSDimitry Andric   emitLEASLrri(*OutStreamer, RegGOT, RegPLT, hiImm, MCRegOP, STI);
217*5ffd83dbSDimitry Andric }
218*5ffd83dbSDimitry Andric 
219*5ffd83dbSDimitry Andric void VEAsmPrinter::lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,
220*5ffd83dbSDimitry Andric                                                 const MCSubtargetInfo &STI) {
221*5ffd83dbSDimitry Andric   const MachineOperand &MO = MI->getOperand(0);
222*5ffd83dbSDimitry Andric   MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
223*5ffd83dbSDimitry Andric   const MachineOperand &Addr = MI->getOperand(1);
224*5ffd83dbSDimitry Andric   MCSymbol *AddrSym = nullptr;
225*5ffd83dbSDimitry Andric 
226*5ffd83dbSDimitry Andric   switch (Addr.getType()) {
227*5ffd83dbSDimitry Andric   default:
228*5ffd83dbSDimitry Andric     llvm_unreachable("<unknown operand type>");
229*5ffd83dbSDimitry Andric     return;
230*5ffd83dbSDimitry Andric   case MachineOperand::MO_MachineBasicBlock:
231*5ffd83dbSDimitry Andric     report_fatal_error("MBB is not supported yet");
232*5ffd83dbSDimitry Andric     return;
233*5ffd83dbSDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
234*5ffd83dbSDimitry Andric     report_fatal_error("ConstantPool is not supported yet");
235*5ffd83dbSDimitry Andric     return;
236*5ffd83dbSDimitry Andric   case MachineOperand::MO_ExternalSymbol:
237*5ffd83dbSDimitry Andric     AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
238*5ffd83dbSDimitry Andric     break;
239*5ffd83dbSDimitry Andric   case MachineOperand::MO_GlobalAddress:
240*5ffd83dbSDimitry Andric     AddrSym = getSymbol(Addr.getGlobal());
241*5ffd83dbSDimitry Andric     break;
242*5ffd83dbSDimitry Andric   }
243*5ffd83dbSDimitry Andric 
244*5ffd83dbSDimitry Andric   if (!isPositionIndependent()) {
245*5ffd83dbSDimitry Andric     llvm_unreachable("Unsupported uses of %plt in not PIC code");
246*5ffd83dbSDimitry Andric     return;
247*5ffd83dbSDimitry Andric   }
248*5ffd83dbSDimitry Andric 
249*5ffd83dbSDimitry Andric   MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
250*5ffd83dbSDimitry Andric 
251*5ffd83dbSDimitry Andric   // lea %dst, %plt_lo(func)(-24)
252*5ffd83dbSDimitry Andric   // and %dst, %dst, (32)0
253*5ffd83dbSDimitry Andric   // sic %plt                            ; FIXME: is it safe to use %plt here?
254*5ffd83dbSDimitry Andric   // lea.sl %dst, %plt_hi(func)(%dst, %plt)
255*5ffd83dbSDimitry Andric   MCOperand cim24 = MCOperand::createImm(-24);
256*5ffd83dbSDimitry Andric   MCOperand loImm =
257*5ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, AddrSym, OutContext);
258*5ffd83dbSDimitry Andric   emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);
259*5ffd83dbSDimitry Andric   MCOperand M032 = MCOperand::createImm(M0(32));
260*5ffd83dbSDimitry Andric   emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);
261*5ffd83dbSDimitry Andric   emitSIC(*OutStreamer, RegPLT, STI);
262*5ffd83dbSDimitry Andric   MCOperand hiImm =
263*5ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, AddrSym, OutContext);
264*5ffd83dbSDimitry Andric   emitLEASLrri(*OutStreamer, MCRegOP, RegPLT, hiImm, MCRegOP, STI);
265*5ffd83dbSDimitry Andric }
266*5ffd83dbSDimitry Andric 
267*5ffd83dbSDimitry Andric void VEAsmPrinter::lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,
268*5ffd83dbSDimitry Andric                                                  const MCSubtargetInfo &STI) {
269*5ffd83dbSDimitry Andric   const MachineOperand &Addr = MI->getOperand(0);
270*5ffd83dbSDimitry Andric   MCSymbol *AddrSym = nullptr;
271*5ffd83dbSDimitry Andric 
272*5ffd83dbSDimitry Andric   switch (Addr.getType()) {
273*5ffd83dbSDimitry Andric   default:
274*5ffd83dbSDimitry Andric     llvm_unreachable("<unknown operand type>");
275*5ffd83dbSDimitry Andric     return;
276*5ffd83dbSDimitry Andric   case MachineOperand::MO_MachineBasicBlock:
277*5ffd83dbSDimitry Andric     report_fatal_error("MBB is not supported yet");
278*5ffd83dbSDimitry Andric     return;
279*5ffd83dbSDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
280*5ffd83dbSDimitry Andric     report_fatal_error("ConstantPool is not supported yet");
281*5ffd83dbSDimitry Andric     return;
282*5ffd83dbSDimitry Andric   case MachineOperand::MO_ExternalSymbol:
283*5ffd83dbSDimitry Andric     AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
284*5ffd83dbSDimitry Andric     break;
285*5ffd83dbSDimitry Andric   case MachineOperand::MO_GlobalAddress:
286*5ffd83dbSDimitry Andric     AddrSym = getSymbol(Addr.getGlobal());
287*5ffd83dbSDimitry Andric     break;
288*5ffd83dbSDimitry Andric   }
289*5ffd83dbSDimitry Andric 
290*5ffd83dbSDimitry Andric   MCOperand RegLR = MCOperand::createReg(VE::SX10);  // LR
291*5ffd83dbSDimitry Andric   MCOperand RegS0 = MCOperand::createReg(VE::SX0);   // S0
292*5ffd83dbSDimitry Andric   MCOperand RegS12 = MCOperand::createReg(VE::SX12); // S12
293*5ffd83dbSDimitry Andric   MCSymbol *GetTLSLabel = OutContext.getOrCreateSymbol(Twine("__tls_get_addr"));
294*5ffd83dbSDimitry Andric 
295*5ffd83dbSDimitry Andric   // lea %s0, sym@tls_gd_lo(-24)
296*5ffd83dbSDimitry Andric   // and %s0, %s0, (32)0
297*5ffd83dbSDimitry Andric   // sic %lr
298*5ffd83dbSDimitry Andric   // lea.sl %s0, sym@tls_gd_hi(%s0, %lr)
299*5ffd83dbSDimitry Andric   // lea %s12, __tls_get_addr@plt_lo(8)
300*5ffd83dbSDimitry Andric   // and %s12, %s12, (32)0
301*5ffd83dbSDimitry Andric   // lea.sl %s12, __tls_get_addr@plt_hi(%s12, %lr)
302*5ffd83dbSDimitry Andric   // bsic %lr, (, %s12)
303*5ffd83dbSDimitry Andric   MCOperand cim24 = MCOperand::createImm(-24);
304*5ffd83dbSDimitry Andric   MCOperand loImm =
305*5ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_LO32, AddrSym, OutContext);
306*5ffd83dbSDimitry Andric   emitLEAzii(*OutStreamer, cim24, loImm, RegS0, STI);
307*5ffd83dbSDimitry Andric   MCOperand M032 = MCOperand::createImm(M0(32));
308*5ffd83dbSDimitry Andric   emitANDrm(*OutStreamer, RegS0, M032, RegS0, STI);
309*5ffd83dbSDimitry Andric   emitSIC(*OutStreamer, RegLR, STI);
310*5ffd83dbSDimitry Andric   MCOperand hiImm =
311*5ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_HI32, AddrSym, OutContext);
312*5ffd83dbSDimitry Andric   emitLEASLrri(*OutStreamer, RegS0, RegLR, hiImm, RegS0, STI);
313*5ffd83dbSDimitry Andric   MCOperand ci8 = MCOperand::createImm(8);
314*5ffd83dbSDimitry Andric   MCOperand loImm2 =
315*5ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, GetTLSLabel, OutContext);
316*5ffd83dbSDimitry Andric   emitLEAzii(*OutStreamer, ci8, loImm2, RegS12, STI);
317*5ffd83dbSDimitry Andric   emitANDrm(*OutStreamer, RegS12, M032, RegS12, STI);
318*5ffd83dbSDimitry Andric   MCOperand hiImm2 =
319*5ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, GetTLSLabel, OutContext);
320*5ffd83dbSDimitry Andric   emitLEASLrri(*OutStreamer, RegS12, RegLR, hiImm2, RegS12, STI);
321*5ffd83dbSDimitry Andric   emitBSIC(*OutStreamer, RegLR, RegS12, STI);
322*5ffd83dbSDimitry Andric }
323*5ffd83dbSDimitry Andric 
324*5ffd83dbSDimitry Andric void VEAsmPrinter::emitInstruction(const MachineInstr *MI) {
325480093f4SDimitry Andric 
326480093f4SDimitry Andric   switch (MI->getOpcode()) {
327480093f4SDimitry Andric   default:
328480093f4SDimitry Andric     break;
329480093f4SDimitry Andric   case TargetOpcode::DBG_VALUE:
330480093f4SDimitry Andric     // FIXME: Debug Value.
331480093f4SDimitry Andric     return;
332*5ffd83dbSDimitry Andric   case VE::GETGOT:
333*5ffd83dbSDimitry Andric     lowerGETGOTAndEmitMCInsts(MI, getSubtargetInfo());
334*5ffd83dbSDimitry Andric     return;
335*5ffd83dbSDimitry Andric   case VE::GETFUNPLT:
336*5ffd83dbSDimitry Andric     lowerGETFunPLTAndEmitMCInsts(MI, getSubtargetInfo());
337*5ffd83dbSDimitry Andric     return;
338*5ffd83dbSDimitry Andric   case VE::GETTLSADDR:
339*5ffd83dbSDimitry Andric     lowerGETTLSAddrAndEmitMCInsts(MI, getSubtargetInfo());
340*5ffd83dbSDimitry Andric     return;
341480093f4SDimitry Andric   }
342*5ffd83dbSDimitry Andric 
343480093f4SDimitry Andric   MachineBasicBlock::const_instr_iterator I = MI->getIterator();
344480093f4SDimitry Andric   MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
345480093f4SDimitry Andric   do {
346480093f4SDimitry Andric     MCInst TmpInst;
347480093f4SDimitry Andric     LowerVEMachineInstrToMCInst(&*I, TmpInst, *this);
348480093f4SDimitry Andric     EmitToStreamer(*OutStreamer, TmpInst);
349480093f4SDimitry Andric   } while ((++I != E) && I->isInsideBundle()); // Delay slot check.
350480093f4SDimitry Andric }
351480093f4SDimitry Andric 
352480093f4SDimitry Andric // Force static initialization.
353480093f4SDimitry Andric extern "C" void LLVMInitializeVEAsmPrinter() {
354480093f4SDimitry Andric   RegisterAsmPrinter<VEAsmPrinter> X(getTheVETarget());
355480093f4SDimitry Andric }
356