xref: /netbsd-src/external/apache2/llvm/dist/llvm/lib/Target/M68k/MCTargetDesc/M68kInstPrinter.cpp (revision 82d56013d7b633d116a93943de88e08335357a7c)
1*82d56013Sjoerg //===-- M68kInstPrinter.cpp - Convert M68k MCInst to asm ----*- C++ -*-===//
2*82d56013Sjoerg //
3*82d56013Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*82d56013Sjoerg // See https://llvm.org/LICENSE.txt for license information.
5*82d56013Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*82d56013Sjoerg //
7*82d56013Sjoerg //===----------------------------------------------------------------------===//
8*82d56013Sjoerg ///
9*82d56013Sjoerg /// \file
10*82d56013Sjoerg /// This file contains definitions for an M68k MCInst printer.
11*82d56013Sjoerg ///
12*82d56013Sjoerg //===----------------------------------------------------------------------===//
13*82d56013Sjoerg 
14*82d56013Sjoerg // TODO Conform with all supported Motorola ASM syntax
15*82d56013Sjoerg // Motorola's assembly has several syntax variants, especially on
16*82d56013Sjoerg // addressing modes.
17*82d56013Sjoerg // For example, you can write pc indirect w/ displacement as
18*82d56013Sjoerg // `x(%pc)`, where `x` is the displacement imm, or `(x,%pc)`.
19*82d56013Sjoerg // Currently we're picking the variant that is different from
20*82d56013Sjoerg // GCC, albeit being recognizable by GNU AS.
21*82d56013Sjoerg // Not sure what is the impact now (e.g. some syntax might
22*82d56013Sjoerg // not be recognized by some old consoles' toolchains, in which
23*82d56013Sjoerg // case we can not use our integrated assembler), but either way,
24*82d56013Sjoerg // it will be great to support all of the variants in the future.
25*82d56013Sjoerg 
26*82d56013Sjoerg #include "M68kInstPrinter.h"
27*82d56013Sjoerg #include "M68kBaseInfo.h"
28*82d56013Sjoerg 
29*82d56013Sjoerg #include "llvm/ADT/StringExtras.h"
30*82d56013Sjoerg #include "llvm/MC/MCExpr.h"
31*82d56013Sjoerg #include "llvm/MC/MCInst.h"
32*82d56013Sjoerg #include "llvm/MC/MCInstrInfo.h"
33*82d56013Sjoerg #include "llvm/MC/MCSymbol.h"
34*82d56013Sjoerg #include "llvm/Support/ErrorHandling.h"
35*82d56013Sjoerg #include "llvm/Support/raw_ostream.h"
36*82d56013Sjoerg 
37*82d56013Sjoerg using namespace llvm;
38*82d56013Sjoerg 
39*82d56013Sjoerg #define DEBUG_TYPE "asm-printer"
40*82d56013Sjoerg 
41*82d56013Sjoerg #define PRINT_ALIAS_INSTR
42*82d56013Sjoerg #include "M68kGenAsmWriter.inc"
43*82d56013Sjoerg 
printRegName(raw_ostream & OS,unsigned RegNo) const44*82d56013Sjoerg void M68kInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
45*82d56013Sjoerg   OS << "%" << getRegisterName(RegNo);
46*82d56013Sjoerg }
47*82d56013Sjoerg 
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & O)48*82d56013Sjoerg void M68kInstPrinter::printInst(const MCInst *MI, uint64_t Address,
49*82d56013Sjoerg                                 StringRef Annot, const MCSubtargetInfo &STI,
50*82d56013Sjoerg                                 raw_ostream &O) {
51*82d56013Sjoerg   if (!printAliasInstr(MI, Address, O))
52*82d56013Sjoerg     printInstruction(MI, Address, O);
53*82d56013Sjoerg 
54*82d56013Sjoerg   printAnnotation(O, Annot);
55*82d56013Sjoerg }
56*82d56013Sjoerg 
printOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)57*82d56013Sjoerg void M68kInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
58*82d56013Sjoerg                                    raw_ostream &O) {
59*82d56013Sjoerg   const MCOperand &MO = MI->getOperand(OpNo);
60*82d56013Sjoerg   if (MO.isReg()) {
61*82d56013Sjoerg     printRegName(O, MO.getReg());
62*82d56013Sjoerg     return;
63*82d56013Sjoerg   }
64*82d56013Sjoerg 
65*82d56013Sjoerg   if (MO.isImm()) {
66*82d56013Sjoerg     printImmediate(MI, OpNo, O);
67*82d56013Sjoerg     return;
68*82d56013Sjoerg   }
69*82d56013Sjoerg 
70*82d56013Sjoerg   assert(MO.isExpr() && "Unknown operand kind in printOperand");
71*82d56013Sjoerg   MO.getExpr()->print(O, &MAI);
72*82d56013Sjoerg }
73*82d56013Sjoerg 
printImmediate(const MCInst * MI,unsigned opNum,raw_ostream & O)74*82d56013Sjoerg void M68kInstPrinter::printImmediate(const MCInst *MI, unsigned opNum,
75*82d56013Sjoerg                                      raw_ostream &O) {
76*82d56013Sjoerg   const MCOperand &MO = MI->getOperand(opNum);
77*82d56013Sjoerg   if (MO.isImm())
78*82d56013Sjoerg     O << '#' << MO.getImm();
79*82d56013Sjoerg   else if (MO.isExpr()) {
80*82d56013Sjoerg     O << '#';
81*82d56013Sjoerg     MO.getExpr()->print(O, &MAI);
82*82d56013Sjoerg   } else
83*82d56013Sjoerg     llvm_unreachable("Unknown immediate kind");
84*82d56013Sjoerg }
85*82d56013Sjoerg 
printMoveMask(const MCInst * MI,unsigned opNum,raw_ostream & O)86*82d56013Sjoerg void M68kInstPrinter::printMoveMask(const MCInst *MI, unsigned opNum,
87*82d56013Sjoerg                                     raw_ostream &O) {
88*82d56013Sjoerg   unsigned Mask = MI->getOperand(opNum).getImm();
89*82d56013Sjoerg   assert((Mask & 0xFFFF) == Mask && "Mask is always 16 bits");
90*82d56013Sjoerg 
91*82d56013Sjoerg   // A move mask is splitted into two parts:
92*82d56013Sjoerg   // bits 0 ~ 7  correspond to D0 ~ D7 regs
93*82d56013Sjoerg   // bits 8 ~ 15 correspond to A0 ~ A7 regs
94*82d56013Sjoerg   //
95*82d56013Sjoerg   // In the assembly syntax, we want to use a dash to replace
96*82d56013Sjoerg   // a continuous range of registers. For example, if the bit
97*82d56013Sjoerg   // mask is 0b101110, we want to print "D1-D3,D5" instead of
98*82d56013Sjoerg   // "D1,D2,D3,D4,D5".
99*82d56013Sjoerg   //
100*82d56013Sjoerg   // However, we don't want a dash to cross between data registers
101*82d56013Sjoerg   // and address registers (i.e. there shouldn't be a dash crossing
102*82d56013Sjoerg   // bit 7 and 8) since that is not really intuitive. So we simply
103*82d56013Sjoerg   // print the data register part (bit 0~7) and address register part
104*82d56013Sjoerg   // separately.
105*82d56013Sjoerg   uint8_t HalfMask;
106*82d56013Sjoerg   unsigned Reg;
107*82d56013Sjoerg   for (int s = 0; s < 16; s += 8) {
108*82d56013Sjoerg     HalfMask = (Mask >> s) & 0xFF;
109*82d56013Sjoerg     // Print separation comma only if
110*82d56013Sjoerg     // both data & register parts have bit(s) set
111*82d56013Sjoerg     if (s != 0 && (Mask & 0xFF) && HalfMask)
112*82d56013Sjoerg       O << ',';
113*82d56013Sjoerg 
114*82d56013Sjoerg     for (int i = 0; HalfMask; ++i) {
115*82d56013Sjoerg       if ((HalfMask >> i) & 0b1) {
116*82d56013Sjoerg         HalfMask ^= 0b1 << i;
117*82d56013Sjoerg         Reg = M68kII::getMaskedSpillRegister(i + s);
118*82d56013Sjoerg         printRegName(O, Reg);
119*82d56013Sjoerg 
120*82d56013Sjoerg         int j = i;
121*82d56013Sjoerg         while ((HalfMask >> (j + 1)) & 0b1)
122*82d56013Sjoerg           HalfMask ^= 0b1 << ++j;
123*82d56013Sjoerg 
124*82d56013Sjoerg         if (j != i) {
125*82d56013Sjoerg           O << '-';
126*82d56013Sjoerg           Reg = M68kII::getMaskedSpillRegister(j + s);
127*82d56013Sjoerg           printRegName(O, Reg);
128*82d56013Sjoerg         }
129*82d56013Sjoerg 
130*82d56013Sjoerg         i = j;
131*82d56013Sjoerg 
132*82d56013Sjoerg         if (HalfMask)
133*82d56013Sjoerg           O << ',';
134*82d56013Sjoerg       }
135*82d56013Sjoerg     }
136*82d56013Sjoerg   }
137*82d56013Sjoerg }
138*82d56013Sjoerg 
printDisp(const MCInst * MI,unsigned opNum,raw_ostream & O)139*82d56013Sjoerg void M68kInstPrinter::printDisp(const MCInst *MI, unsigned opNum,
140*82d56013Sjoerg                                 raw_ostream &O) {
141*82d56013Sjoerg   const MCOperand &Op = MI->getOperand(opNum);
142*82d56013Sjoerg   if (Op.isImm()) {
143*82d56013Sjoerg     O << Op.getImm();
144*82d56013Sjoerg     return;
145*82d56013Sjoerg   }
146*82d56013Sjoerg   assert(Op.isExpr() && "Unknown operand kind in printOperand");
147*82d56013Sjoerg   Op.getExpr()->print(O, &MAI);
148*82d56013Sjoerg }
149*82d56013Sjoerg 
printARIMem(const MCInst * MI,unsigned opNum,raw_ostream & O)150*82d56013Sjoerg void M68kInstPrinter::printARIMem(const MCInst *MI, unsigned opNum,
151*82d56013Sjoerg                                   raw_ostream &O) {
152*82d56013Sjoerg   O << '(';
153*82d56013Sjoerg   printOperand(MI, opNum, O);
154*82d56013Sjoerg   O << ')';
155*82d56013Sjoerg }
156*82d56013Sjoerg 
printARIPIMem(const MCInst * MI,unsigned opNum,raw_ostream & O)157*82d56013Sjoerg void M68kInstPrinter::printARIPIMem(const MCInst *MI, unsigned opNum,
158*82d56013Sjoerg                                     raw_ostream &O) {
159*82d56013Sjoerg   O << "(";
160*82d56013Sjoerg   printOperand(MI, opNum, O);
161*82d56013Sjoerg   O << ")+";
162*82d56013Sjoerg }
163*82d56013Sjoerg 
printARIPDMem(const MCInst * MI,unsigned opNum,raw_ostream & O)164*82d56013Sjoerg void M68kInstPrinter::printARIPDMem(const MCInst *MI, unsigned opNum,
165*82d56013Sjoerg                                     raw_ostream &O) {
166*82d56013Sjoerg   O << "-(";
167*82d56013Sjoerg   printOperand(MI, opNum, O);
168*82d56013Sjoerg   O << ")";
169*82d56013Sjoerg }
170*82d56013Sjoerg 
printARIDMem(const MCInst * MI,unsigned opNum,raw_ostream & O)171*82d56013Sjoerg void M68kInstPrinter::printARIDMem(const MCInst *MI, unsigned opNum,
172*82d56013Sjoerg                                    raw_ostream &O) {
173*82d56013Sjoerg   O << '(';
174*82d56013Sjoerg   printDisp(MI, opNum + M68k::MemDisp, O);
175*82d56013Sjoerg   O << ',';
176*82d56013Sjoerg   printOperand(MI, opNum + M68k::MemBase, O);
177*82d56013Sjoerg   O << ')';
178*82d56013Sjoerg }
179*82d56013Sjoerg 
printARIIMem(const MCInst * MI,unsigned opNum,raw_ostream & O)180*82d56013Sjoerg void M68kInstPrinter::printARIIMem(const MCInst *MI, unsigned opNum,
181*82d56013Sjoerg                                    raw_ostream &O) {
182*82d56013Sjoerg   O << '(';
183*82d56013Sjoerg   printDisp(MI, opNum + M68k::MemDisp, O);
184*82d56013Sjoerg   O << ',';
185*82d56013Sjoerg   printOperand(MI, opNum + M68k::MemBase, O);
186*82d56013Sjoerg   O << ',';
187*82d56013Sjoerg   printOperand(MI, opNum + M68k::MemIndex, O);
188*82d56013Sjoerg   O << ')';
189*82d56013Sjoerg }
190*82d56013Sjoerg 
191*82d56013Sjoerg // NOTE forcing (W,L) size available since M68020 only
printAbsMem(const MCInst * MI,unsigned opNum,raw_ostream & O)192*82d56013Sjoerg void M68kInstPrinter::printAbsMem(const MCInst *MI, unsigned opNum,
193*82d56013Sjoerg                                   raw_ostream &O) {
194*82d56013Sjoerg   const MCOperand &MO = MI->getOperand(opNum);
195*82d56013Sjoerg 
196*82d56013Sjoerg   if (MO.isExpr()) {
197*82d56013Sjoerg     MO.getExpr()->print(O, &MAI);
198*82d56013Sjoerg     return;
199*82d56013Sjoerg   }
200*82d56013Sjoerg 
201*82d56013Sjoerg   assert(MO.isImm() && "absolute memory addressing needs an immediate");
202*82d56013Sjoerg   O << format("$%0" PRIx64, (uint64_t)MO.getImm());
203*82d56013Sjoerg }
204*82d56013Sjoerg 
printPCDMem(const MCInst * MI,uint64_t Address,unsigned opNum,raw_ostream & O)205*82d56013Sjoerg void M68kInstPrinter::printPCDMem(const MCInst *MI, uint64_t Address,
206*82d56013Sjoerg                                   unsigned opNum, raw_ostream &O) {
207*82d56013Sjoerg   O << '(';
208*82d56013Sjoerg   printDisp(MI, opNum + M68k::PCRelDisp, O);
209*82d56013Sjoerg   O << ",%pc)";
210*82d56013Sjoerg }
211*82d56013Sjoerg 
printPCIMem(const MCInst * MI,uint64_t Address,unsigned opNum,raw_ostream & O)212*82d56013Sjoerg void M68kInstPrinter::printPCIMem(const MCInst *MI, uint64_t Address,
213*82d56013Sjoerg                                   unsigned opNum, raw_ostream &O) {
214*82d56013Sjoerg   O << '(';
215*82d56013Sjoerg   printDisp(MI, opNum + M68k::PCRelDisp, O);
216*82d56013Sjoerg   O << ",%pc,";
217*82d56013Sjoerg   printOperand(MI, opNum + M68k::PCRelIndex, O);
218*82d56013Sjoerg   O << ')';
219*82d56013Sjoerg }
220