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>
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_INSTR
34#include "X86GenAsmWriter.inc"
35
36void X86ATTInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
37  OS << markup("<reg:") << '%' << getRegisterName(RegNo) << markup(">");
38}
39
40void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
41                                  StringRef Annot, const MCSubtargetInfo &STI) {
42  const MCInstrDesc &Desc = MII.get(MI->getOpcode());
43  uint64_t TSFlags = Desc.TSFlags;
44
45  // If verbose assembly is enabled, we can print some informative comments.
46  if (CommentStream)
47    HasCustomInstComment =
48        EmitAnyX86InstComments(MI, *CommentStream, getRegisterName);
49
50  if (TSFlags & X86II::LOCK)
51    OS << "\tlock\t";
52
53  // Output CALLpcrel32 as "callq" in 64-bit mode.
54  // In Intel annotation it's always emitted as "call".
55  //
56  // TODO: Probably this hack should be redesigned via InstAlias in
57  // InstrInfo.td as soon as Requires clause is supported properly
58  // for InstAlias.
59  if (MI->getOpcode() == X86::CALLpcrel32 &&
60      (STI.getFeatureBits()[X86::Mode64Bit])) {
61    OS << "\tcallq\t";
62    printPCRelImm(MI, 0, OS);
63  }
64  // Try to print any aliases first.
65  else if (!printAliasInstr(MI, OS))
66    printInstruction(MI, OS);
67
68  // Next always print the annotation.
69  printAnnotation(OS, Annot);
70}
71
72void X86ATTInstPrinter::printSSEAVXCC(const MCInst *MI, unsigned Op,
73                                      raw_ostream &O) {
74  int64_t Imm = MI->getOperand(Op).getImm();
75  switch (Imm) {
76  default: llvm_unreachable("Invalid ssecc/avxcc argument!");
77  case    0: O << "eq"; break;
78  case    1: O << "lt"; break;
79  case    2: O << "le"; break;
80  case    3: O << "unord"; break;
81  case    4: O << "neq"; break;
82  case    5: O << "nlt"; break;
83  case    6: O << "nle"; break;
84  case    7: O << "ord"; break;
85  case    8: O << "eq_uq"; break;
86  case    9: O << "nge"; break;
87  case  0xa: O << "ngt"; break;
88  case  0xb: O << "false"; break;
89  case  0xc: O << "neq_oq"; break;
90  case  0xd: O << "ge"; break;
91  case  0xe: O << "gt"; break;
92  case  0xf: O << "true"; break;
93  case 0x10: O << "eq_os"; break;
94  case 0x11: O << "lt_oq"; break;
95  case 0x12: O << "le_oq"; break;
96  case 0x13: O << "unord_s"; break;
97  case 0x14: O << "neq_us"; break;
98  case 0x15: O << "nlt_uq"; break;
99  case 0x16: O << "nle_uq"; break;
100  case 0x17: O << "ord_s"; break;
101  case 0x18: O << "eq_us"; break;
102  case 0x19: O << "nge_uq"; break;
103  case 0x1a: O << "ngt_uq"; break;
104  case 0x1b: O << "false_os"; break;
105  case 0x1c: O << "neq_os"; break;
106  case 0x1d: O << "ge_oq"; break;
107  case 0x1e: O << "gt_oq"; break;
108  case 0x1f: O << "true_us"; break;
109  }
110}
111
112void X86ATTInstPrinter::printXOPCC(const MCInst *MI, unsigned Op,
113                                   raw_ostream &O) {
114  int64_t Imm = MI->getOperand(Op).getImm();
115  switch (Imm) {
116  default: llvm_unreachable("Invalid xopcc argument!");
117  case 0: O << "lt"; break;
118  case 1: O << "le"; break;
119  case 2: O << "gt"; break;
120  case 3: O << "ge"; break;
121  case 4: O << "eq"; break;
122  case 5: O << "neq"; break;
123  case 6: O << "false"; break;
124  case 7: O << "true"; break;
125  }
126}
127
128void X86ATTInstPrinter::printRoundingControl(const MCInst *MI, unsigned Op,
129                                            raw_ostream &O) {
130  int64_t Imm = MI->getOperand(Op).getImm() & 0x3;
131  switch (Imm) {
132  case 0: O << "{rn-sae}"; break;
133  case 1: O << "{rd-sae}"; break;
134  case 2: O << "{ru-sae}"; break;
135  case 3: O << "{rz-sae}"; break;
136  }
137}
138/// printPCRelImm - This is used to print an immediate value that ends up
139/// being encoded as a pc-relative value (e.g. for jumps and calls).  These
140/// print slightly differently than normal immediates.  For example, a $ is not
141/// emitted.
142void X86ATTInstPrinter::printPCRelImm(const MCInst *MI, unsigned OpNo,
143                                      raw_ostream &O) {
144  const MCOperand &Op = MI->getOperand(OpNo);
145  if (Op.isImm())
146    O << formatImm(Op.getImm());
147  else {
148    assert(Op.isExpr() && "unknown pcrel immediate operand");
149    // If a symbolic branch target was added as a constant expression then print
150    // that address in hex.
151    const MCConstantExpr *BranchTarget = dyn_cast<MCConstantExpr>(Op.getExpr());
152    int64_t Address;
153    if (BranchTarget && BranchTarget->evaluateAsAbsolute(Address)) {
154      O << formatHex((uint64_t)Address);
155    } else {
156      // Otherwise, just print the expression.
157      Op.getExpr()->print(O, &MAI);
158    }
159  }
160}
161
162void 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:") << '$' << formatImm((int64_t)Op.getImm())
170      << markup(">");
171
172    // If there are no instruction-specific comments, add a comment clarifying
173    // the hex value of the immediate operand when it isn't in the range
174    // [-256,255].
175    if (CommentStream && !HasCustomInstComment &&
176        (Op.getImm() > 255 || Op.getImm() < -256))
177      *CommentStream << format("imm = 0x%" PRIX64 "\n", (uint64_t)Op.getImm());
178
179  } else {
180    assert(Op.isExpr() && "unknown operand kind in printOperand");
181    O << markup("<imm:") << '$';
182    Op.getExpr()->print(O, &MAI);
183    O << markup(">");
184  }
185}
186
187void X86ATTInstPrinter::printMemReference(const MCInst *MI, unsigned Op,
188                                          raw_ostream &O) {
189  const MCOperand &BaseReg = MI->getOperand(Op + X86::AddrBaseReg);
190  const MCOperand &IndexReg = MI->getOperand(Op + X86::AddrIndexReg);
191  const MCOperand &DispSpec = MI->getOperand(Op + X86::AddrDisp);
192  const MCOperand &SegReg = MI->getOperand(Op + X86::AddrSegmentReg);
193
194  O << markup("<mem:");
195
196  // If this has a segment register, print it.
197  if (SegReg.getReg()) {
198    printOperand(MI, Op + X86::AddrSegmentReg, O);
199    O << ':';
200  }
201
202  if (DispSpec.isImm()) {
203    int64_t DispVal = DispSpec.getImm();
204    if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg()))
205      O << formatImm(DispVal);
206  } else {
207    assert(DispSpec.isExpr() && "non-immediate displacement for LEA?");
208    DispSpec.getExpr()->print(O, &MAI);
209  }
210
211  if (IndexReg.getReg() || BaseReg.getReg()) {
212    O << '(';
213    if (BaseReg.getReg())
214      printOperand(MI, Op + X86::AddrBaseReg, O);
215
216    if (IndexReg.getReg()) {
217      O << ',';
218      printOperand(MI, Op + X86::AddrIndexReg, O);
219      unsigned ScaleVal = MI->getOperand(Op + X86::AddrScaleAmt).getImm();
220      if (ScaleVal != 1) {
221        O << ',' << markup("<imm:") << ScaleVal // never printed in hex.
222          << markup(">");
223      }
224    }
225    O << ')';
226  }
227
228  O << markup(">");
229}
230
231void X86ATTInstPrinter::printSrcIdx(const MCInst *MI, unsigned Op,
232                                    raw_ostream &O) {
233  const MCOperand &SegReg = MI->getOperand(Op + 1);
234
235  O << markup("<mem:");
236
237  // If this has a segment register, print it.
238  if (SegReg.getReg()) {
239    printOperand(MI, Op + 1, O);
240    O << ':';
241  }
242
243  O << "(";
244  printOperand(MI, Op, O);
245  O << ")";
246
247  O << markup(">");
248}
249
250void X86ATTInstPrinter::printDstIdx(const MCInst *MI, unsigned Op,
251                                    raw_ostream &O) {
252  O << markup("<mem:");
253
254  O << "%es:(";
255  printOperand(MI, Op, O);
256  O << ")";
257
258  O << markup(">");
259}
260
261void X86ATTInstPrinter::printMemOffset(const MCInst *MI, unsigned Op,
262                                       raw_ostream &O) {
263  const MCOperand &DispSpec = MI->getOperand(Op);
264  const MCOperand &SegReg = MI->getOperand(Op + 1);
265
266  O << markup("<mem:");
267
268  // If this has a segment register, print it.
269  if (SegReg.getReg()) {
270    printOperand(MI, Op + 1, O);
271    O << ':';
272  }
273
274  if (DispSpec.isImm()) {
275    O << formatImm(DispSpec.getImm());
276  } else {
277    assert(DispSpec.isExpr() && "non-immediate displacement?");
278    DispSpec.getExpr()->print(O, &MAI);
279  }
280
281  O << markup(">");
282}
283
284void X86ATTInstPrinter::printU8Imm(const MCInst *MI, unsigned Op,
285                                   raw_ostream &O) {
286  O << markup("<imm:") << '$' << formatImm(MI->getOperand(Op).getImm() & 0xff)
287    << markup(">");
288}
289