497 lines · cpp
1//===-- X86IntelInstPrinter.cpp - Intel 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 code for rendering MCInst instances as Intel-style10// assembly.11//12//===----------------------------------------------------------------------===//13 14#include "X86IntelInstPrinter.h"15#include "X86BaseInfo.h"16#include "X86InstComments.h"17#include "llvm/MC/MCAsmInfo.h"18#include "llvm/MC/MCExpr.h"19#include "llvm/MC/MCInst.h"20#include "llvm/MC/MCInstrAnalysis.h"21#include "llvm/MC/MCInstrDesc.h"22#include "llvm/MC/MCInstrInfo.h"23#include "llvm/MC/MCSubtargetInfo.h"24#include "llvm/Support/ErrorHandling.h"25#include <cassert>26#include <cstdint>27 28using namespace llvm;29 30#define DEBUG_TYPE "asm-printer"31 32// Include the auto-generated portion of the assembly writer.33#define PRINT_ALIAS_INSTR34#include "X86GenAsmWriter1.inc"35 36void X86IntelInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {37 markup(OS, Markup::Register) << getRegisterName(Reg);38}39 40void X86IntelInstPrinter::printInst(const MCInst *MI, uint64_t Address,41 StringRef Annot, const MCSubtargetInfo &STI,42 raw_ostream &OS) {43 printInstFlags(MI, OS, STI);44 45 // In 16-bit mode, print data16 as data32.46 if (MI->getOpcode() == X86::DATA16_PREFIX &&47 STI.hasFeature(X86::Is16Bit)) {48 OS << "\tdata32";49 } else if (!printAliasInstr(MI, Address, OS) && !printVecCompareInstr(MI, OS))50 printInstruction(MI, Address, OS);51 52 // Next always print the annotation.53 printAnnotation(OS, Annot);54 55 // If verbose assembly is enabled, we can print some informative comments.56 if (CommentStream)57 EmitAnyX86InstComments(MI, *CommentStream, MII);58}59 60bool X86IntelInstPrinter::printVecCompareInstr(const MCInst *MI, raw_ostream &OS) {61 if (MI->getNumOperands() == 0 ||62 !MI->getOperand(MI->getNumOperands() - 1).isImm())63 return false;64 65 int64_t Imm = MI->getOperand(MI->getNumOperands() - 1).getImm();66 67 const MCInstrDesc &Desc = MII.get(MI->getOpcode());68 69 // Custom print the vector compare instructions to get the immediate70 // translated into the mnemonic.71 switch (MI->getOpcode()) {72 case X86::CMPPDrmi: case X86::CMPPDrri:73 case X86::CMPPSrmi: case X86::CMPPSrri:74 case X86::CMPSDrmi: case X86::CMPSDrri:75 case X86::CMPSDrmi_Int: case X86::CMPSDrri_Int:76 case X86::CMPSSrmi: case X86::CMPSSrri:77 case X86::CMPSSrmi_Int: case X86::CMPSSrri_Int:78 if (Imm >= 0 && Imm <= 7) {79 OS << '\t';80 printCMPMnemonic(MI, /*IsVCMP*/false, OS);81 printOperand(MI, 0, OS);82 OS << ", ";83 // Skip operand 1 as its tied to the dest.84 85 if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) {86 if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XS)87 printdwordmem(MI, 2, OS);88 else if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XD)89 printqwordmem(MI, 2, OS);90 else91 printxmmwordmem(MI, 2, OS);92 } else93 printOperand(MI, 2, OS);94 95 return true;96 }97 break;98 99 case X86::VCMPPDrmi: case X86::VCMPPDrri:100 case X86::VCMPPDYrmi: case X86::VCMPPDYrri:101 case X86::VCMPPDZ128rmi: case X86::VCMPPDZ128rri:102 case X86::VCMPPDZ256rmi: case X86::VCMPPDZ256rri:103 case X86::VCMPPDZrmi: case X86::VCMPPDZrri:104 case X86::VCMPPSrmi: case X86::VCMPPSrri:105 case X86::VCMPPSYrmi: case X86::VCMPPSYrri:106 case X86::VCMPPSZ128rmi: case X86::VCMPPSZ128rri:107 case X86::VCMPPSZ256rmi: case X86::VCMPPSZ256rri:108 case X86::VCMPPSZrmi: case X86::VCMPPSZrri:109 case X86::VCMPSDrmi: case X86::VCMPSDrri:110 case X86::VCMPSDZrmi: case X86::VCMPSDZrri:111 case X86::VCMPSDrmi_Int: case X86::VCMPSDrri_Int:112 case X86::VCMPSDZrmi_Int: case X86::VCMPSDZrri_Int:113 case X86::VCMPSSrmi: case X86::VCMPSSrri:114 case X86::VCMPSSZrmi: case X86::VCMPSSZrri:115 case X86::VCMPSSrmi_Int: case X86::VCMPSSrri_Int:116 case X86::VCMPSSZrmi_Int: case X86::VCMPSSZrri_Int:117 case X86::VCMPPDZ128rmik: case X86::VCMPPDZ128rrik:118 case X86::VCMPPDZ256rmik: case X86::VCMPPDZ256rrik:119 case X86::VCMPPDZrmik: case X86::VCMPPDZrrik:120 case X86::VCMPPSZ128rmik: case X86::VCMPPSZ128rrik:121 case X86::VCMPPSZ256rmik: case X86::VCMPPSZ256rrik:122 case X86::VCMPPSZrmik: case X86::VCMPPSZrrik:123 case X86::VCMPSDZrmik_Int: case X86::VCMPSDZrrik_Int:124 case X86::VCMPSSZrmik_Int: case X86::VCMPSSZrrik_Int:125 case X86::VCMPPDZ128rmbi: case X86::VCMPPDZ128rmbik:126 case X86::VCMPPDZ256rmbi: case X86::VCMPPDZ256rmbik:127 case X86::VCMPPDZrmbi: case X86::VCMPPDZrmbik:128 case X86::VCMPPSZ128rmbi: case X86::VCMPPSZ128rmbik:129 case X86::VCMPPSZ256rmbi: case X86::VCMPPSZ256rmbik:130 case X86::VCMPPSZrmbi: case X86::VCMPPSZrmbik:131 case X86::VCMPPDZrrib: case X86::VCMPPDZrribk:132 case X86::VCMPPSZrrib: case X86::VCMPPSZrribk:133 case X86::VCMPSDZrrib_Int: case X86::VCMPSDZrribk_Int:134 case X86::VCMPSSZrrib_Int: case X86::VCMPSSZrribk_Int:135 case X86::VCMPPHZ128rmi: case X86::VCMPPHZ128rri:136 case X86::VCMPPHZ256rmi: case X86::VCMPPHZ256rri:137 case X86::VCMPPHZrmi: case X86::VCMPPHZrri:138 case X86::VCMPSHZrmi: case X86::VCMPSHZrri:139 case X86::VCMPSHZrmi_Int: case X86::VCMPSHZrri_Int:140 case X86::VCMPPHZ128rmik: case X86::VCMPPHZ128rrik:141 case X86::VCMPPHZ256rmik: case X86::VCMPPHZ256rrik:142 case X86::VCMPPHZrmik: case X86::VCMPPHZrrik:143 case X86::VCMPSHZrmik_Int: case X86::VCMPSHZrrik_Int:144 case X86::VCMPPHZ128rmbi: case X86::VCMPPHZ128rmbik:145 case X86::VCMPPHZ256rmbi: case X86::VCMPPHZ256rmbik:146 case X86::VCMPPHZrmbi: case X86::VCMPPHZrmbik:147 case X86::VCMPPHZrrib: case X86::VCMPPHZrribk:148 case X86::VCMPSHZrrib_Int: case X86::VCMPSHZrribk_Int:149 case X86::VCMPBF16Z128rmi: case X86::VCMPBF16Z128rri:150 case X86::VCMPBF16Z256rmi: case X86::VCMPBF16Z256rri:151 case X86::VCMPBF16Zrmi: case X86::VCMPBF16Zrri:152 case X86::VCMPBF16Z128rmik: case X86::VCMPBF16Z128rrik:153 case X86::VCMPBF16Z256rmik: case X86::VCMPBF16Z256rrik:154 case X86::VCMPBF16Zrmik: case X86::VCMPBF16Zrrik:155 case X86::VCMPBF16Z128rmbi: case X86::VCMPBF16Z128rmbik:156 case X86::VCMPBF16Z256rmbi: case X86::VCMPBF16Z256rmbik:157 case X86::VCMPBF16Zrmbi: case X86::VCMPBF16Zrmbik:158 if (Imm >= 0 && Imm <= 31) {159 OS << '\t';160 printCMPMnemonic(MI, /*IsVCMP*/true, OS);161 162 unsigned CurOp = 0;163 printOperand(MI, CurOp++, OS);164 165 if (Desc.TSFlags & X86II::EVEX_K) {166 // Print mask operand.167 OS << " {";168 printOperand(MI, CurOp++, OS);169 OS << "}";170 }171 OS << ", ";172 printOperand(MI, CurOp++, OS);173 OS << ", ";174 175 if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) {176 if (Desc.TSFlags & X86II::EVEX_B) {177 // Broadcast form.178 // Load size is word for TA map. Otherwise it is based on W-bit.179 if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA) {180 assert(!(Desc.TSFlags & X86II::REX_W) && "Unknown W-bit value!");181 printwordmem(MI, CurOp++, OS);182 } else if (Desc.TSFlags & X86II::REX_W) {183 printqwordmem(MI, CurOp++, OS);184 } else {185 printdwordmem(MI, CurOp++, OS);186 }187 188 // Print the number of elements broadcasted.189 unsigned NumElts;190 if (Desc.TSFlags & X86II::EVEX_L2)191 NumElts = (Desc.TSFlags & X86II::REX_W) ? 8 : 16;192 else if (Desc.TSFlags & X86II::VEX_L)193 NumElts = (Desc.TSFlags & X86II::REX_W) ? 4 : 8;194 else195 NumElts = (Desc.TSFlags & X86II::REX_W) ? 2 : 4;196 if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA) {197 assert(!(Desc.TSFlags & X86II::REX_W) && "Unknown W-bit value!");198 NumElts *= 2;199 }200 OS << "{1to" << NumElts << "}";201 } else {202 if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XS) {203 if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA)204 printwordmem(MI, CurOp++, OS);205 else206 printdwordmem(MI, CurOp++, OS);207 } else if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XD &&208 (Desc.TSFlags & X86II::OpMapMask) != X86II::TA) {209 printqwordmem(MI, CurOp++, OS);210 } else if (Desc.TSFlags & X86II::EVEX_L2) {211 printzmmwordmem(MI, CurOp++, OS);212 } else if (Desc.TSFlags & X86II::VEX_L) {213 printymmwordmem(MI, CurOp++, OS);214 } else {215 printxmmwordmem(MI, CurOp++, OS);216 }217 }218 } else {219 printOperand(MI, CurOp++, OS);220 if (Desc.TSFlags & X86II::EVEX_B)221 OS << ", {sae}";222 }223 224 return true;225 }226 break;227 228 case X86::VPCOMBmi: case X86::VPCOMBri:229 case X86::VPCOMDmi: case X86::VPCOMDri:230 case X86::VPCOMQmi: case X86::VPCOMQri:231 case X86::VPCOMUBmi: case X86::VPCOMUBri:232 case X86::VPCOMUDmi: case X86::VPCOMUDri:233 case X86::VPCOMUQmi: case X86::VPCOMUQri:234 case X86::VPCOMUWmi: case X86::VPCOMUWri:235 case X86::VPCOMWmi: case X86::VPCOMWri:236 if (Imm >= 0 && Imm <= 7) {237 OS << '\t';238 printVPCOMMnemonic(MI, OS);239 printOperand(MI, 0, OS);240 OS << ", ";241 printOperand(MI, 1, OS);242 OS << ", ";243 if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem)244 printxmmwordmem(MI, 2, OS);245 else246 printOperand(MI, 2, OS);247 return true;248 }249 break;250 251 case X86::VPCMPBZ128rmi: case X86::VPCMPBZ128rri:252 case X86::VPCMPBZ256rmi: case X86::VPCMPBZ256rri:253 case X86::VPCMPBZrmi: case X86::VPCMPBZrri:254 case X86::VPCMPDZ128rmi: case X86::VPCMPDZ128rri:255 case X86::VPCMPDZ256rmi: case X86::VPCMPDZ256rri:256 case X86::VPCMPDZrmi: case X86::VPCMPDZrri:257 case X86::VPCMPQZ128rmi: case X86::VPCMPQZ128rri:258 case X86::VPCMPQZ256rmi: case X86::VPCMPQZ256rri:259 case X86::VPCMPQZrmi: case X86::VPCMPQZrri:260 case X86::VPCMPUBZ128rmi: case X86::VPCMPUBZ128rri:261 case X86::VPCMPUBZ256rmi: case X86::VPCMPUBZ256rri:262 case X86::VPCMPUBZrmi: case X86::VPCMPUBZrri:263 case X86::VPCMPUDZ128rmi: case X86::VPCMPUDZ128rri:264 case X86::VPCMPUDZ256rmi: case X86::VPCMPUDZ256rri:265 case X86::VPCMPUDZrmi: case X86::VPCMPUDZrri:266 case X86::VPCMPUQZ128rmi: case X86::VPCMPUQZ128rri:267 case X86::VPCMPUQZ256rmi: case X86::VPCMPUQZ256rri:268 case X86::VPCMPUQZrmi: case X86::VPCMPUQZrri:269 case X86::VPCMPUWZ128rmi: case X86::VPCMPUWZ128rri:270 case X86::VPCMPUWZ256rmi: case X86::VPCMPUWZ256rri:271 case X86::VPCMPUWZrmi: case X86::VPCMPUWZrri:272 case X86::VPCMPWZ128rmi: case X86::VPCMPWZ128rri:273 case X86::VPCMPWZ256rmi: case X86::VPCMPWZ256rri:274 case X86::VPCMPWZrmi: case X86::VPCMPWZrri:275 case X86::VPCMPBZ128rmik: case X86::VPCMPBZ128rrik:276 case X86::VPCMPBZ256rmik: case X86::VPCMPBZ256rrik:277 case X86::VPCMPBZrmik: case X86::VPCMPBZrrik:278 case X86::VPCMPDZ128rmik: case X86::VPCMPDZ128rrik:279 case X86::VPCMPDZ256rmik: case X86::VPCMPDZ256rrik:280 case X86::VPCMPDZrmik: case X86::VPCMPDZrrik:281 case X86::VPCMPQZ128rmik: case X86::VPCMPQZ128rrik:282 case X86::VPCMPQZ256rmik: case X86::VPCMPQZ256rrik:283 case X86::VPCMPQZrmik: case X86::VPCMPQZrrik:284 case X86::VPCMPUBZ128rmik: case X86::VPCMPUBZ128rrik:285 case X86::VPCMPUBZ256rmik: case X86::VPCMPUBZ256rrik:286 case X86::VPCMPUBZrmik: case X86::VPCMPUBZrrik:287 case X86::VPCMPUDZ128rmik: case X86::VPCMPUDZ128rrik:288 case X86::VPCMPUDZ256rmik: case X86::VPCMPUDZ256rrik:289 case X86::VPCMPUDZrmik: case X86::VPCMPUDZrrik:290 case X86::VPCMPUQZ128rmik: case X86::VPCMPUQZ128rrik:291 case X86::VPCMPUQZ256rmik: case X86::VPCMPUQZ256rrik:292 case X86::VPCMPUQZrmik: case X86::VPCMPUQZrrik:293 case X86::VPCMPUWZ128rmik: case X86::VPCMPUWZ128rrik:294 case X86::VPCMPUWZ256rmik: case X86::VPCMPUWZ256rrik:295 case X86::VPCMPUWZrmik: case X86::VPCMPUWZrrik:296 case X86::VPCMPWZ128rmik: case X86::VPCMPWZ128rrik:297 case X86::VPCMPWZ256rmik: case X86::VPCMPWZ256rrik:298 case X86::VPCMPWZrmik: case X86::VPCMPWZrrik:299 case X86::VPCMPDZ128rmbi: case X86::VPCMPDZ128rmbik:300 case X86::VPCMPDZ256rmbi: case X86::VPCMPDZ256rmbik:301 case X86::VPCMPDZrmbi: case X86::VPCMPDZrmbik:302 case X86::VPCMPQZ128rmbi: case X86::VPCMPQZ128rmbik:303 case X86::VPCMPQZ256rmbi: case X86::VPCMPQZ256rmbik:304 case X86::VPCMPQZrmbi: case X86::VPCMPQZrmbik:305 case X86::VPCMPUDZ128rmbi: case X86::VPCMPUDZ128rmbik:306 case X86::VPCMPUDZ256rmbi: case X86::VPCMPUDZ256rmbik:307 case X86::VPCMPUDZrmbi: case X86::VPCMPUDZrmbik:308 case X86::VPCMPUQZ128rmbi: case X86::VPCMPUQZ128rmbik:309 case X86::VPCMPUQZ256rmbi: case X86::VPCMPUQZ256rmbik:310 case X86::VPCMPUQZrmbi: case X86::VPCMPUQZrmbik:311 if ((Imm >= 0 && Imm <= 2) || (Imm >= 4 && Imm <= 6)) {312 OS << '\t';313 printVPCMPMnemonic(MI, OS);314 315 unsigned CurOp = 0;316 printOperand(MI, CurOp++, OS);317 318 if (Desc.TSFlags & X86II::EVEX_K) {319 // Print mask operand.320 OS << " {";321 printOperand(MI, CurOp++, OS);322 OS << "}";323 }324 OS << ", ";325 printOperand(MI, CurOp++, OS);326 OS << ", ";327 328 if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) {329 if (Desc.TSFlags & X86II::EVEX_B) {330 // Broadcast form.331 // Load size is based on W-bit as only D and Q are supported.332 if (Desc.TSFlags & X86II::REX_W)333 printqwordmem(MI, CurOp++, OS);334 else335 printdwordmem(MI, CurOp++, OS);336 337 // Print the number of elements broadcasted.338 unsigned NumElts;339 if (Desc.TSFlags & X86II::EVEX_L2)340 NumElts = (Desc.TSFlags & X86II::REX_W) ? 8 : 16;341 else if (Desc.TSFlags & X86II::VEX_L)342 NumElts = (Desc.TSFlags & X86II::REX_W) ? 4 : 8;343 else344 NumElts = (Desc.TSFlags & X86II::REX_W) ? 2 : 4;345 OS << "{1to" << NumElts << "}";346 } else {347 if (Desc.TSFlags & X86II::EVEX_L2)348 printzmmwordmem(MI, CurOp++, OS);349 else if (Desc.TSFlags & X86II::VEX_L)350 printymmwordmem(MI, CurOp++, OS);351 else352 printxmmwordmem(MI, CurOp++, OS);353 }354 } else {355 printOperand(MI, CurOp++, OS);356 }357 358 return true;359 }360 break;361 }362 363 return false;364}365 366void X86IntelInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,367 raw_ostream &O) {368 const MCOperand &Op = MI->getOperand(OpNo);369 if (Op.isReg()) {370 printRegName(O, Op.getReg());371 } else if (Op.isImm()) {372 markup(O, Markup::Immediate) << formatImm(Op.getImm());373 } else {374 assert(Op.isExpr() && "unknown operand kind in printOperand");375 O << "offset ";376 MAI.printExpr(O, *Op.getExpr());377 }378}379 380void X86IntelInstPrinter::printMemReference(const MCInst *MI, unsigned Op,381 raw_ostream &O) {382 // Do not print the exact form of the memory operand if it references a known383 // binary object.384 if (SymbolizeOperands && MIA) {385 uint64_t Target;386 if (MIA->evaluateBranch(*MI, 0, 0, Target))387 return;388 if (MIA->evaluateMemoryOperandAddress(*MI, /*STI=*/nullptr, 0, 0))389 return;390 }391 const MCOperand &BaseReg = MI->getOperand(Op+X86::AddrBaseReg);392 unsigned ScaleVal = MI->getOperand(Op+X86::AddrScaleAmt).getImm();393 const MCOperand &IndexReg = MI->getOperand(Op+X86::AddrIndexReg);394 const MCOperand &DispSpec = MI->getOperand(Op+X86::AddrDisp);395 396 // If this has a segment register, print it.397 printOptionalSegReg(MI, Op + X86::AddrSegmentReg, O);398 399 WithMarkup M = markup(O, Markup::Memory);400 O << '[';401 402 bool NeedPlus = false;403 if (BaseReg.getReg()) {404 printOperand(MI, Op+X86::AddrBaseReg, O);405 NeedPlus = true;406 }407 408 if (IndexReg.getReg()) {409 if (NeedPlus) O << " + ";410 if (ScaleVal != 1 || !BaseReg.getReg())411 O << ScaleVal << '*';412 printOperand(MI, Op+X86::AddrIndexReg, O);413 NeedPlus = true;414 }415 416 if (!DispSpec.isImm()) {417 if (NeedPlus) O << " + ";418 assert(DispSpec.isExpr() && "non-immediate displacement for LEA?");419 MAI.printExpr(O, *DispSpec.getExpr());420 } else {421 int64_t DispVal = DispSpec.getImm();422 if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) {423 if (NeedPlus) {424 if (DispVal > 0)425 O << " + ";426 else {427 O << " - ";428 DispVal = -DispVal;429 }430 }431 markup(O, Markup::Immediate) << formatImm(DispVal);432 }433 }434 435 O << ']';436}437 438void X86IntelInstPrinter::printSrcIdx(const MCInst *MI, unsigned Op,439 raw_ostream &O) {440 // If this has a segment register, print it.441 printOptionalSegReg(MI, Op + 1, O);442 443 WithMarkup M = markup(O, Markup::Memory);444 O << '[';445 printOperand(MI, Op, O);446 O << ']';447}448 449void X86IntelInstPrinter::printDstIdx(const MCInst *MI, unsigned Op,450 raw_ostream &O) {451 // DI accesses are always ES-based.452 O << "es:";453 454 WithMarkup M = markup(O, Markup::Memory);455 O << '[';456 printOperand(MI, Op, O);457 O << ']';458}459 460void X86IntelInstPrinter::printMemOffset(const MCInst *MI, unsigned Op,461 raw_ostream &O) {462 const MCOperand &DispSpec = MI->getOperand(Op);463 464 // If this has a segment register, print it.465 printOptionalSegReg(MI, Op + 1, O);466 467 WithMarkup M = markup(O, Markup::Memory);468 O << '[';469 470 if (DispSpec.isImm()) {471 markup(O, Markup::Immediate) << formatImm(DispSpec.getImm());472 } else {473 assert(DispSpec.isExpr() && "non-immediate displacement?");474 MAI.printExpr(O, *DispSpec.getExpr());475 }476 477 O << ']';478}479 480void X86IntelInstPrinter::printU8Imm(const MCInst *MI, unsigned Op,481 raw_ostream &O) {482 if (MI->getOperand(Op).isExpr())483 return MAI.printExpr(O, *MI->getOperand(Op).getExpr());484 485 markup(O, Markup::Immediate) << formatImm(MI->getOperand(Op).getImm() & 0xff);486}487 488void X86IntelInstPrinter::printSTiRegOperand(const MCInst *MI, unsigned OpNo,489 raw_ostream &OS) {490 MCRegister Reg = MI->getOperand(OpNo).getReg();491 // Override the default printing to print st(0) instead st.492 if (Reg == X86::ST0)493 OS << "st(0)";494 else495 printRegName(OS, Reg);496}497