PPCMCCodeEmitter.cpp revision ebe69fe11e48d322045d5949c83283927a0d790b
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#include "MCTargetDesc/PPCMCTargetDesc.h"
15#include "MCTargetDesc/PPCFixupKinds.h"
16#include "llvm/ADT/Statistic.h"
17#include "llvm/MC/MCCodeEmitter.h"
18#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
21#include "llvm/MC/MCInstrInfo.h"
22#include "llvm/MC/MCSubtargetInfo.h"
23#include "llvm/Support/ErrorHandling.h"
24#include "llvm/Support/raw_ostream.h"
25#include "llvm/Target/TargetOpcodes.h"
26using namespace llvm;
27
28#define DEBUG_TYPE "mccodeemitter"
29
30STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
31
32namespace {
33class PPCMCCodeEmitter : public MCCodeEmitter {
34  PPCMCCodeEmitter(const PPCMCCodeEmitter &) = delete;
35  void operator=(const PPCMCCodeEmitter &) = delete;
36
37  const MCInstrInfo &MCII;
38  const MCContext &CTX;
39  bool IsLittleEndian;
40
41public:
42  PPCMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx, bool isLittle)
43    : MCII(mcii), CTX(ctx), IsLittleEndian(isLittle) {
44  }
45
46  ~PPCMCCodeEmitter() {}
47
48  unsigned getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
49                               SmallVectorImpl<MCFixup> &Fixups,
50                               const MCSubtargetInfo &STI) const;
51  unsigned getCondBrEncoding(const MCInst &MI, unsigned OpNo,
52                             SmallVectorImpl<MCFixup> &Fixups,
53                             const MCSubtargetInfo &STI) const;
54  unsigned getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo,
55                                  SmallVectorImpl<MCFixup> &Fixups,
56                                  const MCSubtargetInfo &STI) const;
57  unsigned getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo,
58                                SmallVectorImpl<MCFixup> &Fixups,
59                                const MCSubtargetInfo &STI) const;
60  unsigned getImm16Encoding(const MCInst &MI, unsigned OpNo,
61                             SmallVectorImpl<MCFixup> &Fixups,
62                             const MCSubtargetInfo &STI) const;
63  unsigned getMemRIEncoding(const MCInst &MI, unsigned OpNo,
64                            SmallVectorImpl<MCFixup> &Fixups,
65                            const MCSubtargetInfo &STI) const;
66  unsigned getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
67                             SmallVectorImpl<MCFixup> &Fixups,
68                             const MCSubtargetInfo &STI) const;
69  unsigned getSPE8DisEncoding(const MCInst &MI, unsigned OpNo,
70                              SmallVectorImpl<MCFixup> &Fixups,
71                              const MCSubtargetInfo &STI) const;
72  unsigned getSPE4DisEncoding(const MCInst &MI, unsigned OpNo,
73                              SmallVectorImpl<MCFixup> &Fixups,
74                              const MCSubtargetInfo &STI) const;
75  unsigned getSPE2DisEncoding(const MCInst &MI, unsigned OpNo,
76                              SmallVectorImpl<MCFixup> &Fixups,
77                              const MCSubtargetInfo &STI) const;
78  unsigned getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
79                             SmallVectorImpl<MCFixup> &Fixups,
80                             const MCSubtargetInfo &STI) const;
81  unsigned getTLSCallEncoding(const MCInst &MI, unsigned OpNo,
82                              SmallVectorImpl<MCFixup> &Fixups,
83                              const MCSubtargetInfo &STI) const;
84  unsigned get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
85                               SmallVectorImpl<MCFixup> &Fixups,
86                               const MCSubtargetInfo &STI) const;
87
88  /// getMachineOpValue - Return binary encoding of operand. If the machine
89  /// operand requires relocation, record the relocation and return zero.
90  unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
91                             SmallVectorImpl<MCFixup> &Fixups,
92                             const MCSubtargetInfo &STI) const;
93
94  // getBinaryCodeForInstr - TableGen'erated function for getting the
95  // binary encoding for an instruction.
96  uint64_t getBinaryCodeForInstr(const MCInst &MI,
97                                 SmallVectorImpl<MCFixup> &Fixups,
98                                 const MCSubtargetInfo &STI) const;
99  void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
100                         SmallVectorImpl<MCFixup> &Fixups,
101                         const MCSubtargetInfo &STI) const override {
102    // For fast-isel, a float COPY_TO_REGCLASS can survive this long.
103    // It's just a nop to keep the register classes happy, so don't
104    // generate anything.
105    unsigned Opcode = MI.getOpcode();
106    const MCInstrDesc &Desc = MCII.get(Opcode);
107    if (Opcode == TargetOpcode::COPY_TO_REGCLASS)
108      return;
109
110    uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
111
112    // Output the constant in big/little endian byte order.
113    unsigned Size = Desc.getSize();
114    switch (Size) {
115    case 4:
116      if (IsLittleEndian) {
117        OS << (char)(Bits);
118        OS << (char)(Bits >> 8);
119        OS << (char)(Bits >> 16);
120        OS << (char)(Bits >> 24);
121      } else {
122        OS << (char)(Bits >> 24);
123        OS << (char)(Bits >> 16);
124        OS << (char)(Bits >> 8);
125        OS << (char)(Bits);
126      }
127      break;
128    case 8:
129      // If we emit a pair of instructions, the first one is
130      // always in the top 32 bits, even on little-endian.
131      if (IsLittleEndian) {
132        OS << (char)(Bits >> 32);
133        OS << (char)(Bits >> 40);
134        OS << (char)(Bits >> 48);
135        OS << (char)(Bits >> 56);
136        OS << (char)(Bits);
137        OS << (char)(Bits >> 8);
138        OS << (char)(Bits >> 16);
139        OS << (char)(Bits >> 24);
140      } else {
141        OS << (char)(Bits >> 56);
142        OS << (char)(Bits >> 48);
143        OS << (char)(Bits >> 40);
144        OS << (char)(Bits >> 32);
145        OS << (char)(Bits >> 24);
146        OS << (char)(Bits >> 16);
147        OS << (char)(Bits >> 8);
148        OS << (char)(Bits);
149      }
150      break;
151    default:
152      llvm_unreachable ("Invalid instruction size");
153    }
154
155    ++MCNumEmitted;  // Keep track of the # of mi's emitted.
156  }
157
158};
159
160} // end anonymous namespace
161
162MCCodeEmitter *llvm::createPPCMCCodeEmitter(const MCInstrInfo &MCII,
163                                            const MCRegisterInfo &MRI,
164                                            const MCSubtargetInfo &STI,
165                                            MCContext &Ctx) {
166  Triple TT(STI.getTargetTriple());
167  bool IsLittleEndian = TT.getArch() == Triple::ppc64le;
168  return new PPCMCCodeEmitter(MCII, Ctx, IsLittleEndian);
169}
170
171unsigned PPCMCCodeEmitter::
172getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
173                    SmallVectorImpl<MCFixup> &Fixups,
174                    const MCSubtargetInfo &STI) const {
175  const MCOperand &MO = MI.getOperand(OpNo);
176  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
177
178  // Add a fixup for the branch target.
179  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
180                                   (MCFixupKind)PPC::fixup_ppc_br24));
181  return 0;
182}
183
184unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo,
185                                     SmallVectorImpl<MCFixup> &Fixups,
186                                     const MCSubtargetInfo &STI) const {
187  const MCOperand &MO = MI.getOperand(OpNo);
188  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
189
190  // Add a fixup for the branch target.
191  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
192                                   (MCFixupKind)PPC::fixup_ppc_brcond14));
193  return 0;
194}
195
196unsigned PPCMCCodeEmitter::
197getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo,
198                       SmallVectorImpl<MCFixup> &Fixups,
199                       const MCSubtargetInfo &STI) const {
200  const MCOperand &MO = MI.getOperand(OpNo);
201  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
202
203  // Add a fixup for the branch target.
204  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
205                                   (MCFixupKind)PPC::fixup_ppc_br24abs));
206  return 0;
207}
208
209unsigned PPCMCCodeEmitter::
210getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo,
211                     SmallVectorImpl<MCFixup> &Fixups,
212                     const MCSubtargetInfo &STI) const {
213  const MCOperand &MO = MI.getOperand(OpNo);
214  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
215
216  // Add a fixup for the branch target.
217  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
218                                   (MCFixupKind)PPC::fixup_ppc_brcond14abs));
219  return 0;
220}
221
222unsigned PPCMCCodeEmitter::getImm16Encoding(const MCInst &MI, unsigned OpNo,
223                                       SmallVectorImpl<MCFixup> &Fixups,
224                                       const MCSubtargetInfo &STI) const {
225  const MCOperand &MO = MI.getOperand(OpNo);
226  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
227
228  // Add a fixup for the immediate field.
229  Fixups.push_back(MCFixup::Create(IsLittleEndian? 0 : 2, MO.getExpr(),
230                                   (MCFixupKind)PPC::fixup_ppc_half16));
231  return 0;
232}
233
234unsigned PPCMCCodeEmitter::getMemRIEncoding(const MCInst &MI, unsigned OpNo,
235                                            SmallVectorImpl<MCFixup> &Fixups,
236                                            const MCSubtargetInfo &STI) const {
237  // Encode (imm, reg) as a memri, which has the low 16-bits as the
238  // displacement and the next 5 bits as the register #.
239  assert(MI.getOperand(OpNo+1).isReg());
240  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 16;
241
242  const MCOperand &MO = MI.getOperand(OpNo);
243  if (MO.isImm())
244    return (getMachineOpValue(MI, MO, Fixups, STI) & 0xFFFF) | RegBits;
245
246  // Add a fixup for the displacement field.
247  Fixups.push_back(MCFixup::Create(IsLittleEndian? 0 : 2, MO.getExpr(),
248                                   (MCFixupKind)PPC::fixup_ppc_half16));
249  return RegBits;
250}
251
252
253unsigned PPCMCCodeEmitter::getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
254                                       SmallVectorImpl<MCFixup> &Fixups,
255                                       const MCSubtargetInfo &STI) const {
256  // Encode (imm, reg) as a memrix, which has the low 14-bits as the
257  // displacement and the next 5 bits as the register #.
258  assert(MI.getOperand(OpNo+1).isReg());
259  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 14;
260
261  const MCOperand &MO = MI.getOperand(OpNo);
262  if (MO.isImm())
263    return ((getMachineOpValue(MI, MO, Fixups, STI) >> 2) & 0x3FFF) | RegBits;
264
265  // Add a fixup for the displacement field.
266  Fixups.push_back(MCFixup::Create(IsLittleEndian? 0 : 2, MO.getExpr(),
267                                   (MCFixupKind)PPC::fixup_ppc_half16ds));
268  return RegBits;
269}
270
271
272unsigned PPCMCCodeEmitter::getSPE8DisEncoding(const MCInst &MI, unsigned OpNo,
273                                              SmallVectorImpl<MCFixup> &Fixups,
274                                              const MCSubtargetInfo &STI)
275                                              const {
276  // Encode (imm, reg) as a spe8dis, which has the low 5-bits of (imm / 8)
277  // as the displacement and the next 5 bits as the register #.
278  assert(MI.getOperand(OpNo+1).isReg());
279  uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
280
281  const MCOperand &MO = MI.getOperand(OpNo);
282  assert(MO.isImm());
283  uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 3;
284  return reverseBits(Imm | RegBits) >> 22;
285}
286
287
288unsigned PPCMCCodeEmitter::getSPE4DisEncoding(const MCInst &MI, unsigned OpNo,
289                                              SmallVectorImpl<MCFixup> &Fixups,
290                                              const MCSubtargetInfo &STI)
291                                              const {
292  // Encode (imm, reg) as a spe4dis, which has the low 5-bits of (imm / 4)
293  // as the displacement and the next 5 bits as the register #.
294  assert(MI.getOperand(OpNo+1).isReg());
295  uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
296
297  const MCOperand &MO = MI.getOperand(OpNo);
298  assert(MO.isImm());
299  uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 2;
300  return reverseBits(Imm | RegBits) >> 22;
301}
302
303
304unsigned PPCMCCodeEmitter::getSPE2DisEncoding(const MCInst &MI, unsigned OpNo,
305                                              SmallVectorImpl<MCFixup> &Fixups,
306                                              const MCSubtargetInfo &STI)
307                                              const {
308  // Encode (imm, reg) as a spe2dis, which has the low 5-bits of (imm / 2)
309  // as the displacement and the next 5 bits as the register #.
310  assert(MI.getOperand(OpNo+1).isReg());
311  uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
312
313  const MCOperand &MO = MI.getOperand(OpNo);
314  assert(MO.isImm());
315  uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 1;
316  return reverseBits(Imm | RegBits) >> 22;
317}
318
319
320unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
321                                       SmallVectorImpl<MCFixup> &Fixups,
322                                       const MCSubtargetInfo &STI) const {
323  const MCOperand &MO = MI.getOperand(OpNo);
324  if (MO.isReg()) return getMachineOpValue(MI, MO, Fixups, STI);
325
326  // Add a fixup for the TLS register, which simply provides a relocation
327  // hint to the linker that this statement is part of a relocation sequence.
328  // Return the thread-pointer register's encoding.
329  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
330                                   (MCFixupKind)PPC::fixup_ppc_nofixup));
331  Triple TT(STI.getTargetTriple());
332  bool isPPC64 = TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le;
333  return CTX.getRegisterInfo()->getEncodingValue(isPPC64 ? PPC::X13 : PPC::R2);
334}
335
336unsigned PPCMCCodeEmitter::getTLSCallEncoding(const MCInst &MI, unsigned OpNo,
337                                       SmallVectorImpl<MCFixup> &Fixups,
338                                       const MCSubtargetInfo &STI) const {
339  // For special TLS calls, we need two fixups; one for the branch target
340  // (__tls_get_addr), which we create via getDirectBrEncoding as usual,
341  // and one for the TLSGD or TLSLD symbol, which is emitted here.
342  const MCOperand &MO = MI.getOperand(OpNo+1);
343  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
344                                   (MCFixupKind)PPC::fixup_ppc_nofixup));
345  return getDirectBrEncoding(MI, OpNo, Fixups, STI);
346}
347
348unsigned PPCMCCodeEmitter::
349get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
350                    SmallVectorImpl<MCFixup> &Fixups,
351                    const MCSubtargetInfo &STI) const {
352  const MCOperand &MO = MI.getOperand(OpNo);
353  assert((MI.getOpcode() == PPC::MTOCRF || MI.getOpcode() == PPC::MTOCRF8 ||
354          MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) &&
355         (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
356  return 0x80 >> CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
357}
358
359
360unsigned PPCMCCodeEmitter::
361getMachineOpValue(const MCInst &MI, const MCOperand &MO,
362                  SmallVectorImpl<MCFixup> &Fixups,
363                  const MCSubtargetInfo &STI) const {
364  if (MO.isReg()) {
365    // MTOCRF/MFOCRF should go through get_crbitm_encoding for the CR operand.
366    // The GPR operand should come through here though.
367    assert((MI.getOpcode() != PPC::MTOCRF && MI.getOpcode() != PPC::MTOCRF8 &&
368            MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) ||
369           MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
370    return CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
371  }
372
373  assert(MO.isImm() &&
374         "Relocation required in an instruction that we cannot encode!");
375  return MO.getImm();
376}
377
378
379#include "PPCGenMCCodeEmitter.inc"
380