1218885Sdim//===-- X86ATTInstPrinter.cpp - AT&T assembly instruction printing --------===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This file includes code for rendering MCInst instances as AT&T-style 11218885Sdim// assembly. 12218885Sdim// 13218885Sdim//===----------------------------------------------------------------------===// 14218885Sdim 15218885Sdim#define DEBUG_TYPE "asm-printer" 16218885Sdim#include "X86ATTInstPrinter.h" 17243830Sdim#include "MCTargetDesc/X86BaseInfo.h" 18224145Sdim#include "MCTargetDesc/X86MCTargetDesc.h" 19249423Sdim#include "X86InstComments.h" 20218885Sdim#include "llvm/MC/MCAsmInfo.h" 21218885Sdim#include "llvm/MC/MCExpr.h" 22249423Sdim#include "llvm/MC/MCInst.h" 23234353Sdim#include "llvm/MC/MCInstrInfo.h" 24234353Sdim#include "llvm/MC/MCRegisterInfo.h" 25218885Sdim#include "llvm/Support/ErrorHandling.h" 26218885Sdim#include "llvm/Support/Format.h" 27218885Sdim#include "llvm/Support/FormattedStream.h" 28221345Sdim#include <map> 29218885Sdimusing namespace llvm; 30218885Sdim 31218885Sdim// Include the auto-generated portion of the assembly writer. 32221345Sdim#define PRINT_ALIAS_INSTR 33218885Sdim#include "X86GenAsmWriter.inc" 34218885Sdim 35223017Sdimvoid X86ATTInstPrinter::printRegName(raw_ostream &OS, 36223017Sdim unsigned RegNo) const { 37243830Sdim OS << markup("<reg:") 38243830Sdim << '%' << getRegisterName(RegNo) 39243830Sdim << markup(">"); 40223017Sdim} 41223017Sdim 42226633Sdimvoid X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, 43226633Sdim StringRef Annot) { 44243830Sdim const MCInstrDesc &Desc = MII.get(MI->getOpcode()); 45243830Sdim uint64_t TSFlags = Desc.TSFlags; 46243830Sdim 47243830Sdim if (TSFlags & X86II::LOCK) 48243830Sdim OS << "\tlock\n"; 49243830Sdim 50221345Sdim // Try to print any aliases first. 51221345Sdim if (!printAliasInstr(MI, OS)) 52221345Sdim printInstruction(MI, OS); 53263508Sdim 54234353Sdim // Next always print the annotation. 55234353Sdim printAnnotation(OS, Annot); 56234353Sdim 57218885Sdim // If verbose assembly is enabled, we can print some informative comments. 58234353Sdim if (CommentStream) 59218885Sdim EmitAnyX86InstComments(MI, *CommentStream, getRegisterName); 60218885Sdim} 61221345Sdim 62218885Sdimvoid X86ATTInstPrinter::printSSECC(const MCInst *MI, unsigned Op, 63218885Sdim raw_ostream &O) { 64243830Sdim int64_t Imm = MI->getOperand(Op).getImm() & 0xf; 65243830Sdim switch (Imm) { 66234353Sdim default: llvm_unreachable("Invalid ssecc argument!"); 67234353Sdim case 0: O << "eq"; break; 68234353Sdim case 1: O << "lt"; break; 69234353Sdim case 2: O << "le"; break; 70234353Sdim case 3: O << "unord"; break; 71234353Sdim case 4: O << "neq"; break; 72234353Sdim case 5: O << "nlt"; break; 73234353Sdim case 6: O << "nle"; break; 74234353Sdim case 7: O << "ord"; break; 75234353Sdim case 8: O << "eq_uq"; break; 76234353Sdim case 9: O << "nge"; break; 77234353Sdim case 0xa: O << "ngt"; break; 78234353Sdim case 0xb: O << "false"; break; 79234353Sdim case 0xc: O << "neq_oq"; break; 80234353Sdim case 0xd: O << "ge"; break; 81234353Sdim case 0xe: O << "gt"; break; 82234353Sdim case 0xf: O << "true"; break; 83243830Sdim } 84243830Sdim} 85243830Sdim 86243830Sdimvoid X86ATTInstPrinter::printAVXCC(const MCInst *MI, unsigned Op, 87243830Sdim raw_ostream &O) { 88243830Sdim int64_t Imm = MI->getOperand(Op).getImm() & 0x1f; 89243830Sdim switch (Imm) { 90243830Sdim default: llvm_unreachable("Invalid avxcc argument!"); 91243830Sdim case 0: O << "eq"; break; 92243830Sdim case 1: O << "lt"; break; 93243830Sdim case 2: O << "le"; break; 94243830Sdim case 3: O << "unord"; break; 95243830Sdim case 4: O << "neq"; break; 96243830Sdim case 5: O << "nlt"; break; 97243830Sdim case 6: O << "nle"; break; 98243830Sdim case 7: O << "ord"; break; 99243830Sdim case 8: O << "eq_uq"; break; 100243830Sdim case 9: O << "nge"; break; 101243830Sdim case 0xa: O << "ngt"; break; 102243830Sdim case 0xb: O << "false"; break; 103243830Sdim case 0xc: O << "neq_oq"; break; 104243830Sdim case 0xd: O << "ge"; break; 105243830Sdim case 0xe: O << "gt"; break; 106243830Sdim case 0xf: O << "true"; break; 107234353Sdim case 0x10: O << "eq_os"; break; 108234353Sdim case 0x11: O << "lt_oq"; break; 109234353Sdim case 0x12: O << "le_oq"; break; 110234353Sdim case 0x13: O << "unord_s"; break; 111234353Sdim case 0x14: O << "neq_us"; break; 112234353Sdim case 0x15: O << "nlt_uq"; break; 113234353Sdim case 0x16: O << "nle_uq"; break; 114234353Sdim case 0x17: O << "ord_s"; break; 115234353Sdim case 0x18: O << "eq_us"; break; 116234353Sdim case 0x19: O << "nge_uq"; break; 117234353Sdim case 0x1a: O << "ngt_uq"; break; 118234353Sdim case 0x1b: O << "false_os"; break; 119234353Sdim case 0x1c: O << "neq_os"; break; 120234353Sdim case 0x1d: O << "ge_oq"; break; 121234353Sdim case 0x1e: O << "gt_oq"; break; 122234353Sdim case 0x1f: O << "true_us"; break; 123218885Sdim } 124218885Sdim} 125218885Sdim 126243830Sdim/// printPCRelImm - This is used to print an immediate value that ends up 127218885Sdim/// being encoded as a pc-relative value (e.g. for jumps and calls). These 128218885Sdim/// print slightly differently than normal immediates. For example, a $ is not 129218885Sdim/// emitted. 130243830Sdimvoid X86ATTInstPrinter::printPCRelImm(const MCInst *MI, unsigned OpNo, 131243830Sdim raw_ostream &O) { 132218885Sdim const MCOperand &Op = MI->getOperand(OpNo); 133218885Sdim if (Op.isImm()) 134249423Sdim O << formatImm(Op.getImm()); 135218885Sdim else { 136218885Sdim assert(Op.isExpr() && "unknown pcrel immediate operand"); 137234353Sdim // If a symbolic branch target was added as a constant expression then print 138234353Sdim // that address in hex. 139234353Sdim const MCConstantExpr *BranchTarget = dyn_cast<MCConstantExpr>(Op.getExpr()); 140234353Sdim int64_t Address; 141234353Sdim if (BranchTarget && BranchTarget->EvaluateAsAbsolute(Address)) { 142254790Semaste O << formatHex((uint64_t)Address); 143234353Sdim } 144234353Sdim else { 145234353Sdim // Otherwise, just print the expression. 146234353Sdim O << *Op.getExpr(); 147234353Sdim } 148218885Sdim } 149218885Sdim} 150218885Sdim 151218885Sdimvoid X86ATTInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 152218885Sdim raw_ostream &O) { 153218885Sdim const MCOperand &Op = MI->getOperand(OpNo); 154218885Sdim if (Op.isReg()) { 155243830Sdim printRegName(O, Op.getReg()); 156218885Sdim } else if (Op.isImm()) { 157226633Sdim // Print X86 immediates as signed values. 158243830Sdim O << markup("<imm:") 159249423Sdim << '$' << formatImm((int64_t)Op.getImm()) 160243830Sdim << markup(">"); 161263508Sdim 162218885Sdim if (CommentStream && (Op.getImm() > 255 || Op.getImm() < -256)) 163234353Sdim *CommentStream << format("imm = 0x%" PRIX64 "\n", (uint64_t)Op.getImm()); 164263508Sdim 165218885Sdim } else { 166218885Sdim assert(Op.isExpr() && "unknown operand kind in printOperand"); 167243830Sdim O << markup("<imm:") 168243830Sdim << '$' << *Op.getExpr() 169243830Sdim << markup(">"); 170218885Sdim } 171218885Sdim} 172218885Sdim 173218885Sdimvoid X86ATTInstPrinter::printMemReference(const MCInst *MI, unsigned Op, 174218885Sdim raw_ostream &O) { 175218885Sdim const MCOperand &BaseReg = MI->getOperand(Op); 176218885Sdim const MCOperand &IndexReg = MI->getOperand(Op+2); 177218885Sdim const MCOperand &DispSpec = MI->getOperand(Op+3); 178218885Sdim const MCOperand &SegReg = MI->getOperand(Op+4); 179263508Sdim 180243830Sdim O << markup("<mem:"); 181243830Sdim 182218885Sdim // If this has a segment register, print it. 183218885Sdim if (SegReg.getReg()) { 184218885Sdim printOperand(MI, Op+4, O); 185218885Sdim O << ':'; 186218885Sdim } 187263508Sdim 188218885Sdim if (DispSpec.isImm()) { 189218885Sdim int64_t DispVal = DispSpec.getImm(); 190218885Sdim if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) 191249423Sdim O << formatImm(DispVal); 192218885Sdim } else { 193218885Sdim assert(DispSpec.isExpr() && "non-immediate displacement for LEA?"); 194218885Sdim O << *DispSpec.getExpr(); 195218885Sdim } 196263508Sdim 197218885Sdim if (IndexReg.getReg() || BaseReg.getReg()) { 198218885Sdim O << '('; 199218885Sdim if (BaseReg.getReg()) 200218885Sdim printOperand(MI, Op, O); 201263508Sdim 202218885Sdim if (IndexReg.getReg()) { 203218885Sdim O << ','; 204218885Sdim printOperand(MI, Op+2, O); 205218885Sdim unsigned ScaleVal = MI->getOperand(Op+1).getImm(); 206243830Sdim if (ScaleVal != 1) { 207243830Sdim O << ',' 208263508Sdim << markup("<imm:") 209249423Sdim << ScaleVal // never printed in hex. 210263508Sdim << markup(">"); 211243830Sdim } 212218885Sdim } 213218885Sdim O << ')'; 214218885Sdim } 215243830Sdim 216243830Sdim O << markup(">"); 217218885Sdim} 218263508Sdim 219263508Sdimvoid X86ATTInstPrinter::printMemOffset(const MCInst *MI, unsigned Op, 220263508Sdim raw_ostream &O) { 221263508Sdim const MCOperand &DispSpec = MI->getOperand(Op); 222263508Sdim 223263508Sdim O << markup("<mem:"); 224263508Sdim 225263508Sdim if (DispSpec.isImm()) { 226263508Sdim O << formatImm(DispSpec.getImm()); 227263508Sdim } else { 228263508Sdim assert(DispSpec.isExpr() && "non-immediate displacement?"); 229263508Sdim O << *DispSpec.getExpr(); 230263508Sdim } 231263508Sdim 232263508Sdim O << markup(">"); 233263508Sdim} 234