Home | History | Annotate | Download | only in SystemZ
      1 //===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // Streams SystemZ assembly language and associated data, in the form of
     11 // MCInsts and MCExprs respectively.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "SystemZAsmPrinter.h"
     16 #include "InstPrinter/SystemZInstPrinter.h"
     17 #include "SystemZConstantPoolValue.h"
     18 #include "SystemZMCInstLower.h"
     19 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
     20 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
     21 #include "llvm/IR/Mangler.h"
     22 #include "llvm/MC/MCExpr.h"
     23 #include "llvm/MC/MCInstBuilder.h"
     24 #include "llvm/MC/MCStreamer.h"
     25 #include "llvm/Support/TargetRegistry.h"
     26 
     27 using namespace llvm;
     28 
     29 // Return an RI instruction like MI with opcode Opcode, but with the
     30 // GR64 register operands turned into GR32s.
     31 static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) {
     32   if (MI->isCompare())
     33     return MCInstBuilder(Opcode)
     34       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
     35       .addImm(MI->getOperand(1).getImm());
     36   else
     37     return MCInstBuilder(Opcode)
     38       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
     39       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg()))
     40       .addImm(MI->getOperand(2).getImm());
     41 }
     42 
     43 // Return an RI instruction like MI with opcode Opcode, but with the
     44 // GR64 register operands turned into GRH32s.
     45 static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) {
     46   if (MI->isCompare())
     47     return MCInstBuilder(Opcode)
     48       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
     49       .addImm(MI->getOperand(1).getImm());
     50   else
     51     return MCInstBuilder(Opcode)
     52       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
     53       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg()))
     54       .addImm(MI->getOperand(2).getImm());
     55 }
     56 
     57 // Return an RI instruction like MI with opcode Opcode, but with the
     58 // R2 register turned into a GR64.
     59 static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) {
     60   return MCInstBuilder(Opcode)
     61     .addReg(MI->getOperand(0).getReg())
     62     .addReg(MI->getOperand(1).getReg())
     63     .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()))
     64     .addImm(MI->getOperand(3).getImm())
     65     .addImm(MI->getOperand(4).getImm())
     66     .addImm(MI->getOperand(5).getImm());
     67 }
     68 
     69 static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) {
     70   StringRef Name = "__tls_get_offset";
     71   return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
     72                                  MCSymbolRefExpr::VK_PLT,
     73                                  Context);
     74 }
     75 
     76 static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) {
     77   StringRef Name = "_GLOBAL_OFFSET_TABLE_";
     78   return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
     79                                  MCSymbolRefExpr::VK_None,
     80                                  Context);
     81 }
     82 
     83 // MI loads the high part of a vector from memory.  Return an instruction
     84 // that uses replicating vector load Opcode to do the same thing.
     85 static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) {
     86   return MCInstBuilder(Opcode)
     87     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
     88     .addReg(MI->getOperand(1).getReg())
     89     .addImm(MI->getOperand(2).getImm())
     90     .addReg(MI->getOperand(3).getReg());
     91 }
     92 
     93 // MI stores the high part of a vector to memory.  Return an instruction
     94 // that uses elemental vector store Opcode to do the same thing.
     95 static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) {
     96   return MCInstBuilder(Opcode)
     97     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
     98     .addReg(MI->getOperand(1).getReg())
     99     .addImm(MI->getOperand(2).getImm())
    100     .addReg(MI->getOperand(3).getReg())
    101     .addImm(0);
    102 }
    103 
    104 void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) {
    105   SystemZMCInstLower Lower(MF->getContext(), *this);
    106   MCInst LoweredMI;
    107   switch (MI->getOpcode()) {
    108   case SystemZ::Return:
    109     LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D);
    110     break;
    111 
    112   case SystemZ::CallBRASL:
    113     LoweredMI = MCInstBuilder(SystemZ::BRASL)
    114       .addReg(SystemZ::R14D)
    115       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
    116     break;
    117 
    118   case SystemZ::CallBASR:
    119     LoweredMI = MCInstBuilder(SystemZ::BASR)
    120       .addReg(SystemZ::R14D)
    121       .addReg(MI->getOperand(0).getReg());
    122     break;
    123 
    124   case SystemZ::CallJG:
    125     LoweredMI = MCInstBuilder(SystemZ::JG)
    126       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
    127     break;
    128 
    129   case SystemZ::CallBR:
    130     LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R1D);
    131     break;
    132 
    133   case SystemZ::TLS_GDCALL:
    134     LoweredMI = MCInstBuilder(SystemZ::BRASL)
    135       .addReg(SystemZ::R14D)
    136       .addExpr(getTLSGetOffset(MF->getContext()))
    137       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD));
    138     break;
    139 
    140   case SystemZ::TLS_LDCALL:
    141     LoweredMI = MCInstBuilder(SystemZ::BRASL)
    142       .addReg(SystemZ::R14D)
    143       .addExpr(getTLSGetOffset(MF->getContext()))
    144       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM));
    145     break;
    146 
    147   case SystemZ::GOT:
    148     LoweredMI = MCInstBuilder(SystemZ::LARL)
    149       .addReg(MI->getOperand(0).getReg())
    150       .addExpr(getGlobalOffsetTable(MF->getContext()));
    151     break;
    152 
    153   case SystemZ::IILF64:
    154     LoweredMI = MCInstBuilder(SystemZ::IILF)
    155       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
    156       .addImm(MI->getOperand(2).getImm());
    157     break;
    158 
    159   case SystemZ::IIHF64:
    160     LoweredMI = MCInstBuilder(SystemZ::IIHF)
    161       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
    162       .addImm(MI->getOperand(2).getImm());
    163     break;
    164 
    165   case SystemZ::RISBHH:
    166   case SystemZ::RISBHL:
    167     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);
    168     break;
    169 
    170   case SystemZ::RISBLH:
    171   case SystemZ::RISBLL:
    172     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);
    173     break;
    174 
    175   case SystemZ::VLVGP32:
    176     LoweredMI = MCInstBuilder(SystemZ::VLVGP)
    177       .addReg(MI->getOperand(0).getReg())
    178       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg()))
    179       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()));
    180     break;
    181 
    182   case SystemZ::VLR32:
    183   case SystemZ::VLR64:
    184     LoweredMI = MCInstBuilder(SystemZ::VLR)
    185       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
    186       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()));
    187     break;
    188 
    189   case SystemZ::VL32:
    190     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF);
    191     break;
    192 
    193   case SystemZ::VL64:
    194     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG);
    195     break;
    196 
    197   case SystemZ::VST32:
    198     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF);
    199     break;
    200 
    201   case SystemZ::VST64:
    202     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG);
    203     break;
    204 
    205   case SystemZ::LFER:
    206     LoweredMI = MCInstBuilder(SystemZ::VLGVF)
    207       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg()))
    208       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()))
    209       .addReg(0).addImm(0);
    210     break;
    211 
    212   case SystemZ::LEFR:
    213     LoweredMI = MCInstBuilder(SystemZ::VLVGF)
    214       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
    215       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
    216       .addReg(MI->getOperand(1).getReg())
    217       .addReg(0).addImm(0);
    218     break;
    219 
    220 #define LOWER_LOW(NAME)                                                 \
    221   case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break
    222 
    223   LOWER_LOW(IILL);
    224   LOWER_LOW(IILH);
    225   LOWER_LOW(TMLL);
    226   LOWER_LOW(TMLH);
    227   LOWER_LOW(NILL);
    228   LOWER_LOW(NILH);
    229   LOWER_LOW(NILF);
    230   LOWER_LOW(OILL);
    231   LOWER_LOW(OILH);
    232   LOWER_LOW(OILF);
    233   LOWER_LOW(XILF);
    234 
    235 #undef LOWER_LOW
    236 
    237 #define LOWER_HIGH(NAME) \
    238   case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break
    239 
    240   LOWER_HIGH(IIHL);
    241   LOWER_HIGH(IIHH);
    242   LOWER_HIGH(TMHL);
    243   LOWER_HIGH(TMHH);
    244   LOWER_HIGH(NIHL);
    245   LOWER_HIGH(NIHH);
    246   LOWER_HIGH(NIHF);
    247   LOWER_HIGH(OIHL);
    248   LOWER_HIGH(OIHH);
    249   LOWER_HIGH(OIHF);
    250   LOWER_HIGH(XIHF);
    251 
    252 #undef LOWER_HIGH
    253 
    254   case SystemZ::Serialize:
    255     if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization())
    256       LoweredMI = MCInstBuilder(SystemZ::AsmBCR)
    257         .addImm(14).addReg(SystemZ::R0D);
    258     else
    259       LoweredMI = MCInstBuilder(SystemZ::AsmBCR)
    260         .addImm(15).addReg(SystemZ::R0D);
    261     break;
    262 
    263   default:
    264     Lower.lower(MI, LoweredMI);
    265     break;
    266   }
    267   EmitToStreamer(*OutStreamer, LoweredMI);
    268 }
    269 
    270 // Convert a SystemZ-specific constant pool modifier into the associated
    271 // MCSymbolRefExpr variant kind.
    272 static MCSymbolRefExpr::VariantKind
    273 getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) {
    274   switch (Modifier) {
    275   case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD;
    276   case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM;
    277   case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF;
    278   case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
    279   }
    280   llvm_unreachable("Invalid SystemCPModifier!");
    281 }
    282 
    283 void SystemZAsmPrinter::
    284 EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
    285   auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
    286 
    287   const MCExpr *Expr =
    288     MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()),
    289                             getModifierVariantKind(ZCPV->getModifier()),
    290                             OutContext);
    291   uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());
    292 
    293   OutStreamer->EmitValue(Expr, Size);
    294 }
    295 
    296 bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
    297                                         unsigned OpNo,
    298                                         unsigned AsmVariant,
    299                                         const char *ExtraCode,
    300                                         raw_ostream &OS) {
    301   if (ExtraCode && *ExtraCode == 'n') {
    302     if (!MI->getOperand(OpNo).isImm())
    303       return true;
    304     OS << -int64_t(MI->getOperand(OpNo).getImm());
    305   } else {
    306     SystemZMCInstLower Lower(MF->getContext(), *this);
    307     MCOperand MO(Lower.lowerOperand(MI->getOperand(OpNo)));
    308     SystemZInstPrinter::printOperand(MO, MAI, OS);
    309   }
    310   return false;
    311 }
    312 
    313 bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
    314                                               unsigned OpNo,
    315                                               unsigned AsmVariant,
    316                                               const char *ExtraCode,
    317                                               raw_ostream &OS) {
    318   SystemZInstPrinter::printAddress(MI->getOperand(OpNo).getReg(),
    319                                    MI->getOperand(OpNo + 1).getImm(),
    320                                    MI->getOperand(OpNo + 2).getReg(), OS);
    321   return false;
    322 }
    323 
    324 // Force static initialization.
    325 extern "C" void LLVMInitializeSystemZAsmPrinter() {
    326   RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget);
    327 }
    328