Home | History | Annotate | Download | only in InstPrinter
      1 //===-- X86ATTInstPrinter.cpp - AT&T assembly instruction printing --------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file includes code for rendering MCInst instances as AT&T-style
     11 // assembly.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "X86ATTInstPrinter.h"
     16 #include "MCTargetDesc/X86BaseInfo.h"
     17 #include "MCTargetDesc/X86MCTargetDesc.h"
     18 #include "X86InstComments.h"
     19 #include "llvm/MC/MCAsmInfo.h"
     20 #include "llvm/MC/MCExpr.h"
     21 #include "llvm/MC/MCInst.h"
     22 #include "llvm/MC/MCInstrInfo.h"
     23 #include "llvm/MC/MCRegisterInfo.h"
     24 #include "llvm/Support/ErrorHandling.h"
     25 #include "llvm/Support/Format.h"
     26 #include "llvm/Support/FormattedStream.h"
     27 #include <map>
     28 using namespace llvm;
     29 
     30 #define DEBUG_TYPE "asm-printer"
     31 
     32 // Include the auto-generated portion of the assembly writer.
     33 #define PRINT_ALIAS_INSTR
     34 #include "X86GenAsmWriter.inc"
     35 
     36 void X86ATTInstPrinter::printRegName(raw_ostream &OS,
     37                                      unsigned RegNo) const {
     38   OS << markup("<reg:")
     39      << '%' << getRegisterName(RegNo)
     40      << markup(">");
     41 }
     42 
     43 void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
     44                                   StringRef Annot) {
     45   const MCInstrDesc &Desc = MII.get(MI->getOpcode());
     46   uint64_t TSFlags = Desc.TSFlags;
     47 
     48   if (TSFlags & X86II::LOCK)
     49     OS << "\tlock\n";
     50 
     51   // Try to print any aliases first.
     52   if (!printAliasInstr(MI, OS))
     53     printInstruction(MI, OS);
     54 
     55   // Next always print the annotation.
     56   printAnnotation(OS, Annot);
     57 
     58   // If verbose assembly is enabled, we can print some informative comments.
     59   if (CommentStream)
     60     EmitAnyX86InstComments(MI, *CommentStream, getRegisterName);
     61 }
     62 
     63 void X86ATTInstPrinter::printSSECC(const MCInst *MI, unsigned Op,
     64                                    raw_ostream &O) {
     65   int64_t Imm = MI->getOperand(Op).getImm() & 0xf;
     66   switch (Imm) {
     67   default: llvm_unreachable("Invalid ssecc argument!");
     68   case    0: O << "eq"; break;
     69   case    1: O << "lt"; break;
     70   case    2: O << "le"; break;
     71   case    3: O << "unord"; break;
     72   case    4: O << "neq"; break;
     73   case    5: O << "nlt"; break;
     74   case    6: O << "nle"; break;
     75   case    7: O << "ord"; break;
     76   case    8: O << "eq_uq"; break;
     77   case    9: O << "nge"; break;
     78   case  0xa: O << "ngt"; break;
     79   case  0xb: O << "false"; break;
     80   case  0xc: O << "neq_oq"; break;
     81   case  0xd: O << "ge"; break;
     82   case  0xe: O << "gt"; break;
     83   case  0xf: O << "true"; break;
     84   }
     85 }
     86 
     87 void X86ATTInstPrinter::printAVXCC(const MCInst *MI, unsigned Op,
     88                                    raw_ostream &O) {
     89   int64_t Imm = MI->getOperand(Op).getImm() & 0x1f;
     90   switch (Imm) {
     91   default: llvm_unreachable("Invalid avxcc argument!");
     92   case    0: O << "eq"; break;
     93   case    1: O << "lt"; break;
     94   case    2: O << "le"; break;
     95   case    3: O << "unord"; break;
     96   case    4: O << "neq"; break;
     97   case    5: O << "nlt"; break;
     98   case    6: O << "nle"; break;
     99   case    7: O << "ord"; break;
    100   case    8: O << "eq_uq"; break;
    101   case    9: O << "nge"; break;
    102   case  0xa: O << "ngt"; break;
    103   case  0xb: O << "false"; break;
    104   case  0xc: O << "neq_oq"; break;
    105   case  0xd: O << "ge"; break;
    106   case  0xe: O << "gt"; break;
    107   case  0xf: O << "true"; break;
    108   case 0x10: O << "eq_os"; break;
    109   case 0x11: O << "lt_oq"; break;
    110   case 0x12: O << "le_oq"; break;
    111   case 0x13: O << "unord_s"; break;
    112   case 0x14: O << "neq_us"; break;
    113   case 0x15: O << "nlt_uq"; break;
    114   case 0x16: O << "nle_uq"; break;
    115   case 0x17: O << "ord_s"; break;
    116   case 0x18: O << "eq_us"; break;
    117   case 0x19: O << "nge_uq"; break;
    118   case 0x1a: O << "ngt_uq"; break;
    119   case 0x1b: O << "false_os"; break;
    120   case 0x1c: O << "neq_os"; break;
    121   case 0x1d: O << "ge_oq"; break;
    122   case 0x1e: O << "gt_oq"; break;
    123   case 0x1f: O << "true_us"; break;
    124   }
    125 }
    126 
    127 void X86ATTInstPrinter::printRoundingControl(const MCInst *MI, unsigned Op,
    128                                    raw_ostream &O) {
    129   int64_t Imm = MI->getOperand(Op).getImm() & 0x3;
    130   switch (Imm) {
    131   case 0: O << "{rn-sae}"; break;
    132   case 1: O << "{rd-sae}"; break;
    133   case 2: O << "{ru-sae}"; break;
    134   case 3: O << "{rz-sae}"; break;
    135   }
    136 }
    137 /// printPCRelImm - This is used to print an immediate value that ends up
    138 /// being encoded as a pc-relative value (e.g. for jumps and calls).  These
    139 /// print slightly differently than normal immediates.  For example, a $ is not
    140 /// emitted.
    141 void X86ATTInstPrinter::printPCRelImm(const MCInst *MI, unsigned OpNo,
    142                                       raw_ostream &O) {
    143   const MCOperand &Op = MI->getOperand(OpNo);
    144   if (Op.isImm())
    145     O << formatImm(Op.getImm());
    146   else {
    147     assert(Op.isExpr() && "unknown pcrel immediate operand");
    148     // If a symbolic branch target was added as a constant expression then print
    149     // that address in hex.
    150     const MCConstantExpr *BranchTarget = dyn_cast<MCConstantExpr>(Op.getExpr());
    151     int64_t Address;
    152     if (BranchTarget && BranchTarget->EvaluateAsAbsolute(Address)) {
    153       O << formatHex((uint64_t)Address);
    154     }
    155     else {
    156       // Otherwise, just print the expression.
    157       O << *Op.getExpr();
    158     }
    159   }
    160 }
    161 
    162 void X86ATTInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
    163                                      raw_ostream &O) {
    164   const MCOperand &Op = MI->getOperand(OpNo);
    165   if (Op.isReg()) {
    166     printRegName(O, Op.getReg());
    167   } else if (Op.isImm()) {
    168     // Print X86 immediates as signed values.
    169     O << markup("<imm:")
    170       << '$' << formatImm((int64_t)Op.getImm())
    171       << markup(">");
    172 
    173     if (CommentStream && (Op.getImm() > 255 || Op.getImm() < -256))
    174       *CommentStream << format("imm = 0x%" PRIX64 "\n", (uint64_t)Op.getImm());
    175 
    176   } else {
    177     assert(Op.isExpr() && "unknown operand kind in printOperand");
    178     O << markup("<imm:")
    179       << '$' << *Op.getExpr()
    180       << markup(">");
    181   }
    182 }
    183 
    184 void X86ATTInstPrinter::printMemReference(const MCInst *MI, unsigned Op,
    185                                           raw_ostream &O) {
    186   const MCOperand &BaseReg  = MI->getOperand(Op+X86::AddrBaseReg);
    187   const MCOperand &IndexReg = MI->getOperand(Op+X86::AddrIndexReg);
    188   const MCOperand &DispSpec = MI->getOperand(Op+X86::AddrDisp);
    189   const MCOperand &SegReg = MI->getOperand(Op+X86::AddrSegmentReg);
    190 
    191   O << markup("<mem:");
    192 
    193   // If this has a segment register, print it.
    194   if (SegReg.getReg()) {
    195     printOperand(MI, Op+X86::AddrSegmentReg, O);
    196     O << ':';
    197   }
    198 
    199   if (DispSpec.isImm()) {
    200     int64_t DispVal = DispSpec.getImm();
    201     if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg()))
    202       O << formatImm(DispVal);
    203   } else {
    204     assert(DispSpec.isExpr() && "non-immediate displacement for LEA?");
    205     O << *DispSpec.getExpr();
    206   }
    207 
    208   if (IndexReg.getReg() || BaseReg.getReg()) {
    209     O << '(';
    210     if (BaseReg.getReg())
    211       printOperand(MI, Op+X86::AddrBaseReg, O);
    212 
    213     if (IndexReg.getReg()) {
    214       O << ',';
    215       printOperand(MI, Op+X86::AddrIndexReg, O);
    216       unsigned ScaleVal = MI->getOperand(Op+X86::AddrScaleAmt).getImm();
    217       if (ScaleVal != 1) {
    218         O << ','
    219           << markup("<imm:")
    220           << ScaleVal // never printed in hex.
    221           << markup(">");
    222       }
    223     }
    224     O << ')';
    225   }
    226 
    227   O << markup(">");
    228 }
    229 
    230 void X86ATTInstPrinter::printSrcIdx(const MCInst *MI, unsigned Op,
    231                                     raw_ostream &O) {
    232   const MCOperand &SegReg = MI->getOperand(Op+1);
    233 
    234   O << markup("<mem:");
    235 
    236   // If this has a segment register, print it.
    237   if (SegReg.getReg()) {
    238     printOperand(MI, Op+1, O);
    239     O << ':';
    240   }
    241 
    242   O << "(";
    243   printOperand(MI, Op, O);
    244   O << ")";
    245 
    246   O << markup(">");
    247 }
    248 
    249 void X86ATTInstPrinter::printDstIdx(const MCInst *MI, unsigned Op,
    250                                     raw_ostream &O) {
    251   O << markup("<mem:");
    252 
    253   O << "%es:(";
    254   printOperand(MI, Op, O);
    255   O << ")";
    256 
    257   O << markup(">");
    258 }
    259 
    260 void X86ATTInstPrinter::printMemOffset(const MCInst *MI, unsigned Op,
    261                                        raw_ostream &O) {
    262   const MCOperand &DispSpec = MI->getOperand(Op);
    263   const MCOperand &SegReg = MI->getOperand(Op+1);
    264 
    265   O << markup("<mem:");
    266 
    267   // If this has a segment register, print it.
    268   if (SegReg.getReg()) {
    269     printOperand(MI, Op+1, O);
    270     O << ':';
    271   }
    272 
    273   if (DispSpec.isImm()) {
    274     O << formatImm(DispSpec.getImm());
    275   } else {
    276     assert(DispSpec.isExpr() && "non-immediate displacement?");
    277     O << *DispSpec.getExpr();
    278   }
    279 
    280   O << markup(">");
    281 }
    282