1 //===- HexagonInstPrinter.cpp - Convert Hexagon MCInst to assembly syntax -===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This class prints an Hexagon MCInst to a .s file.
12 //===----------------------------------------------------------------------===//
14 #include "HexagonAsmPrinter.h"
16 #include "HexagonInstPrinter.h"
17 #include "MCTargetDesc/HexagonMCInstrInfo.h"
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/MC/MCAsmInfo.h"
20 #include "llvm/MC/MCExpr.h"
21 #include "llvm/MC/MCInst.h"
22 #include "llvm/Support/raw_ostream.h"
26 #define DEBUG_TYPE "asm-printer"
28 #define GET_INSTRUCTION_NAME
29 #include "HexagonGenAsmWriter.inc"
31 // Return the minimum value that a constant extendable operand can have
32 // without being extended.
33 static int getMinValue(uint64_t TSFlags) {
35 (TSFlags >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask;
37 (TSFlags >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask;
40 return -1U << (bits - 1);
45 // Return the maximum value that a constant extendable operand can have
46 // without being extended.
47 static int getMaxValue(uint64_t TSFlags) {
49 (TSFlags >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask;
51 (TSFlags >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask;
54 return ~(-1U << (bits - 1));
56 return ~(-1U << bits);
59 // Return true if the instruction must be extended.
60 static bool isExtended(uint64_t TSFlags) {
61 return (TSFlags >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask;
64 // Currently just used in an assert statement
65 static bool isExtendable(uint64_t TSFlags) LLVM_ATTRIBUTE_UNUSED;
66 // Return true if the instruction may be extended based on the operand value.
67 static bool isExtendable(uint64_t TSFlags) {
68 return (TSFlags >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask;
71 StringRef HexagonInstPrinter::getOpcodeName(unsigned Opcode) const {
72 return MII.getName(Opcode);
75 void HexagonInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
76 OS << getRegisterName(RegNo);
79 void HexagonInstPrinter::setExtender(MCInst const &MCI) {
80 HasExtender = HexagonMCInstrInfo::isImmext(MCI);
83 void HexagonInstPrinter::printInst(MCInst const *MI, raw_ostream &OS,
85 MCSubtargetInfo const &STI) {
86 assert(HexagonMCInstrInfo::isBundle(*MI));
87 assert(HexagonMCInstrInfo::bundleSize(*MI) <= HEXAGON_PACKET_SIZE);
89 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(*MI)) {
90 MCInst const &MCI = *I.getInst();
91 if (HexagonMCInstrInfo::isDuplex(MII, MCI)) {
92 printInstruction(MCI.getOperand(1).getInst(), OS);
95 printInstruction(MCI.getOperand(0).getInst(), OS);
97 printInstruction(&MCI, OS);
103 if (HexagonMCInstrInfo::isInnerLoop(*MI)) {
107 ME.setOpcode(Hexagon::ENDLOOP0);
108 printInstruction(&ME, OS);
110 if (HexagonMCInstrInfo::isOuterLoop(*MI)) {
114 ME.setOpcode(Hexagon::ENDLOOP1);
115 printInstruction(&ME, OS);
119 void HexagonInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
120 raw_ostream &O) const {
121 const MCOperand& MO = MI->getOperand(OpNo);
124 printRegName(O, MO.getReg());
125 } else if(MO.isExpr()) {
126 MO.getExpr()->print(O, &MAI);
127 } else if(MO.isImm()) {
128 printImmOperand(MI, OpNo, O);
130 llvm_unreachable("Unknown operand");
134 void HexagonInstPrinter::printImmOperand(const MCInst *MI, unsigned OpNo,
135 raw_ostream &O) const {
136 const MCOperand& MO = MI->getOperand(OpNo);
139 MO.getExpr()->print(O, &MAI);
140 } else if(MO.isImm()) {
141 O << MI->getOperand(OpNo).getImm();
143 llvm_unreachable("Unknown operand");
147 void HexagonInstPrinter::printExtOperand(const MCInst *MI, unsigned OpNo,
148 raw_ostream &O) const {
149 const MCOperand &MO = MI->getOperand(OpNo);
150 const MCInstrDesc &MII = getMII().get(MI->getOpcode());
152 assert((isExtendable(MII.TSFlags) || isExtended(MII.TSFlags)) &&
153 "Expecting an extendable operand");
155 if (MO.isExpr() || isExtended(MII.TSFlags)) {
157 } else if (MO.isImm()) {
158 int ImmValue = MO.getImm();
159 if (ImmValue < getMinValue(MII.TSFlags) ||
160 ImmValue > getMaxValue(MII.TSFlags))
163 printOperand(MI, OpNo, O);
166 void HexagonInstPrinter::printUnsignedImmOperand(const MCInst *MI,
167 unsigned OpNo, raw_ostream &O) const {
168 O << MI->getOperand(OpNo).getImm();
171 void HexagonInstPrinter::printNegImmOperand(const MCInst *MI, unsigned OpNo,
172 raw_ostream &O) const {
173 O << -MI->getOperand(OpNo).getImm();
176 void HexagonInstPrinter::printNOneImmOperand(const MCInst *MI, unsigned OpNo,
177 raw_ostream &O) const {
181 void HexagonInstPrinter::prints3_6ImmOperand(MCInst const *MI, unsigned OpNo,
182 raw_ostream &O) const {
183 int64_t Imm = MI->getOperand(OpNo).getImm();
184 assert(((Imm & 0x3f) == 0) && "Lower 6 bits must be ZERO.");
185 O << formatImm(Imm/64);
188 void HexagonInstPrinter::prints3_7ImmOperand(MCInst const *MI, unsigned OpNo,
189 raw_ostream &O) const {
190 int64_t Imm = MI->getOperand(OpNo).getImm();
191 assert(((Imm & 0x7f) == 0) && "Lower 7 bits must be ZERO.");
192 O << formatImm(Imm/128);
195 void HexagonInstPrinter::prints4_6ImmOperand(MCInst const *MI, unsigned OpNo,
196 raw_ostream &O) const {
197 int64_t Imm = MI->getOperand(OpNo).getImm();
198 assert(((Imm & 0x3f) == 0) && "Lower 6 bits must be ZERO.");
199 O << formatImm(Imm/64);
202 void HexagonInstPrinter::prints4_7ImmOperand(MCInst const *MI, unsigned OpNo,
203 raw_ostream &O) const {
204 int64_t Imm = MI->getOperand(OpNo).getImm();
205 assert(((Imm & 0x7f) == 0) && "Lower 7 bits must be ZERO.");
206 O << formatImm(Imm/128);
209 void HexagonInstPrinter::printMEMriOperand(const MCInst *MI, unsigned OpNo,
210 raw_ostream &O) const {
211 const MCOperand& MO0 = MI->getOperand(OpNo);
212 const MCOperand& MO1 = MI->getOperand(OpNo + 1);
214 printRegName(O, MO0.getReg());
215 O << " + #" << MO1.getImm();
218 void HexagonInstPrinter::printFrameIndexOperand(const MCInst *MI, unsigned OpNo,
219 raw_ostream &O) const {
220 const MCOperand& MO0 = MI->getOperand(OpNo);
221 const MCOperand& MO1 = MI->getOperand(OpNo + 1);
223 printRegName(O, MO0.getReg());
224 O << ", #" << MO1.getImm();
227 void HexagonInstPrinter::printGlobalOperand(const MCInst *MI, unsigned OpNo,
228 raw_ostream &O) const {
229 assert(MI->getOperand(OpNo).isExpr() && "Expecting expression");
231 printOperand(MI, OpNo, O);
234 void HexagonInstPrinter::printJumpTable(const MCInst *MI, unsigned OpNo,
235 raw_ostream &O) const {
236 assert(MI->getOperand(OpNo).isExpr() && "Expecting expression");
238 printOperand(MI, OpNo, O);
241 void HexagonInstPrinter::printConstantPool(const MCInst *MI, unsigned OpNo,
242 raw_ostream &O) const {
243 assert(MI->getOperand(OpNo).isExpr() && "Expecting expression");
245 printOperand(MI, OpNo, O);
248 void HexagonInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo,
249 raw_ostream &O) const {
250 // Branches can take an immediate operand. This is used by the branch
251 // selection pass to print $+8, an eight byte displacement from the PC.
252 llvm_unreachable("Unknown branch operand.");
255 void HexagonInstPrinter::printCallOperand(const MCInst *MI, unsigned OpNo,
256 raw_ostream &O) const {
259 void HexagonInstPrinter::printAbsAddrOperand(const MCInst *MI, unsigned OpNo,
260 raw_ostream &O) const {
263 void HexagonInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
264 raw_ostream &O) const {
267 void HexagonInstPrinter::printSymbol(const MCInst *MI, unsigned OpNo,
268 raw_ostream &O, bool hi) const {
269 assert(MI->getOperand(OpNo).isImm() && "Unknown symbol operand");
271 O << '#' << (hi ? "HI" : "LO") << "(#";
272 printOperand(MI, OpNo, O);
276 void HexagonInstPrinter::printExtBrtarget(const MCInst *MI, unsigned OpNo,
277 raw_ostream &O) const {
278 const MCOperand &MO = MI->getOperand(OpNo);
279 const MCInstrDesc &MII = getMII().get(MI->getOpcode());
281 assert((isExtendable(MII.TSFlags) || isExtended(MII.TSFlags)) &&
282 "Expecting an extendable operand");
284 if (MO.isExpr() || isExtended(MII.TSFlags)) {
287 printOperand(MI, OpNo, O);