1 //===-- X86ATTInstPrinter.cpp - AT&T assembly instruction printing --------===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file includes code for rendering MCInst instances as AT&T-style 10 // assembly. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "X86ATTInstPrinter.h" 15 #include "X86BaseInfo.h" 16 #include "X86InstComments.h" 17 #include "llvm/MC/MCExpr.h" 18 #include "llvm/MC/MCInst.h" 19 #include "llvm/MC/MCInstrInfo.h" 20 #include "llvm/MC/MCSubtargetInfo.h" 21 #include "llvm/Support/Casting.h" 22 #include "llvm/Support/ErrorHandling.h" 23 #include "llvm/Support/Format.h" 24 #include "llvm/Support/raw_ostream.h" 25 #include <cassert> 26 #include <cinttypes> 27 #include <cstdint> 28 29 using namespace llvm; 30 31 #define DEBUG_TYPE "asm-printer" 32 33 // Include the auto-generated portion of the assembly writer. 34 #define PRINT_ALIAS_INSTR 35 #include "X86GenAsmWriter.inc" 36 37 void X86ATTInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { 38 OS << markup("<reg:") << '%' << getRegisterName(RegNo) << markup(">"); 39 } 40 41 void X86ATTInstPrinter::printInst(const MCInst *MI, uint64_t Address, 42 StringRef Annot, const MCSubtargetInfo &STI, 43 raw_ostream &OS) { 44 // If verbose assembly is enabled, we can print some informative comments. 45 if (CommentStream) 46 HasCustomInstComment = EmitAnyX86InstComments(MI, *CommentStream, MII); 47 48 printInstFlags(MI, OS); 49 50 // Output CALLpcrel32 as "callq" in 64-bit mode. 51 // In Intel annotation it's always emitted as "call". 52 // 53 // TODO: Probably this hack should be redesigned via InstAlias in 54 // InstrInfo.td as soon as Requires clause is supported properly 55 // for InstAlias. 56 if (MI->getOpcode() == X86::CALLpcrel32 && 57 (STI.getFeatureBits()[X86::Mode64Bit])) { 58 OS << "\tcallq\t"; 59 printPCRelImm(MI, Address, 0, OS); 60 } 61 // data16 and data32 both have the same encoding of 0x66. While data32 is 62 // valid only in 16 bit systems, data16 is valid in the rest. 63 // There seems to be some lack of support of the Requires clause that causes 64 // 0x66 to be interpreted as "data16" by the asm printer. 65 // Thus we add an adjustment here in order to print the "right" instruction. 66 else if (MI->getOpcode() == X86::DATA16_PREFIX && 67 STI.getFeatureBits()[X86::Mode16Bit]) { 68 OS << "\tdata32"; 69 } 70 // Try to print any aliases first. 71 else if (!printAliasInstr(MI, Address, OS) && !printVecCompareInstr(MI, OS)) 72 printInstruction(MI, Address, OS); 73 74 // Next always print the annotation. 75 printAnnotation(OS, Annot); 76 } 77 78 bool X86ATTInstPrinter::printVecCompareInstr(const MCInst *MI, 79 raw_ostream &OS) { 80 if (MI->getNumOperands() == 0 || 81 !MI->getOperand(MI->getNumOperands() - 1).isImm()) 82 return false; 83 84 int64_t Imm = MI->getOperand(MI->getNumOperands() - 1).getImm(); 85 86 const MCInstrDesc &Desc = MII.get(MI->getOpcode()); 87 88 // Custom print the vector compare instructions to get the immediate 89 // translated into the mnemonic. 90 switch (MI->getOpcode()) { 91 case X86::CMPPDrmi: case X86::CMPPDrri: 92 case X86::CMPPSrmi: case X86::CMPPSrri: 93 case X86::CMPSDrm: case X86::CMPSDrr: 94 case X86::CMPSDrm_Int: case X86::CMPSDrr_Int: 95 case X86::CMPSSrm: case X86::CMPSSrr: 96 case X86::CMPSSrm_Int: case X86::CMPSSrr_Int: 97 if (Imm >= 0 && Imm <= 7) { 98 OS << '\t'; 99 printCMPMnemonic(MI, /*IsVCMP*/false, OS); 100 101 if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) { 102 if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XS) 103 printdwordmem(MI, 2, OS); 104 else if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XD) 105 printqwordmem(MI, 2, OS); 106 else 107 printxmmwordmem(MI, 2, OS); 108 } else 109 printOperand(MI, 2, OS); 110 111 // Skip operand 1 as its tied to the dest. 112 113 OS << ", "; 114 printOperand(MI, 0, OS); 115 return true; 116 } 117 break; 118 119 case X86::VCMPPDrmi: case X86::VCMPPDrri: 120 case X86::VCMPPDYrmi: case X86::VCMPPDYrri: 121 case X86::VCMPPDZ128rmi: case X86::VCMPPDZ128rri: 122 case X86::VCMPPDZ256rmi: case X86::VCMPPDZ256rri: 123 case X86::VCMPPDZrmi: case X86::VCMPPDZrri: 124 case X86::VCMPPSrmi: case X86::VCMPPSrri: 125 case X86::VCMPPSYrmi: case X86::VCMPPSYrri: 126 case X86::VCMPPSZ128rmi: case X86::VCMPPSZ128rri: 127 case X86::VCMPPSZ256rmi: case X86::VCMPPSZ256rri: 128 case X86::VCMPPSZrmi: case X86::VCMPPSZrri: 129 case X86::VCMPSDrm: case X86::VCMPSDrr: 130 case X86::VCMPSDZrm: case X86::VCMPSDZrr: 131 case X86::VCMPSDrm_Int: case X86::VCMPSDrr_Int: 132 case X86::VCMPSDZrm_Int: case X86::VCMPSDZrr_Int: 133 case X86::VCMPSSrm: case X86::VCMPSSrr: 134 case X86::VCMPSSZrm: case X86::VCMPSSZrr: 135 case X86::VCMPSSrm_Int: case X86::VCMPSSrr_Int: 136 case X86::VCMPSSZrm_Int: case X86::VCMPSSZrr_Int: 137 case X86::VCMPPDZ128rmik: case X86::VCMPPDZ128rrik: 138 case X86::VCMPPDZ256rmik: case X86::VCMPPDZ256rrik: 139 case X86::VCMPPDZrmik: case X86::VCMPPDZrrik: 140 case X86::VCMPPSZ128rmik: case X86::VCMPPSZ128rrik: 141 case X86::VCMPPSZ256rmik: case X86::VCMPPSZ256rrik: 142 case X86::VCMPPSZrmik: case X86::VCMPPSZrrik: 143 case X86::VCMPSDZrm_Intk: case X86::VCMPSDZrr_Intk: 144 case X86::VCMPSSZrm_Intk: case X86::VCMPSSZrr_Intk: 145 case X86::VCMPPDZ128rmbi: case X86::VCMPPDZ128rmbik: 146 case X86::VCMPPDZ256rmbi: case X86::VCMPPDZ256rmbik: 147 case X86::VCMPPDZrmbi: case X86::VCMPPDZrmbik: 148 case X86::VCMPPSZ128rmbi: case X86::VCMPPSZ128rmbik: 149 case X86::VCMPPSZ256rmbi: case X86::VCMPPSZ256rmbik: 150 case X86::VCMPPSZrmbi: case X86::VCMPPSZrmbik: 151 case X86::VCMPPDZrrib: case X86::VCMPPDZrribk: 152 case X86::VCMPPSZrrib: case X86::VCMPPSZrribk: 153 case X86::VCMPSDZrrb_Int: case X86::VCMPSDZrrb_Intk: 154 case X86::VCMPSSZrrb_Int: case X86::VCMPSSZrrb_Intk: 155 if (Imm >= 0 && Imm <= 31) { 156 OS << '\t'; 157 printCMPMnemonic(MI, /*IsVCMP*/true, OS); 158 159 unsigned CurOp = (Desc.TSFlags & X86II::EVEX_K) ? 3 : 2; 160 161 if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) { 162 if (Desc.TSFlags & X86II::EVEX_B) { 163 // Broadcast form. 164 // Load size is based on W-bit. 165 if (Desc.TSFlags & X86II::VEX_W) 166 printqwordmem(MI, CurOp--, OS); 167 else 168 printdwordmem(MI, CurOp--, OS); 169 170 // Print the number of elements broadcasted. 171 unsigned NumElts; 172 if (Desc.TSFlags & X86II::EVEX_L2) 173 NumElts = (Desc.TSFlags & X86II::VEX_W) ? 8 : 16; 174 else if (Desc.TSFlags & X86II::VEX_L) 175 NumElts = (Desc.TSFlags & X86II::VEX_W) ? 4 : 8; 176 else 177 NumElts = (Desc.TSFlags & X86II::VEX_W) ? 2 : 4; 178 OS << "{1to" << NumElts << "}"; 179 } else { 180 if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XS) 181 printdwordmem(MI, CurOp--, OS); 182 else if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XD) 183 printqwordmem(MI, CurOp--, OS); 184 else if (Desc.TSFlags & X86II::EVEX_L2) 185 printzmmwordmem(MI, CurOp--, OS); 186 else if (Desc.TSFlags & X86II::VEX_L) 187 printymmwordmem(MI, CurOp--, OS); 188 else 189 printxmmwordmem(MI, CurOp--, OS); 190 } 191 } else { 192 if (Desc.TSFlags & X86II::EVEX_B) 193 OS << "{sae}, "; 194 printOperand(MI, CurOp--, OS); 195 } 196 197 OS << ", "; 198 printOperand(MI, CurOp--, OS); 199 OS << ", "; 200 printOperand(MI, 0, OS); 201 if (CurOp > 0) { 202 // Print mask operand. 203 OS << " {"; 204 printOperand(MI, CurOp--, OS); 205 OS << "}"; 206 } 207 208 return true; 209 } 210 break; 211 212 case X86::VPCOMBmi: case X86::VPCOMBri: 213 case X86::VPCOMDmi: case X86::VPCOMDri: 214 case X86::VPCOMQmi: case X86::VPCOMQri: 215 case X86::VPCOMUBmi: case X86::VPCOMUBri: 216 case X86::VPCOMUDmi: case X86::VPCOMUDri: 217 case X86::VPCOMUQmi: case X86::VPCOMUQri: 218 case X86::VPCOMUWmi: case X86::VPCOMUWri: 219 case X86::VPCOMWmi: case X86::VPCOMWri: 220 if (Imm >= 0 && Imm <= 7) { 221 OS << '\t'; 222 printVPCOMMnemonic(MI, OS); 223 224 if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) 225 printxmmwordmem(MI, 2, OS); 226 else 227 printOperand(MI, 2, OS); 228 229 OS << ", "; 230 printOperand(MI, 1, OS); 231 OS << ", "; 232 printOperand(MI, 0, OS); 233 return true; 234 } 235 break; 236 237 case X86::VPCMPBZ128rmi: case X86::VPCMPBZ128rri: 238 case X86::VPCMPBZ256rmi: case X86::VPCMPBZ256rri: 239 case X86::VPCMPBZrmi: case X86::VPCMPBZrri: 240 case X86::VPCMPDZ128rmi: case X86::VPCMPDZ128rri: 241 case X86::VPCMPDZ256rmi: case X86::VPCMPDZ256rri: 242 case X86::VPCMPDZrmi: case X86::VPCMPDZrri: 243 case X86::VPCMPQZ128rmi: case X86::VPCMPQZ128rri: 244 case X86::VPCMPQZ256rmi: case X86::VPCMPQZ256rri: 245 case X86::VPCMPQZrmi: case X86::VPCMPQZrri: 246 case X86::VPCMPUBZ128rmi: case X86::VPCMPUBZ128rri: 247 case X86::VPCMPUBZ256rmi: case X86::VPCMPUBZ256rri: 248 case X86::VPCMPUBZrmi: case X86::VPCMPUBZrri: 249 case X86::VPCMPUDZ128rmi: case X86::VPCMPUDZ128rri: 250 case X86::VPCMPUDZ256rmi: case X86::VPCMPUDZ256rri: 251 case X86::VPCMPUDZrmi: case X86::VPCMPUDZrri: 252 case X86::VPCMPUQZ128rmi: case X86::VPCMPUQZ128rri: 253 case X86::VPCMPUQZ256rmi: case X86::VPCMPUQZ256rri: 254 case X86::VPCMPUQZrmi: case X86::VPCMPUQZrri: 255 case X86::VPCMPUWZ128rmi: case X86::VPCMPUWZ128rri: 256 case X86::VPCMPUWZ256rmi: case X86::VPCMPUWZ256rri: 257 case X86::VPCMPUWZrmi: case X86::VPCMPUWZrri: 258 case X86::VPCMPWZ128rmi: case X86::VPCMPWZ128rri: 259 case X86::VPCMPWZ256rmi: case X86::VPCMPWZ256rri: 260 case X86::VPCMPWZrmi: case X86::VPCMPWZrri: 261 case X86::VPCMPBZ128rmik: case X86::VPCMPBZ128rrik: 262 case X86::VPCMPBZ256rmik: case X86::VPCMPBZ256rrik: 263 case X86::VPCMPBZrmik: case X86::VPCMPBZrrik: 264 case X86::VPCMPDZ128rmik: case X86::VPCMPDZ128rrik: 265 case X86::VPCMPDZ256rmik: case X86::VPCMPDZ256rrik: 266 case X86::VPCMPDZrmik: case X86::VPCMPDZrrik: 267 case X86::VPCMPQZ128rmik: case X86::VPCMPQZ128rrik: 268 case X86::VPCMPQZ256rmik: case X86::VPCMPQZ256rrik: 269 case X86::VPCMPQZrmik: case X86::VPCMPQZrrik: 270 case X86::VPCMPUBZ128rmik: case X86::VPCMPUBZ128rrik: 271 case X86::VPCMPUBZ256rmik: case X86::VPCMPUBZ256rrik: 272 case X86::VPCMPUBZrmik: case X86::VPCMPUBZrrik: 273 case X86::VPCMPUDZ128rmik: case X86::VPCMPUDZ128rrik: 274 case X86::VPCMPUDZ256rmik: case X86::VPCMPUDZ256rrik: 275 case X86::VPCMPUDZrmik: case X86::VPCMPUDZrrik: 276 case X86::VPCMPUQZ128rmik: case X86::VPCMPUQZ128rrik: 277 case X86::VPCMPUQZ256rmik: case X86::VPCMPUQZ256rrik: 278 case X86::VPCMPUQZrmik: case X86::VPCMPUQZrrik: 279 case X86::VPCMPUWZ128rmik: case X86::VPCMPUWZ128rrik: 280 case X86::VPCMPUWZ256rmik: case X86::VPCMPUWZ256rrik: 281 case X86::VPCMPUWZrmik: case X86::VPCMPUWZrrik: 282 case X86::VPCMPWZ128rmik: case X86::VPCMPWZ128rrik: 283 case X86::VPCMPWZ256rmik: case X86::VPCMPWZ256rrik: 284 case X86::VPCMPWZrmik: case X86::VPCMPWZrrik: 285 case X86::VPCMPDZ128rmib: case X86::VPCMPDZ128rmibk: 286 case X86::VPCMPDZ256rmib: case X86::VPCMPDZ256rmibk: 287 case X86::VPCMPDZrmib: case X86::VPCMPDZrmibk: 288 case X86::VPCMPQZ128rmib: case X86::VPCMPQZ128rmibk: 289 case X86::VPCMPQZ256rmib: case X86::VPCMPQZ256rmibk: 290 case X86::VPCMPQZrmib: case X86::VPCMPQZrmibk: 291 case X86::VPCMPUDZ128rmib: case X86::VPCMPUDZ128rmibk: 292 case X86::VPCMPUDZ256rmib: case X86::VPCMPUDZ256rmibk: 293 case X86::VPCMPUDZrmib: case X86::VPCMPUDZrmibk: 294 case X86::VPCMPUQZ128rmib: case X86::VPCMPUQZ128rmibk: 295 case X86::VPCMPUQZ256rmib: case X86::VPCMPUQZ256rmibk: 296 case X86::VPCMPUQZrmib: case X86::VPCMPUQZrmibk: 297 if ((Imm >= 0 && Imm <= 2) || (Imm >= 4 && Imm <= 6)) { 298 OS << '\t'; 299 printVPCMPMnemonic(MI, OS); 300 301 unsigned CurOp = (Desc.TSFlags & X86II::EVEX_K) ? 3 : 2; 302 303 if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) { 304 if (Desc.TSFlags & X86II::EVEX_B) { 305 // Broadcast form. 306 // Load size is based on W-bit as only D and Q are supported. 307 if (Desc.TSFlags & X86II::VEX_W) 308 printqwordmem(MI, CurOp--, OS); 309 else 310 printdwordmem(MI, CurOp--, OS); 311 312 // Print the number of elements broadcasted. 313 unsigned NumElts; 314 if (Desc.TSFlags & X86II::EVEX_L2) 315 NumElts = (Desc.TSFlags & X86II::VEX_W) ? 8 : 16; 316 else if (Desc.TSFlags & X86II::VEX_L) 317 NumElts = (Desc.TSFlags & X86II::VEX_W) ? 4 : 8; 318 else 319 NumElts = (Desc.TSFlags & X86II::VEX_W) ? 2 : 4; 320 OS << "{1to" << NumElts << "}"; 321 } else { 322 if (Desc.TSFlags & X86II::EVEX_L2) 323 printzmmwordmem(MI, CurOp--, OS); 324 else if (Desc.TSFlags & X86II::VEX_L) 325 printymmwordmem(MI, CurOp--, OS); 326 else 327 printxmmwordmem(MI, CurOp--, OS); 328 } 329 } else { 330 printOperand(MI, CurOp--, OS); 331 } 332 333 OS << ", "; 334 printOperand(MI, CurOp--, OS); 335 OS << ", "; 336 printOperand(MI, 0, OS); 337 if (CurOp > 0) { 338 // Print mask operand. 339 OS << " {"; 340 printOperand(MI, CurOp--, OS); 341 OS << "}"; 342 } 343 344 return true; 345 } 346 break; 347 } 348 349 return false; 350 } 351 352 void X86ATTInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 353 raw_ostream &O) { 354 const MCOperand &Op = MI->getOperand(OpNo); 355 if (Op.isReg()) { 356 printRegName(O, Op.getReg()); 357 } else if (Op.isImm()) { 358 // Print immediates as signed values. 359 int64_t Imm = Op.getImm(); 360 O << markup("<imm:") << '$' << formatImm(Imm) << markup(">"); 361 362 // TODO: This should be in a helper function in the base class, so it can 363 // be used by other printers. 364 365 // If there are no instruction-specific comments, add a comment clarifying 366 // the hex value of the immediate operand when it isn't in the range 367 // [-256,255]. 368 if (CommentStream && !HasCustomInstComment && (Imm > 255 || Imm < -256)) { 369 // Don't print unnecessary hex sign bits. 370 if (Imm == (int16_t)(Imm)) 371 *CommentStream << format("imm = 0x%" PRIX16 "\n", (uint16_t)Imm); 372 else if (Imm == (int32_t)(Imm)) 373 *CommentStream << format("imm = 0x%" PRIX32 "\n", (uint32_t)Imm); 374 else 375 *CommentStream << format("imm = 0x%" PRIX64 "\n", (uint64_t)Imm); 376 } 377 } else { 378 assert(Op.isExpr() && "unknown operand kind in printOperand"); 379 O << markup("<imm:") << '$'; 380 Op.getExpr()->print(O, &MAI); 381 O << markup(">"); 382 } 383 } 384 385 void X86ATTInstPrinter::printMemReference(const MCInst *MI, unsigned Op, 386 raw_ostream &O) { 387 const MCOperand &BaseReg = MI->getOperand(Op + X86::AddrBaseReg); 388 const MCOperand &IndexReg = MI->getOperand(Op + X86::AddrIndexReg); 389 const MCOperand &DispSpec = MI->getOperand(Op + X86::AddrDisp); 390 391 O << markup("<mem:"); 392 393 // If this has a segment register, print it. 394 printOptionalSegReg(MI, Op + X86::AddrSegmentReg, O); 395 396 if (DispSpec.isImm()) { 397 int64_t DispVal = DispSpec.getImm(); 398 if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) 399 O << formatImm(DispVal); 400 } else { 401 assert(DispSpec.isExpr() && "non-immediate displacement for LEA?"); 402 DispSpec.getExpr()->print(O, &MAI); 403 } 404 405 if (IndexReg.getReg() || BaseReg.getReg()) { 406 O << '('; 407 if (BaseReg.getReg()) 408 printOperand(MI, Op + X86::AddrBaseReg, O); 409 410 if (IndexReg.getReg()) { 411 O << ','; 412 printOperand(MI, Op + X86::AddrIndexReg, O); 413 unsigned ScaleVal = MI->getOperand(Op + X86::AddrScaleAmt).getImm(); 414 if (ScaleVal != 1) { 415 O << ',' << markup("<imm:") << ScaleVal // never printed in hex. 416 << markup(">"); 417 } 418 } 419 O << ')'; 420 } 421 422 O << markup(">"); 423 } 424 425 void X86ATTInstPrinter::printSrcIdx(const MCInst *MI, unsigned Op, 426 raw_ostream &O) { 427 O << markup("<mem:"); 428 429 // If this has a segment register, print it. 430 printOptionalSegReg(MI, Op + 1, O); 431 432 O << "("; 433 printOperand(MI, Op, O); 434 O << ")"; 435 436 O << markup(">"); 437 } 438 439 void X86ATTInstPrinter::printDstIdx(const MCInst *MI, unsigned Op, 440 raw_ostream &O) { 441 O << markup("<mem:"); 442 443 O << "%es:("; 444 printOperand(MI, Op, O); 445 O << ")"; 446 447 O << markup(">"); 448 } 449 450 void X86ATTInstPrinter::printMemOffset(const MCInst *MI, unsigned Op, 451 raw_ostream &O) { 452 const MCOperand &DispSpec = MI->getOperand(Op); 453 454 O << markup("<mem:"); 455 456 // If this has a segment register, print it. 457 printOptionalSegReg(MI, Op + 1, O); 458 459 if (DispSpec.isImm()) { 460 O << formatImm(DispSpec.getImm()); 461 } else { 462 assert(DispSpec.isExpr() && "non-immediate displacement?"); 463 DispSpec.getExpr()->print(O, &MAI); 464 } 465 466 O << markup(">"); 467 } 468 469 void X86ATTInstPrinter::printU8Imm(const MCInst *MI, unsigned Op, 470 raw_ostream &O) { 471 if (MI->getOperand(Op).isExpr()) 472 return printOperand(MI, Op, O); 473 474 O << markup("<imm:") << '$' << formatImm(MI->getOperand(Op).getImm() & 0xff) 475 << markup(">"); 476 } 477 478 void X86ATTInstPrinter::printSTiRegOperand(const MCInst *MI, unsigned OpNo, 479 raw_ostream &OS) { 480 const MCOperand &Op = MI->getOperand(OpNo); 481 unsigned Reg = Op.getReg(); 482 // Override the default printing to print st(0) instead st. 483 if (Reg == X86::ST0) 484 OS << markup("<reg:") << "%st(0)" << markup(">"); 485 else 486 printRegName(OS, Reg); 487 } 488