#include "X86ATTInstPrinter.h"
#include "MCTargetDesc/X86BaseInfo.h"
#include "X86InstComments.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cinttypes>
#include <cstdint>
using namespace llvm;
#define DEBUG_TYPE "asm-printer"
#define PRINT_ALIAS_INSTR
#include "X86GenAsmWriter.inc"
void X86ATTInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
OS << markup("<reg:") << '%' << getRegisterName(RegNo) << markup(">");
}
void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
StringRef Annot, const MCSubtargetInfo &STI) {
if (CommentStream)
HasCustomInstComment = EmitAnyX86InstComments(MI, *CommentStream, MII);
printInstFlags(MI, OS);
if (MI->getOpcode() == X86::CALLpcrel32 &&
(STI.getFeatureBits()[X86::Mode64Bit])) {
OS << "\tcallq\t";
printPCRelImm(MI, 0, OS);
}
else if (MI->getOpcode() == X86::DATA16_PREFIX &&
STI.getFeatureBits()[X86::Mode16Bit]) {
OS << "\tdata32";
}
else if (!printAliasInstr(MI, OS))
printInstruction(MI, OS);
printAnnotation(OS, Annot);
}
void X86ATTInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isReg()) {
printRegName(O, Op.getReg());
} else if (Op.isImm()) {
int64_t Imm = Op.getImm();
O << markup("<imm:") << '$' << formatImm(Imm) << markup(">");
if (CommentStream && !HasCustomInstComment && (Imm > 255 || Imm < -256)) {
if (Imm == (int16_t)(Imm))
*CommentStream << format("imm = 0x%" PRIX16 "\n", (uint16_t)Imm);
else if (Imm == (int32_t)(Imm))
*CommentStream << format("imm = 0x%" PRIX32 "\n", (uint32_t)Imm);
else
*CommentStream << format("imm = 0x%" PRIX64 "\n", (uint64_t)Imm);
}
} else {
assert(Op.isExpr() && "unknown operand kind in printOperand");
O << markup("<imm:") << '$';
Op.getExpr()->print(O, &MAI);
O << markup(">");
}
}
void X86ATTInstPrinter::printMemReference(const MCInst *MI, unsigned Op,
raw_ostream &O) {
const MCOperand &BaseReg = MI->getOperand(Op + X86::AddrBaseReg);
const MCOperand &IndexReg = MI->getOperand(Op + X86::AddrIndexReg);
const MCOperand &DispSpec = MI->getOperand(Op + X86::AddrDisp);
O << markup("<mem:");
printOptionalSegReg(MI, Op + X86::AddrSegmentReg, O);
if (DispSpec.isImm()) {
int64_t DispVal = DispSpec.getImm();
if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg()))
O << formatImm(DispVal);
} else {
assert(DispSpec.isExpr() && "non-immediate displacement for LEA?");
DispSpec.getExpr()->print(O, &MAI);
}
if (IndexReg.getReg() || BaseReg.getReg()) {
O << '(';
if (BaseReg.getReg())
printOperand(MI, Op + X86::AddrBaseReg, O);
if (IndexReg.getReg()) {
O << ',';
printOperand(MI, Op + X86::AddrIndexReg, O);
unsigned ScaleVal = MI->getOperand(Op + X86::AddrScaleAmt).getImm();
if (ScaleVal != 1) {
O << ',' << markup("<imm:") << ScaleVal
<< markup(">");
}
}
O << ')';
}
O << markup(">");
}
void X86ATTInstPrinter::printSrcIdx(const MCInst *MI, unsigned Op,
raw_ostream &O) {
O << markup("<mem:");
printOptionalSegReg(MI, Op + 1, O);
O << "(";
printOperand(MI, Op, O);
O << ")";
O << markup(">");
}
void X86ATTInstPrinter::printDstIdx(const MCInst *MI, unsigned Op,
raw_ostream &O) {
O << markup("<mem:");
O << "%es:(";
printOperand(MI, Op, O);
O << ")";
O << markup(">");
}
void X86ATTInstPrinter::printMemOffset(const MCInst *MI, unsigned Op,
raw_ostream &O) {
const MCOperand &DispSpec = MI->getOperand(Op);
O << markup("<mem:");
printOptionalSegReg(MI, Op + 1, O);
if (DispSpec.isImm()) {
O << formatImm(DispSpec.getImm());
} else {
assert(DispSpec.isExpr() && "non-immediate displacement?");
DispSpec.getExpr()->print(O, &MAI);
}
O << markup(">");
}
void X86ATTInstPrinter::printU8Imm(const MCInst *MI, unsigned Op,
raw_ostream &O) {
if (MI->getOperand(Op).isExpr())
return printOperand(MI, Op, O);
O << markup("<imm:") << '$' << formatImm(MI->getOperand(Op).getImm() & 0xff)
<< markup(">");
}