| //===- HexagonInstPrinter.cpp - Convert Hexagon MCInst to assembly syntax -===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This class prints an Hexagon MCInst to a .s file. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #define DEBUG_TYPE "asm-printer" |
| #include "HexagonAsmPrinter.h" |
| #include "Hexagon.h" |
| #include "HexagonInstPrinter.h" |
| #include "MCTargetDesc/HexagonMCInst.h" |
| #include "llvm/MC/MCInst.h" |
| #include "llvm/ADT/StringExtras.h" |
| #include "llvm/MC/MCAsmInfo.h" |
| #include "llvm/MC/MCExpr.h" |
| #include "llvm/Support/raw_ostream.h" |
| #include <cstdio> |
| |
| using namespace llvm; |
| |
| #define GET_INSTRUCTION_NAME |
| #include "HexagonGenAsmWriter.inc" |
| |
| const char HexagonInstPrinter::PacketPadding = '\t'; |
| |
| StringRef HexagonInstPrinter::getOpcodeName(unsigned Opcode) const { |
| return MII.getName(Opcode); |
| } |
| |
| StringRef HexagonInstPrinter::getRegName(unsigned RegNo) const { |
| return getRegisterName(RegNo); |
| } |
| |
| void HexagonInstPrinter::printInst(const MCInst *MI, raw_ostream &O, |
| StringRef Annot) { |
| printInst((const HexagonMCInst*)(MI), O, Annot); |
| } |
| |
| void HexagonInstPrinter::printInst(const HexagonMCInst *MI, raw_ostream &O, |
| StringRef Annot) { |
| const char startPacket = '{', |
| endPacket = '}'; |
| // TODO: add outer HW loop when it's supported too. |
| if (MI->getOpcode() == Hexagon::ENDLOOP0) { |
| // Ending a harware loop is different from ending an regular packet. |
| assert(MI->isPacketEnd() && "Loop-end must also end the packet"); |
| |
| if (MI->isPacketStart()) { |
| // There must be a packet to end a loop. |
| // FIXME: when shuffling is always run, this shouldn't be needed. |
| HexagonMCInst Nop; |
| StringRef NoAnnot; |
| |
| Nop.setOpcode (Hexagon::NOP); |
| Nop.setPacketStart (MI->isPacketStart()); |
| printInst (&Nop, O, NoAnnot); |
| } |
| |
| // Close the packet. |
| if (MI->isPacketEnd()) |
| O << PacketPadding << endPacket; |
| |
| printInstruction(MI, O); |
| } |
| else { |
| // Prefix the insn opening the packet. |
| if (MI->isPacketStart()) |
| O << PacketPadding << startPacket << '\n'; |
| |
| printInstruction(MI, O); |
| |
| // Suffix the insn closing the packet. |
| if (MI->isPacketEnd()) |
| // Suffix the packet in a new line always, since the GNU assembler has |
| // issues with a closing brace on the same line as CONST{32,64}. |
| O << '\n' << PacketPadding << endPacket; |
| } |
| |
| printAnnotation(O, Annot); |
| } |
| |
| void HexagonInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, |
| raw_ostream &O) const { |
| const MCOperand& MO = MI->getOperand(OpNo); |
| |
| if (MO.isReg()) { |
| O << getRegisterName(MO.getReg()); |
| } else if(MO.isExpr()) { |
| O << *MO.getExpr(); |
| } else if(MO.isImm()) { |
| printImmOperand(MI, OpNo, O); |
| } else { |
| llvm_unreachable("Unknown operand"); |
| } |
| } |
| |
| void HexagonInstPrinter::printImmOperand(const MCInst *MI, unsigned OpNo, |
| raw_ostream &O) const { |
| const MCOperand& MO = MI->getOperand(OpNo); |
| |
| if(MO.isExpr()) { |
| O << *MO.getExpr(); |
| } else if(MO.isImm()) { |
| O << MI->getOperand(OpNo).getImm(); |
| } else { |
| llvm_unreachable("Unknown operand"); |
| } |
| } |
| |
| void HexagonInstPrinter::printExtOperand(const MCInst *MI, unsigned OpNo, |
| raw_ostream &O) const { |
| const HexagonMCInst *HMCI = static_cast<const HexagonMCInst*>(MI); |
| if (HMCI->isConstExtended()) |
| O << "#"; |
| printOperand(MI, OpNo, O); |
| } |
| |
| void HexagonInstPrinter::printUnsignedImmOperand(const MCInst *MI, |
| unsigned OpNo, raw_ostream &O) const { |
| O << MI->getOperand(OpNo).getImm(); |
| } |
| |
| void HexagonInstPrinter::printNegImmOperand(const MCInst *MI, unsigned OpNo, |
| raw_ostream &O) const { |
| O << -MI->getOperand(OpNo).getImm(); |
| } |
| |
| void HexagonInstPrinter::printNOneImmOperand(const MCInst *MI, unsigned OpNo, |
| raw_ostream &O) const { |
| O << -1; |
| } |
| |
| void HexagonInstPrinter::printMEMriOperand(const MCInst *MI, unsigned OpNo, |
| raw_ostream &O) const { |
| const MCOperand& MO0 = MI->getOperand(OpNo); |
| const MCOperand& MO1 = MI->getOperand(OpNo + 1); |
| |
| O << getRegisterName(MO0.getReg()); |
| O << " + #" << MO1.getImm(); |
| } |
| |
| void HexagonInstPrinter::printFrameIndexOperand(const MCInst *MI, unsigned OpNo, |
| raw_ostream &O) const { |
| const MCOperand& MO0 = MI->getOperand(OpNo); |
| const MCOperand& MO1 = MI->getOperand(OpNo + 1); |
| |
| O << getRegisterName(MO0.getReg()) << ", #" << MO1.getImm(); |
| } |
| |
| void HexagonInstPrinter::printGlobalOperand(const MCInst *MI, unsigned OpNo, |
| raw_ostream &O) const { |
| assert(MI->getOperand(OpNo).isExpr() && "Expecting expression"); |
| |
| printOperand(MI, OpNo, O); |
| } |
| |
| void HexagonInstPrinter::printJumpTable(const MCInst *MI, unsigned OpNo, |
| raw_ostream &O) const { |
| assert(MI->getOperand(OpNo).isExpr() && "Expecting expression"); |
| |
| printOperand(MI, OpNo, O); |
| } |
| |
| void HexagonInstPrinter::printConstantPool(const MCInst *MI, unsigned OpNo, |
| raw_ostream &O) const { |
| assert(MI->getOperand(OpNo).isExpr() && "Expecting expression"); |
| |
| printOperand(MI, OpNo, O); |
| } |
| |
| void HexagonInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo, |
| raw_ostream &O) const { |
| // Branches can take an immediate operand. This is used by the branch |
| // selection pass to print $+8, an eight byte displacement from the PC. |
| assert("Unknown branch operand."); |
| } |
| |
| void HexagonInstPrinter::printCallOperand(const MCInst *MI, unsigned OpNo, |
| raw_ostream &O) const { |
| } |
| |
| void HexagonInstPrinter::printAbsAddrOperand(const MCInst *MI, unsigned OpNo, |
| raw_ostream &O) const { |
| } |
| |
| void HexagonInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo, |
| raw_ostream &O) const { |
| } |
| |
| void HexagonInstPrinter::printSymbol(const MCInst *MI, unsigned OpNo, |
| raw_ostream &O, bool hi) const { |
| const MCOperand& MO = MI->getOperand(OpNo); |
| |
| O << '#' << (hi? "HI": "LO") << '('; |
| if (MO.isImm()) { |
| O << '#'; |
| printOperand(MI, OpNo, O); |
| } else { |
| assert("Unknown symbol operand"); |
| printOperand(MI, OpNo, O); |
| } |
| O << ')'; |
| } |