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