1 //===-- PPCMCCodeEmitter.cpp - Convert PPC code to machine code -----------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the PPCMCCodeEmitter class.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #define DEBUG_TYPE "mccodeemitter"
15 #include "MCTargetDesc/PPCMCTargetDesc.h"
16 #include "MCTargetDesc/PPCFixupKinds.h"
17 #include "llvm/ADT/Statistic.h"
18 #include "llvm/MC/MCCodeEmitter.h"
19 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCExpr.h"
21 #include "llvm/MC/MCInst.h"
22 #include "llvm/MC/MCInstrInfo.h"
23 #include "llvm/MC/MCSubtargetInfo.h"
24 #include "llvm/Support/ErrorHandling.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include "llvm/Target/TargetOpcodes.h"
27 using namespace llvm;
28 
29 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
30 
31 namespace {
32 class PPCMCCodeEmitter : public MCCodeEmitter {
33   PPCMCCodeEmitter(const PPCMCCodeEmitter &) LLVM_DELETED_FUNCTION;
34   void operator=(const PPCMCCodeEmitter &) LLVM_DELETED_FUNCTION;
35 
36   const MCInstrInfo &MCII;
37   const MCContext &CTX;
38 
39 public:
40   PPCMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
41     : MCII(mcii), CTX(ctx) {
42   }
43 
44   ~PPCMCCodeEmitter() {}
45 
46   unsigned getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
47                                SmallVectorImpl<MCFixup> &Fixups,
48                                const MCSubtargetInfo &STI) const;
49   unsigned getCondBrEncoding(const MCInst &MI, unsigned OpNo,
50                              SmallVectorImpl<MCFixup> &Fixups,
51                              const MCSubtargetInfo &STI) const;
52   unsigned getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo,
53                                   SmallVectorImpl<MCFixup> &Fixups,
54                                   const MCSubtargetInfo &STI) const;
55   unsigned getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo,
56                                 SmallVectorImpl<MCFixup> &Fixups,
57                                 const MCSubtargetInfo &STI) const;
58   unsigned getImm16Encoding(const MCInst &MI, unsigned OpNo,
59                              SmallVectorImpl<MCFixup> &Fixups,
60                              const MCSubtargetInfo &STI) const;
61   unsigned getMemRIEncoding(const MCInst &MI, unsigned OpNo,
62                             SmallVectorImpl<MCFixup> &Fixups,
63                             const MCSubtargetInfo &STI) const;
64   unsigned getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
65                              SmallVectorImpl<MCFixup> &Fixups,
66                              const MCSubtargetInfo &STI) const;
67   unsigned getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
68                              SmallVectorImpl<MCFixup> &Fixups,
69                              const MCSubtargetInfo &STI) const;
70   unsigned getTLSCallEncoding(const MCInst &MI, unsigned OpNo,
71                               SmallVectorImpl<MCFixup> &Fixups,
72                               const MCSubtargetInfo &STI) const;
73   unsigned get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
74                                SmallVectorImpl<MCFixup> &Fixups,
75                                const MCSubtargetInfo &STI) const;
76 
77   /// getMachineOpValue - Return binary encoding of operand. If the machine
78   /// operand requires relocation, record the relocation and return zero.
79   unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
80                              SmallVectorImpl<MCFixup> &Fixups,
81                              const MCSubtargetInfo &STI) const;
82 
83   // getBinaryCodeForInstr - TableGen'erated function for getting the
84   // binary encoding for an instruction.
85   uint64_t getBinaryCodeForInstr(const MCInst &MI,
86                                  SmallVectorImpl<MCFixup> &Fixups,
87                                  const MCSubtargetInfo &STI) const;
88   void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
89                          SmallVectorImpl<MCFixup> &Fixups,
90                          const MCSubtargetInfo &STI) const {
91     // For fast-isel, a float COPY_TO_REGCLASS can survive this long.
92     // It's just a nop to keep the register classes happy, so don't
93     // generate anything.
94     unsigned Opcode = MI.getOpcode();
95     const MCInstrDesc &Desc = MCII.get(Opcode);
96     if (Opcode == TargetOpcode::COPY_TO_REGCLASS)
97       return;
98 
99     uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
100 
101     // Output the constant in big endian byte order.
102     unsigned Size = Desc.getSize();
103     int ShiftValue = (Size * 8) - 8;
104     for (unsigned i = 0; i != Size; ++i) {
105       OS << (char)(Bits >> ShiftValue);
106       Bits <<= 8;
107     }
108 
109     ++MCNumEmitted;  // Keep track of the # of mi's emitted.
110   }
111 
112 };
113 
114 } // end anonymous namespace
115 
116 MCCodeEmitter *llvm::createPPCMCCodeEmitter(const MCInstrInfo &MCII,
117                                             const MCRegisterInfo &MRI,
118                                             const MCSubtargetInfo &STI,
119                                             MCContext &Ctx) {
120   return new PPCMCCodeEmitter(MCII, Ctx);
121 }
122 
123 unsigned PPCMCCodeEmitter::
124 getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
125                     SmallVectorImpl<MCFixup> &Fixups,
126                     const MCSubtargetInfo &STI) const {
127   const MCOperand &MO = MI.getOperand(OpNo);
128   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
129 
130   // Add a fixup for the branch target.
131   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
132                                    (MCFixupKind)PPC::fixup_ppc_br24));
133   return 0;
134 }
135 
136 unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo,
137                                      SmallVectorImpl<MCFixup> &Fixups,
138                                      const MCSubtargetInfo &STI) const {
139   const MCOperand &MO = MI.getOperand(OpNo);
140   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
141 
142   // Add a fixup for the branch target.
143   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
144                                    (MCFixupKind)PPC::fixup_ppc_brcond14));
145   return 0;
146 }
147 
148 unsigned PPCMCCodeEmitter::
149 getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo,
150                        SmallVectorImpl<MCFixup> &Fixups,
151                        const MCSubtargetInfo &STI) const {
152   const MCOperand &MO = MI.getOperand(OpNo);
153   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
154 
155   // Add a fixup for the branch target.
156   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
157                                    (MCFixupKind)PPC::fixup_ppc_br24abs));
158   return 0;
159 }
160 
161 unsigned PPCMCCodeEmitter::
162 getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo,
163                      SmallVectorImpl<MCFixup> &Fixups,
164                      const MCSubtargetInfo &STI) const {
165   const MCOperand &MO = MI.getOperand(OpNo);
166   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
167 
168   // Add a fixup for the branch target.
169   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
170                                    (MCFixupKind)PPC::fixup_ppc_brcond14abs));
171   return 0;
172 }
173 
174 unsigned PPCMCCodeEmitter::getImm16Encoding(const MCInst &MI, unsigned OpNo,
175                                        SmallVectorImpl<MCFixup> &Fixups,
176                                        const MCSubtargetInfo &STI) const {
177   const MCOperand &MO = MI.getOperand(OpNo);
178   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
179 
180   // Add a fixup for the immediate field.
181   Fixups.push_back(MCFixup::Create(2, MO.getExpr(),
182                                    (MCFixupKind)PPC::fixup_ppc_half16));
183   return 0;
184 }
185 
186 unsigned PPCMCCodeEmitter::getMemRIEncoding(const MCInst &MI, unsigned OpNo,
187                                             SmallVectorImpl<MCFixup> &Fixups,
188                                             const MCSubtargetInfo &STI) const {
189   // Encode (imm, reg) as a memri, which has the low 16-bits as the
190   // displacement and the next 5 bits as the register #.
191   assert(MI.getOperand(OpNo+1).isReg());
192   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 16;
193 
194   const MCOperand &MO = MI.getOperand(OpNo);
195   if (MO.isImm())
196     return (getMachineOpValue(MI, MO, Fixups, STI) & 0xFFFF) | RegBits;
197 
198   // Add a fixup for the displacement field.
199   Fixups.push_back(MCFixup::Create(2, MO.getExpr(),
200                                    (MCFixupKind)PPC::fixup_ppc_half16));
201   return RegBits;
202 }
203 
204 
205 unsigned PPCMCCodeEmitter::getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
206                                        SmallVectorImpl<MCFixup> &Fixups,
207                                        const MCSubtargetInfo &STI) const {
208   // Encode (imm, reg) as a memrix, which has the low 14-bits as the
209   // displacement and the next 5 bits as the register #.
210   assert(MI.getOperand(OpNo+1).isReg());
211   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 14;
212 
213   const MCOperand &MO = MI.getOperand(OpNo);
214   if (MO.isImm())
215     return ((getMachineOpValue(MI, MO, Fixups, STI) >> 2) & 0x3FFF) | RegBits;
216 
217   // Add a fixup for the displacement field.
218   Fixups.push_back(MCFixup::Create(2, MO.getExpr(),
219                                    (MCFixupKind)PPC::fixup_ppc_half16ds));
220   return RegBits;
221 }
222 
223 
224 unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
225                                        SmallVectorImpl<MCFixup> &Fixups,
226                                        const MCSubtargetInfo &STI) const {
227   const MCOperand &MO = MI.getOperand(OpNo);
228   if (MO.isReg()) return getMachineOpValue(MI, MO, Fixups, STI);
229 
230   // Add a fixup for the TLS register, which simply provides a relocation
231   // hint to the linker that this statement is part of a relocation sequence.
232   // Return the thread-pointer register's encoding.
233   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
234                                    (MCFixupKind)PPC::fixup_ppc_nofixup));
235   Triple TT(STI.getTargetTriple());
236   bool isPPC64 = TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le;
237   return CTX.getRegisterInfo()->getEncodingValue(isPPC64 ? PPC::X13 : PPC::R2);
238 }
239 
240 unsigned PPCMCCodeEmitter::getTLSCallEncoding(const MCInst &MI, unsigned OpNo,
241                                        SmallVectorImpl<MCFixup> &Fixups,
242                                        const MCSubtargetInfo &STI) const {
243   // For special TLS calls, we need two fixups; one for the branch target
244   // (__tls_get_addr), which we create via getDirectBrEncoding as usual,
245   // and one for the TLSGD or TLSLD symbol, which is emitted here.
246   const MCOperand &MO = MI.getOperand(OpNo+1);
247   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
248                                    (MCFixupKind)PPC::fixup_ppc_nofixup));
249   return getDirectBrEncoding(MI, OpNo, Fixups, STI);
250 }
251 
252 unsigned PPCMCCodeEmitter::
253 get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
254                     SmallVectorImpl<MCFixup> &Fixups,
255                     const MCSubtargetInfo &STI) const {
256   const MCOperand &MO = MI.getOperand(OpNo);
257   assert((MI.getOpcode() == PPC::MTOCRF || MI.getOpcode() == PPC::MTOCRF8 ||
258           MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) &&
259          (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
260   return 0x80 >> CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
261 }
262 
263 
264 unsigned PPCMCCodeEmitter::
265 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
266                   SmallVectorImpl<MCFixup> &Fixups,
267                   const MCSubtargetInfo &STI) const {
268   if (MO.isReg()) {
269     // MTOCRF/MFOCRF should go through get_crbitm_encoding for the CR operand.
270     // The GPR operand should come through here though.
271     assert((MI.getOpcode() != PPC::MTOCRF && MI.getOpcode() != PPC::MTOCRF8 &&
272             MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) ||
273            MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
274     return CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
275   }
276 
277   assert(MO.isImm() &&
278          "Relocation required in an instruction that we cannot encode!");
279   return MO.getImm();
280 }
281 
282 
283 #include "PPCGenMCCodeEmitter.inc"
284