1 //===--- X86InstPrinterCommon.cpp - X86 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 common code for rendering MCInst instances as Intel-style 10 // and Intel-style assembly. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "X86InstPrinterCommon.h" 15 #include "X86BaseInfo.h" 16 #include "llvm/MC/MCAsmInfo.h" 17 #include "llvm/MC/MCExpr.h" 18 #include "llvm/MC/MCInst.h" 19 #include "llvm/MC/MCInstrDesc.h" 20 #include "llvm/MC/MCInstrInfo.h" 21 #include "llvm/MC/MCSubtargetInfo.h" 22 #include "llvm/Support/Casting.h" 23 #include "llvm/Support/raw_ostream.h" 24 #include <cassert> 25 #include <cstdint> 26 27 using namespace llvm; 28 29 void X86InstPrinterCommon::printCondCode(const MCInst *MI, unsigned Op, 30 raw_ostream &O) { 31 int64_t Imm = MI->getOperand(Op).getImm(); 32 unsigned Opc = MI->getOpcode(); 33 bool IsCMPCCXADD = X86::isCMPCCXADD(Opc); 34 bool IsCCMPOrCTEST = X86::isCCMPCC(Opc) || X86::isCTESTCC(Opc); 35 36 // clang-format off 37 switch (Imm) { 38 default: llvm_unreachable("Invalid condcode argument!"); 39 case 0: O << "o"; break; 40 case 1: O << "no"; break; 41 case 2: O << "b"; break; 42 case 3: O << (IsCMPCCXADD ? "nb" : "ae"); break; 43 case 4: O << (IsCMPCCXADD ? "z" : "e"); break; 44 case 5: O << (IsCMPCCXADD ? "nz" : "ne"); break; 45 case 6: O << "be"; break; 46 case 7: O << (IsCMPCCXADD ? "nbe" : "a"); break; 47 case 8: O << "s"; break; 48 case 9: O << "ns"; break; 49 case 0xa: O << (IsCCMPOrCTEST ? "t" : "p"); break; 50 case 0xb: O << (IsCCMPOrCTEST ? "f" : "np"); break; 51 case 0xc: O << "l"; break; 52 case 0xd: O << (IsCMPCCXADD ? "nl" : "ge"); break; 53 case 0xe: O << "le"; break; 54 case 0xf: O << (IsCMPCCXADD ? "nle" : "g"); break; 55 } 56 // clang-format on 57 } 58 59 void X86InstPrinterCommon::printCondFlags(const MCInst *MI, unsigned Op, 60 raw_ostream &O) { 61 // +----+----+----+----+ 62 // | OF | SF | ZF | CF | 63 // +----+----+----+----+ 64 int64_t Imm = MI->getOperand(Op).getImm(); 65 assert(Imm >= 0 && Imm < 16 && "Invalid condition flags"); 66 O << "{dfv="; 67 std::string Flags; 68 if (Imm & 0x8) 69 Flags += "of,"; 70 if (Imm & 0x4) 71 Flags += "sf,"; 72 if (Imm & 0x2) 73 Flags += "zf,"; 74 if (Imm & 0x1) 75 Flags += "cf,"; 76 StringRef SimplifiedFlags = StringRef(Flags).rtrim(","); 77 O << SimplifiedFlags << "}"; 78 } 79 80 void X86InstPrinterCommon::printSSEAVXCC(const MCInst *MI, unsigned Op, 81 raw_ostream &O) { 82 int64_t Imm = MI->getOperand(Op).getImm(); 83 switch (Imm) { 84 default: llvm_unreachable("Invalid ssecc/avxcc argument!"); 85 case 0: O << "eq"; break; 86 case 1: O << "lt"; break; 87 case 2: O << "le"; break; 88 case 3: O << "unord"; break; 89 case 4: O << "neq"; break; 90 case 5: O << "nlt"; break; 91 case 6: O << "nle"; break; 92 case 7: O << "ord"; break; 93 case 8: O << "eq_uq"; break; 94 case 9: O << "nge"; break; 95 case 0xa: O << "ngt"; break; 96 case 0xb: O << "false"; break; 97 case 0xc: O << "neq_oq"; break; 98 case 0xd: O << "ge"; break; 99 case 0xe: O << "gt"; break; 100 case 0xf: O << "true"; break; 101 case 0x10: O << "eq_os"; break; 102 case 0x11: O << "lt_oq"; break; 103 case 0x12: O << "le_oq"; break; 104 case 0x13: O << "unord_s"; break; 105 case 0x14: O << "neq_us"; break; 106 case 0x15: O << "nlt_uq"; break; 107 case 0x16: O << "nle_uq"; break; 108 case 0x17: O << "ord_s"; break; 109 case 0x18: O << "eq_us"; break; 110 case 0x19: O << "nge_uq"; break; 111 case 0x1a: O << "ngt_uq"; break; 112 case 0x1b: O << "false_os"; break; 113 case 0x1c: O << "neq_os"; break; 114 case 0x1d: O << "ge_oq"; break; 115 case 0x1e: O << "gt_oq"; break; 116 case 0x1f: O << "true_us"; break; 117 } 118 } 119 120 void X86InstPrinterCommon::printVPCOMMnemonic(const MCInst *MI, 121 raw_ostream &OS) { 122 OS << "vpcom"; 123 124 int64_t Imm = MI->getOperand(MI->getNumOperands() - 1).getImm(); 125 switch (Imm) { 126 default: llvm_unreachable("Invalid vpcom argument!"); 127 case 0: OS << "lt"; break; 128 case 1: OS << "le"; break; 129 case 2: OS << "gt"; break; 130 case 3: OS << "ge"; break; 131 case 4: OS << "eq"; break; 132 case 5: OS << "neq"; break; 133 case 6: OS << "false"; break; 134 case 7: OS << "true"; break; 135 } 136 137 switch (MI->getOpcode()) { 138 default: llvm_unreachable("Unexpected opcode!"); 139 case X86::VPCOMBmi: case X86::VPCOMBri: OS << "b\t"; break; 140 case X86::VPCOMDmi: case X86::VPCOMDri: OS << "d\t"; break; 141 case X86::VPCOMQmi: case X86::VPCOMQri: OS << "q\t"; break; 142 case X86::VPCOMUBmi: case X86::VPCOMUBri: OS << "ub\t"; break; 143 case X86::VPCOMUDmi: case X86::VPCOMUDri: OS << "ud\t"; break; 144 case X86::VPCOMUQmi: case X86::VPCOMUQri: OS << "uq\t"; break; 145 case X86::VPCOMUWmi: case X86::VPCOMUWri: OS << "uw\t"; break; 146 case X86::VPCOMWmi: case X86::VPCOMWri: OS << "w\t"; break; 147 } 148 } 149 150 void X86InstPrinterCommon::printVPCMPMnemonic(const MCInst *MI, 151 raw_ostream &OS) { 152 OS << "vpcmp"; 153 154 printSSEAVXCC(MI, MI->getNumOperands() - 1, OS); 155 156 switch (MI->getOpcode()) { 157 default: llvm_unreachable("Unexpected opcode!"); 158 case X86::VPCMPBZ128rmi: case X86::VPCMPBZ128rri: 159 case X86::VPCMPBZ256rmi: case X86::VPCMPBZ256rri: 160 case X86::VPCMPBZrmi: case X86::VPCMPBZrri: 161 case X86::VPCMPBZ128rmik: case X86::VPCMPBZ128rrik: 162 case X86::VPCMPBZ256rmik: case X86::VPCMPBZ256rrik: 163 case X86::VPCMPBZrmik: case X86::VPCMPBZrrik: 164 OS << "b\t"; 165 break; 166 case X86::VPCMPDZ128rmi: case X86::VPCMPDZ128rri: 167 case X86::VPCMPDZ256rmi: case X86::VPCMPDZ256rri: 168 case X86::VPCMPDZrmi: case X86::VPCMPDZrri: 169 case X86::VPCMPDZ128rmik: case X86::VPCMPDZ128rrik: 170 case X86::VPCMPDZ256rmik: case X86::VPCMPDZ256rrik: 171 case X86::VPCMPDZrmik: case X86::VPCMPDZrrik: 172 case X86::VPCMPDZ128rmib: case X86::VPCMPDZ128rmibk: 173 case X86::VPCMPDZ256rmib: case X86::VPCMPDZ256rmibk: 174 case X86::VPCMPDZrmib: case X86::VPCMPDZrmibk: 175 OS << "d\t"; 176 break; 177 case X86::VPCMPQZ128rmi: case X86::VPCMPQZ128rri: 178 case X86::VPCMPQZ256rmi: case X86::VPCMPQZ256rri: 179 case X86::VPCMPQZrmi: case X86::VPCMPQZrri: 180 case X86::VPCMPQZ128rmik: case X86::VPCMPQZ128rrik: 181 case X86::VPCMPQZ256rmik: case X86::VPCMPQZ256rrik: 182 case X86::VPCMPQZrmik: case X86::VPCMPQZrrik: 183 case X86::VPCMPQZ128rmib: case X86::VPCMPQZ128rmibk: 184 case X86::VPCMPQZ256rmib: case X86::VPCMPQZ256rmibk: 185 case X86::VPCMPQZrmib: case X86::VPCMPQZrmibk: 186 OS << "q\t"; 187 break; 188 case X86::VPCMPUBZ128rmi: case X86::VPCMPUBZ128rri: 189 case X86::VPCMPUBZ256rmi: case X86::VPCMPUBZ256rri: 190 case X86::VPCMPUBZrmi: case X86::VPCMPUBZrri: 191 case X86::VPCMPUBZ128rmik: case X86::VPCMPUBZ128rrik: 192 case X86::VPCMPUBZ256rmik: case X86::VPCMPUBZ256rrik: 193 case X86::VPCMPUBZrmik: case X86::VPCMPUBZrrik: 194 OS << "ub\t"; 195 break; 196 case X86::VPCMPUDZ128rmi: case X86::VPCMPUDZ128rri: 197 case X86::VPCMPUDZ256rmi: case X86::VPCMPUDZ256rri: 198 case X86::VPCMPUDZrmi: case X86::VPCMPUDZrri: 199 case X86::VPCMPUDZ128rmik: case X86::VPCMPUDZ128rrik: 200 case X86::VPCMPUDZ256rmik: case X86::VPCMPUDZ256rrik: 201 case X86::VPCMPUDZrmik: case X86::VPCMPUDZrrik: 202 case X86::VPCMPUDZ128rmib: case X86::VPCMPUDZ128rmibk: 203 case X86::VPCMPUDZ256rmib: case X86::VPCMPUDZ256rmibk: 204 case X86::VPCMPUDZrmib: case X86::VPCMPUDZrmibk: 205 OS << "ud\t"; 206 break; 207 case X86::VPCMPUQZ128rmi: case X86::VPCMPUQZ128rri: 208 case X86::VPCMPUQZ256rmi: case X86::VPCMPUQZ256rri: 209 case X86::VPCMPUQZrmi: case X86::VPCMPUQZrri: 210 case X86::VPCMPUQZ128rmik: case X86::VPCMPUQZ128rrik: 211 case X86::VPCMPUQZ256rmik: case X86::VPCMPUQZ256rrik: 212 case X86::VPCMPUQZrmik: case X86::VPCMPUQZrrik: 213 case X86::VPCMPUQZ128rmib: case X86::VPCMPUQZ128rmibk: 214 case X86::VPCMPUQZ256rmib: case X86::VPCMPUQZ256rmibk: 215 case X86::VPCMPUQZrmib: case X86::VPCMPUQZrmibk: 216 OS << "uq\t"; 217 break; 218 case X86::VPCMPUWZ128rmi: case X86::VPCMPUWZ128rri: 219 case X86::VPCMPUWZ256rri: case X86::VPCMPUWZ256rmi: 220 case X86::VPCMPUWZrmi: case X86::VPCMPUWZrri: 221 case X86::VPCMPUWZ128rmik: case X86::VPCMPUWZ128rrik: 222 case X86::VPCMPUWZ256rrik: case X86::VPCMPUWZ256rmik: 223 case X86::VPCMPUWZrmik: case X86::VPCMPUWZrrik: 224 OS << "uw\t"; 225 break; 226 case X86::VPCMPWZ128rmi: case X86::VPCMPWZ128rri: 227 case X86::VPCMPWZ256rmi: case X86::VPCMPWZ256rri: 228 case X86::VPCMPWZrmi: case X86::VPCMPWZrri: 229 case X86::VPCMPWZ128rmik: case X86::VPCMPWZ128rrik: 230 case X86::VPCMPWZ256rmik: case X86::VPCMPWZ256rrik: 231 case X86::VPCMPWZrmik: case X86::VPCMPWZrrik: 232 OS << "w\t"; 233 break; 234 } 235 } 236 237 void X86InstPrinterCommon::printCMPMnemonic(const MCInst *MI, bool IsVCmp, 238 raw_ostream &OS) { 239 OS << (IsVCmp ? "vcmp" : "cmp"); 240 241 printSSEAVXCC(MI, MI->getNumOperands() - 1, OS); 242 243 switch (MI->getOpcode()) { 244 default: llvm_unreachable("Unexpected opcode!"); 245 case X86::CMPPDrmi: case X86::CMPPDrri: 246 case X86::VCMPPDrmi: case X86::VCMPPDrri: 247 case X86::VCMPPDYrmi: case X86::VCMPPDYrri: 248 case X86::VCMPPDZ128rmi: case X86::VCMPPDZ128rri: 249 case X86::VCMPPDZ256rmi: case X86::VCMPPDZ256rri: 250 case X86::VCMPPDZrmi: case X86::VCMPPDZrri: 251 case X86::VCMPPDZ128rmik: case X86::VCMPPDZ128rrik: 252 case X86::VCMPPDZ256rmik: case X86::VCMPPDZ256rrik: 253 case X86::VCMPPDZrmik: case X86::VCMPPDZrrik: 254 case X86::VCMPPDZ128rmbi: case X86::VCMPPDZ128rmbik: 255 case X86::VCMPPDZ256rmbi: case X86::VCMPPDZ256rmbik: 256 case X86::VCMPPDZrmbi: case X86::VCMPPDZrmbik: 257 case X86::VCMPPDZrrib: case X86::VCMPPDZrribk: 258 OS << "pd\t"; 259 break; 260 case X86::CMPPSrmi: case X86::CMPPSrri: 261 case X86::VCMPPSrmi: case X86::VCMPPSrri: 262 case X86::VCMPPSYrmi: case X86::VCMPPSYrri: 263 case X86::VCMPPSZ128rmi: case X86::VCMPPSZ128rri: 264 case X86::VCMPPSZ256rmi: case X86::VCMPPSZ256rri: 265 case X86::VCMPPSZrmi: case X86::VCMPPSZrri: 266 case X86::VCMPPSZ128rmik: case X86::VCMPPSZ128rrik: 267 case X86::VCMPPSZ256rmik: case X86::VCMPPSZ256rrik: 268 case X86::VCMPPSZrmik: case X86::VCMPPSZrrik: 269 case X86::VCMPPSZ128rmbi: case X86::VCMPPSZ128rmbik: 270 case X86::VCMPPSZ256rmbi: case X86::VCMPPSZ256rmbik: 271 case X86::VCMPPSZrmbi: case X86::VCMPPSZrmbik: 272 case X86::VCMPPSZrrib: case X86::VCMPPSZrribk: 273 OS << "ps\t"; 274 break; 275 case X86::CMPSDrmi: case X86::CMPSDrri: 276 case X86::CMPSDrmi_Int: case X86::CMPSDrri_Int: 277 case X86::VCMPSDrmi: case X86::VCMPSDrri: 278 case X86::VCMPSDrmi_Int: case X86::VCMPSDrri_Int: 279 case X86::VCMPSDZrmi: case X86::VCMPSDZrri: 280 case X86::VCMPSDZrmi_Int: case X86::VCMPSDZrri_Int: 281 case X86::VCMPSDZrmi_Intk: case X86::VCMPSDZrri_Intk: 282 case X86::VCMPSDZrrib_Int: case X86::VCMPSDZrrib_Intk: 283 OS << "sd\t"; 284 break; 285 case X86::CMPSSrmi: case X86::CMPSSrri: 286 case X86::CMPSSrmi_Int: case X86::CMPSSrri_Int: 287 case X86::VCMPSSrmi: case X86::VCMPSSrri: 288 case X86::VCMPSSrmi_Int: case X86::VCMPSSrri_Int: 289 case X86::VCMPSSZrmi: case X86::VCMPSSZrri: 290 case X86::VCMPSSZrmi_Int: case X86::VCMPSSZrri_Int: 291 case X86::VCMPSSZrmi_Intk: case X86::VCMPSSZrri_Intk: 292 case X86::VCMPSSZrrib_Int: case X86::VCMPSSZrrib_Intk: 293 OS << "ss\t"; 294 break; 295 case X86::VCMPPHZ128rmi: case X86::VCMPPHZ128rri: 296 case X86::VCMPPHZ256rmi: case X86::VCMPPHZ256rri: 297 case X86::VCMPPHZrmi: case X86::VCMPPHZrri: 298 case X86::VCMPPHZ128rmik: case X86::VCMPPHZ128rrik: 299 case X86::VCMPPHZ256rmik: case X86::VCMPPHZ256rrik: 300 case X86::VCMPPHZrmik: case X86::VCMPPHZrrik: 301 case X86::VCMPPHZ128rmbi: case X86::VCMPPHZ128rmbik: 302 case X86::VCMPPHZ256rmbi: case X86::VCMPPHZ256rmbik: 303 case X86::VCMPPHZrmbi: case X86::VCMPPHZrmbik: 304 case X86::VCMPPHZrrib: case X86::VCMPPHZrribk: 305 OS << "ph\t"; 306 break; 307 case X86::VCMPSHZrmi: case X86::VCMPSHZrri: 308 case X86::VCMPSHZrmi_Int: case X86::VCMPSHZrri_Int: 309 case X86::VCMPSHZrrib_Int: case X86::VCMPSHZrrib_Intk: 310 case X86::VCMPSHZrmi_Intk: case X86::VCMPSHZrri_Intk: 311 OS << "sh\t"; 312 break; 313 } 314 } 315 316 void X86InstPrinterCommon::printRoundingControl(const MCInst *MI, unsigned Op, 317 raw_ostream &O) { 318 int64_t Imm = MI->getOperand(Op).getImm(); 319 switch (Imm) { 320 default: 321 llvm_unreachable("Invalid rounding control!"); 322 case X86::TO_NEAREST_INT: 323 O << "{rn-sae}"; 324 break; 325 case X86::TO_NEG_INF: 326 O << "{rd-sae}"; 327 break; 328 case X86::TO_POS_INF: 329 O << "{ru-sae}"; 330 break; 331 case X86::TO_ZERO: 332 O << "{rz-sae}"; 333 break; 334 } 335 } 336 337 /// value (e.g. for jumps and calls). In Intel-style these print slightly 338 /// differently than normal immediates. For example, a $ is not emitted. 339 /// 340 /// \p Address The address of the next instruction. 341 /// \see MCInstPrinter::printInst 342 void X86InstPrinterCommon::printPCRelImm(const MCInst *MI, uint64_t Address, 343 unsigned OpNo, raw_ostream &O) { 344 // Do not print the numberic target address when symbolizing. 345 if (SymbolizeOperands) 346 return; 347 348 const MCOperand &Op = MI->getOperand(OpNo); 349 if (Op.isImm()) { 350 if (PrintBranchImmAsAddress) { 351 uint64_t Target = Address + Op.getImm(); 352 if (MAI.getCodePointerSize() == 4) 353 Target &= 0xffffffff; 354 markup(O, Markup::Target) << formatHex(Target); 355 } else 356 markup(O, Markup::Immediate) << formatImm(Op.getImm()); 357 } else { 358 assert(Op.isExpr() && "unknown pcrel immediate operand"); 359 // If a symbolic branch target was added as a constant expression then print 360 // that address in hex. 361 const MCConstantExpr *BranchTarget = dyn_cast<MCConstantExpr>(Op.getExpr()); 362 int64_t Address; 363 if (BranchTarget && BranchTarget->evaluateAsAbsolute(Address)) { 364 markup(O, Markup::Immediate) << formatHex((uint64_t)Address); 365 } else { 366 // Otherwise, just print the expression. 367 Op.getExpr()->print(O, &MAI); 368 } 369 } 370 } 371 372 void X86InstPrinterCommon::printOptionalSegReg(const MCInst *MI, unsigned OpNo, 373 raw_ostream &O) { 374 if (MI->getOperand(OpNo).getReg()) { 375 printOperand(MI, OpNo, O); 376 O << ':'; 377 } 378 } 379 380 void X86InstPrinterCommon::printInstFlags(const MCInst *MI, raw_ostream &O, 381 const MCSubtargetInfo &STI) { 382 const MCInstrDesc &Desc = MII.get(MI->getOpcode()); 383 uint64_t TSFlags = Desc.TSFlags; 384 unsigned Flags = MI->getFlags(); 385 386 if ((TSFlags & X86II::LOCK) || (Flags & X86::IP_HAS_LOCK)) 387 O << "\tlock\t"; 388 389 if ((TSFlags & X86II::NOTRACK) || (Flags & X86::IP_HAS_NOTRACK)) 390 O << "\tnotrack\t"; 391 392 if (Flags & X86::IP_HAS_REPEAT_NE) 393 O << "\trepne\t"; 394 else if (Flags & X86::IP_HAS_REPEAT) 395 O << "\trep\t"; 396 397 if (TSFlags & X86II::EVEX_NF && !X86::isCFCMOVCC(MI->getOpcode())) 398 O << "\t{nf}"; 399 400 // These all require a pseudo prefix 401 if ((Flags & X86::IP_USE_VEX) || 402 (TSFlags & X86II::ExplicitOpPrefixMask) == X86II::ExplicitVEXPrefix) 403 O << "\t{vex}"; 404 else if (Flags & X86::IP_USE_VEX2) 405 O << "\t{vex2}"; 406 else if (Flags & X86::IP_USE_VEX3) 407 O << "\t{vex3}"; 408 else if ((Flags & X86::IP_USE_EVEX) || 409 (TSFlags & X86II::ExplicitOpPrefixMask) == X86II::ExplicitEVEXPrefix) 410 O << "\t{evex}"; 411 412 if (Flags & X86::IP_USE_DISP8) 413 O << "\t{disp8}"; 414 else if (Flags & X86::IP_USE_DISP32) 415 O << "\t{disp32}"; 416 417 // Determine where the memory operand starts, if present 418 int MemoryOperand = X86II::getMemoryOperandNo(TSFlags); 419 if (MemoryOperand != -1) 420 MemoryOperand += X86II::getOperandBias(Desc); 421 422 // Address-Size override prefix 423 if (Flags & X86::IP_HAS_AD_SIZE && 424 !X86_MC::needsAddressSizeOverride(*MI, STI, MemoryOperand, TSFlags)) { 425 if (STI.hasFeature(X86::Is16Bit) || STI.hasFeature(X86::Is64Bit)) 426 O << "\taddr32\t"; 427 else if (STI.hasFeature(X86::Is32Bit)) 428 O << "\taddr16\t"; 429 } 430 } 431 432 void X86InstPrinterCommon::printVKPair(const MCInst *MI, unsigned OpNo, 433 raw_ostream &OS) { 434 // In assembly listings, a pair is represented by one of its members, any 435 // of the two. Here, we pick k0, k2, k4, k6, but we could as well 436 // print K2_K3 as "k3". It would probably make a lot more sense, if 437 // the assembly would look something like: 438 // "vp2intersect %zmm5, %zmm7, {%k2, %k3}" 439 // but this can work too. 440 switch (MI->getOperand(OpNo).getReg()) { 441 case X86::K0_K1: 442 printRegName(OS, X86::K0); 443 return; 444 case X86::K2_K3: 445 printRegName(OS, X86::K2); 446 return; 447 case X86::K4_K5: 448 printRegName(OS, X86::K4); 449 return; 450 case X86::K6_K7: 451 printRegName(OS, X86::K6); 452 return; 453 } 454 llvm_unreachable("Unknown mask pair register name"); 455 } 456