| Ulrich Weigand | 5f613df | 2013-05-06 16:15:19 +0000 | [diff] [blame] | 1 | //===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===// | 
|  | 2 | // | 
| Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | 4 | // See https://llvm.org/LICENSE.txt for license information. | 
|  | 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
| Ulrich Weigand | 5f613df | 2013-05-06 16:15:19 +0000 | [diff] [blame] | 6 | // | 
|  | 7 | //===----------------------------------------------------------------------===// | 
|  | 8 | // | 
|  | 9 | // Streams SystemZ assembly language and associated data, in the form of | 
|  | 10 | // MCInsts and MCExprs respectively. | 
|  | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 |  | 
|  | 14 | #include "SystemZAsmPrinter.h" | 
|  | 15 | #include "InstPrinter/SystemZInstPrinter.h" | 
|  | 16 | #include "SystemZConstantPoolValue.h" | 
|  | 17 | #include "SystemZMCInstLower.h" | 
|  | 18 | #include "llvm/CodeGen/MachineModuleInfoImpls.h" | 
|  | 19 | #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" | 
| Rafael Espindola | 894843c | 2014-01-07 21:19:40 +0000 | [diff] [blame] | 20 | #include "llvm/IR/Mangler.h" | 
| Ulrich Weigand | 5f613df | 2013-05-06 16:15:19 +0000 | [diff] [blame] | 21 | #include "llvm/MC/MCExpr.h" | 
| Richard Sandiford | 9ab97cd | 2013-09-25 10:20:08 +0000 | [diff] [blame] | 22 | #include "llvm/MC/MCInstBuilder.h" | 
| Ulrich Weigand | 5f613df | 2013-05-06 16:15:19 +0000 | [diff] [blame] | 23 | #include "llvm/MC/MCStreamer.h" | 
|  | 24 | #include "llvm/Support/TargetRegistry.h" | 
| Ulrich Weigand | 5f613df | 2013-05-06 16:15:19 +0000 | [diff] [blame] | 25 |  | 
|  | 26 | using namespace llvm; | 
|  | 27 |  | 
| Richard Sandiford | 652784e | 2013-09-25 11:11:53 +0000 | [diff] [blame] | 28 | // Return an RI instruction like MI with opcode Opcode, but with the | 
|  | 29 | // GR64 register operands turned into GR32s. | 
|  | 30 | static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) { | 
| Richard Sandiford | f03789c | 2013-11-22 17:28:28 +0000 | [diff] [blame] | 31 | if (MI->isCompare()) | 
|  | 32 | return MCInstBuilder(Opcode) | 
|  | 33 | .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) | 
|  | 34 | .addImm(MI->getOperand(1).getImm()); | 
|  | 35 | else | 
|  | 36 | return MCInstBuilder(Opcode) | 
|  | 37 | .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) | 
|  | 38 | .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg())) | 
|  | 39 | .addImm(MI->getOperand(2).getImm()); | 
| Richard Sandiford | 652784e | 2013-09-25 11:11:53 +0000 | [diff] [blame] | 40 | } | 
|  | 41 |  | 
| Richard Sandiford | 0755c93 | 2013-10-01 11:26:28 +0000 | [diff] [blame] | 42 | // Return an RI instruction like MI with opcode Opcode, but with the | 
| Richard Sandiford | 1a56931 | 2013-10-01 13:18:56 +0000 | [diff] [blame] | 43 | // GR64 register operands turned into GRH32s. | 
|  | 44 | static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) { | 
| Richard Sandiford | f03789c | 2013-11-22 17:28:28 +0000 | [diff] [blame] | 45 | if (MI->isCompare()) | 
|  | 46 | return MCInstBuilder(Opcode) | 
|  | 47 | .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) | 
|  | 48 | .addImm(MI->getOperand(1).getImm()); | 
|  | 49 | else | 
|  | 50 | return MCInstBuilder(Opcode) | 
|  | 51 | .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) | 
|  | 52 | .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg())) | 
|  | 53 | .addImm(MI->getOperand(2).getImm()); | 
| Richard Sandiford | 1a56931 | 2013-10-01 13:18:56 +0000 | [diff] [blame] | 54 | } | 
|  | 55 |  | 
|  | 56 | // Return an RI instruction like MI with opcode Opcode, but with the | 
| Richard Sandiford | 0755c93 | 2013-10-01 11:26:28 +0000 | [diff] [blame] | 57 | // R2 register turned into a GR64. | 
|  | 58 | static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) { | 
|  | 59 | return MCInstBuilder(Opcode) | 
|  | 60 | .addReg(MI->getOperand(0).getReg()) | 
|  | 61 | .addReg(MI->getOperand(1).getReg()) | 
|  | 62 | .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())) | 
|  | 63 | .addImm(MI->getOperand(3).getImm()) | 
|  | 64 | .addImm(MI->getOperand(4).getImm()) | 
|  | 65 | .addImm(MI->getOperand(5).getImm()); | 
|  | 66 | } | 
|  | 67 |  | 
| Ulrich Weigand | 7db6918 | 2015-02-18 09:13:27 +0000 | [diff] [blame] | 68 | static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) { | 
|  | 69 | StringRef Name = "__tls_get_offset"; | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 70 | return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name), | 
| Ulrich Weigand | 7db6918 | 2015-02-18 09:13:27 +0000 | [diff] [blame] | 71 | MCSymbolRefExpr::VK_PLT, | 
|  | 72 | Context); | 
|  | 73 | } | 
|  | 74 |  | 
|  | 75 | static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) { | 
|  | 76 | StringRef Name = "_GLOBAL_OFFSET_TABLE_"; | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 77 | return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name), | 
| Ulrich Weigand | 7db6918 | 2015-02-18 09:13:27 +0000 | [diff] [blame] | 78 | MCSymbolRefExpr::VK_None, | 
|  | 79 | Context); | 
|  | 80 | } | 
|  | 81 |  | 
| Ulrich Weigand | 49506d7 | 2015-05-05 19:28:34 +0000 | [diff] [blame] | 82 | // MI loads the high part of a vector from memory.  Return an instruction | 
|  | 83 | // that uses replicating vector load Opcode to do the same thing. | 
|  | 84 | static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) { | 
|  | 85 | return MCInstBuilder(Opcode) | 
|  | 86 | .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) | 
|  | 87 | .addReg(MI->getOperand(1).getReg()) | 
|  | 88 | .addImm(MI->getOperand(2).getImm()) | 
|  | 89 | .addReg(MI->getOperand(3).getReg()); | 
|  | 90 | } | 
|  | 91 |  | 
|  | 92 | // MI stores the high part of a vector to memory.  Return an instruction | 
|  | 93 | // that uses elemental vector store Opcode to do the same thing. | 
|  | 94 | static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) { | 
|  | 95 | return MCInstBuilder(Opcode) | 
|  | 96 | .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) | 
|  | 97 | .addReg(MI->getOperand(1).getReg()) | 
|  | 98 | .addImm(MI->getOperand(2).getImm()) | 
|  | 99 | .addReg(MI->getOperand(3).getReg()) | 
|  | 100 | .addImm(0); | 
|  | 101 | } | 
|  | 102 |  | 
| Ulrich Weigand | 5f613df | 2013-05-06 16:15:19 +0000 | [diff] [blame] | 103 | void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) { | 
| Rafael Espindola | 69c1d63 | 2013-10-29 16:18:15 +0000 | [diff] [blame] | 104 | SystemZMCInstLower Lower(MF->getContext(), *this); | 
| Ulrich Weigand | 5f613df | 2013-05-06 16:15:19 +0000 | [diff] [blame] | 105 | MCInst LoweredMI; | 
| Richard Sandiford | 9ab97cd | 2013-09-25 10:20:08 +0000 | [diff] [blame] | 106 | switch (MI->getOpcode()) { | 
|  | 107 | case SystemZ::Return: | 
|  | 108 | LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D); | 
|  | 109 | break; | 
|  | 110 |  | 
| Ulrich Weigand | 2eb027d | 2016-04-07 16:11:44 +0000 | [diff] [blame] | 111 | case SystemZ::CondReturn: | 
|  | 112 | LoweredMI = MCInstBuilder(SystemZ::BCR) | 
|  | 113 | .addImm(MI->getOperand(0).getImm()) | 
|  | 114 | .addImm(MI->getOperand(1).getImm()) | 
|  | 115 | .addReg(SystemZ::R14D); | 
|  | 116 | break; | 
|  | 117 |  | 
|  | 118 | case SystemZ::CRBReturn: | 
|  | 119 | LoweredMI = MCInstBuilder(SystemZ::CRB) | 
|  | 120 | .addReg(MI->getOperand(0).getReg()) | 
|  | 121 | .addReg(MI->getOperand(1).getReg()) | 
|  | 122 | .addImm(MI->getOperand(2).getImm()) | 
|  | 123 | .addReg(SystemZ::R14D) | 
|  | 124 | .addImm(0); | 
|  | 125 | break; | 
|  | 126 |  | 
|  | 127 | case SystemZ::CGRBReturn: | 
|  | 128 | LoweredMI = MCInstBuilder(SystemZ::CGRB) | 
|  | 129 | .addReg(MI->getOperand(0).getReg()) | 
|  | 130 | .addReg(MI->getOperand(1).getReg()) | 
|  | 131 | .addImm(MI->getOperand(2).getImm()) | 
|  | 132 | .addReg(SystemZ::R14D) | 
|  | 133 | .addImm(0); | 
|  | 134 | break; | 
|  | 135 |  | 
|  | 136 | case SystemZ::CIBReturn: | 
|  | 137 | LoweredMI = MCInstBuilder(SystemZ::CIB) | 
|  | 138 | .addReg(MI->getOperand(0).getReg()) | 
|  | 139 | .addImm(MI->getOperand(1).getImm()) | 
|  | 140 | .addImm(MI->getOperand(2).getImm()) | 
|  | 141 | .addReg(SystemZ::R14D) | 
|  | 142 | .addImm(0); | 
|  | 143 | break; | 
|  | 144 |  | 
|  | 145 | case SystemZ::CGIBReturn: | 
|  | 146 | LoweredMI = MCInstBuilder(SystemZ::CGIB) | 
|  | 147 | .addReg(MI->getOperand(0).getReg()) | 
|  | 148 | .addImm(MI->getOperand(1).getImm()) | 
|  | 149 | .addImm(MI->getOperand(2).getImm()) | 
|  | 150 | .addReg(SystemZ::R14D) | 
|  | 151 | .addImm(0); | 
|  | 152 | break; | 
|  | 153 |  | 
|  | 154 | case SystemZ::CLRBReturn: | 
|  | 155 | LoweredMI = MCInstBuilder(SystemZ::CLRB) | 
|  | 156 | .addReg(MI->getOperand(0).getReg()) | 
|  | 157 | .addReg(MI->getOperand(1).getReg()) | 
|  | 158 | .addImm(MI->getOperand(2).getImm()) | 
|  | 159 | .addReg(SystemZ::R14D) | 
|  | 160 | .addImm(0); | 
|  | 161 | break; | 
|  | 162 |  | 
|  | 163 | case SystemZ::CLGRBReturn: | 
|  | 164 | LoweredMI = MCInstBuilder(SystemZ::CLGRB) | 
|  | 165 | .addReg(MI->getOperand(0).getReg()) | 
|  | 166 | .addReg(MI->getOperand(1).getReg()) | 
|  | 167 | .addImm(MI->getOperand(2).getImm()) | 
|  | 168 | .addReg(SystemZ::R14D) | 
|  | 169 | .addImm(0); | 
|  | 170 | break; | 
|  | 171 |  | 
|  | 172 | case SystemZ::CLIBReturn: | 
|  | 173 | LoweredMI = MCInstBuilder(SystemZ::CLIB) | 
|  | 174 | .addReg(MI->getOperand(0).getReg()) | 
|  | 175 | .addImm(MI->getOperand(1).getImm()) | 
|  | 176 | .addImm(MI->getOperand(2).getImm()) | 
|  | 177 | .addReg(SystemZ::R14D) | 
|  | 178 | .addImm(0); | 
|  | 179 | break; | 
|  | 180 |  | 
|  | 181 | case SystemZ::CLGIBReturn: | 
|  | 182 | LoweredMI = MCInstBuilder(SystemZ::CLGIB) | 
|  | 183 | .addReg(MI->getOperand(0).getReg()) | 
|  | 184 | .addImm(MI->getOperand(1).getImm()) | 
|  | 185 | .addImm(MI->getOperand(2).getImm()) | 
|  | 186 | .addReg(SystemZ::R14D) | 
|  | 187 | .addImm(0); | 
|  | 188 | break; | 
|  | 189 |  | 
| Richard Sandiford | f348f83 | 2013-09-25 10:37:17 +0000 | [diff] [blame] | 190 | case SystemZ::CallBRASL: | 
|  | 191 | LoweredMI = MCInstBuilder(SystemZ::BRASL) | 
|  | 192 | .addReg(SystemZ::R14D) | 
|  | 193 | .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); | 
|  | 194 | break; | 
|  | 195 |  | 
|  | 196 | case SystemZ::CallBASR: | 
|  | 197 | LoweredMI = MCInstBuilder(SystemZ::BASR) | 
|  | 198 | .addReg(SystemZ::R14D) | 
|  | 199 | .addReg(MI->getOperand(0).getReg()); | 
|  | 200 | break; | 
|  | 201 |  | 
|  | 202 | case SystemZ::CallJG: | 
|  | 203 | LoweredMI = MCInstBuilder(SystemZ::JG) | 
|  | 204 | .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); | 
|  | 205 | break; | 
|  | 206 |  | 
| Ulrich Weigand | fa2dffb | 2016-04-08 17:22:19 +0000 | [diff] [blame] | 207 | case SystemZ::CallBRCL: | 
|  | 208 | LoweredMI = MCInstBuilder(SystemZ::BRCL) | 
|  | 209 | .addImm(MI->getOperand(0).getImm()) | 
|  | 210 | .addImm(MI->getOperand(1).getImm()) | 
|  | 211 | .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT)); | 
|  | 212 | break; | 
|  | 213 |  | 
| Richard Sandiford | f348f83 | 2013-09-25 10:37:17 +0000 | [diff] [blame] | 214 | case SystemZ::CallBR: | 
|  | 215 | LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R1D); | 
|  | 216 | break; | 
|  | 217 |  | 
| Ulrich Weigand | 848a513 | 2016-04-11 12:12:32 +0000 | [diff] [blame] | 218 | case SystemZ::CallBCR: | 
|  | 219 | LoweredMI = MCInstBuilder(SystemZ::BCR) | 
|  | 220 | .addImm(MI->getOperand(0).getImm()) | 
|  | 221 | .addImm(MI->getOperand(1).getImm()) | 
|  | 222 | .addReg(SystemZ::R1D); | 
|  | 223 | break; | 
|  | 224 |  | 
|  | 225 | case SystemZ::CRBCall: | 
|  | 226 | LoweredMI = MCInstBuilder(SystemZ::CRB) | 
|  | 227 | .addReg(MI->getOperand(0).getReg()) | 
|  | 228 | .addReg(MI->getOperand(1).getReg()) | 
|  | 229 | .addImm(MI->getOperand(2).getImm()) | 
|  | 230 | .addReg(SystemZ::R1D) | 
|  | 231 | .addImm(0); | 
|  | 232 | break; | 
|  | 233 |  | 
|  | 234 | case SystemZ::CGRBCall: | 
|  | 235 | LoweredMI = MCInstBuilder(SystemZ::CGRB) | 
|  | 236 | .addReg(MI->getOperand(0).getReg()) | 
|  | 237 | .addReg(MI->getOperand(1).getReg()) | 
|  | 238 | .addImm(MI->getOperand(2).getImm()) | 
|  | 239 | .addReg(SystemZ::R1D) | 
|  | 240 | .addImm(0); | 
|  | 241 | break; | 
|  | 242 |  | 
|  | 243 | case SystemZ::CIBCall: | 
|  | 244 | LoweredMI = MCInstBuilder(SystemZ::CIB) | 
|  | 245 | .addReg(MI->getOperand(0).getReg()) | 
|  | 246 | .addImm(MI->getOperand(1).getImm()) | 
|  | 247 | .addImm(MI->getOperand(2).getImm()) | 
|  | 248 | .addReg(SystemZ::R1D) | 
|  | 249 | .addImm(0); | 
|  | 250 | break; | 
|  | 251 |  | 
|  | 252 | case SystemZ::CGIBCall: | 
|  | 253 | LoweredMI = MCInstBuilder(SystemZ::CGIB) | 
|  | 254 | .addReg(MI->getOperand(0).getReg()) | 
|  | 255 | .addImm(MI->getOperand(1).getImm()) | 
|  | 256 | .addImm(MI->getOperand(2).getImm()) | 
|  | 257 | .addReg(SystemZ::R1D) | 
|  | 258 | .addImm(0); | 
|  | 259 | break; | 
|  | 260 |  | 
|  | 261 | case SystemZ::CLRBCall: | 
|  | 262 | LoweredMI = MCInstBuilder(SystemZ::CLRB) | 
|  | 263 | .addReg(MI->getOperand(0).getReg()) | 
|  | 264 | .addReg(MI->getOperand(1).getReg()) | 
|  | 265 | .addImm(MI->getOperand(2).getImm()) | 
|  | 266 | .addReg(SystemZ::R1D) | 
|  | 267 | .addImm(0); | 
|  | 268 | break; | 
|  | 269 |  | 
|  | 270 | case SystemZ::CLGRBCall: | 
|  | 271 | LoweredMI = MCInstBuilder(SystemZ::CLGRB) | 
|  | 272 | .addReg(MI->getOperand(0).getReg()) | 
|  | 273 | .addReg(MI->getOperand(1).getReg()) | 
|  | 274 | .addImm(MI->getOperand(2).getImm()) | 
|  | 275 | .addReg(SystemZ::R1D) | 
|  | 276 | .addImm(0); | 
|  | 277 | break; | 
|  | 278 |  | 
|  | 279 | case SystemZ::CLIBCall: | 
|  | 280 | LoweredMI = MCInstBuilder(SystemZ::CLIB) | 
|  | 281 | .addReg(MI->getOperand(0).getReg()) | 
|  | 282 | .addImm(MI->getOperand(1).getImm()) | 
|  | 283 | .addImm(MI->getOperand(2).getImm()) | 
|  | 284 | .addReg(SystemZ::R1D) | 
|  | 285 | .addImm(0); | 
|  | 286 | break; | 
|  | 287 |  | 
|  | 288 | case SystemZ::CLGIBCall: | 
|  | 289 | LoweredMI = MCInstBuilder(SystemZ::CLGIB) | 
|  | 290 | .addReg(MI->getOperand(0).getReg()) | 
|  | 291 | .addImm(MI->getOperand(1).getImm()) | 
|  | 292 | .addImm(MI->getOperand(2).getImm()) | 
|  | 293 | .addReg(SystemZ::R1D) | 
|  | 294 | .addImm(0); | 
|  | 295 | break; | 
|  | 296 |  | 
| Ulrich Weigand | 7db6918 | 2015-02-18 09:13:27 +0000 | [diff] [blame] | 297 | case SystemZ::TLS_GDCALL: | 
|  | 298 | LoweredMI = MCInstBuilder(SystemZ::BRASL) | 
|  | 299 | .addReg(SystemZ::R14D) | 
|  | 300 | .addExpr(getTLSGetOffset(MF->getContext())) | 
|  | 301 | .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD)); | 
|  | 302 | break; | 
|  | 303 |  | 
|  | 304 | case SystemZ::TLS_LDCALL: | 
|  | 305 | LoweredMI = MCInstBuilder(SystemZ::BRASL) | 
|  | 306 | .addReg(SystemZ::R14D) | 
|  | 307 | .addExpr(getTLSGetOffset(MF->getContext())) | 
|  | 308 | .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM)); | 
|  | 309 | break; | 
|  | 310 |  | 
|  | 311 | case SystemZ::GOT: | 
|  | 312 | LoweredMI = MCInstBuilder(SystemZ::LARL) | 
|  | 313 | .addReg(MI->getOperand(0).getReg()) | 
|  | 314 | .addExpr(getGlobalOffsetTable(MF->getContext())); | 
|  | 315 | break; | 
|  | 316 |  | 
| Richard Sandiford | 652784e | 2013-09-25 11:11:53 +0000 | [diff] [blame] | 317 | case SystemZ::IILF64: | 
|  | 318 | LoweredMI = MCInstBuilder(SystemZ::IILF) | 
|  | 319 | .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) | 
|  | 320 | .addImm(MI->getOperand(2).getImm()); | 
|  | 321 | break; | 
|  | 322 |  | 
| Richard Sandiford | 0124023 | 2013-10-01 13:02:28 +0000 | [diff] [blame] | 323 | case SystemZ::IIHF64: | 
|  | 324 | LoweredMI = MCInstBuilder(SystemZ::IIHF) | 
|  | 325 | .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) | 
|  | 326 | .addImm(MI->getOperand(2).getImm()); | 
|  | 327 | break; | 
|  | 328 |  | 
| Richard Sandiford | 0755c93 | 2013-10-01 11:26:28 +0000 | [diff] [blame] | 329 | case SystemZ::RISBHH: | 
|  | 330 | case SystemZ::RISBHL: | 
|  | 331 | LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG); | 
|  | 332 | break; | 
|  | 333 |  | 
|  | 334 | case SystemZ::RISBLH: | 
|  | 335 | case SystemZ::RISBLL: | 
|  | 336 | LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG); | 
|  | 337 | break; | 
|  | 338 |  | 
| Ulrich Weigand | ce4c109 | 2015-05-05 19:25:42 +0000 | [diff] [blame] | 339 | case SystemZ::VLVGP32: | 
|  | 340 | LoweredMI = MCInstBuilder(SystemZ::VLVGP) | 
|  | 341 | .addReg(MI->getOperand(0).getReg()) | 
|  | 342 | .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg())) | 
|  | 343 | .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())); | 
|  | 344 | break; | 
|  | 345 |  | 
| Ulrich Weigand | 49506d7 | 2015-05-05 19:28:34 +0000 | [diff] [blame] | 346 | case SystemZ::VLR32: | 
|  | 347 | case SystemZ::VLR64: | 
|  | 348 | LoweredMI = MCInstBuilder(SystemZ::VLR) | 
|  | 349 | .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) | 
|  | 350 | .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())); | 
|  | 351 | break; | 
|  | 352 |  | 
|  | 353 | case SystemZ::VL32: | 
|  | 354 | LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF); | 
|  | 355 | break; | 
|  | 356 |  | 
|  | 357 | case SystemZ::VL64: | 
|  | 358 | LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG); | 
|  | 359 | break; | 
|  | 360 |  | 
|  | 361 | case SystemZ::VST32: | 
|  | 362 | LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF); | 
|  | 363 | break; | 
|  | 364 |  | 
|  | 365 | case SystemZ::VST64: | 
|  | 366 | LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG); | 
|  | 367 | break; | 
|  | 368 |  | 
| Ulrich Weigand | 80b3af7 | 2015-05-05 19:27:45 +0000 | [diff] [blame] | 369 | case SystemZ::LFER: | 
|  | 370 | LoweredMI = MCInstBuilder(SystemZ::VLGVF) | 
|  | 371 | .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg())) | 
|  | 372 | .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())) | 
|  | 373 | .addReg(0).addImm(0); | 
|  | 374 | break; | 
|  | 375 |  | 
|  | 376 | case SystemZ::LEFR: | 
|  | 377 | LoweredMI = MCInstBuilder(SystemZ::VLVGF) | 
|  | 378 | .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) | 
|  | 379 | .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) | 
|  | 380 | .addReg(MI->getOperand(1).getReg()) | 
|  | 381 | .addReg(0).addImm(0); | 
|  | 382 | break; | 
|  | 383 |  | 
| Richard Sandiford | 652784e | 2013-09-25 11:11:53 +0000 | [diff] [blame] | 384 | #define LOWER_LOW(NAME)                                                 \ | 
|  | 385 | case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break | 
|  | 386 |  | 
|  | 387 | LOWER_LOW(IILL); | 
|  | 388 | LOWER_LOW(IILH); | 
| Richard Sandiford | f03789c | 2013-11-22 17:28:28 +0000 | [diff] [blame] | 389 | LOWER_LOW(TMLL); | 
|  | 390 | LOWER_LOW(TMLH); | 
| Richard Sandiford | 652784e | 2013-09-25 11:11:53 +0000 | [diff] [blame] | 391 | LOWER_LOW(NILL); | 
|  | 392 | LOWER_LOW(NILH); | 
|  | 393 | LOWER_LOW(NILF); | 
|  | 394 | LOWER_LOW(OILL); | 
|  | 395 | LOWER_LOW(OILH); | 
|  | 396 | LOWER_LOW(OILF); | 
|  | 397 | LOWER_LOW(XILF); | 
|  | 398 |  | 
|  | 399 | #undef LOWER_LOW | 
|  | 400 |  | 
| Richard Sandiford | 1a56931 | 2013-10-01 13:18:56 +0000 | [diff] [blame] | 401 | #define LOWER_HIGH(NAME) \ | 
|  | 402 | case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break | 
|  | 403 |  | 
|  | 404 | LOWER_HIGH(IIHL); | 
|  | 405 | LOWER_HIGH(IIHH); | 
| Richard Sandiford | f03789c | 2013-11-22 17:28:28 +0000 | [diff] [blame] | 406 | LOWER_HIGH(TMHL); | 
|  | 407 | LOWER_HIGH(TMHH); | 
| Richard Sandiford | 7028428 | 2013-10-01 14:20:41 +0000 | [diff] [blame] | 408 | LOWER_HIGH(NIHL); | 
|  | 409 | LOWER_HIGH(NIHH); | 
|  | 410 | LOWER_HIGH(NIHF); | 
| Richard Sandiford | 6e96ac6 | 2013-10-01 13:22:41 +0000 | [diff] [blame] | 411 | LOWER_HIGH(OIHL); | 
|  | 412 | LOWER_HIGH(OIHH); | 
|  | 413 | LOWER_HIGH(OIHF); | 
| Richard Sandiford | 5718dac | 2013-10-01 14:08:44 +0000 | [diff] [blame] | 414 | LOWER_HIGH(XIHF); | 
| Richard Sandiford | 1a56931 | 2013-10-01 13:18:56 +0000 | [diff] [blame] | 415 |  | 
|  | 416 | #undef LOWER_HIGH | 
|  | 417 |  | 
| Richard Sandiford | 9afe613 | 2013-12-10 10:36:34 +0000 | [diff] [blame] | 418 | case SystemZ::Serialize: | 
| Eric Christopher | d84f5d3 | 2015-02-19 01:26:28 +0000 | [diff] [blame] | 419 | if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization()) | 
| Ulrich Weigand | d2148ca | 2016-11-08 18:30:50 +0000 | [diff] [blame] | 420 | LoweredMI = MCInstBuilder(SystemZ::BCRAsm) | 
| Richard Sandiford | 9afe613 | 2013-12-10 10:36:34 +0000 | [diff] [blame] | 421 | .addImm(14).addReg(SystemZ::R0D); | 
|  | 422 | else | 
| Ulrich Weigand | d2148ca | 2016-11-08 18:30:50 +0000 | [diff] [blame] | 423 | LoweredMI = MCInstBuilder(SystemZ::BCRAsm) | 
| Richard Sandiford | 9afe613 | 2013-12-10 10:36:34 +0000 | [diff] [blame] | 424 | .addImm(15).addReg(SystemZ::R0D); | 
|  | 425 | break; | 
|  | 426 |  | 
| Ulrich Weigand | a9ac6d6 | 2016-04-04 12:45:44 +0000 | [diff] [blame] | 427 | // Emit nothing here but a comment if we can. | 
|  | 428 | case SystemZ::MemBarrier: | 
|  | 429 | OutStreamer->emitRawComment("MEMBARRIER"); | 
|  | 430 | return; | 
|  | 431 |  | 
| Zhan Jun Liau | ab42cbc | 2016-06-10 19:58:10 +0000 | [diff] [blame] | 432 | // We want to emit "j .+2" for traps, jumping to the relative immediate field | 
|  | 433 | // of the jump instruction, which is an illegal instruction. We cannot emit a | 
|  | 434 | // "." symbol, so create and emit a temp label before the instruction and use | 
|  | 435 | // that instead. | 
|  | 436 | case SystemZ::Trap: { | 
|  | 437 | MCSymbol *DotSym = OutContext.createTempSymbol(); | 
|  | 438 | OutStreamer->EmitLabel(DotSym); | 
|  | 439 |  | 
|  | 440 | const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); | 
|  | 441 | const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); | 
|  | 442 | LoweredMI = MCInstBuilder(SystemZ::J) | 
|  | 443 | .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); | 
|  | 444 | } | 
|  | 445 | break; | 
|  | 446 |  | 
|  | 447 | // Conditional traps will create a branch on condition instruction that jumps | 
|  | 448 | // to the relative immediate field of the jump instruction. (eg. "jo .+2") | 
|  | 449 | case SystemZ::CondTrap: { | 
|  | 450 | MCSymbol *DotSym = OutContext.createTempSymbol(); | 
|  | 451 | OutStreamer->EmitLabel(DotSym); | 
|  | 452 |  | 
|  | 453 | const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); | 
|  | 454 | const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); | 
|  | 455 | LoweredMI = MCInstBuilder(SystemZ::BRC) | 
|  | 456 | .addImm(MI->getOperand(0).getImm()) | 
|  | 457 | .addImm(MI->getOperand(1).getImm()) | 
|  | 458 | .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); | 
|  | 459 | } | 
|  | 460 | break; | 
|  | 461 |  | 
| Ulrich Weigand | 5eb6411 | 2018-03-02 20:39:30 +0000 | [diff] [blame] | 462 | case TargetOpcode::STACKMAP: | 
|  | 463 | LowerSTACKMAP(*MI); | 
|  | 464 | return; | 
|  | 465 |  | 
|  | 466 | case TargetOpcode::PATCHPOINT: | 
|  | 467 | LowerPATCHPOINT(*MI, Lower); | 
|  | 468 | return; | 
|  | 469 |  | 
| Richard Sandiford | 9ab97cd | 2013-09-25 10:20:08 +0000 | [diff] [blame] | 470 | default: | 
| Richard Sandiford | f348f83 | 2013-09-25 10:37:17 +0000 | [diff] [blame] | 471 | Lower.lower(MI, LoweredMI); | 
| Richard Sandiford | 9ab97cd | 2013-09-25 10:20:08 +0000 | [diff] [blame] | 472 | break; | 
|  | 473 | } | 
| Lang Hames | 9ff69c8 | 2015-04-24 19:11:51 +0000 | [diff] [blame] | 474 | EmitToStreamer(*OutStreamer, LoweredMI); | 
| Ulrich Weigand | 5f613df | 2013-05-06 16:15:19 +0000 | [diff] [blame] | 475 | } | 
|  | 476 |  | 
| Ulrich Weigand | 5eb6411 | 2018-03-02 20:39:30 +0000 | [diff] [blame] | 477 |  | 
|  | 478 | // Emit the largest nop instruction smaller than or equal to NumBytes | 
|  | 479 | // bytes.  Return the size of nop emitted. | 
|  | 480 | static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer, | 
|  | 481 | unsigned NumBytes, const MCSubtargetInfo &STI) { | 
|  | 482 | if (NumBytes < 2) { | 
|  | 483 | llvm_unreachable("Zero nops?"); | 
|  | 484 | return 0; | 
|  | 485 | } | 
|  | 486 | else if (NumBytes < 4) { | 
|  | 487 | OutStreamer.EmitInstruction(MCInstBuilder(SystemZ::BCRAsm) | 
|  | 488 | .addImm(0).addReg(SystemZ::R0D), STI); | 
|  | 489 | return 2; | 
|  | 490 | } | 
|  | 491 | else if (NumBytes < 6) { | 
|  | 492 | OutStreamer.EmitInstruction(MCInstBuilder(SystemZ::BCAsm) | 
|  | 493 | .addImm(0).addReg(0).addImm(0).addReg(0), | 
|  | 494 | STI); | 
|  | 495 | return 4; | 
|  | 496 | } | 
|  | 497 | else { | 
|  | 498 | MCSymbol *DotSym = OutContext.createTempSymbol(); | 
|  | 499 | const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext); | 
|  | 500 | OutStreamer.EmitInstruction(MCInstBuilder(SystemZ::BRCLAsm) | 
|  | 501 | .addImm(0).addExpr(Dot), STI); | 
|  | 502 | OutStreamer.EmitLabel(DotSym); | 
|  | 503 | return 6; | 
|  | 504 | } | 
|  | 505 | } | 
|  | 506 |  | 
|  | 507 | void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) { | 
|  | 508 | const SystemZInstrInfo *TII = | 
|  | 509 | static_cast<const SystemZInstrInfo *>(MF->getSubtarget().getInstrInfo()); | 
|  | 510 |  | 
|  | 511 | unsigned NumNOPBytes = MI.getOperand(1).getImm(); | 
|  | 512 |  | 
|  | 513 | SM.recordStackMap(MI); | 
|  | 514 | assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!"); | 
|  | 515 |  | 
|  | 516 | // Scan ahead to trim the shadow. | 
|  | 517 | unsigned ShadowBytes = 0; | 
|  | 518 | const MachineBasicBlock &MBB = *MI.getParent(); | 
|  | 519 | MachineBasicBlock::const_iterator MII(MI); | 
|  | 520 | ++MII; | 
|  | 521 | while (ShadowBytes < NumNOPBytes) { | 
|  | 522 | if (MII == MBB.end() || | 
|  | 523 | MII->getOpcode() == TargetOpcode::PATCHPOINT || | 
|  | 524 | MII->getOpcode() == TargetOpcode::STACKMAP) | 
|  | 525 | break; | 
|  | 526 | ShadowBytes += TII->getInstSizeInBytes(*MII); | 
|  | 527 | if (MII->isCall()) | 
|  | 528 | break; | 
|  | 529 | ++MII; | 
|  | 530 | } | 
|  | 531 |  | 
|  | 532 | // Emit nops. | 
|  | 533 | while (ShadowBytes < NumNOPBytes) | 
|  | 534 | ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes, | 
|  | 535 | getSubtargetInfo()); | 
|  | 536 | } | 
|  | 537 |  | 
|  | 538 | // Lower a patchpoint of the form: | 
|  | 539 | // [<def>], <id>, <numBytes>, <target>, <numArgs> | 
|  | 540 | void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI, | 
|  | 541 | SystemZMCInstLower &Lower) { | 
|  | 542 | SM.recordPatchPoint(MI); | 
|  | 543 | PatchPointOpers Opers(&MI); | 
|  | 544 |  | 
|  | 545 | unsigned EncodedBytes = 0; | 
|  | 546 | const MachineOperand &CalleeMO = Opers.getCallTarget(); | 
|  | 547 |  | 
|  | 548 | if (CalleeMO.isImm()) { | 
|  | 549 | uint64_t CallTarget = CalleeMO.getImm(); | 
|  | 550 | if (CallTarget) { | 
|  | 551 | unsigned ScratchIdx = -1; | 
|  | 552 | unsigned ScratchReg = 0; | 
|  | 553 | do { | 
|  | 554 | ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1); | 
|  | 555 | ScratchReg = MI.getOperand(ScratchIdx).getReg(); | 
|  | 556 | } while (ScratchReg == SystemZ::R0D); | 
|  | 557 |  | 
|  | 558 | // Materialize the call target address | 
|  | 559 | EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF) | 
|  | 560 | .addReg(ScratchReg) | 
|  | 561 | .addImm(CallTarget & 0xFFFFFFFF)); | 
|  | 562 | EncodedBytes += 6; | 
|  | 563 | if (CallTarget >> 32) { | 
|  | 564 | EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF) | 
|  | 565 | .addReg(ScratchReg) | 
|  | 566 | .addImm(CallTarget >> 32)); | 
|  | 567 | EncodedBytes += 6; | 
|  | 568 | } | 
|  | 569 |  | 
|  | 570 | EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) | 
|  | 571 | .addReg(SystemZ::R14D) | 
|  | 572 | .addReg(ScratchReg)); | 
|  | 573 | EncodedBytes += 2; | 
|  | 574 | } | 
|  | 575 | } else if (CalleeMO.isGlobal()) { | 
|  | 576 | const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT); | 
|  | 577 | EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL) | 
|  | 578 | .addReg(SystemZ::R14D) | 
|  | 579 | .addExpr(Expr)); | 
|  | 580 | EncodedBytes += 6; | 
|  | 581 | } | 
|  | 582 |  | 
|  | 583 | // Emit padding. | 
|  | 584 | unsigned NumBytes = Opers.getNumPatchBytes(); | 
|  | 585 | assert(NumBytes >= EncodedBytes && | 
|  | 586 | "Patchpoint can't request size less than the length of a call."); | 
|  | 587 | assert((NumBytes - EncodedBytes) % 2 == 0 && | 
|  | 588 | "Invalid number of NOP bytes requested!"); | 
|  | 589 | while (EncodedBytes < NumBytes) | 
|  | 590 | EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes, | 
|  | 591 | getSubtargetInfo()); | 
|  | 592 | } | 
|  | 593 |  | 
| Ulrich Weigand | 5f613df | 2013-05-06 16:15:19 +0000 | [diff] [blame] | 594 | // Convert a SystemZ-specific constant pool modifier into the associated | 
|  | 595 | // MCSymbolRefExpr variant kind. | 
|  | 596 | static MCSymbolRefExpr::VariantKind | 
|  | 597 | getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) { | 
|  | 598 | switch (Modifier) { | 
| Ulrich Weigand | 7db6918 | 2015-02-18 09:13:27 +0000 | [diff] [blame] | 599 | case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD; | 
|  | 600 | case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM; | 
|  | 601 | case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF; | 
| Ulrich Weigand | 5f613df | 2013-05-06 16:15:19 +0000 | [diff] [blame] | 602 | case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF; | 
|  | 603 | } | 
|  | 604 | llvm_unreachable("Invalid SystemCPModifier!"); | 
|  | 605 | } | 
|  | 606 |  | 
|  | 607 | void SystemZAsmPrinter:: | 
|  | 608 | EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { | 
| Richard Sandiford | 21f5d68 | 2014-03-06 11:22:58 +0000 | [diff] [blame] | 609 | auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV); | 
| Ulrich Weigand | 5f613df | 2013-05-06 16:15:19 +0000 | [diff] [blame] | 610 |  | 
|  | 611 | const MCExpr *Expr = | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 612 | MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()), | 
| Ulrich Weigand | 5f613df | 2013-05-06 16:15:19 +0000 | [diff] [blame] | 613 | getModifierVariantKind(ZCPV->getModifier()), | 
|  | 614 | OutContext); | 
| Mehdi Amini | bd7287e | 2015-07-16 06:11:10 +0000 | [diff] [blame] | 615 | uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType()); | 
| Ulrich Weigand | 5f613df | 2013-05-06 16:15:19 +0000 | [diff] [blame] | 616 |  | 
| Lang Hames | 9ff69c8 | 2015-04-24 19:11:51 +0000 | [diff] [blame] | 617 | OutStreamer->EmitValue(Expr, Size); | 
| Ulrich Weigand | 5f613df | 2013-05-06 16:15:19 +0000 | [diff] [blame] | 618 | } | 
|  | 619 |  | 
| Nick Desaulniers | 5277b3f | 2019-04-10 16:38:43 +0000 | [diff] [blame] | 620 | bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, | 
| Ulrich Weigand | 5f613df | 2013-05-06 16:15:19 +0000 | [diff] [blame] | 621 | const char *ExtraCode, | 
|  | 622 | raw_ostream &OS) { | 
| Nick Desaulniers | 7ab164c | 2019-04-26 18:45:04 +0000 | [diff] [blame] | 623 | if (ExtraCode) | 
|  | 624 | return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS); | 
|  | 625 | SystemZMCInstLower Lower(MF->getContext(), *this); | 
|  | 626 | MCOperand MO(Lower.lowerOperand(MI->getOperand(OpNo))); | 
|  | 627 | SystemZInstPrinter::printOperand(MO, MAI, OS); | 
| Ulrich Weigand | 5f613df | 2013-05-06 16:15:19 +0000 | [diff] [blame] | 628 | return false; | 
|  | 629 | } | 
|  | 630 |  | 
|  | 631 | bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, | 
|  | 632 | unsigned OpNo, | 
| Ulrich Weigand | 5f613df | 2013-05-06 16:15:19 +0000 | [diff] [blame] | 633 | const char *ExtraCode, | 
|  | 634 | raw_ostream &OS) { | 
|  | 635 | SystemZInstPrinter::printAddress(MI->getOperand(OpNo).getReg(), | 
|  | 636 | MI->getOperand(OpNo + 1).getImm(), | 
|  | 637 | MI->getOperand(OpNo + 2).getReg(), OS); | 
|  | 638 | return false; | 
|  | 639 | } | 
|  | 640 |  | 
| Ulrich Weigand | 5eb6411 | 2018-03-02 20:39:30 +0000 | [diff] [blame] | 641 | void SystemZAsmPrinter::EmitEndOfAsmFile(Module &M) { | 
| Than McIntosh | 30c804b | 2018-11-26 18:43:48 +0000 | [diff] [blame] | 642 | emitStackMaps(SM); | 
| Ulrich Weigand | 5eb6411 | 2018-03-02 20:39:30 +0000 | [diff] [blame] | 643 | } | 
|  | 644 |  | 
| Ulrich Weigand | 5f613df | 2013-05-06 16:15:19 +0000 | [diff] [blame] | 645 | // Force static initialization. | 
|  | 646 | extern "C" void LLVMInitializeSystemZAsmPrinter() { | 
| Mehdi Amini | f42454b | 2016-10-09 23:00:34 +0000 | [diff] [blame] | 647 | RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget()); | 
| Ulrich Weigand | 5f613df | 2013-05-06 16:15:19 +0000 | [diff] [blame] | 648 | } |