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