xref: /openbsd-src/gnu/llvm/llvm/lib/Target/VE/VEAsmPrinter.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===-- VEAsmPrinter.cpp - VE LLVM assembly writer ------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file contains a printer that converts from our internal representation
1009467b48Spatrick // of machine-dependent LLVM code to GAS-format VE assembly language.
1109467b48Spatrick //
1209467b48Spatrick //===----------------------------------------------------------------------===//
1309467b48Spatrick 
14097a140dSpatrick #include "MCTargetDesc/VEInstPrinter.h"
15097a140dSpatrick #include "MCTargetDesc/VEMCExpr.h"
1609467b48Spatrick #include "MCTargetDesc/VETargetStreamer.h"
17097a140dSpatrick #include "TargetInfo/VETargetInfo.h"
1809467b48Spatrick #include "VE.h"
1909467b48Spatrick #include "VEInstrInfo.h"
2009467b48Spatrick #include "VETargetMachine.h"
2109467b48Spatrick #include "llvm/CodeGen/AsmPrinter.h"
2209467b48Spatrick #include "llvm/CodeGen/MachineInstr.h"
2309467b48Spatrick #include "llvm/CodeGen/MachineModuleInfoImpls.h"
2409467b48Spatrick #include "llvm/CodeGen/MachineRegisterInfo.h"
2509467b48Spatrick #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
2609467b48Spatrick #include "llvm/IR/Mangler.h"
2709467b48Spatrick #include "llvm/MC/MCAsmInfo.h"
2809467b48Spatrick #include "llvm/MC/MCContext.h"
2909467b48Spatrick #include "llvm/MC/MCInst.h"
3009467b48Spatrick #include "llvm/MC/MCInstBuilder.h"
3109467b48Spatrick #include "llvm/MC/MCStreamer.h"
3209467b48Spatrick #include "llvm/MC/MCSymbol.h"
33*d415bd75Srobert #include "llvm/MC/TargetRegistry.h"
3409467b48Spatrick #include "llvm/Support/raw_ostream.h"
3509467b48Spatrick using namespace llvm;
3609467b48Spatrick 
3709467b48Spatrick #define DEBUG_TYPE "ve-asmprinter"
3809467b48Spatrick 
3909467b48Spatrick namespace {
4009467b48Spatrick class VEAsmPrinter : public AsmPrinter {
getTargetStreamer()4109467b48Spatrick   VETargetStreamer &getTargetStreamer() {
4209467b48Spatrick     return static_cast<VETargetStreamer &>(*OutStreamer->getTargetStreamer());
4309467b48Spatrick   }
4409467b48Spatrick 
4509467b48Spatrick public:
VEAsmPrinter(TargetMachine & TM,std::unique_ptr<MCStreamer> Streamer)4609467b48Spatrick   explicit VEAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
4709467b48Spatrick       : AsmPrinter(TM, std::move(Streamer)) {}
4809467b48Spatrick 
getPassName() const4909467b48Spatrick   StringRef getPassName() const override { return "VE Assembly Printer"; }
5009467b48Spatrick 
51097a140dSpatrick   void lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,
52097a140dSpatrick                                  const MCSubtargetInfo &STI);
53097a140dSpatrick   void lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,
54097a140dSpatrick                                     const MCSubtargetInfo &STI);
55097a140dSpatrick   void lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,
56097a140dSpatrick                                      const MCSubtargetInfo &STI);
57097a140dSpatrick 
58097a140dSpatrick   void emitInstruction(const MachineInstr *MI) override;
5909467b48Spatrick 
getRegisterName(MCRegister Reg)60*d415bd75Srobert   static const char *getRegisterName(MCRegister Reg) {
61*d415bd75Srobert     return VEInstPrinter::getRegisterName(Reg);
6209467b48Spatrick   }
6373471bf0Spatrick   void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &OS);
6473471bf0Spatrick   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
6573471bf0Spatrick                        const char *ExtraCode, raw_ostream &O) override;
66*d415bd75Srobert   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
67*d415bd75Srobert                              const char *ExtraCode, raw_ostream &O) override;
6809467b48Spatrick };
6909467b48Spatrick } // end of anonymous namespace
7009467b48Spatrick 
createVEMCOperand(VEMCExpr::VariantKind Kind,MCSymbol * Sym,MCContext & OutContext)71097a140dSpatrick static MCOperand createVEMCOperand(VEMCExpr::VariantKind Kind, MCSymbol *Sym,
72097a140dSpatrick                                    MCContext &OutContext) {
73097a140dSpatrick   const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym, OutContext);
74097a140dSpatrick   const VEMCExpr *expr = VEMCExpr::create(Kind, MCSym, OutContext);
75097a140dSpatrick   return MCOperand::createExpr(expr);
76097a140dSpatrick }
77097a140dSpatrick 
createGOTRelExprOp(VEMCExpr::VariantKind Kind,MCSymbol * GOTLabel,MCContext & OutContext)78097a140dSpatrick static MCOperand createGOTRelExprOp(VEMCExpr::VariantKind Kind,
79097a140dSpatrick                                     MCSymbol *GOTLabel, MCContext &OutContext) {
80097a140dSpatrick   const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext);
81097a140dSpatrick   const VEMCExpr *expr = VEMCExpr::create(Kind, GOT, OutContext);
82097a140dSpatrick   return MCOperand::createExpr(expr);
83097a140dSpatrick }
84097a140dSpatrick 
emitSIC(MCStreamer & OutStreamer,MCOperand & RD,const MCSubtargetInfo & STI)85097a140dSpatrick static void emitSIC(MCStreamer &OutStreamer, MCOperand &RD,
86097a140dSpatrick                     const MCSubtargetInfo &STI) {
87097a140dSpatrick   MCInst SICInst;
88097a140dSpatrick   SICInst.setOpcode(VE::SIC);
89097a140dSpatrick   SICInst.addOperand(RD);
90097a140dSpatrick   OutStreamer.emitInstruction(SICInst, STI);
91097a140dSpatrick }
92097a140dSpatrick 
emitBSIC(MCStreamer & OutStreamer,MCOperand & R1,MCOperand & R2,const MCSubtargetInfo & STI)93097a140dSpatrick static void emitBSIC(MCStreamer &OutStreamer, MCOperand &R1, MCOperand &R2,
94097a140dSpatrick                      const MCSubtargetInfo &STI) {
95097a140dSpatrick   MCInst BSICInst;
96097a140dSpatrick   BSICInst.setOpcode(VE::BSICrii);
97097a140dSpatrick   BSICInst.addOperand(R1);
98097a140dSpatrick   BSICInst.addOperand(R2);
99097a140dSpatrick   MCOperand czero = MCOperand::createImm(0);
100097a140dSpatrick   BSICInst.addOperand(czero);
101097a140dSpatrick   BSICInst.addOperand(czero);
102097a140dSpatrick   OutStreamer.emitInstruction(BSICInst, STI);
103097a140dSpatrick }
104097a140dSpatrick 
emitLEAzzi(MCStreamer & OutStreamer,MCOperand & Imm,MCOperand & RD,const MCSubtargetInfo & STI)105097a140dSpatrick static void emitLEAzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
106097a140dSpatrick                        const MCSubtargetInfo &STI) {
107097a140dSpatrick   MCInst LEAInst;
108097a140dSpatrick   LEAInst.setOpcode(VE::LEAzii);
109097a140dSpatrick   LEAInst.addOperand(RD);
110097a140dSpatrick   MCOperand CZero = MCOperand::createImm(0);
111097a140dSpatrick   LEAInst.addOperand(CZero);
112097a140dSpatrick   LEAInst.addOperand(CZero);
113097a140dSpatrick   LEAInst.addOperand(Imm);
114097a140dSpatrick   OutStreamer.emitInstruction(LEAInst, STI);
115097a140dSpatrick }
116097a140dSpatrick 
emitLEASLzzi(MCStreamer & OutStreamer,MCOperand & Imm,MCOperand & RD,const MCSubtargetInfo & STI)117097a140dSpatrick static void emitLEASLzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
118097a140dSpatrick                          const MCSubtargetInfo &STI) {
119097a140dSpatrick   MCInst LEASLInst;
120097a140dSpatrick   LEASLInst.setOpcode(VE::LEASLzii);
121097a140dSpatrick   LEASLInst.addOperand(RD);
122097a140dSpatrick   MCOperand CZero = MCOperand::createImm(0);
123097a140dSpatrick   LEASLInst.addOperand(CZero);
124097a140dSpatrick   LEASLInst.addOperand(CZero);
125097a140dSpatrick   LEASLInst.addOperand(Imm);
126097a140dSpatrick   OutStreamer.emitInstruction(LEASLInst, STI);
127097a140dSpatrick }
128097a140dSpatrick 
emitLEAzii(MCStreamer & OutStreamer,MCOperand & RS1,MCOperand & Imm,MCOperand & RD,const MCSubtargetInfo & STI)129097a140dSpatrick static void emitLEAzii(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,
130097a140dSpatrick                        MCOperand &RD, const MCSubtargetInfo &STI) {
131097a140dSpatrick   MCInst LEAInst;
132097a140dSpatrick   LEAInst.setOpcode(VE::LEAzii);
133097a140dSpatrick   LEAInst.addOperand(RD);
134097a140dSpatrick   MCOperand CZero = MCOperand::createImm(0);
135097a140dSpatrick   LEAInst.addOperand(CZero);
136097a140dSpatrick   LEAInst.addOperand(RS1);
137097a140dSpatrick   LEAInst.addOperand(Imm);
138097a140dSpatrick   OutStreamer.emitInstruction(LEAInst, STI);
139097a140dSpatrick }
140097a140dSpatrick 
emitLEASLrri(MCStreamer & OutStreamer,MCOperand & RS1,MCOperand & RS2,MCOperand & Imm,MCOperand & RD,const MCSubtargetInfo & STI)141097a140dSpatrick static void emitLEASLrri(MCStreamer &OutStreamer, MCOperand &RS1,
142097a140dSpatrick                          MCOperand &RS2, MCOperand &Imm, MCOperand &RD,
143097a140dSpatrick                          const MCSubtargetInfo &STI) {
144097a140dSpatrick   MCInst LEASLInst;
145097a140dSpatrick   LEASLInst.setOpcode(VE::LEASLrri);
146097a140dSpatrick   LEASLInst.addOperand(RD);
147097a140dSpatrick   LEASLInst.addOperand(RS1);
148097a140dSpatrick   LEASLInst.addOperand(RS2);
149097a140dSpatrick   LEASLInst.addOperand(Imm);
150097a140dSpatrick   OutStreamer.emitInstruction(LEASLInst, STI);
151097a140dSpatrick }
152097a140dSpatrick 
emitBinary(MCStreamer & OutStreamer,unsigned Opcode,MCOperand & RS1,MCOperand & Src2,MCOperand & RD,const MCSubtargetInfo & STI)153097a140dSpatrick static void emitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1,
154097a140dSpatrick                        MCOperand &Src2, MCOperand &RD,
155097a140dSpatrick                        const MCSubtargetInfo &STI) {
156097a140dSpatrick   MCInst Inst;
157097a140dSpatrick   Inst.setOpcode(Opcode);
158097a140dSpatrick   Inst.addOperand(RD);
159097a140dSpatrick   Inst.addOperand(RS1);
160097a140dSpatrick   Inst.addOperand(Src2);
161097a140dSpatrick   OutStreamer.emitInstruction(Inst, STI);
162097a140dSpatrick }
163097a140dSpatrick 
emitANDrm(MCStreamer & OutStreamer,MCOperand & RS1,MCOperand & Imm,MCOperand & RD,const MCSubtargetInfo & STI)164097a140dSpatrick static void emitANDrm(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,
165097a140dSpatrick                       MCOperand &RD, const MCSubtargetInfo &STI) {
166097a140dSpatrick   emitBinary(OutStreamer, VE::ANDrm, RS1, Imm, RD, STI);
167097a140dSpatrick }
168097a140dSpatrick 
emitHiLo(MCStreamer & OutStreamer,MCSymbol * GOTSym,VEMCExpr::VariantKind HiKind,VEMCExpr::VariantKind LoKind,MCOperand & RD,MCContext & OutContext,const MCSubtargetInfo & STI)169097a140dSpatrick static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym,
170097a140dSpatrick                      VEMCExpr::VariantKind HiKind, VEMCExpr::VariantKind LoKind,
171097a140dSpatrick                      MCOperand &RD, MCContext &OutContext,
172097a140dSpatrick                      const MCSubtargetInfo &STI) {
173097a140dSpatrick 
174097a140dSpatrick   MCOperand hi = createVEMCOperand(HiKind, GOTSym, OutContext);
175097a140dSpatrick   MCOperand lo = createVEMCOperand(LoKind, GOTSym, OutContext);
176097a140dSpatrick   emitLEAzzi(OutStreamer, lo, RD, STI);
177097a140dSpatrick   MCOperand M032 = MCOperand::createImm(M0(32));
178097a140dSpatrick   emitANDrm(OutStreamer, RD, M032, RD, STI);
179097a140dSpatrick   emitLEASLzzi(OutStreamer, hi, RD, STI);
180097a140dSpatrick }
181097a140dSpatrick 
lowerGETGOTAndEmitMCInsts(const MachineInstr * MI,const MCSubtargetInfo & STI)182097a140dSpatrick void VEAsmPrinter::lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,
183097a140dSpatrick                                              const MCSubtargetInfo &STI) {
184097a140dSpatrick   MCSymbol *GOTLabel =
185097a140dSpatrick       OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
186097a140dSpatrick 
187097a140dSpatrick   const MachineOperand &MO = MI->getOperand(0);
188097a140dSpatrick   MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
189097a140dSpatrick 
190097a140dSpatrick   if (!isPositionIndependent()) {
191097a140dSpatrick     // Just load the address of GOT to MCRegOP.
192097a140dSpatrick     switch (TM.getCodeModel()) {
193097a140dSpatrick     default:
194097a140dSpatrick       llvm_unreachable("Unsupported absolute code model");
195097a140dSpatrick     case CodeModel::Small:
196097a140dSpatrick     case CodeModel::Medium:
197097a140dSpatrick     case CodeModel::Large:
198097a140dSpatrick       emitHiLo(*OutStreamer, GOTLabel, VEMCExpr::VK_VE_HI32,
199097a140dSpatrick                VEMCExpr::VK_VE_LO32, MCRegOP, OutContext, STI);
200097a140dSpatrick       break;
201097a140dSpatrick     }
202097a140dSpatrick     return;
203097a140dSpatrick   }
204097a140dSpatrick 
205097a140dSpatrick   MCOperand RegGOT = MCOperand::createReg(VE::SX15); // GOT
206097a140dSpatrick   MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
207097a140dSpatrick 
208097a140dSpatrick   // lea %got, _GLOBAL_OFFSET_TABLE_@PC_LO(-24)
209097a140dSpatrick   // and %got, %got, (32)0
210097a140dSpatrick   // sic %plt
21173471bf0Spatrick   // lea.sl %got, _GLOBAL_OFFSET_TABLE_@PC_HI(%plt, %got)
212097a140dSpatrick   MCOperand cim24 = MCOperand::createImm(-24);
213097a140dSpatrick   MCOperand loImm =
214097a140dSpatrick       createGOTRelExprOp(VEMCExpr::VK_VE_PC_LO32, GOTLabel, OutContext);
215097a140dSpatrick   emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);
216097a140dSpatrick   MCOperand M032 = MCOperand::createImm(M0(32));
217097a140dSpatrick   emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);
218097a140dSpatrick   emitSIC(*OutStreamer, RegPLT, STI);
219097a140dSpatrick   MCOperand hiImm =
220097a140dSpatrick       createGOTRelExprOp(VEMCExpr::VK_VE_PC_HI32, GOTLabel, OutContext);
221097a140dSpatrick   emitLEASLrri(*OutStreamer, RegGOT, RegPLT, hiImm, MCRegOP, STI);
222097a140dSpatrick }
223097a140dSpatrick 
lowerGETFunPLTAndEmitMCInsts(const MachineInstr * MI,const MCSubtargetInfo & STI)224097a140dSpatrick void VEAsmPrinter::lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,
225097a140dSpatrick                                                 const MCSubtargetInfo &STI) {
226097a140dSpatrick   const MachineOperand &MO = MI->getOperand(0);
227097a140dSpatrick   MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
228097a140dSpatrick   const MachineOperand &Addr = MI->getOperand(1);
229097a140dSpatrick   MCSymbol *AddrSym = nullptr;
230097a140dSpatrick 
231097a140dSpatrick   switch (Addr.getType()) {
232097a140dSpatrick   default:
233097a140dSpatrick     llvm_unreachable("<unknown operand type>");
234097a140dSpatrick     return;
235097a140dSpatrick   case MachineOperand::MO_MachineBasicBlock:
236097a140dSpatrick     report_fatal_error("MBB is not supported yet");
237097a140dSpatrick     return;
238097a140dSpatrick   case MachineOperand::MO_ConstantPoolIndex:
239097a140dSpatrick     report_fatal_error("ConstantPool is not supported yet");
240097a140dSpatrick     return;
241097a140dSpatrick   case MachineOperand::MO_ExternalSymbol:
242097a140dSpatrick     AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
243097a140dSpatrick     break;
244097a140dSpatrick   case MachineOperand::MO_GlobalAddress:
245097a140dSpatrick     AddrSym = getSymbol(Addr.getGlobal());
246097a140dSpatrick     break;
247097a140dSpatrick   }
248097a140dSpatrick 
249097a140dSpatrick   if (!isPositionIndependent()) {
250097a140dSpatrick     llvm_unreachable("Unsupported uses of %plt in not PIC code");
251097a140dSpatrick     return;
252097a140dSpatrick   }
253097a140dSpatrick 
254097a140dSpatrick   MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
255097a140dSpatrick 
25673471bf0Spatrick   // lea %dst, func@plt_lo(-24)
257097a140dSpatrick   // and %dst, %dst, (32)0
258097a140dSpatrick   // sic %plt                            ; FIXME: is it safe to use %plt here?
25973471bf0Spatrick   // lea.sl %dst, func@plt_hi(%plt, %dst)
260097a140dSpatrick   MCOperand cim24 = MCOperand::createImm(-24);
261097a140dSpatrick   MCOperand loImm =
262097a140dSpatrick       createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, AddrSym, OutContext);
263097a140dSpatrick   emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);
264097a140dSpatrick   MCOperand M032 = MCOperand::createImm(M0(32));
265097a140dSpatrick   emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);
266097a140dSpatrick   emitSIC(*OutStreamer, RegPLT, STI);
267097a140dSpatrick   MCOperand hiImm =
268097a140dSpatrick       createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, AddrSym, OutContext);
269097a140dSpatrick   emitLEASLrri(*OutStreamer, MCRegOP, RegPLT, hiImm, MCRegOP, STI);
270097a140dSpatrick }
271097a140dSpatrick 
lowerGETTLSAddrAndEmitMCInsts(const MachineInstr * MI,const MCSubtargetInfo & STI)272097a140dSpatrick void VEAsmPrinter::lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,
273097a140dSpatrick                                                  const MCSubtargetInfo &STI) {
274097a140dSpatrick   const MachineOperand &Addr = MI->getOperand(0);
275097a140dSpatrick   MCSymbol *AddrSym = nullptr;
276097a140dSpatrick 
277097a140dSpatrick   switch (Addr.getType()) {
278097a140dSpatrick   default:
279097a140dSpatrick     llvm_unreachable("<unknown operand type>");
280097a140dSpatrick     return;
281097a140dSpatrick   case MachineOperand::MO_MachineBasicBlock:
282097a140dSpatrick     report_fatal_error("MBB is not supported yet");
283097a140dSpatrick     return;
284097a140dSpatrick   case MachineOperand::MO_ConstantPoolIndex:
285097a140dSpatrick     report_fatal_error("ConstantPool is not supported yet");
286097a140dSpatrick     return;
287097a140dSpatrick   case MachineOperand::MO_ExternalSymbol:
288097a140dSpatrick     AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
289097a140dSpatrick     break;
290097a140dSpatrick   case MachineOperand::MO_GlobalAddress:
291097a140dSpatrick     AddrSym = getSymbol(Addr.getGlobal());
292097a140dSpatrick     break;
293097a140dSpatrick   }
294097a140dSpatrick 
295097a140dSpatrick   MCOperand RegLR = MCOperand::createReg(VE::SX10);  // LR
296097a140dSpatrick   MCOperand RegS0 = MCOperand::createReg(VE::SX0);   // S0
297097a140dSpatrick   MCOperand RegS12 = MCOperand::createReg(VE::SX12); // S12
298097a140dSpatrick   MCSymbol *GetTLSLabel = OutContext.getOrCreateSymbol(Twine("__tls_get_addr"));
299097a140dSpatrick 
300097a140dSpatrick   // lea %s0, sym@tls_gd_lo(-24)
301097a140dSpatrick   // and %s0, %s0, (32)0
302097a140dSpatrick   // sic %lr
30373471bf0Spatrick   // lea.sl %s0, sym@tls_gd_hi(%lr, %s0)
304097a140dSpatrick   // lea %s12, __tls_get_addr@plt_lo(8)
305097a140dSpatrick   // and %s12, %s12, (32)0
306097a140dSpatrick   // lea.sl %s12, __tls_get_addr@plt_hi(%s12, %lr)
307097a140dSpatrick   // bsic %lr, (, %s12)
308097a140dSpatrick   MCOperand cim24 = MCOperand::createImm(-24);
309097a140dSpatrick   MCOperand loImm =
310097a140dSpatrick       createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_LO32, AddrSym, OutContext);
311097a140dSpatrick   emitLEAzii(*OutStreamer, cim24, loImm, RegS0, STI);
312097a140dSpatrick   MCOperand M032 = MCOperand::createImm(M0(32));
313097a140dSpatrick   emitANDrm(*OutStreamer, RegS0, M032, RegS0, STI);
314097a140dSpatrick   emitSIC(*OutStreamer, RegLR, STI);
315097a140dSpatrick   MCOperand hiImm =
316097a140dSpatrick       createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_HI32, AddrSym, OutContext);
317097a140dSpatrick   emitLEASLrri(*OutStreamer, RegS0, RegLR, hiImm, RegS0, STI);
318097a140dSpatrick   MCOperand ci8 = MCOperand::createImm(8);
319097a140dSpatrick   MCOperand loImm2 =
320097a140dSpatrick       createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, GetTLSLabel, OutContext);
321097a140dSpatrick   emitLEAzii(*OutStreamer, ci8, loImm2, RegS12, STI);
322097a140dSpatrick   emitANDrm(*OutStreamer, RegS12, M032, RegS12, STI);
323097a140dSpatrick   MCOperand hiImm2 =
324097a140dSpatrick       createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, GetTLSLabel, OutContext);
325097a140dSpatrick   emitLEASLrri(*OutStreamer, RegS12, RegLR, hiImm2, RegS12, STI);
326097a140dSpatrick   emitBSIC(*OutStreamer, RegLR, RegS12, STI);
327097a140dSpatrick }
328097a140dSpatrick 
emitInstruction(const MachineInstr * MI)329097a140dSpatrick void VEAsmPrinter::emitInstruction(const MachineInstr *MI) {
330*d415bd75Srobert   VE_MC::verifyInstructionPredicates(MI->getOpcode(),
331*d415bd75Srobert                                      getSubtargetInfo().getFeatureBits());
33209467b48Spatrick 
33309467b48Spatrick   switch (MI->getOpcode()) {
33409467b48Spatrick   default:
33509467b48Spatrick     break;
33609467b48Spatrick   case TargetOpcode::DBG_VALUE:
33709467b48Spatrick     // FIXME: Debug Value.
33809467b48Spatrick     return;
339097a140dSpatrick   case VE::GETGOT:
340097a140dSpatrick     lowerGETGOTAndEmitMCInsts(MI, getSubtargetInfo());
341097a140dSpatrick     return;
342097a140dSpatrick   case VE::GETFUNPLT:
343097a140dSpatrick     lowerGETFunPLTAndEmitMCInsts(MI, getSubtargetInfo());
344097a140dSpatrick     return;
345097a140dSpatrick   case VE::GETTLSADDR:
346097a140dSpatrick     lowerGETTLSAddrAndEmitMCInsts(MI, getSubtargetInfo());
347097a140dSpatrick     return;
34809467b48Spatrick   }
349097a140dSpatrick 
35009467b48Spatrick   MachineBasicBlock::const_instr_iterator I = MI->getIterator();
35109467b48Spatrick   MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
35209467b48Spatrick   do {
35309467b48Spatrick     MCInst TmpInst;
35409467b48Spatrick     LowerVEMachineInstrToMCInst(&*I, TmpInst, *this);
35509467b48Spatrick     EmitToStreamer(*OutStreamer, TmpInst);
35609467b48Spatrick   } while ((++I != E) && I->isInsideBundle()); // Delay slot check.
35709467b48Spatrick }
35809467b48Spatrick 
printOperand(const MachineInstr * MI,int OpNum,raw_ostream & O)35973471bf0Spatrick void VEAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
36073471bf0Spatrick                                 raw_ostream &O) {
36173471bf0Spatrick   const MachineOperand &MO = MI->getOperand(OpNum);
36273471bf0Spatrick 
36373471bf0Spatrick   switch (MO.getType()) {
36473471bf0Spatrick   case MachineOperand::MO_Register:
36573471bf0Spatrick     O << "%" << StringRef(getRegisterName(MO.getReg())).lower();
36673471bf0Spatrick     break;
367*d415bd75Srobert   case MachineOperand::MO_Immediate:
368*d415bd75Srobert     O << (int)MO.getImm();
369*d415bd75Srobert     break;
37073471bf0Spatrick   default:
37173471bf0Spatrick     llvm_unreachable("<unknown operand type>");
37273471bf0Spatrick   }
37373471bf0Spatrick }
37473471bf0Spatrick 
37573471bf0Spatrick // PrintAsmOperand - Print out an operand for an inline asm expression.
PrintAsmOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & O)37673471bf0Spatrick bool VEAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
37773471bf0Spatrick                                    const char *ExtraCode, raw_ostream &O) {
37873471bf0Spatrick   if (ExtraCode && ExtraCode[0]) {
37973471bf0Spatrick     if (ExtraCode[1] != 0)
38073471bf0Spatrick       return true; // Unknown modifier.
38173471bf0Spatrick 
38273471bf0Spatrick     switch (ExtraCode[0]) {
38373471bf0Spatrick     default:
38473471bf0Spatrick       // See if this is a generic print operand
38573471bf0Spatrick       return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
38673471bf0Spatrick     case 'r':
38773471bf0Spatrick     case 'v':
38873471bf0Spatrick       break;
38973471bf0Spatrick     }
39073471bf0Spatrick   }
39173471bf0Spatrick 
39273471bf0Spatrick   printOperand(MI, OpNo, O);
39373471bf0Spatrick 
39473471bf0Spatrick   return false;
39573471bf0Spatrick }
39673471bf0Spatrick 
PrintAsmMemoryOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & O)397*d415bd75Srobert bool VEAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
398*d415bd75Srobert                                          const char *ExtraCode,
399*d415bd75Srobert                                          raw_ostream &O) {
400*d415bd75Srobert   if (ExtraCode && ExtraCode[0])
401*d415bd75Srobert     return true;  // Unknown modifier
402*d415bd75Srobert 
403*d415bd75Srobert   if (MI->getOperand(OpNo+1).isImm() &&
404*d415bd75Srobert       MI->getOperand(OpNo+1).getImm() == 0) {
405*d415bd75Srobert     // don't print "+0"
406*d415bd75Srobert   } else {
407*d415bd75Srobert     printOperand(MI, OpNo+1, O);
408*d415bd75Srobert   }
409*d415bd75Srobert   if (MI->getOperand(OpNo).isImm() &&
410*d415bd75Srobert       MI->getOperand(OpNo).getImm() == 0) {
411*d415bd75Srobert     if (MI->getOperand(OpNo+1).isImm() &&
412*d415bd75Srobert         MI->getOperand(OpNo+1).getImm() == 0) {
413*d415bd75Srobert       O << "0";
414*d415bd75Srobert     } else {
415*d415bd75Srobert       // don't print "(0)"
416*d415bd75Srobert     }
417*d415bd75Srobert   } else {
418*d415bd75Srobert     O << "(";
419*d415bd75Srobert     printOperand(MI, OpNo, O);
420*d415bd75Srobert     O << ")";
421*d415bd75Srobert   }
422*d415bd75Srobert   return false;
423*d415bd75Srobert }
424*d415bd75Srobert 
42509467b48Spatrick // Force static initialization.
LLVMInitializeVEAsmPrinter()42673471bf0Spatrick extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeVEAsmPrinter() {
42709467b48Spatrick   RegisterAsmPrinter<VEAsmPrinter> X(getTheVETarget());
42809467b48Spatrick }
429