xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/MSP430/MCTargetDesc/MSP430InstPrinter.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //===-- MSP430InstPrinter.cpp - Convert MSP430 MCInst to assembly syntax --===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This class prints an MSP430 MCInst to a .s file.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "MSP430InstPrinter.h"
140b57cec5SDimitry Andric #include "MSP430.h"
150b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
190b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
200b57cec5SDimitry Andric #include "llvm/Support/FormattedStream.h"
210b57cec5SDimitry Andric using namespace llvm;
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric #define DEBUG_TYPE "asm-printer"
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric // Include the auto-generated portion of the assembly writer.
260b57cec5SDimitry Andric #define PRINT_ALIAS_INSTR
270b57cec5SDimitry Andric #include "MSP430GenAsmWriter.inc"
280b57cec5SDimitry Andric 
printRegName(raw_ostream & O,MCRegister Reg) const29*06c3fb27SDimitry Andric void MSP430InstPrinter::printRegName(raw_ostream &O, MCRegister Reg) const {
30*06c3fb27SDimitry Andric   O << getRegisterName(Reg);
31*06c3fb27SDimitry Andric }
32*06c3fb27SDimitry Andric 
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & O)33480093f4SDimitry Andric void MSP430InstPrinter::printInst(const MCInst *MI, uint64_t Address,
34480093f4SDimitry Andric                                   StringRef Annot, const MCSubtargetInfo &STI,
35480093f4SDimitry Andric                                   raw_ostream &O) {
365ffd83dbSDimitry Andric   if (!printAliasInstr(MI, Address, O))
37480093f4SDimitry Andric     printInstruction(MI, Address, O);
380b57cec5SDimitry Andric   printAnnotation(O, Annot);
390b57cec5SDimitry Andric }
400b57cec5SDimitry Andric 
printPCRelImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)410b57cec5SDimitry Andric void MSP430InstPrinter::printPCRelImmOperand(const MCInst *MI, unsigned OpNo,
420b57cec5SDimitry Andric                                              raw_ostream &O) {
430b57cec5SDimitry Andric   const MCOperand &Op = MI->getOperand(OpNo);
440b57cec5SDimitry Andric   if (Op.isImm()) {
450b57cec5SDimitry Andric     int64_t Imm = Op.getImm() * 2 + 2;
460b57cec5SDimitry Andric     O << "$";
470b57cec5SDimitry Andric     if (Imm >= 0)
480b57cec5SDimitry Andric       O << '+';
490b57cec5SDimitry Andric     O << Imm;
500b57cec5SDimitry Andric   } else {
510b57cec5SDimitry Andric     assert(Op.isExpr() && "unknown pcrel immediate operand");
520b57cec5SDimitry Andric     Op.getExpr()->print(O, &MAI);
530b57cec5SDimitry Andric   }
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
printOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O,const char * Modifier)560b57cec5SDimitry Andric void MSP430InstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
570b57cec5SDimitry Andric                                      raw_ostream &O, const char *Modifier) {
580b57cec5SDimitry Andric   assert((Modifier == nullptr || Modifier[0] == 0) && "No modifiers supported");
590b57cec5SDimitry Andric   const MCOperand &Op = MI->getOperand(OpNo);
600b57cec5SDimitry Andric   if (Op.isReg()) {
610b57cec5SDimitry Andric     O << getRegisterName(Op.getReg());
620b57cec5SDimitry Andric   } else if (Op.isImm()) {
630b57cec5SDimitry Andric     O << '#' << Op.getImm();
640b57cec5SDimitry Andric   } else {
650b57cec5SDimitry Andric     assert(Op.isExpr() && "unknown operand kind in printOperand");
660b57cec5SDimitry Andric     O << '#';
670b57cec5SDimitry Andric     Op.getExpr()->print(O, &MAI);
680b57cec5SDimitry Andric   }
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric 
printSrcMemOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O,const char * Modifier)710b57cec5SDimitry Andric void MSP430InstPrinter::printSrcMemOperand(const MCInst *MI, unsigned OpNo,
720b57cec5SDimitry Andric                                            raw_ostream &O,
730b57cec5SDimitry Andric                                            const char *Modifier) {
740b57cec5SDimitry Andric   const MCOperand &Base = MI->getOperand(OpNo);
750b57cec5SDimitry Andric   const MCOperand &Disp = MI->getOperand(OpNo+1);
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   // Print displacement first
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   // If the global address expression is a part of displacement field with a
800b57cec5SDimitry Andric   // register base, we should not emit any prefix symbol here, e.g.
810b57cec5SDimitry Andric   //   mov.w &foo, r1
820b57cec5SDimitry Andric   // vs
830b57cec5SDimitry Andric   //   mov.w glb(r1), r2
840b57cec5SDimitry Andric   // Otherwise (!) msp430-as will silently miscompile the output :(
850b57cec5SDimitry Andric   if (Base.getReg() == MSP430::SR)
860b57cec5SDimitry Andric     O << '&';
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   if (Disp.isExpr())
890b57cec5SDimitry Andric     Disp.getExpr()->print(O, &MAI);
900b57cec5SDimitry Andric   else {
910b57cec5SDimitry Andric     assert(Disp.isImm() && "Expected immediate in displacement field");
920b57cec5SDimitry Andric     O << Disp.getImm();
930b57cec5SDimitry Andric   }
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   // Print register base field
960b57cec5SDimitry Andric   if ((Base.getReg() != MSP430::SR) &&
970b57cec5SDimitry Andric       (Base.getReg() != MSP430::PC))
980b57cec5SDimitry Andric     O << '(' << getRegisterName(Base.getReg()) << ')';
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric 
printIndRegOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)1010b57cec5SDimitry Andric void MSP430InstPrinter::printIndRegOperand(const MCInst *MI, unsigned OpNo,
1020b57cec5SDimitry Andric                                            raw_ostream &O) {
1030b57cec5SDimitry Andric   const MCOperand &Base = MI->getOperand(OpNo);
1040b57cec5SDimitry Andric   O << "@" << getRegisterName(Base.getReg());
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric 
printPostIndRegOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)1070b57cec5SDimitry Andric void MSP430InstPrinter::printPostIndRegOperand(const MCInst *MI, unsigned OpNo,
1080b57cec5SDimitry Andric                                                raw_ostream &O) {
1090b57cec5SDimitry Andric   const MCOperand &Base = MI->getOperand(OpNo);
1100b57cec5SDimitry Andric   O << "@" << getRegisterName(Base.getReg()) << "+";
1110b57cec5SDimitry Andric }
1120b57cec5SDimitry Andric 
printCCOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)1130b57cec5SDimitry Andric void MSP430InstPrinter::printCCOperand(const MCInst *MI, unsigned OpNo,
1140b57cec5SDimitry Andric                                        raw_ostream &O) {
1150b57cec5SDimitry Andric   unsigned CC = MI->getOperand(OpNo).getImm();
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   switch (CC) {
1180b57cec5SDimitry Andric   default:
1190b57cec5SDimitry Andric    llvm_unreachable("Unsupported CC code");
1200b57cec5SDimitry Andric   case MSP430CC::COND_E:
1210b57cec5SDimitry Andric    O << "eq";
1220b57cec5SDimitry Andric    break;
1230b57cec5SDimitry Andric   case MSP430CC::COND_NE:
1240b57cec5SDimitry Andric    O << "ne";
1250b57cec5SDimitry Andric    break;
1260b57cec5SDimitry Andric   case MSP430CC::COND_HS:
1270b57cec5SDimitry Andric    O << "hs";
1280b57cec5SDimitry Andric    break;
1290b57cec5SDimitry Andric   case MSP430CC::COND_LO:
1300b57cec5SDimitry Andric    O << "lo";
1310b57cec5SDimitry Andric    break;
1320b57cec5SDimitry Andric   case MSP430CC::COND_GE:
1330b57cec5SDimitry Andric    O << "ge";
1340b57cec5SDimitry Andric    break;
1350b57cec5SDimitry Andric   case MSP430CC::COND_L:
1360b57cec5SDimitry Andric    O << 'l';
1370b57cec5SDimitry Andric    break;
1380b57cec5SDimitry Andric   case MSP430CC::COND_N:
1390b57cec5SDimitry Andric    O << 'n';
1400b57cec5SDimitry Andric    break;
1410b57cec5SDimitry Andric   }
1420b57cec5SDimitry Andric }
143