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"
33349cc55cSDimitry Andric #include "llvm/MC/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 {
getTargetStreamer()41480093f4SDimitry Andric   VETargetStreamer &getTargetStreamer() {
42480093f4SDimitry Andric     return static_cast<VETargetStreamer &>(*OutStreamer->getTargetStreamer());
43480093f4SDimitry Andric   }
44480093f4SDimitry Andric 
45480093f4SDimitry Andric public:
VEAsmPrinter(TargetMachine & TM,std::unique_ptr<MCStreamer> Streamer)46480093f4SDimitry Andric   explicit VEAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
47480093f4SDimitry Andric       : AsmPrinter(TM, std::move(Streamer)) {}
48480093f4SDimitry Andric 
getPassName() const49480093f4SDimitry 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 
getRegisterName(MCRegister Reg)60*bdd1243dSDimitry Andric   static const char *getRegisterName(MCRegister Reg) {
61*bdd1243dSDimitry Andric     return VEInstPrinter::getRegisterName(Reg);
62480093f4SDimitry Andric   }
63e8d8bef9SDimitry Andric   void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &OS);
64e8d8bef9SDimitry Andric   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
65e8d8bef9SDimitry Andric                        const char *ExtraCode, raw_ostream &O) override;
66*bdd1243dSDimitry Andric   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
67*bdd1243dSDimitry Andric                              const char *ExtraCode, raw_ostream &O) override;
68480093f4SDimitry Andric };
69480093f4SDimitry Andric } // end of anonymous namespace
70480093f4SDimitry Andric 
createVEMCOperand(VEMCExpr::VariantKind Kind,MCSymbol * Sym,MCContext & OutContext)715ffd83dbSDimitry Andric static MCOperand createVEMCOperand(VEMCExpr::VariantKind Kind, MCSymbol *Sym,
725ffd83dbSDimitry Andric                                    MCContext &OutContext) {
735ffd83dbSDimitry Andric   const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym, OutContext);
745ffd83dbSDimitry Andric   const VEMCExpr *expr = VEMCExpr::create(Kind, MCSym, OutContext);
755ffd83dbSDimitry Andric   return MCOperand::createExpr(expr);
765ffd83dbSDimitry Andric }
775ffd83dbSDimitry Andric 
createGOTRelExprOp(VEMCExpr::VariantKind Kind,MCSymbol * GOTLabel,MCContext & OutContext)785ffd83dbSDimitry Andric static MCOperand createGOTRelExprOp(VEMCExpr::VariantKind Kind,
795ffd83dbSDimitry Andric                                     MCSymbol *GOTLabel, MCContext &OutContext) {
805ffd83dbSDimitry Andric   const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext);
815ffd83dbSDimitry Andric   const VEMCExpr *expr = VEMCExpr::create(Kind, GOT, OutContext);
825ffd83dbSDimitry Andric   return MCOperand::createExpr(expr);
835ffd83dbSDimitry Andric }
845ffd83dbSDimitry Andric 
emitSIC(MCStreamer & OutStreamer,MCOperand & RD,const MCSubtargetInfo & STI)855ffd83dbSDimitry Andric static void emitSIC(MCStreamer &OutStreamer, MCOperand &RD,
865ffd83dbSDimitry Andric                     const MCSubtargetInfo &STI) {
875ffd83dbSDimitry Andric   MCInst SICInst;
885ffd83dbSDimitry Andric   SICInst.setOpcode(VE::SIC);
895ffd83dbSDimitry Andric   SICInst.addOperand(RD);
905ffd83dbSDimitry Andric   OutStreamer.emitInstruction(SICInst, STI);
915ffd83dbSDimitry Andric }
925ffd83dbSDimitry Andric 
emitBSIC(MCStreamer & OutStreamer,MCOperand & R1,MCOperand & R2,const MCSubtargetInfo & STI)935ffd83dbSDimitry Andric static void emitBSIC(MCStreamer &OutStreamer, MCOperand &R1, MCOperand &R2,
945ffd83dbSDimitry Andric                      const MCSubtargetInfo &STI) {
955ffd83dbSDimitry Andric   MCInst BSICInst;
965ffd83dbSDimitry Andric   BSICInst.setOpcode(VE::BSICrii);
975ffd83dbSDimitry Andric   BSICInst.addOperand(R1);
985ffd83dbSDimitry Andric   BSICInst.addOperand(R2);
995ffd83dbSDimitry Andric   MCOperand czero = MCOperand::createImm(0);
1005ffd83dbSDimitry Andric   BSICInst.addOperand(czero);
1015ffd83dbSDimitry Andric   BSICInst.addOperand(czero);
1025ffd83dbSDimitry Andric   OutStreamer.emitInstruction(BSICInst, STI);
1035ffd83dbSDimitry Andric }
1045ffd83dbSDimitry Andric 
emitLEAzzi(MCStreamer & OutStreamer,MCOperand & Imm,MCOperand & RD,const MCSubtargetInfo & STI)1055ffd83dbSDimitry Andric static void emitLEAzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
1065ffd83dbSDimitry Andric                        const MCSubtargetInfo &STI) {
1075ffd83dbSDimitry Andric   MCInst LEAInst;
1085ffd83dbSDimitry Andric   LEAInst.setOpcode(VE::LEAzii);
1095ffd83dbSDimitry Andric   LEAInst.addOperand(RD);
1105ffd83dbSDimitry Andric   MCOperand CZero = MCOperand::createImm(0);
1115ffd83dbSDimitry Andric   LEAInst.addOperand(CZero);
1125ffd83dbSDimitry Andric   LEAInst.addOperand(CZero);
1135ffd83dbSDimitry Andric   LEAInst.addOperand(Imm);
1145ffd83dbSDimitry Andric   OutStreamer.emitInstruction(LEAInst, STI);
1155ffd83dbSDimitry Andric }
1165ffd83dbSDimitry Andric 
emitLEASLzzi(MCStreamer & OutStreamer,MCOperand & Imm,MCOperand & RD,const MCSubtargetInfo & STI)1175ffd83dbSDimitry Andric static void emitLEASLzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
1185ffd83dbSDimitry Andric                          const MCSubtargetInfo &STI) {
1195ffd83dbSDimitry Andric   MCInst LEASLInst;
1205ffd83dbSDimitry Andric   LEASLInst.setOpcode(VE::LEASLzii);
1215ffd83dbSDimitry Andric   LEASLInst.addOperand(RD);
1225ffd83dbSDimitry Andric   MCOperand CZero = MCOperand::createImm(0);
1235ffd83dbSDimitry Andric   LEASLInst.addOperand(CZero);
1245ffd83dbSDimitry Andric   LEASLInst.addOperand(CZero);
1255ffd83dbSDimitry Andric   LEASLInst.addOperand(Imm);
1265ffd83dbSDimitry Andric   OutStreamer.emitInstruction(LEASLInst, STI);
1275ffd83dbSDimitry Andric }
1285ffd83dbSDimitry Andric 
emitLEAzii(MCStreamer & OutStreamer,MCOperand & RS1,MCOperand & Imm,MCOperand & RD,const MCSubtargetInfo & STI)1295ffd83dbSDimitry Andric static void emitLEAzii(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,
1305ffd83dbSDimitry Andric                        MCOperand &RD, const MCSubtargetInfo &STI) {
1315ffd83dbSDimitry Andric   MCInst LEAInst;
1325ffd83dbSDimitry Andric   LEAInst.setOpcode(VE::LEAzii);
1335ffd83dbSDimitry Andric   LEAInst.addOperand(RD);
1345ffd83dbSDimitry Andric   MCOperand CZero = MCOperand::createImm(0);
1355ffd83dbSDimitry Andric   LEAInst.addOperand(CZero);
1365ffd83dbSDimitry Andric   LEAInst.addOperand(RS1);
1375ffd83dbSDimitry Andric   LEAInst.addOperand(Imm);
1385ffd83dbSDimitry Andric   OutStreamer.emitInstruction(LEAInst, STI);
1395ffd83dbSDimitry Andric }
1405ffd83dbSDimitry Andric 
emitLEASLrri(MCStreamer & OutStreamer,MCOperand & RS1,MCOperand & RS2,MCOperand & Imm,MCOperand & RD,const MCSubtargetInfo & STI)1415ffd83dbSDimitry Andric static void emitLEASLrri(MCStreamer &OutStreamer, MCOperand &RS1,
1425ffd83dbSDimitry Andric                          MCOperand &RS2, MCOperand &Imm, MCOperand &RD,
1435ffd83dbSDimitry Andric                          const MCSubtargetInfo &STI) {
1445ffd83dbSDimitry Andric   MCInst LEASLInst;
1455ffd83dbSDimitry Andric   LEASLInst.setOpcode(VE::LEASLrri);
1465ffd83dbSDimitry Andric   LEASLInst.addOperand(RD);
1475ffd83dbSDimitry Andric   LEASLInst.addOperand(RS1);
1485ffd83dbSDimitry Andric   LEASLInst.addOperand(RS2);
1495ffd83dbSDimitry Andric   LEASLInst.addOperand(Imm);
1505ffd83dbSDimitry Andric   OutStreamer.emitInstruction(LEASLInst, STI);
1515ffd83dbSDimitry Andric }
1525ffd83dbSDimitry Andric 
emitBinary(MCStreamer & OutStreamer,unsigned Opcode,MCOperand & RS1,MCOperand & Src2,MCOperand & RD,const MCSubtargetInfo & STI)1535ffd83dbSDimitry Andric static void emitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1,
1545ffd83dbSDimitry Andric                        MCOperand &Src2, MCOperand &RD,
1555ffd83dbSDimitry Andric                        const MCSubtargetInfo &STI) {
1565ffd83dbSDimitry Andric   MCInst Inst;
1575ffd83dbSDimitry Andric   Inst.setOpcode(Opcode);
1585ffd83dbSDimitry Andric   Inst.addOperand(RD);
1595ffd83dbSDimitry Andric   Inst.addOperand(RS1);
1605ffd83dbSDimitry Andric   Inst.addOperand(Src2);
1615ffd83dbSDimitry Andric   OutStreamer.emitInstruction(Inst, STI);
1625ffd83dbSDimitry Andric }
1635ffd83dbSDimitry Andric 
emitANDrm(MCStreamer & OutStreamer,MCOperand & RS1,MCOperand & Imm,MCOperand & RD,const MCSubtargetInfo & STI)1645ffd83dbSDimitry Andric static void emitANDrm(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,
1655ffd83dbSDimitry Andric                       MCOperand &RD, const MCSubtargetInfo &STI) {
1665ffd83dbSDimitry Andric   emitBinary(OutStreamer, VE::ANDrm, RS1, Imm, RD, STI);
1675ffd83dbSDimitry Andric }
1685ffd83dbSDimitry Andric 
emitHiLo(MCStreamer & OutStreamer,MCSymbol * GOTSym,VEMCExpr::VariantKind HiKind,VEMCExpr::VariantKind LoKind,MCOperand & RD,MCContext & OutContext,const MCSubtargetInfo & STI)1695ffd83dbSDimitry Andric static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym,
1705ffd83dbSDimitry Andric                      VEMCExpr::VariantKind HiKind, VEMCExpr::VariantKind LoKind,
1715ffd83dbSDimitry Andric                      MCOperand &RD, MCContext &OutContext,
1725ffd83dbSDimitry Andric                      const MCSubtargetInfo &STI) {
1735ffd83dbSDimitry Andric 
1745ffd83dbSDimitry Andric   MCOperand hi = createVEMCOperand(HiKind, GOTSym, OutContext);
1755ffd83dbSDimitry Andric   MCOperand lo = createVEMCOperand(LoKind, GOTSym, OutContext);
1765ffd83dbSDimitry Andric   emitLEAzzi(OutStreamer, lo, RD, STI);
1775ffd83dbSDimitry Andric   MCOperand M032 = MCOperand::createImm(M0(32));
1785ffd83dbSDimitry Andric   emitANDrm(OutStreamer, RD, M032, RD, STI);
1795ffd83dbSDimitry Andric   emitLEASLzzi(OutStreamer, hi, RD, STI);
1805ffd83dbSDimitry Andric }
1815ffd83dbSDimitry Andric 
lowerGETGOTAndEmitMCInsts(const MachineInstr * MI,const MCSubtargetInfo & STI)1825ffd83dbSDimitry Andric void VEAsmPrinter::lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,
1835ffd83dbSDimitry Andric                                              const MCSubtargetInfo &STI) {
1845ffd83dbSDimitry Andric   MCSymbol *GOTLabel =
1855ffd83dbSDimitry Andric       OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
1865ffd83dbSDimitry Andric 
1875ffd83dbSDimitry Andric   const MachineOperand &MO = MI->getOperand(0);
1885ffd83dbSDimitry Andric   MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
1895ffd83dbSDimitry Andric 
1905ffd83dbSDimitry Andric   if (!isPositionIndependent()) {
1915ffd83dbSDimitry Andric     // Just load the address of GOT to MCRegOP.
1925ffd83dbSDimitry Andric     switch (TM.getCodeModel()) {
1935ffd83dbSDimitry Andric     default:
1945ffd83dbSDimitry Andric       llvm_unreachable("Unsupported absolute code model");
1955ffd83dbSDimitry Andric     case CodeModel::Small:
1965ffd83dbSDimitry Andric     case CodeModel::Medium:
1975ffd83dbSDimitry Andric     case CodeModel::Large:
1985ffd83dbSDimitry Andric       emitHiLo(*OutStreamer, GOTLabel, VEMCExpr::VK_VE_HI32,
1995ffd83dbSDimitry Andric                VEMCExpr::VK_VE_LO32, MCRegOP, OutContext, STI);
2005ffd83dbSDimitry Andric       break;
2015ffd83dbSDimitry Andric     }
2025ffd83dbSDimitry Andric     return;
2035ffd83dbSDimitry Andric   }
2045ffd83dbSDimitry Andric 
2055ffd83dbSDimitry Andric   MCOperand RegGOT = MCOperand::createReg(VE::SX15); // GOT
2065ffd83dbSDimitry Andric   MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
2075ffd83dbSDimitry Andric 
2085ffd83dbSDimitry Andric   // lea %got, _GLOBAL_OFFSET_TABLE_@PC_LO(-24)
2095ffd83dbSDimitry Andric   // and %got, %got, (32)0
2105ffd83dbSDimitry Andric   // sic %plt
211e8d8bef9SDimitry Andric   // lea.sl %got, _GLOBAL_OFFSET_TABLE_@PC_HI(%plt, %got)
2125ffd83dbSDimitry Andric   MCOperand cim24 = MCOperand::createImm(-24);
2135ffd83dbSDimitry Andric   MCOperand loImm =
2145ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_PC_LO32, GOTLabel, OutContext);
2155ffd83dbSDimitry Andric   emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);
2165ffd83dbSDimitry Andric   MCOperand M032 = MCOperand::createImm(M0(32));
2175ffd83dbSDimitry Andric   emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);
2185ffd83dbSDimitry Andric   emitSIC(*OutStreamer, RegPLT, STI);
2195ffd83dbSDimitry Andric   MCOperand hiImm =
2205ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_PC_HI32, GOTLabel, OutContext);
2215ffd83dbSDimitry Andric   emitLEASLrri(*OutStreamer, RegGOT, RegPLT, hiImm, MCRegOP, STI);
2225ffd83dbSDimitry Andric }
2235ffd83dbSDimitry Andric 
lowerGETFunPLTAndEmitMCInsts(const MachineInstr * MI,const MCSubtargetInfo & STI)2245ffd83dbSDimitry Andric void VEAsmPrinter::lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,
2255ffd83dbSDimitry Andric                                                 const MCSubtargetInfo &STI) {
2265ffd83dbSDimitry Andric   const MachineOperand &MO = MI->getOperand(0);
2275ffd83dbSDimitry Andric   MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
2285ffd83dbSDimitry Andric   const MachineOperand &Addr = MI->getOperand(1);
2295ffd83dbSDimitry Andric   MCSymbol *AddrSym = nullptr;
2305ffd83dbSDimitry Andric 
2315ffd83dbSDimitry Andric   switch (Addr.getType()) {
2325ffd83dbSDimitry Andric   default:
2335ffd83dbSDimitry Andric     llvm_unreachable("<unknown operand type>");
2345ffd83dbSDimitry Andric     return;
2355ffd83dbSDimitry Andric   case MachineOperand::MO_MachineBasicBlock:
2365ffd83dbSDimitry Andric     report_fatal_error("MBB is not supported yet");
2375ffd83dbSDimitry Andric     return;
2385ffd83dbSDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
2395ffd83dbSDimitry Andric     report_fatal_error("ConstantPool is not supported yet");
2405ffd83dbSDimitry Andric     return;
2415ffd83dbSDimitry Andric   case MachineOperand::MO_ExternalSymbol:
2425ffd83dbSDimitry Andric     AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
2435ffd83dbSDimitry Andric     break;
2445ffd83dbSDimitry Andric   case MachineOperand::MO_GlobalAddress:
2455ffd83dbSDimitry Andric     AddrSym = getSymbol(Addr.getGlobal());
2465ffd83dbSDimitry Andric     break;
2475ffd83dbSDimitry Andric   }
2485ffd83dbSDimitry Andric 
2495ffd83dbSDimitry Andric   if (!isPositionIndependent()) {
2505ffd83dbSDimitry Andric     llvm_unreachable("Unsupported uses of %plt in not PIC code");
2515ffd83dbSDimitry Andric     return;
2525ffd83dbSDimitry Andric   }
2535ffd83dbSDimitry Andric 
2545ffd83dbSDimitry Andric   MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
2555ffd83dbSDimitry Andric 
256e8d8bef9SDimitry Andric   // lea %dst, func@plt_lo(-24)
2575ffd83dbSDimitry Andric   // and %dst, %dst, (32)0
2585ffd83dbSDimitry Andric   // sic %plt                            ; FIXME: is it safe to use %plt here?
259e8d8bef9SDimitry Andric   // lea.sl %dst, func@plt_hi(%plt, %dst)
2605ffd83dbSDimitry Andric   MCOperand cim24 = MCOperand::createImm(-24);
2615ffd83dbSDimitry Andric   MCOperand loImm =
2625ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, AddrSym, OutContext);
2635ffd83dbSDimitry Andric   emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);
2645ffd83dbSDimitry Andric   MCOperand M032 = MCOperand::createImm(M0(32));
2655ffd83dbSDimitry Andric   emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);
2665ffd83dbSDimitry Andric   emitSIC(*OutStreamer, RegPLT, STI);
2675ffd83dbSDimitry Andric   MCOperand hiImm =
2685ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, AddrSym, OutContext);
2695ffd83dbSDimitry Andric   emitLEASLrri(*OutStreamer, MCRegOP, RegPLT, hiImm, MCRegOP, STI);
2705ffd83dbSDimitry Andric }
2715ffd83dbSDimitry Andric 
lowerGETTLSAddrAndEmitMCInsts(const MachineInstr * MI,const MCSubtargetInfo & STI)2725ffd83dbSDimitry Andric void VEAsmPrinter::lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,
2735ffd83dbSDimitry Andric                                                  const MCSubtargetInfo &STI) {
2745ffd83dbSDimitry Andric   const MachineOperand &Addr = MI->getOperand(0);
2755ffd83dbSDimitry Andric   MCSymbol *AddrSym = nullptr;
2765ffd83dbSDimitry Andric 
2775ffd83dbSDimitry Andric   switch (Addr.getType()) {
2785ffd83dbSDimitry Andric   default:
2795ffd83dbSDimitry Andric     llvm_unreachable("<unknown operand type>");
2805ffd83dbSDimitry Andric     return;
2815ffd83dbSDimitry Andric   case MachineOperand::MO_MachineBasicBlock:
2825ffd83dbSDimitry Andric     report_fatal_error("MBB is not supported yet");
2835ffd83dbSDimitry Andric     return;
2845ffd83dbSDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
2855ffd83dbSDimitry Andric     report_fatal_error("ConstantPool is not supported yet");
2865ffd83dbSDimitry Andric     return;
2875ffd83dbSDimitry Andric   case MachineOperand::MO_ExternalSymbol:
2885ffd83dbSDimitry Andric     AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
2895ffd83dbSDimitry Andric     break;
2905ffd83dbSDimitry Andric   case MachineOperand::MO_GlobalAddress:
2915ffd83dbSDimitry Andric     AddrSym = getSymbol(Addr.getGlobal());
2925ffd83dbSDimitry Andric     break;
2935ffd83dbSDimitry Andric   }
2945ffd83dbSDimitry Andric 
2955ffd83dbSDimitry Andric   MCOperand RegLR = MCOperand::createReg(VE::SX10);  // LR
2965ffd83dbSDimitry Andric   MCOperand RegS0 = MCOperand::createReg(VE::SX0);   // S0
2975ffd83dbSDimitry Andric   MCOperand RegS12 = MCOperand::createReg(VE::SX12); // S12
2985ffd83dbSDimitry Andric   MCSymbol *GetTLSLabel = OutContext.getOrCreateSymbol(Twine("__tls_get_addr"));
2995ffd83dbSDimitry Andric 
3005ffd83dbSDimitry Andric   // lea %s0, sym@tls_gd_lo(-24)
3015ffd83dbSDimitry Andric   // and %s0, %s0, (32)0
3025ffd83dbSDimitry Andric   // sic %lr
303e8d8bef9SDimitry Andric   // lea.sl %s0, sym@tls_gd_hi(%lr, %s0)
3045ffd83dbSDimitry Andric   // lea %s12, __tls_get_addr@plt_lo(8)
3055ffd83dbSDimitry Andric   // and %s12, %s12, (32)0
3065ffd83dbSDimitry Andric   // lea.sl %s12, __tls_get_addr@plt_hi(%s12, %lr)
3075ffd83dbSDimitry Andric   // bsic %lr, (, %s12)
3085ffd83dbSDimitry Andric   MCOperand cim24 = MCOperand::createImm(-24);
3095ffd83dbSDimitry Andric   MCOperand loImm =
3105ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_LO32, AddrSym, OutContext);
3115ffd83dbSDimitry Andric   emitLEAzii(*OutStreamer, cim24, loImm, RegS0, STI);
3125ffd83dbSDimitry Andric   MCOperand M032 = MCOperand::createImm(M0(32));
3135ffd83dbSDimitry Andric   emitANDrm(*OutStreamer, RegS0, M032, RegS0, STI);
3145ffd83dbSDimitry Andric   emitSIC(*OutStreamer, RegLR, STI);
3155ffd83dbSDimitry Andric   MCOperand hiImm =
3165ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_HI32, AddrSym, OutContext);
3175ffd83dbSDimitry Andric   emitLEASLrri(*OutStreamer, RegS0, RegLR, hiImm, RegS0, STI);
3185ffd83dbSDimitry Andric   MCOperand ci8 = MCOperand::createImm(8);
3195ffd83dbSDimitry Andric   MCOperand loImm2 =
3205ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, GetTLSLabel, OutContext);
3215ffd83dbSDimitry Andric   emitLEAzii(*OutStreamer, ci8, loImm2, RegS12, STI);
3225ffd83dbSDimitry Andric   emitANDrm(*OutStreamer, RegS12, M032, RegS12, STI);
3235ffd83dbSDimitry Andric   MCOperand hiImm2 =
3245ffd83dbSDimitry Andric       createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, GetTLSLabel, OutContext);
3255ffd83dbSDimitry Andric   emitLEASLrri(*OutStreamer, RegS12, RegLR, hiImm2, RegS12, STI);
3265ffd83dbSDimitry Andric   emitBSIC(*OutStreamer, RegLR, RegS12, STI);
3275ffd83dbSDimitry Andric }
3285ffd83dbSDimitry Andric 
emitInstruction(const MachineInstr * MI)3295ffd83dbSDimitry Andric void VEAsmPrinter::emitInstruction(const MachineInstr *MI) {
330753f127fSDimitry Andric   VE_MC::verifyInstructionPredicates(MI->getOpcode(),
331753f127fSDimitry Andric                                      getSubtargetInfo().getFeatureBits());
332480093f4SDimitry Andric 
333480093f4SDimitry Andric   switch (MI->getOpcode()) {
334480093f4SDimitry Andric   default:
335480093f4SDimitry Andric     break;
336480093f4SDimitry Andric   case TargetOpcode::DBG_VALUE:
337480093f4SDimitry Andric     // FIXME: Debug Value.
338480093f4SDimitry Andric     return;
3395ffd83dbSDimitry Andric   case VE::GETGOT:
3405ffd83dbSDimitry Andric     lowerGETGOTAndEmitMCInsts(MI, getSubtargetInfo());
3415ffd83dbSDimitry Andric     return;
3425ffd83dbSDimitry Andric   case VE::GETFUNPLT:
3435ffd83dbSDimitry Andric     lowerGETFunPLTAndEmitMCInsts(MI, getSubtargetInfo());
3445ffd83dbSDimitry Andric     return;
3455ffd83dbSDimitry Andric   case VE::GETTLSADDR:
3465ffd83dbSDimitry Andric     lowerGETTLSAddrAndEmitMCInsts(MI, getSubtargetInfo());
3475ffd83dbSDimitry Andric     return;
348480093f4SDimitry Andric   }
3495ffd83dbSDimitry Andric 
350480093f4SDimitry Andric   MachineBasicBlock::const_instr_iterator I = MI->getIterator();
351480093f4SDimitry Andric   MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
352480093f4SDimitry Andric   do {
353480093f4SDimitry Andric     MCInst TmpInst;
354480093f4SDimitry Andric     LowerVEMachineInstrToMCInst(&*I, TmpInst, *this);
355480093f4SDimitry Andric     EmitToStreamer(*OutStreamer, TmpInst);
356480093f4SDimitry Andric   } while ((++I != E) && I->isInsideBundle()); // Delay slot check.
357480093f4SDimitry Andric }
358480093f4SDimitry Andric 
printOperand(const MachineInstr * MI,int OpNum,raw_ostream & O)359e8d8bef9SDimitry Andric void VEAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
360e8d8bef9SDimitry Andric                                 raw_ostream &O) {
361e8d8bef9SDimitry Andric   const MachineOperand &MO = MI->getOperand(OpNum);
362e8d8bef9SDimitry Andric 
363e8d8bef9SDimitry Andric   switch (MO.getType()) {
364e8d8bef9SDimitry Andric   case MachineOperand::MO_Register:
365e8d8bef9SDimitry Andric     O << "%" << StringRef(getRegisterName(MO.getReg())).lower();
366e8d8bef9SDimitry Andric     break;
367*bdd1243dSDimitry Andric   case MachineOperand::MO_Immediate:
368*bdd1243dSDimitry Andric     O << (int)MO.getImm();
369*bdd1243dSDimitry Andric     break;
370e8d8bef9SDimitry Andric   default:
371e8d8bef9SDimitry Andric     llvm_unreachable("<unknown operand type>");
372e8d8bef9SDimitry Andric   }
373e8d8bef9SDimitry Andric }
374e8d8bef9SDimitry Andric 
375e8d8bef9SDimitry Andric // PrintAsmOperand - Print out an operand for an inline asm expression.
PrintAsmOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & O)376e8d8bef9SDimitry Andric bool VEAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
377e8d8bef9SDimitry Andric                                    const char *ExtraCode, raw_ostream &O) {
378e8d8bef9SDimitry Andric   if (ExtraCode && ExtraCode[0]) {
379e8d8bef9SDimitry Andric     if (ExtraCode[1] != 0)
380e8d8bef9SDimitry Andric       return true; // Unknown modifier.
381e8d8bef9SDimitry Andric 
382e8d8bef9SDimitry Andric     switch (ExtraCode[0]) {
383e8d8bef9SDimitry Andric     default:
384e8d8bef9SDimitry Andric       // See if this is a generic print operand
385e8d8bef9SDimitry Andric       return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
386e8d8bef9SDimitry Andric     case 'r':
387e8d8bef9SDimitry Andric     case 'v':
388e8d8bef9SDimitry Andric       break;
389e8d8bef9SDimitry Andric     }
390e8d8bef9SDimitry Andric   }
391e8d8bef9SDimitry Andric 
392e8d8bef9SDimitry Andric   printOperand(MI, OpNo, O);
393e8d8bef9SDimitry Andric 
394e8d8bef9SDimitry Andric   return false;
395e8d8bef9SDimitry Andric }
396e8d8bef9SDimitry Andric 
PrintAsmMemoryOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & O)397*bdd1243dSDimitry Andric bool VEAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
398*bdd1243dSDimitry Andric                                          const char *ExtraCode,
399*bdd1243dSDimitry Andric                                          raw_ostream &O) {
400*bdd1243dSDimitry Andric   if (ExtraCode && ExtraCode[0])
401*bdd1243dSDimitry Andric     return true;  // Unknown modifier
402*bdd1243dSDimitry Andric 
403*bdd1243dSDimitry Andric   if (MI->getOperand(OpNo+1).isImm() &&
404*bdd1243dSDimitry Andric       MI->getOperand(OpNo+1).getImm() == 0) {
405*bdd1243dSDimitry Andric     // don't print "+0"
406*bdd1243dSDimitry Andric   } else {
407*bdd1243dSDimitry Andric     printOperand(MI, OpNo+1, O);
408*bdd1243dSDimitry Andric   }
409*bdd1243dSDimitry Andric   if (MI->getOperand(OpNo).isImm() &&
410*bdd1243dSDimitry Andric       MI->getOperand(OpNo).getImm() == 0) {
411*bdd1243dSDimitry Andric     if (MI->getOperand(OpNo+1).isImm() &&
412*bdd1243dSDimitry Andric         MI->getOperand(OpNo+1).getImm() == 0) {
413*bdd1243dSDimitry Andric       O << "0";
414*bdd1243dSDimitry Andric     } else {
415*bdd1243dSDimitry Andric       // don't print "(0)"
416*bdd1243dSDimitry Andric     }
417*bdd1243dSDimitry Andric   } else {
418*bdd1243dSDimitry Andric     O << "(";
419*bdd1243dSDimitry Andric     printOperand(MI, OpNo, O);
420*bdd1243dSDimitry Andric     O << ")";
421*bdd1243dSDimitry Andric   }
422*bdd1243dSDimitry Andric   return false;
423*bdd1243dSDimitry Andric }
424*bdd1243dSDimitry Andric 
425480093f4SDimitry Andric // Force static initialization.
LLVMInitializeVEAsmPrinter()426e8d8bef9SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeVEAsmPrinter() {
427480093f4SDimitry Andric   RegisterAsmPrinter<VEAsmPrinter> X(getTheVETarget());
428480093f4SDimitry Andric }
429