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