xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/VE/VEAsmPrinter.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
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 
145ffd83dbSDimitry Andric #include "MCTargetDesc/VEInstPrinter.h"
155ffd83dbSDimitry Andric #include "MCTargetDesc/VEMCExpr.h"
16480093f4SDimitry Andric #include "MCTargetDesc/VETargetStreamer.h"
175ffd83dbSDimitry 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 
515ffd83dbSDimitry Andric   void lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,
525ffd83dbSDimitry Andric                                  const MCSubtargetInfo &STI);
535ffd83dbSDimitry Andric   void lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,
545ffd83dbSDimitry Andric                                     const MCSubtargetInfo &STI);
555ffd83dbSDimitry Andric   void lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,
565ffd83dbSDimitry Andric                                      const MCSubtargetInfo &STI);
575ffd83dbSDimitry Andric 
585ffd83dbSDimitry 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   }
63*e8d8bef9SDimitry Andric   void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &OS);
64*e8d8bef9SDimitry Andric   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
65*e8d8bef9SDimitry Andric                        const char *ExtraCode, raw_ostream &O) override;
66480093f4SDimitry Andric };
67480093f4SDimitry Andric } // end of anonymous namespace
68480093f4SDimitry Andric 
695ffd83dbSDimitry Andric static MCOperand createVEMCOperand(VEMCExpr::VariantKind Kind, MCSymbol *Sym,
705ffd83dbSDimitry Andric                                    MCContext &OutContext) {
715ffd83dbSDimitry Andric   const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym, OutContext);
725ffd83dbSDimitry Andric   const VEMCExpr *expr = VEMCExpr::create(Kind, MCSym, OutContext);
735ffd83dbSDimitry Andric   return MCOperand::createExpr(expr);
745ffd83dbSDimitry Andric }
755ffd83dbSDimitry Andric 
765ffd83dbSDimitry Andric static MCOperand createGOTRelExprOp(VEMCExpr::VariantKind Kind,
775ffd83dbSDimitry Andric                                     MCSymbol *GOTLabel, MCContext &OutContext) {
785ffd83dbSDimitry Andric   const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext);
795ffd83dbSDimitry Andric   const VEMCExpr *expr = VEMCExpr::create(Kind, GOT, OutContext);
805ffd83dbSDimitry Andric   return MCOperand::createExpr(expr);
815ffd83dbSDimitry Andric }
825ffd83dbSDimitry Andric 
835ffd83dbSDimitry Andric static void emitSIC(MCStreamer &OutStreamer, MCOperand &RD,
845ffd83dbSDimitry Andric                     const MCSubtargetInfo &STI) {
855ffd83dbSDimitry Andric   MCInst SICInst;
865ffd83dbSDimitry Andric   SICInst.setOpcode(VE::SIC);
875ffd83dbSDimitry Andric   SICInst.addOperand(RD);
885ffd83dbSDimitry Andric   OutStreamer.emitInstruction(SICInst, STI);
895ffd83dbSDimitry Andric }
905ffd83dbSDimitry Andric 
915ffd83dbSDimitry Andric static void emitBSIC(MCStreamer &OutStreamer, MCOperand &R1, MCOperand &R2,
925ffd83dbSDimitry Andric                      const MCSubtargetInfo &STI) {
935ffd83dbSDimitry Andric   MCInst BSICInst;
945ffd83dbSDimitry Andric   BSICInst.setOpcode(VE::BSICrii);
955ffd83dbSDimitry Andric   BSICInst.addOperand(R1);
965ffd83dbSDimitry Andric   BSICInst.addOperand(R2);
975ffd83dbSDimitry Andric   MCOperand czero = MCOperand::createImm(0);
985ffd83dbSDimitry Andric   BSICInst.addOperand(czero);
995ffd83dbSDimitry Andric   BSICInst.addOperand(czero);
1005ffd83dbSDimitry Andric   OutStreamer.emitInstruction(BSICInst, STI);
1015ffd83dbSDimitry Andric }
1025ffd83dbSDimitry Andric 
1035ffd83dbSDimitry Andric static void emitLEAzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
1045ffd83dbSDimitry Andric                        const MCSubtargetInfo &STI) {
1055ffd83dbSDimitry Andric   MCInst LEAInst;
1065ffd83dbSDimitry Andric   LEAInst.setOpcode(VE::LEAzii);
1075ffd83dbSDimitry Andric   LEAInst.addOperand(RD);
1085ffd83dbSDimitry Andric   MCOperand CZero = MCOperand::createImm(0);
1095ffd83dbSDimitry Andric   LEAInst.addOperand(CZero);
1105ffd83dbSDimitry Andric   LEAInst.addOperand(CZero);
1115ffd83dbSDimitry Andric   LEAInst.addOperand(Imm);
1125ffd83dbSDimitry Andric   OutStreamer.emitInstruction(LEAInst, STI);
1135ffd83dbSDimitry Andric }
1145ffd83dbSDimitry Andric 
1155ffd83dbSDimitry Andric static void emitLEASLzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
1165ffd83dbSDimitry Andric                          const MCSubtargetInfo &STI) {
1175ffd83dbSDimitry Andric   MCInst LEASLInst;
1185ffd83dbSDimitry Andric   LEASLInst.setOpcode(VE::LEASLzii);
1195ffd83dbSDimitry Andric   LEASLInst.addOperand(RD);
1205ffd83dbSDimitry Andric   MCOperand CZero = MCOperand::createImm(0);
1215ffd83dbSDimitry Andric   LEASLInst.addOperand(CZero);
1225ffd83dbSDimitry Andric   LEASLInst.addOperand(CZero);
1235ffd83dbSDimitry Andric   LEASLInst.addOperand(Imm);
1245ffd83dbSDimitry Andric   OutStreamer.emitInstruction(LEASLInst, STI);
1255ffd83dbSDimitry Andric }
1265ffd83dbSDimitry Andric 
1275ffd83dbSDimitry Andric static void emitLEAzii(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,
1285ffd83dbSDimitry Andric                        MCOperand &RD, const MCSubtargetInfo &STI) {
1295ffd83dbSDimitry Andric   MCInst LEAInst;
1305ffd83dbSDimitry Andric   LEAInst.setOpcode(VE::LEAzii);
1315ffd83dbSDimitry Andric   LEAInst.addOperand(RD);
1325ffd83dbSDimitry Andric   MCOperand CZero = MCOperand::createImm(0);
1335ffd83dbSDimitry Andric   LEAInst.addOperand(CZero);
1345ffd83dbSDimitry Andric   LEAInst.addOperand(RS1);
1355ffd83dbSDimitry Andric   LEAInst.addOperand(Imm);
1365ffd83dbSDimitry Andric   OutStreamer.emitInstruction(LEAInst, STI);
1375ffd83dbSDimitry Andric }
1385ffd83dbSDimitry Andric 
1395ffd83dbSDimitry Andric static void emitLEASLrri(MCStreamer &OutStreamer, MCOperand &RS1,
1405ffd83dbSDimitry Andric                          MCOperand &RS2, MCOperand &Imm, MCOperand &RD,
1415ffd83dbSDimitry Andric                          const MCSubtargetInfo &STI) {
1425ffd83dbSDimitry Andric   MCInst LEASLInst;
1435ffd83dbSDimitry Andric   LEASLInst.setOpcode(VE::LEASLrri);
1445ffd83dbSDimitry Andric   LEASLInst.addOperand(RD);
1455ffd83dbSDimitry Andric   LEASLInst.addOperand(RS1);
1465ffd83dbSDimitry Andric   LEASLInst.addOperand(RS2);
1475ffd83dbSDimitry Andric   LEASLInst.addOperand(Imm);
1485ffd83dbSDimitry Andric   OutStreamer.emitInstruction(LEASLInst, STI);
1495ffd83dbSDimitry Andric }
1505ffd83dbSDimitry Andric 
1515ffd83dbSDimitry Andric static void emitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1,
1525ffd83dbSDimitry Andric                        MCOperand &Src2, MCOperand &RD,
1535ffd83dbSDimitry Andric                        const MCSubtargetInfo &STI) {
1545ffd83dbSDimitry Andric   MCInst Inst;
1555ffd83dbSDimitry Andric   Inst.setOpcode(Opcode);
1565ffd83dbSDimitry Andric   Inst.addOperand(RD);
1575ffd83dbSDimitry Andric   Inst.addOperand(RS1);
1585ffd83dbSDimitry Andric   Inst.addOperand(Src2);
1595ffd83dbSDimitry Andric   OutStreamer.emitInstruction(Inst, STI);
1605ffd83dbSDimitry Andric }
1615ffd83dbSDimitry Andric 
1625ffd83dbSDimitry Andric static void emitANDrm(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,
1635ffd83dbSDimitry Andric                       MCOperand &RD, const MCSubtargetInfo &STI) {
1645ffd83dbSDimitry Andric   emitBinary(OutStreamer, VE::ANDrm, RS1, Imm, RD, STI);
1655ffd83dbSDimitry Andric }
1665ffd83dbSDimitry Andric 
1675ffd83dbSDimitry Andric static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym,
1685ffd83dbSDimitry Andric                      VEMCExpr::VariantKind HiKind, VEMCExpr::VariantKind LoKind,
1695ffd83dbSDimitry Andric                      MCOperand &RD, MCContext &OutContext,
1705ffd83dbSDimitry Andric                      const MCSubtargetInfo &STI) {
1715ffd83dbSDimitry Andric 
1725ffd83dbSDimitry Andric   MCOperand hi = createVEMCOperand(HiKind, GOTSym, OutContext);
1735ffd83dbSDimitry Andric   MCOperand lo = createVEMCOperand(LoKind, GOTSym, OutContext);
1745ffd83dbSDimitry Andric   emitLEAzzi(OutStreamer, lo, RD, STI);
1755ffd83dbSDimitry Andric   MCOperand M032 = MCOperand::createImm(M0(32));
1765ffd83dbSDimitry Andric   emitANDrm(OutStreamer, RD, M032, RD, STI);
1775ffd83dbSDimitry Andric   emitLEASLzzi(OutStreamer, hi, RD, STI);
1785ffd83dbSDimitry Andric }
1795ffd83dbSDimitry Andric 
1805ffd83dbSDimitry Andric void VEAsmPrinter::lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,
1815ffd83dbSDimitry Andric                                              const MCSubtargetInfo &STI) {
1825ffd83dbSDimitry Andric   MCSymbol *GOTLabel =
1835ffd83dbSDimitry Andric       OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
1845ffd83dbSDimitry Andric 
1855ffd83dbSDimitry Andric   const MachineOperand &MO = MI->getOperand(0);
1865ffd83dbSDimitry Andric   MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
1875ffd83dbSDimitry Andric 
1885ffd83dbSDimitry Andric   if (!isPositionIndependent()) {
1895ffd83dbSDimitry Andric     // Just load the address of GOT to MCRegOP.
1905ffd83dbSDimitry Andric     switch (TM.getCodeModel()) {
1915ffd83dbSDimitry Andric     default:
1925ffd83dbSDimitry Andric       llvm_unreachable("Unsupported absolute code model");
1935ffd83dbSDimitry Andric     case CodeModel::Small:
1945ffd83dbSDimitry Andric     case CodeModel::Medium:
1955ffd83dbSDimitry Andric     case CodeModel::Large:
1965ffd83dbSDimitry Andric       emitHiLo(*OutStreamer, GOTLabel, VEMCExpr::VK_VE_HI32,
1975ffd83dbSDimitry Andric                VEMCExpr::VK_VE_LO32, MCRegOP, OutContext, STI);
1985ffd83dbSDimitry Andric       break;
1995ffd83dbSDimitry Andric     }
2005ffd83dbSDimitry Andric     return;
2015ffd83dbSDimitry Andric   }
2025ffd83dbSDimitry Andric 
2035ffd83dbSDimitry Andric   MCOperand RegGOT = MCOperand::createReg(VE::SX15); // GOT
2045ffd83dbSDimitry Andric   MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
2055ffd83dbSDimitry Andric 
2065ffd83dbSDimitry Andric   // lea %got, _GLOBAL_OFFSET_TABLE_@PC_LO(-24)
2075ffd83dbSDimitry Andric   // and %got, %got, (32)0
2085ffd83dbSDimitry Andric   // sic %plt
209*e8d8bef9SDimitry Andric   // lea.sl %got, _GLOBAL_OFFSET_TABLE_@PC_HI(%plt, %got)
2105ffd83dbSDimitry Andric   MCOperand cim24 = MCOperand::createImm(-24);
2115ffd83dbSDimitry Andric   MCOperand loImm =
2125ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_PC_LO32, GOTLabel, OutContext);
2135ffd83dbSDimitry Andric   emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);
2145ffd83dbSDimitry Andric   MCOperand M032 = MCOperand::createImm(M0(32));
2155ffd83dbSDimitry Andric   emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);
2165ffd83dbSDimitry Andric   emitSIC(*OutStreamer, RegPLT, STI);
2175ffd83dbSDimitry Andric   MCOperand hiImm =
2185ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_PC_HI32, GOTLabel, OutContext);
2195ffd83dbSDimitry Andric   emitLEASLrri(*OutStreamer, RegGOT, RegPLT, hiImm, MCRegOP, STI);
2205ffd83dbSDimitry Andric }
2215ffd83dbSDimitry Andric 
2225ffd83dbSDimitry Andric void VEAsmPrinter::lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,
2235ffd83dbSDimitry Andric                                                 const MCSubtargetInfo &STI) {
2245ffd83dbSDimitry Andric   const MachineOperand &MO = MI->getOperand(0);
2255ffd83dbSDimitry Andric   MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
2265ffd83dbSDimitry Andric   const MachineOperand &Addr = MI->getOperand(1);
2275ffd83dbSDimitry Andric   MCSymbol *AddrSym = nullptr;
2285ffd83dbSDimitry Andric 
2295ffd83dbSDimitry Andric   switch (Addr.getType()) {
2305ffd83dbSDimitry Andric   default:
2315ffd83dbSDimitry Andric     llvm_unreachable("<unknown operand type>");
2325ffd83dbSDimitry Andric     return;
2335ffd83dbSDimitry Andric   case MachineOperand::MO_MachineBasicBlock:
2345ffd83dbSDimitry Andric     report_fatal_error("MBB is not supported yet");
2355ffd83dbSDimitry Andric     return;
2365ffd83dbSDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
2375ffd83dbSDimitry Andric     report_fatal_error("ConstantPool is not supported yet");
2385ffd83dbSDimitry Andric     return;
2395ffd83dbSDimitry Andric   case MachineOperand::MO_ExternalSymbol:
2405ffd83dbSDimitry Andric     AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
2415ffd83dbSDimitry Andric     break;
2425ffd83dbSDimitry Andric   case MachineOperand::MO_GlobalAddress:
2435ffd83dbSDimitry Andric     AddrSym = getSymbol(Addr.getGlobal());
2445ffd83dbSDimitry Andric     break;
2455ffd83dbSDimitry Andric   }
2465ffd83dbSDimitry Andric 
2475ffd83dbSDimitry Andric   if (!isPositionIndependent()) {
2485ffd83dbSDimitry Andric     llvm_unreachable("Unsupported uses of %plt in not PIC code");
2495ffd83dbSDimitry Andric     return;
2505ffd83dbSDimitry Andric   }
2515ffd83dbSDimitry Andric 
2525ffd83dbSDimitry Andric   MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
2535ffd83dbSDimitry Andric 
254*e8d8bef9SDimitry Andric   // lea %dst, func@plt_lo(-24)
2555ffd83dbSDimitry Andric   // and %dst, %dst, (32)0
2565ffd83dbSDimitry Andric   // sic %plt                            ; FIXME: is it safe to use %plt here?
257*e8d8bef9SDimitry Andric   // lea.sl %dst, func@plt_hi(%plt, %dst)
2585ffd83dbSDimitry Andric   MCOperand cim24 = MCOperand::createImm(-24);
2595ffd83dbSDimitry Andric   MCOperand loImm =
2605ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, AddrSym, OutContext);
2615ffd83dbSDimitry Andric   emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);
2625ffd83dbSDimitry Andric   MCOperand M032 = MCOperand::createImm(M0(32));
2635ffd83dbSDimitry Andric   emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);
2645ffd83dbSDimitry Andric   emitSIC(*OutStreamer, RegPLT, STI);
2655ffd83dbSDimitry Andric   MCOperand hiImm =
2665ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, AddrSym, OutContext);
2675ffd83dbSDimitry Andric   emitLEASLrri(*OutStreamer, MCRegOP, RegPLT, hiImm, MCRegOP, STI);
2685ffd83dbSDimitry Andric }
2695ffd83dbSDimitry Andric 
2705ffd83dbSDimitry Andric void VEAsmPrinter::lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,
2715ffd83dbSDimitry Andric                                                  const MCSubtargetInfo &STI) {
2725ffd83dbSDimitry Andric   const MachineOperand &Addr = MI->getOperand(0);
2735ffd83dbSDimitry Andric   MCSymbol *AddrSym = nullptr;
2745ffd83dbSDimitry Andric 
2755ffd83dbSDimitry Andric   switch (Addr.getType()) {
2765ffd83dbSDimitry Andric   default:
2775ffd83dbSDimitry Andric     llvm_unreachable("<unknown operand type>");
2785ffd83dbSDimitry Andric     return;
2795ffd83dbSDimitry Andric   case MachineOperand::MO_MachineBasicBlock:
2805ffd83dbSDimitry Andric     report_fatal_error("MBB is not supported yet");
2815ffd83dbSDimitry Andric     return;
2825ffd83dbSDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
2835ffd83dbSDimitry Andric     report_fatal_error("ConstantPool is not supported yet");
2845ffd83dbSDimitry Andric     return;
2855ffd83dbSDimitry Andric   case MachineOperand::MO_ExternalSymbol:
2865ffd83dbSDimitry Andric     AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
2875ffd83dbSDimitry Andric     break;
2885ffd83dbSDimitry Andric   case MachineOperand::MO_GlobalAddress:
2895ffd83dbSDimitry Andric     AddrSym = getSymbol(Addr.getGlobal());
2905ffd83dbSDimitry Andric     break;
2915ffd83dbSDimitry Andric   }
2925ffd83dbSDimitry Andric 
2935ffd83dbSDimitry Andric   MCOperand RegLR = MCOperand::createReg(VE::SX10);  // LR
2945ffd83dbSDimitry Andric   MCOperand RegS0 = MCOperand::createReg(VE::SX0);   // S0
2955ffd83dbSDimitry Andric   MCOperand RegS12 = MCOperand::createReg(VE::SX12); // S12
2965ffd83dbSDimitry Andric   MCSymbol *GetTLSLabel = OutContext.getOrCreateSymbol(Twine("__tls_get_addr"));
2975ffd83dbSDimitry Andric 
2985ffd83dbSDimitry Andric   // lea %s0, sym@tls_gd_lo(-24)
2995ffd83dbSDimitry Andric   // and %s0, %s0, (32)0
3005ffd83dbSDimitry Andric   // sic %lr
301*e8d8bef9SDimitry Andric   // lea.sl %s0, sym@tls_gd_hi(%lr, %s0)
3025ffd83dbSDimitry Andric   // lea %s12, __tls_get_addr@plt_lo(8)
3035ffd83dbSDimitry Andric   // and %s12, %s12, (32)0
3045ffd83dbSDimitry Andric   // lea.sl %s12, __tls_get_addr@plt_hi(%s12, %lr)
3055ffd83dbSDimitry Andric   // bsic %lr, (, %s12)
3065ffd83dbSDimitry Andric   MCOperand cim24 = MCOperand::createImm(-24);
3075ffd83dbSDimitry Andric   MCOperand loImm =
3085ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_LO32, AddrSym, OutContext);
3095ffd83dbSDimitry Andric   emitLEAzii(*OutStreamer, cim24, loImm, RegS0, STI);
3105ffd83dbSDimitry Andric   MCOperand M032 = MCOperand::createImm(M0(32));
3115ffd83dbSDimitry Andric   emitANDrm(*OutStreamer, RegS0, M032, RegS0, STI);
3125ffd83dbSDimitry Andric   emitSIC(*OutStreamer, RegLR, STI);
3135ffd83dbSDimitry Andric   MCOperand hiImm =
3145ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_HI32, AddrSym, OutContext);
3155ffd83dbSDimitry Andric   emitLEASLrri(*OutStreamer, RegS0, RegLR, hiImm, RegS0, STI);
3165ffd83dbSDimitry Andric   MCOperand ci8 = MCOperand::createImm(8);
3175ffd83dbSDimitry Andric   MCOperand loImm2 =
3185ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, GetTLSLabel, OutContext);
3195ffd83dbSDimitry Andric   emitLEAzii(*OutStreamer, ci8, loImm2, RegS12, STI);
3205ffd83dbSDimitry Andric   emitANDrm(*OutStreamer, RegS12, M032, RegS12, STI);
3215ffd83dbSDimitry Andric   MCOperand hiImm2 =
3225ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, GetTLSLabel, OutContext);
3235ffd83dbSDimitry Andric   emitLEASLrri(*OutStreamer, RegS12, RegLR, hiImm2, RegS12, STI);
3245ffd83dbSDimitry Andric   emitBSIC(*OutStreamer, RegLR, RegS12, STI);
3255ffd83dbSDimitry Andric }
3265ffd83dbSDimitry Andric 
3275ffd83dbSDimitry Andric void VEAsmPrinter::emitInstruction(const MachineInstr *MI) {
328480093f4SDimitry Andric 
329480093f4SDimitry Andric   switch (MI->getOpcode()) {
330480093f4SDimitry Andric   default:
331480093f4SDimitry Andric     break;
332480093f4SDimitry Andric   case TargetOpcode::DBG_VALUE:
333480093f4SDimitry Andric     // FIXME: Debug Value.
334480093f4SDimitry Andric     return;
3355ffd83dbSDimitry Andric   case VE::GETGOT:
3365ffd83dbSDimitry Andric     lowerGETGOTAndEmitMCInsts(MI, getSubtargetInfo());
3375ffd83dbSDimitry Andric     return;
3385ffd83dbSDimitry Andric   case VE::GETFUNPLT:
3395ffd83dbSDimitry Andric     lowerGETFunPLTAndEmitMCInsts(MI, getSubtargetInfo());
3405ffd83dbSDimitry Andric     return;
3415ffd83dbSDimitry Andric   case VE::GETTLSADDR:
3425ffd83dbSDimitry Andric     lowerGETTLSAddrAndEmitMCInsts(MI, getSubtargetInfo());
3435ffd83dbSDimitry Andric     return;
344480093f4SDimitry Andric   }
3455ffd83dbSDimitry Andric 
346480093f4SDimitry Andric   MachineBasicBlock::const_instr_iterator I = MI->getIterator();
347480093f4SDimitry Andric   MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
348480093f4SDimitry Andric   do {
349480093f4SDimitry Andric     MCInst TmpInst;
350480093f4SDimitry Andric     LowerVEMachineInstrToMCInst(&*I, TmpInst, *this);
351480093f4SDimitry Andric     EmitToStreamer(*OutStreamer, TmpInst);
352480093f4SDimitry Andric   } while ((++I != E) && I->isInsideBundle()); // Delay slot check.
353480093f4SDimitry Andric }
354480093f4SDimitry Andric 
355*e8d8bef9SDimitry Andric void VEAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
356*e8d8bef9SDimitry Andric                                 raw_ostream &O) {
357*e8d8bef9SDimitry Andric   const MachineOperand &MO = MI->getOperand(OpNum);
358*e8d8bef9SDimitry Andric 
359*e8d8bef9SDimitry Andric   switch (MO.getType()) {
360*e8d8bef9SDimitry Andric   case MachineOperand::MO_Register:
361*e8d8bef9SDimitry Andric     O << "%" << StringRef(getRegisterName(MO.getReg())).lower();
362*e8d8bef9SDimitry Andric     break;
363*e8d8bef9SDimitry Andric   default:
364*e8d8bef9SDimitry Andric     llvm_unreachable("<unknown operand type>");
365*e8d8bef9SDimitry Andric   }
366*e8d8bef9SDimitry Andric }
367*e8d8bef9SDimitry Andric 
368*e8d8bef9SDimitry Andric // PrintAsmOperand - Print out an operand for an inline asm expression.
369*e8d8bef9SDimitry Andric bool VEAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
370*e8d8bef9SDimitry Andric                                    const char *ExtraCode, raw_ostream &O) {
371*e8d8bef9SDimitry Andric   if (ExtraCode && ExtraCode[0]) {
372*e8d8bef9SDimitry Andric     if (ExtraCode[1] != 0)
373*e8d8bef9SDimitry Andric       return true; // Unknown modifier.
374*e8d8bef9SDimitry Andric 
375*e8d8bef9SDimitry Andric     switch (ExtraCode[0]) {
376*e8d8bef9SDimitry Andric     default:
377*e8d8bef9SDimitry Andric       // See if this is a generic print operand
378*e8d8bef9SDimitry Andric       return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
379*e8d8bef9SDimitry Andric     case 'r':
380*e8d8bef9SDimitry Andric     case 'v':
381*e8d8bef9SDimitry Andric       break;
382*e8d8bef9SDimitry Andric     }
383*e8d8bef9SDimitry Andric   }
384*e8d8bef9SDimitry Andric 
385*e8d8bef9SDimitry Andric   printOperand(MI, OpNo, O);
386*e8d8bef9SDimitry Andric 
387*e8d8bef9SDimitry Andric   return false;
388*e8d8bef9SDimitry Andric }
389*e8d8bef9SDimitry Andric 
390480093f4SDimitry Andric // Force static initialization.
391*e8d8bef9SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeVEAsmPrinter() {
392480093f4SDimitry Andric   RegisterAsmPrinter<VEAsmPrinter> X(getTheVETarget());
393480093f4SDimitry Andric }
394