Path: blob/main/contrib/llvm-project/llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.cpp
35294 views
//===-- X86IntelInstPrinter.cpp - Intel assembly instruction printing -----===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file includes code for rendering MCInst instances as Intel-style9// assembly.10//11//===----------------------------------------------------------------------===//1213#include "X86IntelInstPrinter.h"14#include "X86BaseInfo.h"15#include "X86InstComments.h"16#include "llvm/MC/MCExpr.h"17#include "llvm/MC/MCInst.h"18#include "llvm/MC/MCInstrAnalysis.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/ErrorHandling.h"24#include <cassert>25#include <cstdint>2627using namespace llvm;2829#define DEBUG_TYPE "asm-printer"3031// Include the auto-generated portion of the assembly writer.32#define PRINT_ALIAS_INSTR33#include "X86GenAsmWriter1.inc"3435void X86IntelInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) const {36markup(OS, Markup::Register) << getRegisterName(Reg);37}3839void X86IntelInstPrinter::printInst(const MCInst *MI, uint64_t Address,40StringRef Annot, const MCSubtargetInfo &STI,41raw_ostream &OS) {42printInstFlags(MI, OS, STI);4344// In 16-bit mode, print data16 as data32.45if (MI->getOpcode() == X86::DATA16_PREFIX &&46STI.hasFeature(X86::Is16Bit)) {47OS << "\tdata32";48} else if (!printAliasInstr(MI, Address, OS) && !printVecCompareInstr(MI, OS))49printInstruction(MI, Address, OS);5051// Next always print the annotation.52printAnnotation(OS, Annot);5354// If verbose assembly is enabled, we can print some informative comments.55if (CommentStream)56EmitAnyX86InstComments(MI, *CommentStream, MII);57}5859bool X86IntelInstPrinter::printVecCompareInstr(const MCInst *MI, raw_ostream &OS) {60if (MI->getNumOperands() == 0 ||61!MI->getOperand(MI->getNumOperands() - 1).isImm())62return false;6364int64_t Imm = MI->getOperand(MI->getNumOperands() - 1).getImm();6566const MCInstrDesc &Desc = MII.get(MI->getOpcode());6768// Custom print the vector compare instructions to get the immediate69// translated into the mnemonic.70switch (MI->getOpcode()) {71case X86::CMPPDrmi: case X86::CMPPDrri:72case X86::CMPPSrmi: case X86::CMPPSrri:73case X86::CMPSDrmi: case X86::CMPSDrri:74case X86::CMPSDrmi_Int: case X86::CMPSDrri_Int:75case X86::CMPSSrmi: case X86::CMPSSrri:76case X86::CMPSSrmi_Int: case X86::CMPSSrri_Int:77if (Imm >= 0 && Imm <= 7) {78OS << '\t';79printCMPMnemonic(MI, /*IsVCMP*/false, OS);80printOperand(MI, 0, OS);81OS << ", ";82// Skip operand 1 as its tied to the dest.8384if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) {85if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XS)86printdwordmem(MI, 2, OS);87else if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XD)88printqwordmem(MI, 2, OS);89else90printxmmwordmem(MI, 2, OS);91} else92printOperand(MI, 2, OS);9394return true;95}96break;9798case X86::VCMPPDrmi: case X86::VCMPPDrri:99case X86::VCMPPDYrmi: case X86::VCMPPDYrri:100case X86::VCMPPDZ128rmi: case X86::VCMPPDZ128rri:101case X86::VCMPPDZ256rmi: case X86::VCMPPDZ256rri:102case X86::VCMPPDZrmi: case X86::VCMPPDZrri:103case X86::VCMPPSrmi: case X86::VCMPPSrri:104case X86::VCMPPSYrmi: case X86::VCMPPSYrri:105case X86::VCMPPSZ128rmi: case X86::VCMPPSZ128rri:106case X86::VCMPPSZ256rmi: case X86::VCMPPSZ256rri:107case X86::VCMPPSZrmi: case X86::VCMPPSZrri:108case X86::VCMPSDrmi: case X86::VCMPSDrri:109case X86::VCMPSDZrmi: case X86::VCMPSDZrri:110case X86::VCMPSDrmi_Int: case X86::VCMPSDrri_Int:111case X86::VCMPSDZrmi_Int: case X86::VCMPSDZrri_Int:112case X86::VCMPSSrmi: case X86::VCMPSSrri:113case X86::VCMPSSZrmi: case X86::VCMPSSZrri:114case X86::VCMPSSrmi_Int: case X86::VCMPSSrri_Int:115case X86::VCMPSSZrmi_Int: case X86::VCMPSSZrri_Int:116case X86::VCMPPDZ128rmik: case X86::VCMPPDZ128rrik:117case X86::VCMPPDZ256rmik: case X86::VCMPPDZ256rrik:118case X86::VCMPPDZrmik: case X86::VCMPPDZrrik:119case X86::VCMPPSZ128rmik: case X86::VCMPPSZ128rrik:120case X86::VCMPPSZ256rmik: case X86::VCMPPSZ256rrik:121case X86::VCMPPSZrmik: case X86::VCMPPSZrrik:122case X86::VCMPSDZrmi_Intk: case X86::VCMPSDZrri_Intk:123case X86::VCMPSSZrmi_Intk: case X86::VCMPSSZrri_Intk:124case X86::VCMPPDZ128rmbi: case X86::VCMPPDZ128rmbik:125case X86::VCMPPDZ256rmbi: case X86::VCMPPDZ256rmbik:126case X86::VCMPPDZrmbi: case X86::VCMPPDZrmbik:127case X86::VCMPPSZ128rmbi: case X86::VCMPPSZ128rmbik:128case X86::VCMPPSZ256rmbi: case X86::VCMPPSZ256rmbik:129case X86::VCMPPSZrmbi: case X86::VCMPPSZrmbik:130case X86::VCMPPDZrrib: case X86::VCMPPDZrribk:131case X86::VCMPPSZrrib: case X86::VCMPPSZrribk:132case X86::VCMPSDZrrib_Int: case X86::VCMPSDZrrib_Intk:133case X86::VCMPSSZrrib_Int: case X86::VCMPSSZrrib_Intk:134case X86::VCMPPHZ128rmi: case X86::VCMPPHZ128rri:135case X86::VCMPPHZ256rmi: case X86::VCMPPHZ256rri:136case X86::VCMPPHZrmi: case X86::VCMPPHZrri:137case X86::VCMPSHZrmi: case X86::VCMPSHZrri:138case X86::VCMPSHZrmi_Int: case X86::VCMPSHZrri_Int:139case X86::VCMPPHZ128rmik: case X86::VCMPPHZ128rrik:140case X86::VCMPPHZ256rmik: case X86::VCMPPHZ256rrik:141case X86::VCMPPHZrmik: case X86::VCMPPHZrrik:142case X86::VCMPSHZrmi_Intk: case X86::VCMPSHZrri_Intk:143case X86::VCMPPHZ128rmbi: case X86::VCMPPHZ128rmbik:144case X86::VCMPPHZ256rmbi: case X86::VCMPPHZ256rmbik:145case X86::VCMPPHZrmbi: case X86::VCMPPHZrmbik:146case X86::VCMPPHZrrib: case X86::VCMPPHZrribk:147case X86::VCMPSHZrrib_Int: case X86::VCMPSHZrrib_Intk:148if (Imm >= 0 && Imm <= 31) {149OS << '\t';150printCMPMnemonic(MI, /*IsVCMP*/true, OS);151152unsigned CurOp = 0;153printOperand(MI, CurOp++, OS);154155if (Desc.TSFlags & X86II::EVEX_K) {156// Print mask operand.157OS << " {";158printOperand(MI, CurOp++, OS);159OS << "}";160}161OS << ", ";162printOperand(MI, CurOp++, OS);163OS << ", ";164165if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) {166if (Desc.TSFlags & X86II::EVEX_B) {167// Broadcast form.168// Load size is word for TA map. Otherwise it is based on W-bit.169if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA) {170assert(!(Desc.TSFlags & X86II::REX_W) && "Unknown W-bit value!");171printwordmem(MI, CurOp++, OS);172} else if (Desc.TSFlags & X86II::REX_W) {173printqwordmem(MI, CurOp++, OS);174} else {175printdwordmem(MI, CurOp++, OS);176}177178// Print the number of elements broadcasted.179unsigned NumElts;180if (Desc.TSFlags & X86II::EVEX_L2)181NumElts = (Desc.TSFlags & X86II::REX_W) ? 8 : 16;182else if (Desc.TSFlags & X86II::VEX_L)183NumElts = (Desc.TSFlags & X86II::REX_W) ? 4 : 8;184else185NumElts = (Desc.TSFlags & X86II::REX_W) ? 2 : 4;186if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA) {187assert(!(Desc.TSFlags & X86II::REX_W) && "Unknown W-bit value!");188NumElts *= 2;189}190OS << "{1to" << NumElts << "}";191} else {192if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XS) {193if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA)194printwordmem(MI, CurOp++, OS);195else196printdwordmem(MI, CurOp++, OS);197} else if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XD) {198assert((Desc.TSFlags & X86II::OpMapMask) != X86II::TA &&199"Unexpected op map!");200printqwordmem(MI, CurOp++, OS);201} else if (Desc.TSFlags & X86II::EVEX_L2) {202printzmmwordmem(MI, CurOp++, OS);203} else if (Desc.TSFlags & X86II::VEX_L) {204printymmwordmem(MI, CurOp++, OS);205} else {206printxmmwordmem(MI, CurOp++, OS);207}208}209} else {210printOperand(MI, CurOp++, OS);211if (Desc.TSFlags & X86II::EVEX_B)212OS << ", {sae}";213}214215return true;216}217break;218219case X86::VPCOMBmi: case X86::VPCOMBri:220case X86::VPCOMDmi: case X86::VPCOMDri:221case X86::VPCOMQmi: case X86::VPCOMQri:222case X86::VPCOMUBmi: case X86::VPCOMUBri:223case X86::VPCOMUDmi: case X86::VPCOMUDri:224case X86::VPCOMUQmi: case X86::VPCOMUQri:225case X86::VPCOMUWmi: case X86::VPCOMUWri:226case X86::VPCOMWmi: case X86::VPCOMWri:227if (Imm >= 0 && Imm <= 7) {228OS << '\t';229printVPCOMMnemonic(MI, OS);230printOperand(MI, 0, OS);231OS << ", ";232printOperand(MI, 1, OS);233OS << ", ";234if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem)235printxmmwordmem(MI, 2, OS);236else237printOperand(MI, 2, OS);238return true;239}240break;241242case X86::VPCMPBZ128rmi: case X86::VPCMPBZ128rri:243case X86::VPCMPBZ256rmi: case X86::VPCMPBZ256rri:244case X86::VPCMPBZrmi: case X86::VPCMPBZrri:245case X86::VPCMPDZ128rmi: case X86::VPCMPDZ128rri:246case X86::VPCMPDZ256rmi: case X86::VPCMPDZ256rri:247case X86::VPCMPDZrmi: case X86::VPCMPDZrri:248case X86::VPCMPQZ128rmi: case X86::VPCMPQZ128rri:249case X86::VPCMPQZ256rmi: case X86::VPCMPQZ256rri:250case X86::VPCMPQZrmi: case X86::VPCMPQZrri:251case X86::VPCMPUBZ128rmi: case X86::VPCMPUBZ128rri:252case X86::VPCMPUBZ256rmi: case X86::VPCMPUBZ256rri:253case X86::VPCMPUBZrmi: case X86::VPCMPUBZrri:254case X86::VPCMPUDZ128rmi: case X86::VPCMPUDZ128rri:255case X86::VPCMPUDZ256rmi: case X86::VPCMPUDZ256rri:256case X86::VPCMPUDZrmi: case X86::VPCMPUDZrri:257case X86::VPCMPUQZ128rmi: case X86::VPCMPUQZ128rri:258case X86::VPCMPUQZ256rmi: case X86::VPCMPUQZ256rri:259case X86::VPCMPUQZrmi: case X86::VPCMPUQZrri:260case X86::VPCMPUWZ128rmi: case X86::VPCMPUWZ128rri:261case X86::VPCMPUWZ256rmi: case X86::VPCMPUWZ256rri:262case X86::VPCMPUWZrmi: case X86::VPCMPUWZrri:263case X86::VPCMPWZ128rmi: case X86::VPCMPWZ128rri:264case X86::VPCMPWZ256rmi: case X86::VPCMPWZ256rri:265case X86::VPCMPWZrmi: case X86::VPCMPWZrri:266case X86::VPCMPBZ128rmik: case X86::VPCMPBZ128rrik:267case X86::VPCMPBZ256rmik: case X86::VPCMPBZ256rrik:268case X86::VPCMPBZrmik: case X86::VPCMPBZrrik:269case X86::VPCMPDZ128rmik: case X86::VPCMPDZ128rrik:270case X86::VPCMPDZ256rmik: case X86::VPCMPDZ256rrik:271case X86::VPCMPDZrmik: case X86::VPCMPDZrrik:272case X86::VPCMPQZ128rmik: case X86::VPCMPQZ128rrik:273case X86::VPCMPQZ256rmik: case X86::VPCMPQZ256rrik:274case X86::VPCMPQZrmik: case X86::VPCMPQZrrik:275case X86::VPCMPUBZ128rmik: case X86::VPCMPUBZ128rrik:276case X86::VPCMPUBZ256rmik: case X86::VPCMPUBZ256rrik:277case X86::VPCMPUBZrmik: case X86::VPCMPUBZrrik:278case X86::VPCMPUDZ128rmik: case X86::VPCMPUDZ128rrik:279case X86::VPCMPUDZ256rmik: case X86::VPCMPUDZ256rrik:280case X86::VPCMPUDZrmik: case X86::VPCMPUDZrrik:281case X86::VPCMPUQZ128rmik: case X86::VPCMPUQZ128rrik:282case X86::VPCMPUQZ256rmik: case X86::VPCMPUQZ256rrik:283case X86::VPCMPUQZrmik: case X86::VPCMPUQZrrik:284case X86::VPCMPUWZ128rmik: case X86::VPCMPUWZ128rrik:285case X86::VPCMPUWZ256rmik: case X86::VPCMPUWZ256rrik:286case X86::VPCMPUWZrmik: case X86::VPCMPUWZrrik:287case X86::VPCMPWZ128rmik: case X86::VPCMPWZ128rrik:288case X86::VPCMPWZ256rmik: case X86::VPCMPWZ256rrik:289case X86::VPCMPWZrmik: case X86::VPCMPWZrrik:290case X86::VPCMPDZ128rmib: case X86::VPCMPDZ128rmibk:291case X86::VPCMPDZ256rmib: case X86::VPCMPDZ256rmibk:292case X86::VPCMPDZrmib: case X86::VPCMPDZrmibk:293case X86::VPCMPQZ128rmib: case X86::VPCMPQZ128rmibk:294case X86::VPCMPQZ256rmib: case X86::VPCMPQZ256rmibk:295case X86::VPCMPQZrmib: case X86::VPCMPQZrmibk:296case X86::VPCMPUDZ128rmib: case X86::VPCMPUDZ128rmibk:297case X86::VPCMPUDZ256rmib: case X86::VPCMPUDZ256rmibk:298case X86::VPCMPUDZrmib: case X86::VPCMPUDZrmibk:299case X86::VPCMPUQZ128rmib: case X86::VPCMPUQZ128rmibk:300case X86::VPCMPUQZ256rmib: case X86::VPCMPUQZ256rmibk:301case X86::VPCMPUQZrmib: case X86::VPCMPUQZrmibk:302if ((Imm >= 0 && Imm <= 2) || (Imm >= 4 && Imm <= 6)) {303OS << '\t';304printVPCMPMnemonic(MI, OS);305306unsigned CurOp = 0;307printOperand(MI, CurOp++, OS);308309if (Desc.TSFlags & X86II::EVEX_K) {310// Print mask operand.311OS << " {";312printOperand(MI, CurOp++, OS);313OS << "}";314}315OS << ", ";316printOperand(MI, CurOp++, OS);317OS << ", ";318319if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) {320if (Desc.TSFlags & X86II::EVEX_B) {321// Broadcast form.322// Load size is based on W-bit as only D and Q are supported.323if (Desc.TSFlags & X86II::REX_W)324printqwordmem(MI, CurOp++, OS);325else326printdwordmem(MI, CurOp++, OS);327328// Print the number of elements broadcasted.329unsigned NumElts;330if (Desc.TSFlags & X86II::EVEX_L2)331NumElts = (Desc.TSFlags & X86II::REX_W) ? 8 : 16;332else if (Desc.TSFlags & X86II::VEX_L)333NumElts = (Desc.TSFlags & X86II::REX_W) ? 4 : 8;334else335NumElts = (Desc.TSFlags & X86II::REX_W) ? 2 : 4;336OS << "{1to" << NumElts << "}";337} else {338if (Desc.TSFlags & X86II::EVEX_L2)339printzmmwordmem(MI, CurOp++, OS);340else if (Desc.TSFlags & X86II::VEX_L)341printymmwordmem(MI, CurOp++, OS);342else343printxmmwordmem(MI, CurOp++, OS);344}345} else {346printOperand(MI, CurOp++, OS);347}348349return true;350}351break;352}353354return false;355}356357void X86IntelInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,358raw_ostream &O) {359const MCOperand &Op = MI->getOperand(OpNo);360if (Op.isReg()) {361printRegName(O, Op.getReg());362} else if (Op.isImm()) {363markup(O, Markup::Immediate) << formatImm((int64_t)Op.getImm());364} else {365assert(Op.isExpr() && "unknown operand kind in printOperand");366O << "offset ";367Op.getExpr()->print(O, &MAI);368}369}370371void X86IntelInstPrinter::printMemReference(const MCInst *MI, unsigned Op,372raw_ostream &O) {373// Do not print the exact form of the memory operand if it references a known374// binary object.375if (SymbolizeOperands && MIA) {376uint64_t Target;377if (MIA->evaluateBranch(*MI, 0, 0, Target))378return;379if (MIA->evaluateMemoryOperandAddress(*MI, /*STI=*/nullptr, 0, 0))380return;381}382const MCOperand &BaseReg = MI->getOperand(Op+X86::AddrBaseReg);383unsigned ScaleVal = MI->getOperand(Op+X86::AddrScaleAmt).getImm();384const MCOperand &IndexReg = MI->getOperand(Op+X86::AddrIndexReg);385const MCOperand &DispSpec = MI->getOperand(Op+X86::AddrDisp);386387// If this has a segment register, print it.388printOptionalSegReg(MI, Op + X86::AddrSegmentReg, O);389390WithMarkup M = markup(O, Markup::Memory);391O << '[';392393bool NeedPlus = false;394if (BaseReg.getReg()) {395printOperand(MI, Op+X86::AddrBaseReg, O);396NeedPlus = true;397}398399if (IndexReg.getReg()) {400if (NeedPlus) O << " + ";401if (ScaleVal != 1 || !BaseReg.getReg())402O << ScaleVal << '*';403printOperand(MI, Op+X86::AddrIndexReg, O);404NeedPlus = true;405}406407if (!DispSpec.isImm()) {408if (NeedPlus) O << " + ";409assert(DispSpec.isExpr() && "non-immediate displacement for LEA?");410DispSpec.getExpr()->print(O, &MAI);411} else {412int64_t DispVal = DispSpec.getImm();413if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) {414if (NeedPlus) {415if (DispVal > 0)416O << " + ";417else {418O << " - ";419DispVal = -DispVal;420}421}422markup(O, Markup::Immediate) << formatImm(DispVal);423}424}425426O << ']';427}428429void X86IntelInstPrinter::printSrcIdx(const MCInst *MI, unsigned Op,430raw_ostream &O) {431// If this has a segment register, print it.432printOptionalSegReg(MI, Op + 1, O);433434WithMarkup M = markup(O, Markup::Memory);435O << '[';436printOperand(MI, Op, O);437O << ']';438}439440void X86IntelInstPrinter::printDstIdx(const MCInst *MI, unsigned Op,441raw_ostream &O) {442// DI accesses are always ES-based.443O << "es:";444445WithMarkup M = markup(O, Markup::Memory);446O << '[';447printOperand(MI, Op, O);448O << ']';449}450451void X86IntelInstPrinter::printMemOffset(const MCInst *MI, unsigned Op,452raw_ostream &O) {453const MCOperand &DispSpec = MI->getOperand(Op);454455// If this has a segment register, print it.456printOptionalSegReg(MI, Op + 1, O);457458WithMarkup M = markup(O, Markup::Memory);459O << '[';460461if (DispSpec.isImm()) {462markup(O, Markup::Immediate) << formatImm(DispSpec.getImm());463} else {464assert(DispSpec.isExpr() && "non-immediate displacement?");465DispSpec.getExpr()->print(O, &MAI);466}467468O << ']';469}470471void X86IntelInstPrinter::printU8Imm(const MCInst *MI, unsigned Op,472raw_ostream &O) {473if (MI->getOperand(Op).isExpr())474return MI->getOperand(Op).getExpr()->print(O, &MAI);475476markup(O, Markup::Immediate) << formatImm(MI->getOperand(Op).getImm() & 0xff);477}478479void X86IntelInstPrinter::printSTiRegOperand(const MCInst *MI, unsigned OpNo,480raw_ostream &OS) {481const MCOperand &Op = MI->getOperand(OpNo);482unsigned Reg = Op.getReg();483// Override the default printing to print st(0) instead st.484if (Reg == X86::ST0)485OS << "st(0)";486else487printRegName(OS, Reg);488}489490491