xref: /aosp_15_r20/external/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- SparcMCCodeEmitter.cpp - Convert Sparc code to machine code -------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file implements the SparcMCCodeEmitter class.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker 
14*9880d681SAndroid Build Coastguard Worker #include "SparcMCExpr.h"
15*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/SparcFixupKinds.h"
16*9880d681SAndroid Build Coastguard Worker #include "SparcMCTargetDesc.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCCodeEmitter.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCExpr.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInst.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCRegisterInfo.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSymbol.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmInfo.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/EndianStream.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
27*9880d681SAndroid Build Coastguard Worker 
28*9880d681SAndroid Build Coastguard Worker using namespace llvm;
29*9880d681SAndroid Build Coastguard Worker 
30*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "mccodeemitter"
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
33*9880d681SAndroid Build Coastguard Worker 
34*9880d681SAndroid Build Coastguard Worker namespace {
35*9880d681SAndroid Build Coastguard Worker class SparcMCCodeEmitter : public MCCodeEmitter {
36*9880d681SAndroid Build Coastguard Worker   SparcMCCodeEmitter(const SparcMCCodeEmitter &) = delete;
37*9880d681SAndroid Build Coastguard Worker   void operator=(const SparcMCCodeEmitter &) = delete;
38*9880d681SAndroid Build Coastguard Worker   MCContext &Ctx;
39*9880d681SAndroid Build Coastguard Worker 
40*9880d681SAndroid Build Coastguard Worker public:
SparcMCCodeEmitter(MCContext & ctx)41*9880d681SAndroid Build Coastguard Worker   SparcMCCodeEmitter(MCContext &ctx): Ctx(ctx) {}
42*9880d681SAndroid Build Coastguard Worker 
~SparcMCCodeEmitter()43*9880d681SAndroid Build Coastguard Worker   ~SparcMCCodeEmitter() override {}
44*9880d681SAndroid Build Coastguard Worker 
45*9880d681SAndroid Build Coastguard Worker   void encodeInstruction(const MCInst &MI, raw_ostream &OS,
46*9880d681SAndroid Build Coastguard Worker                          SmallVectorImpl<MCFixup> &Fixups,
47*9880d681SAndroid Build Coastguard Worker                          const MCSubtargetInfo &STI) const override;
48*9880d681SAndroid Build Coastguard Worker 
49*9880d681SAndroid Build Coastguard Worker   // getBinaryCodeForInstr - TableGen'erated function for getting the
50*9880d681SAndroid Build Coastguard Worker   // binary encoding for an instruction.
51*9880d681SAndroid Build Coastguard Worker   uint64_t getBinaryCodeForInstr(const MCInst &MI,
52*9880d681SAndroid Build Coastguard Worker                                  SmallVectorImpl<MCFixup> &Fixups,
53*9880d681SAndroid Build Coastguard Worker                                  const MCSubtargetInfo &STI) const;
54*9880d681SAndroid Build Coastguard Worker 
55*9880d681SAndroid Build Coastguard Worker   /// getMachineOpValue - Return binary encoding of operand. If the machine
56*9880d681SAndroid Build Coastguard Worker   /// operand requires relocation, record the relocation and return zero.
57*9880d681SAndroid Build Coastguard Worker   unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
58*9880d681SAndroid Build Coastguard Worker                              SmallVectorImpl<MCFixup> &Fixups,
59*9880d681SAndroid Build Coastguard Worker                              const MCSubtargetInfo &STI) const;
60*9880d681SAndroid Build Coastguard Worker 
61*9880d681SAndroid Build Coastguard Worker   unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
62*9880d681SAndroid Build Coastguard Worker                              SmallVectorImpl<MCFixup> &Fixups,
63*9880d681SAndroid Build Coastguard Worker                              const MCSubtargetInfo &STI) const;
64*9880d681SAndroid Build Coastguard Worker   unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
65*9880d681SAndroid Build Coastguard Worker                              SmallVectorImpl<MCFixup> &Fixups,
66*9880d681SAndroid Build Coastguard Worker                              const MCSubtargetInfo &STI) const;
67*9880d681SAndroid Build Coastguard Worker   unsigned getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
68*9880d681SAndroid Build Coastguard Worker                                       SmallVectorImpl<MCFixup> &Fixups,
69*9880d681SAndroid Build Coastguard Worker                                       const MCSubtargetInfo &STI) const;
70*9880d681SAndroid Build Coastguard Worker   unsigned getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
71*9880d681SAndroid Build Coastguard Worker                                        SmallVectorImpl<MCFixup> &Fixups,
72*9880d681SAndroid Build Coastguard Worker                                        const MCSubtargetInfo &STI) const;
73*9880d681SAndroid Build Coastguard Worker 
74*9880d681SAndroid Build Coastguard Worker };
75*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
76*9880d681SAndroid Build Coastguard Worker 
createSparcMCCodeEmitter(const MCInstrInfo & MCII,const MCRegisterInfo & MRI,MCContext & Ctx)77*9880d681SAndroid Build Coastguard Worker MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
78*9880d681SAndroid Build Coastguard Worker                                               const MCRegisterInfo &MRI,
79*9880d681SAndroid Build Coastguard Worker                                               MCContext &Ctx) {
80*9880d681SAndroid Build Coastguard Worker   return new SparcMCCodeEmitter(Ctx);
81*9880d681SAndroid Build Coastguard Worker }
82*9880d681SAndroid Build Coastguard Worker 
encodeInstruction(const MCInst & MI,raw_ostream & OS,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const83*9880d681SAndroid Build Coastguard Worker void SparcMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
84*9880d681SAndroid Build Coastguard Worker                                            SmallVectorImpl<MCFixup> &Fixups,
85*9880d681SAndroid Build Coastguard Worker                                            const MCSubtargetInfo &STI) const {
86*9880d681SAndroid Build Coastguard Worker   unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI);
87*9880d681SAndroid Build Coastguard Worker 
88*9880d681SAndroid Build Coastguard Worker   if (Ctx.getAsmInfo()->isLittleEndian()) {
89*9880d681SAndroid Build Coastguard Worker     // Output the bits in little-endian byte order.
90*9880d681SAndroid Build Coastguard Worker     support::endian::Writer<support::little>(OS).write<uint32_t>(Bits);
91*9880d681SAndroid Build Coastguard Worker   } else {
92*9880d681SAndroid Build Coastguard Worker     // Output the bits in big-endian byte order.
93*9880d681SAndroid Build Coastguard Worker     support::endian::Writer<support::big>(OS).write<uint32_t>(Bits);
94*9880d681SAndroid Build Coastguard Worker   }
95*9880d681SAndroid Build Coastguard Worker   unsigned tlsOpNo = 0;
96*9880d681SAndroid Build Coastguard Worker   switch (MI.getOpcode()) {
97*9880d681SAndroid Build Coastguard Worker   default: break;
98*9880d681SAndroid Build Coastguard Worker   case SP::TLS_CALL:   tlsOpNo = 1; break;
99*9880d681SAndroid Build Coastguard Worker   case SP::TLS_ADDrr:
100*9880d681SAndroid Build Coastguard Worker   case SP::TLS_ADDXrr:
101*9880d681SAndroid Build Coastguard Worker   case SP::TLS_LDrr:
102*9880d681SAndroid Build Coastguard Worker   case SP::TLS_LDXrr:  tlsOpNo = 3; break;
103*9880d681SAndroid Build Coastguard Worker   }
104*9880d681SAndroid Build Coastguard Worker   if (tlsOpNo != 0) {
105*9880d681SAndroid Build Coastguard Worker     const MCOperand &MO = MI.getOperand(tlsOpNo);
106*9880d681SAndroid Build Coastguard Worker     uint64_t op = getMachineOpValue(MI, MO, Fixups, STI);
107*9880d681SAndroid Build Coastguard Worker     assert(op == 0 && "Unexpected operand value!");
108*9880d681SAndroid Build Coastguard Worker     (void)op; // suppress warning.
109*9880d681SAndroid Build Coastguard Worker   }
110*9880d681SAndroid Build Coastguard Worker 
111*9880d681SAndroid Build Coastguard Worker   ++MCNumEmitted;  // Keep track of the # of mi's emitted.
112*9880d681SAndroid Build Coastguard Worker }
113*9880d681SAndroid Build Coastguard Worker 
114*9880d681SAndroid Build Coastguard Worker 
115*9880d681SAndroid Build Coastguard Worker unsigned SparcMCCodeEmitter::
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const116*9880d681SAndroid Build Coastguard Worker getMachineOpValue(const MCInst &MI, const MCOperand &MO,
117*9880d681SAndroid Build Coastguard Worker                   SmallVectorImpl<MCFixup> &Fixups,
118*9880d681SAndroid Build Coastguard Worker                   const MCSubtargetInfo &STI) const {
119*9880d681SAndroid Build Coastguard Worker 
120*9880d681SAndroid Build Coastguard Worker   if (MO.isReg())
121*9880d681SAndroid Build Coastguard Worker     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
122*9880d681SAndroid Build Coastguard Worker 
123*9880d681SAndroid Build Coastguard Worker   if (MO.isImm())
124*9880d681SAndroid Build Coastguard Worker     return MO.getImm();
125*9880d681SAndroid Build Coastguard Worker 
126*9880d681SAndroid Build Coastguard Worker   assert(MO.isExpr());
127*9880d681SAndroid Build Coastguard Worker   const MCExpr *Expr = MO.getExpr();
128*9880d681SAndroid Build Coastguard Worker   if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
129*9880d681SAndroid Build Coastguard Worker     MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind();
130*9880d681SAndroid Build Coastguard Worker     Fixups.push_back(MCFixup::create(0, Expr, Kind));
131*9880d681SAndroid Build Coastguard Worker     return 0;
132*9880d681SAndroid Build Coastguard Worker   }
133*9880d681SAndroid Build Coastguard Worker 
134*9880d681SAndroid Build Coastguard Worker   int64_t Res;
135*9880d681SAndroid Build Coastguard Worker   if (Expr->evaluateAsAbsolute(Res))
136*9880d681SAndroid Build Coastguard Worker     return Res;
137*9880d681SAndroid Build Coastguard Worker 
138*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Unhandled expression!");
139*9880d681SAndroid Build Coastguard Worker   return 0;
140*9880d681SAndroid Build Coastguard Worker }
141*9880d681SAndroid Build Coastguard Worker 
142*9880d681SAndroid Build Coastguard Worker unsigned SparcMCCodeEmitter::
getCallTargetOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const143*9880d681SAndroid Build Coastguard Worker getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
144*9880d681SAndroid Build Coastguard Worker                      SmallVectorImpl<MCFixup> &Fixups,
145*9880d681SAndroid Build Coastguard Worker                      const MCSubtargetInfo &STI) const {
146*9880d681SAndroid Build Coastguard Worker   const MCOperand &MO = MI.getOperand(OpNo);
147*9880d681SAndroid Build Coastguard Worker   if (MO.isReg() || MO.isImm())
148*9880d681SAndroid Build Coastguard Worker     return getMachineOpValue(MI, MO, Fixups, STI);
149*9880d681SAndroid Build Coastguard Worker 
150*9880d681SAndroid Build Coastguard Worker   if (MI.getOpcode() == SP::TLS_CALL) {
151*9880d681SAndroid Build Coastguard Worker     // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in
152*9880d681SAndroid Build Coastguard Worker     // encodeInstruction.
153*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
154*9880d681SAndroid Build Coastguard Worker     // Verify that the callee is actually __tls_get_addr.
155*9880d681SAndroid Build Coastguard Worker     const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr());
156*9880d681SAndroid Build Coastguard Worker     assert(SExpr && SExpr->getSubExpr()->getKind() == MCExpr::SymbolRef &&
157*9880d681SAndroid Build Coastguard Worker            "Unexpected expression in TLS_CALL");
158*9880d681SAndroid Build Coastguard Worker     const MCSymbolRefExpr *SymExpr = cast<MCSymbolRefExpr>(SExpr->getSubExpr());
159*9880d681SAndroid Build Coastguard Worker     assert(SymExpr->getSymbol().getName() == "__tls_get_addr" &&
160*9880d681SAndroid Build Coastguard Worker            "Unexpected function for TLS_CALL");
161*9880d681SAndroid Build Coastguard Worker #endif
162*9880d681SAndroid Build Coastguard Worker     return 0;
163*9880d681SAndroid Build Coastguard Worker   }
164*9880d681SAndroid Build Coastguard Worker 
165*9880d681SAndroid Build Coastguard Worker   MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30;
166*9880d681SAndroid Build Coastguard Worker 
167*9880d681SAndroid Build Coastguard Worker   if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr())) {
168*9880d681SAndroid Build Coastguard Worker     if (SExpr->getKind() == SparcMCExpr::VK_Sparc_WPLT30)
169*9880d681SAndroid Build Coastguard Worker       fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30;
170*9880d681SAndroid Build Coastguard Worker   }
171*9880d681SAndroid Build Coastguard Worker 
172*9880d681SAndroid Build Coastguard Worker   Fixups.push_back(MCFixup::create(0, MO.getExpr(), fixupKind));
173*9880d681SAndroid Build Coastguard Worker 
174*9880d681SAndroid Build Coastguard Worker   return 0;
175*9880d681SAndroid Build Coastguard Worker }
176*9880d681SAndroid Build Coastguard Worker 
177*9880d681SAndroid Build Coastguard Worker unsigned SparcMCCodeEmitter::
getBranchTargetOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const178*9880d681SAndroid Build Coastguard Worker getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
179*9880d681SAndroid Build Coastguard Worker                   SmallVectorImpl<MCFixup> &Fixups,
180*9880d681SAndroid Build Coastguard Worker                   const MCSubtargetInfo &STI) const {
181*9880d681SAndroid Build Coastguard Worker   const MCOperand &MO = MI.getOperand(OpNo);
182*9880d681SAndroid Build Coastguard Worker   if (MO.isReg() || MO.isImm())
183*9880d681SAndroid Build Coastguard Worker     return getMachineOpValue(MI, MO, Fixups, STI);
184*9880d681SAndroid Build Coastguard Worker 
185*9880d681SAndroid Build Coastguard Worker   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
186*9880d681SAndroid Build Coastguard Worker                                    (MCFixupKind)Sparc::fixup_sparc_br22));
187*9880d681SAndroid Build Coastguard Worker   return 0;
188*9880d681SAndroid Build Coastguard Worker }
189*9880d681SAndroid Build Coastguard Worker 
190*9880d681SAndroid Build Coastguard Worker unsigned SparcMCCodeEmitter::
getBranchPredTargetOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const191*9880d681SAndroid Build Coastguard Worker getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
192*9880d681SAndroid Build Coastguard Worker                            SmallVectorImpl<MCFixup> &Fixups,
193*9880d681SAndroid Build Coastguard Worker                            const MCSubtargetInfo &STI) const {
194*9880d681SAndroid Build Coastguard Worker   const MCOperand &MO = MI.getOperand(OpNo);
195*9880d681SAndroid Build Coastguard Worker   if (MO.isReg() || MO.isImm())
196*9880d681SAndroid Build Coastguard Worker     return getMachineOpValue(MI, MO, Fixups, STI);
197*9880d681SAndroid Build Coastguard Worker 
198*9880d681SAndroid Build Coastguard Worker   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
199*9880d681SAndroid Build Coastguard Worker                                    (MCFixupKind)Sparc::fixup_sparc_br19));
200*9880d681SAndroid Build Coastguard Worker   return 0;
201*9880d681SAndroid Build Coastguard Worker }
202*9880d681SAndroid Build Coastguard Worker unsigned SparcMCCodeEmitter::
getBranchOnRegTargetOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const203*9880d681SAndroid Build Coastguard Worker getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
204*9880d681SAndroid Build Coastguard Worker                            SmallVectorImpl<MCFixup> &Fixups,
205*9880d681SAndroid Build Coastguard Worker                            const MCSubtargetInfo &STI) const {
206*9880d681SAndroid Build Coastguard Worker   const MCOperand &MO = MI.getOperand(OpNo);
207*9880d681SAndroid Build Coastguard Worker   if (MO.isReg() || MO.isImm())
208*9880d681SAndroid Build Coastguard Worker     return getMachineOpValue(MI, MO, Fixups, STI);
209*9880d681SAndroid Build Coastguard Worker 
210*9880d681SAndroid Build Coastguard Worker   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
211*9880d681SAndroid Build Coastguard Worker                                    (MCFixupKind)Sparc::fixup_sparc_br16_2));
212*9880d681SAndroid Build Coastguard Worker   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
213*9880d681SAndroid Build Coastguard Worker                                    (MCFixupKind)Sparc::fixup_sparc_br16_14));
214*9880d681SAndroid Build Coastguard Worker 
215*9880d681SAndroid Build Coastguard Worker   return 0;
216*9880d681SAndroid Build Coastguard Worker }
217*9880d681SAndroid Build Coastguard Worker 
218*9880d681SAndroid Build Coastguard Worker 
219*9880d681SAndroid Build Coastguard Worker 
220*9880d681SAndroid Build Coastguard Worker #include "SparcGenMCCodeEmitter.inc"
221