Gabor Buella | 349ffce | 2018-06-05 10:41:39 +0000 | [diff] [blame] | 1 | //===--- X86InstPrinterCommon.cpp - X86 assembly instruction printing -----===// |
| 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
Gabor Buella | 349ffce | 2018-06-05 10:41:39 +0000 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // This file includes common code for rendering MCInst instances as Intel-style |
| 10 | // and Intel-style assembly. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #include "X86InstPrinterCommon.h" |
| 15 | #include "MCTargetDesc/X86BaseInfo.h" |
| 16 | #include "llvm/MC/MCExpr.h" |
| 17 | #include "llvm/MC/MCInst.h" |
| 18 | #include "llvm/MC/MCInstrDesc.h" |
| 19 | #include "llvm/MC/MCInstrInfo.h" |
| 20 | #include "llvm/Support/raw_ostream.h" |
| 21 | #include "llvm/Support/Casting.h" |
| 22 | #include <cstdint> |
| 23 | #include <cassert> |
| 24 | |
| 25 | using namespace llvm; |
| 26 | |
| 27 | void X86InstPrinterCommon::printSSEAVXCC(const MCInst *MI, unsigned Op, |
| 28 | raw_ostream &O) { |
| 29 | int64_t Imm = MI->getOperand(Op).getImm(); |
| 30 | switch (Imm) { |
| 31 | default: llvm_unreachable("Invalid ssecc/avxcc argument!"); |
| 32 | case 0: O << "eq"; break; |
| 33 | case 1: O << "lt"; break; |
| 34 | case 2: O << "le"; break; |
| 35 | case 3: O << "unord"; break; |
| 36 | case 4: O << "neq"; break; |
| 37 | case 5: O << "nlt"; break; |
| 38 | case 6: O << "nle"; break; |
| 39 | case 7: O << "ord"; break; |
| 40 | case 8: O << "eq_uq"; break; |
| 41 | case 9: O << "nge"; break; |
| 42 | case 0xa: O << "ngt"; break; |
| 43 | case 0xb: O << "false"; break; |
| 44 | case 0xc: O << "neq_oq"; break; |
| 45 | case 0xd: O << "ge"; break; |
| 46 | case 0xe: O << "gt"; break; |
| 47 | case 0xf: O << "true"; break; |
| 48 | case 0x10: O << "eq_os"; break; |
| 49 | case 0x11: O << "lt_oq"; break; |
| 50 | case 0x12: O << "le_oq"; break; |
| 51 | case 0x13: O << "unord_s"; break; |
| 52 | case 0x14: O << "neq_us"; break; |
| 53 | case 0x15: O << "nlt_uq"; break; |
| 54 | case 0x16: O << "nle_uq"; break; |
| 55 | case 0x17: O << "ord_s"; break; |
| 56 | case 0x18: O << "eq_us"; break; |
| 57 | case 0x19: O << "nge_uq"; break; |
| 58 | case 0x1a: O << "ngt_uq"; break; |
| 59 | case 0x1b: O << "false_os"; break; |
| 60 | case 0x1c: O << "neq_os"; break; |
| 61 | case 0x1d: O << "ge_oq"; break; |
| 62 | case 0x1e: O << "gt_oq"; break; |
| 63 | case 0x1f: O << "true_us"; break; |
| 64 | } |
| 65 | } |
| 66 | |
| 67 | void X86InstPrinterCommon::printXOPCC(const MCInst *MI, unsigned Op, |
| 68 | raw_ostream &O) { |
| 69 | int64_t Imm = MI->getOperand(Op).getImm(); |
| 70 | switch (Imm) { |
| 71 | default: llvm_unreachable("Invalid xopcc argument!"); |
| 72 | case 0: O << "lt"; break; |
| 73 | case 1: O << "le"; break; |
| 74 | case 2: O << "gt"; break; |
| 75 | case 3: O << "ge"; break; |
| 76 | case 4: O << "eq"; break; |
| 77 | case 5: O << "neq"; break; |
| 78 | case 6: O << "false"; break; |
| 79 | case 7: O << "true"; break; |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | void X86InstPrinterCommon::printRoundingControl(const MCInst *MI, unsigned Op, |
| 84 | raw_ostream &O) { |
| 85 | int64_t Imm = MI->getOperand(Op).getImm() & 0x3; |
| 86 | switch (Imm) { |
| 87 | case 0: O << "{rn-sae}"; break; |
| 88 | case 1: O << "{rd-sae}"; break; |
| 89 | case 2: O << "{ru-sae}"; break; |
| 90 | case 3: O << "{rz-sae}"; break; |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | /// printPCRelImm - This is used to print an immediate value that ends up |
| 95 | /// being encoded as a pc-relative value (e.g. for jumps and calls). In |
| 96 | /// Intel-style these print slightly differently than normal immediates. |
| 97 | /// for example, a $ is not emitted. |
| 98 | void X86InstPrinterCommon::printPCRelImm(const MCInst *MI, unsigned OpNo, |
| 99 | raw_ostream &O) { |
| 100 | const MCOperand &Op = MI->getOperand(OpNo); |
| 101 | if (Op.isImm()) |
| 102 | O << formatImm(Op.getImm()); |
| 103 | else { |
| 104 | assert(Op.isExpr() && "unknown pcrel immediate operand"); |
| 105 | // If a symbolic branch target was added as a constant expression then print |
| 106 | // that address in hex. |
| 107 | const MCConstantExpr *BranchTarget = dyn_cast<MCConstantExpr>(Op.getExpr()); |
| 108 | int64_t Address; |
| 109 | if (BranchTarget && BranchTarget->evaluateAsAbsolute(Address)) { |
| 110 | O << formatHex((uint64_t)Address); |
| 111 | } else { |
| 112 | // Otherwise, just print the expression. |
| 113 | Op.getExpr()->print(O, &MAI); |
| 114 | } |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | void X86InstPrinterCommon::printOptionalSegReg(const MCInst *MI, unsigned OpNo, |
| 119 | raw_ostream &O) { |
| 120 | if (MI->getOperand(OpNo).getReg()) { |
| 121 | printOperand(MI, OpNo, O); |
| 122 | O << ':'; |
| 123 | } |
| 124 | } |
| 125 | |
| 126 | void X86InstPrinterCommon::printInstFlags(const MCInst *MI, raw_ostream &O) { |
| 127 | const MCInstrDesc &Desc = MII.get(MI->getOpcode()); |
| 128 | uint64_t TSFlags = Desc.TSFlags; |
| 129 | unsigned Flags = MI->getFlags(); |
| 130 | |
| 131 | if ((TSFlags & X86II::LOCK) || (Flags & X86::IP_HAS_LOCK)) |
| 132 | O << "\tlock\t"; |
| 133 | |
| 134 | if ((TSFlags & X86II::NOTRACK) || (Flags & X86::IP_HAS_NOTRACK)) |
| 135 | O << "\tnotrack\t"; |
| 136 | |
| 137 | if (Flags & X86::IP_HAS_REPEAT_NE) |
| 138 | O << "\trepne\t"; |
| 139 | else if (Flags & X86::IP_HAS_REPEAT) |
| 140 | O << "\trep\t"; |
| 141 | } |