1 | //===-- MSP430InstPrinter.cpp - Convert MSP430 MCInst to assembly syntax --===// |
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This class prints an MSP430 MCInst to a .s file. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "MSP430InstPrinter.h" |
14 | #include "MSP430.h" |
15 | #include "llvm/MC/MCAsmInfo.h" |
16 | #include "llvm/MC/MCExpr.h" |
17 | #include "llvm/MC/MCInst.h" |
18 | #include "llvm/MC/MCInstrInfo.h" |
19 | #include "llvm/Support/ErrorHandling.h" |
20 | #include "llvm/Support/FormattedStream.h" |
21 | using namespace llvm; |
22 | |
23 | #define DEBUG_TYPE "asm-printer" |
24 | |
25 | // Include the auto-generated portion of the assembly writer. |
26 | #define PRINT_ALIAS_INSTR |
27 | #include "MSP430GenAsmWriter.inc" |
28 | |
29 | void MSP430InstPrinter::printRegName(raw_ostream &O, MCRegister Reg) const { |
30 | O << getRegisterName(Reg); |
31 | } |
32 | |
33 | void MSP430InstPrinter::printInst(const MCInst *MI, uint64_t Address, |
34 | StringRef Annot, const MCSubtargetInfo &STI, |
35 | raw_ostream &O) { |
36 | if (!printAliasInstr(MI, Address, OS&: O)) |
37 | printInstruction(MI, Address, O); |
38 | printAnnotation(OS&: O, Annot); |
39 | } |
40 | |
41 | void MSP430InstPrinter::printPCRelImmOperand(const MCInst *MI, unsigned OpNo, |
42 | raw_ostream &O) { |
43 | const MCOperand &Op = MI->getOperand(i: OpNo); |
44 | if (Op.isImm()) { |
45 | int64_t Imm = Op.getImm() * 2 + 2; |
46 | O << "$" ; |
47 | if (Imm >= 0) |
48 | O << '+'; |
49 | O << Imm; |
50 | } else { |
51 | assert(Op.isExpr() && "unknown pcrel immediate operand" ); |
52 | Op.getExpr()->print(OS&: O, MAI: &MAI); |
53 | } |
54 | } |
55 | |
56 | void MSP430InstPrinter::printOperand(const MCInst *MI, unsigned OpNo, |
57 | raw_ostream &O, const char *Modifier) { |
58 | assert((Modifier == nullptr || Modifier[0] == 0) && "No modifiers supported" ); |
59 | const MCOperand &Op = MI->getOperand(i: OpNo); |
60 | if (Op.isReg()) { |
61 | O << getRegisterName(Reg: Op.getReg()); |
62 | } else if (Op.isImm()) { |
63 | O << '#' << Op.getImm(); |
64 | } else { |
65 | assert(Op.isExpr() && "unknown operand kind in printOperand" ); |
66 | O << '#'; |
67 | Op.getExpr()->print(OS&: O, MAI: &MAI); |
68 | } |
69 | } |
70 | |
71 | void MSP430InstPrinter::printSrcMemOperand(const MCInst *MI, unsigned OpNo, |
72 | raw_ostream &O, |
73 | const char *Modifier) { |
74 | const MCOperand &Base = MI->getOperand(i: OpNo); |
75 | const MCOperand &Disp = MI->getOperand(i: OpNo+1); |
76 | |
77 | // Print displacement first |
78 | |
79 | // If the global address expression is a part of displacement field with a |
80 | // register base, we should not emit any prefix symbol here, e.g. |
81 | // mov.w &foo, r1 |
82 | // vs |
83 | // mov.w glb(r1), r2 |
84 | // Otherwise (!) msp430-as will silently miscompile the output :( |
85 | if (Base.getReg() == MSP430::SR) |
86 | O << '&'; |
87 | |
88 | if (Disp.isExpr()) |
89 | Disp.getExpr()->print(OS&: O, MAI: &MAI); |
90 | else { |
91 | assert(Disp.isImm() && "Expected immediate in displacement field" ); |
92 | O << Disp.getImm(); |
93 | } |
94 | |
95 | // Print register base field |
96 | if ((Base.getReg() != MSP430::SR) && |
97 | (Base.getReg() != MSP430::PC)) |
98 | O << '(' << getRegisterName(Reg: Base.getReg()) << ')'; |
99 | } |
100 | |
101 | void MSP430InstPrinter::printIndRegOperand(const MCInst *MI, unsigned OpNo, |
102 | raw_ostream &O) { |
103 | const MCOperand &Base = MI->getOperand(i: OpNo); |
104 | O << "@" << getRegisterName(Reg: Base.getReg()); |
105 | } |
106 | |
107 | void MSP430InstPrinter::printPostIndRegOperand(const MCInst *MI, unsigned OpNo, |
108 | raw_ostream &O) { |
109 | const MCOperand &Base = MI->getOperand(i: OpNo); |
110 | O << "@" << getRegisterName(Reg: Base.getReg()) << "+" ; |
111 | } |
112 | |
113 | void MSP430InstPrinter::printCCOperand(const MCInst *MI, unsigned OpNo, |
114 | raw_ostream &O) { |
115 | unsigned CC = MI->getOperand(i: OpNo).getImm(); |
116 | |
117 | switch (CC) { |
118 | default: |
119 | llvm_unreachable("Unsupported CC code" ); |
120 | case MSP430CC::COND_E: |
121 | O << "eq" ; |
122 | break; |
123 | case MSP430CC::COND_NE: |
124 | O << "ne" ; |
125 | break; |
126 | case MSP430CC::COND_HS: |
127 | O << "hs" ; |
128 | break; |
129 | case MSP430CC::COND_LO: |
130 | O << "lo" ; |
131 | break; |
132 | case MSP430CC::COND_GE: |
133 | O << "ge" ; |
134 | break; |
135 | case MSP430CC::COND_L: |
136 | O << 'l'; |
137 | break; |
138 | case MSP430CC::COND_N: |
139 | O << 'n'; |
140 | break; |
141 | } |
142 | } |
143 | |