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/PPCBaseInfo.h"
17#include "MCTargetDesc/PPCFixupKinds.h"
18#include "llvm/ADT/Statistic.h"
19#include "llvm/MC/MCCodeEmitter.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"
26using namespace llvm;
27
28STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
29
30namespace {
31class PPCMCCodeEmitter : public MCCodeEmitter {
32  PPCMCCodeEmitter(const PPCMCCodeEmitter &) LLVM_DELETED_FUNCTION;
33  void operator=(const PPCMCCodeEmitter &) LLVM_DELETED_FUNCTION;
34
35  const MCSubtargetInfo &STI;
36  Triple TT;
37
38public:
39  PPCMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
40                   MCContext &ctx)
41    : STI(sti), TT(STI.getTargetTriple()) {
42  }
43
44  ~PPCMCCodeEmitter() {}
45
46  bool is64BitMode() const {
47    return (STI.getFeatureBits() & PPC::Feature64Bit) != 0;
48  }
49
50  bool isSVR4ABI() const {
51    return TT.isMacOSX() == 0;
52  }
53
54  unsigned getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
55                               SmallVectorImpl<MCFixup> &Fixups) const;
56  unsigned getCondBrEncoding(const MCInst &MI, unsigned OpNo,
57                             SmallVectorImpl<MCFixup> &Fixups) const;
58  unsigned getHA16Encoding(const MCInst &MI, unsigned OpNo,
59                           SmallVectorImpl<MCFixup> &Fixups) const;
60  unsigned getLO16Encoding(const MCInst &MI, unsigned OpNo,
61                           SmallVectorImpl<MCFixup> &Fixups) const;
62  unsigned getMemRIEncoding(const MCInst &MI, unsigned OpNo,
63                            SmallVectorImpl<MCFixup> &Fixups) const;
64  unsigned getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
65                             SmallVectorImpl<MCFixup> &Fixups) const;
66  unsigned getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
67                             SmallVectorImpl<MCFixup> &Fixups) const;
68  unsigned get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
69                               SmallVectorImpl<MCFixup> &Fixups) const;
70
71  /// getMachineOpValue - Return binary encoding of operand. If the machine
72  /// operand requires relocation, record the relocation and return zero.
73  unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
74                             SmallVectorImpl<MCFixup> &Fixups) const;
75
76  // getBinaryCodeForInstr - TableGen'erated function for getting the
77  // binary encoding for an instruction.
78  uint64_t getBinaryCodeForInstr(const MCInst &MI,
79                                 SmallVectorImpl<MCFixup> &Fixups) const;
80  void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
81                         SmallVectorImpl<MCFixup> &Fixups) const {
82    uint64_t Bits = getBinaryCodeForInstr(MI, Fixups);
83
84    // BL8_NOP_ELF, BLA8_NOP_ELF, etc., all have a size of 8 because of the
85    // following 'nop'.
86    unsigned Size = 4; // FIXME: Have Desc.getSize() return the correct value!
87    unsigned Opcode = MI.getOpcode();
88    if (Opcode == PPC::BL8_NOP_ELF || Opcode == PPC::BLA8_NOP_ELF ||
89        Opcode == PPC::BL8_NOP_ELF_TLSGD || Opcode == PPC::BL8_NOP_ELF_TLSLD)
90      Size = 8;
91
92    // Output the constant in big endian byte order.
93    int ShiftValue = (Size * 8) - 8;
94    for (unsigned i = 0; i != Size; ++i) {
95      OS << (char)(Bits >> ShiftValue);
96      Bits <<= 8;
97    }
98
99    ++MCNumEmitted;  // Keep track of the # of mi's emitted.
100  }
101
102};
103
104} // end anonymous namespace
105
106MCCodeEmitter *llvm::createPPCMCCodeEmitter(const MCInstrInfo &MCII,
107                                            const MCRegisterInfo &MRI,
108                                            const MCSubtargetInfo &STI,
109                                            MCContext &Ctx) {
110  return new PPCMCCodeEmitter(MCII, STI, Ctx);
111}
112
113unsigned PPCMCCodeEmitter::
114getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
115                    SmallVectorImpl<MCFixup> &Fixups) const {
116  const MCOperand &MO = MI.getOperand(OpNo);
117  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
118
119  // Add a fixup for the branch target.
120  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
121                                   (MCFixupKind)PPC::fixup_ppc_br24));
122
123  // For special TLS calls, add another fixup for the symbol.  Apparently
124  // BL8_NOP_ELF, BL8_NOP_ELF_TLSGD, and BL8_NOP_ELF_TLSLD are sufficiently
125  // similar that TblGen will not generate a separate case for the latter
126  // two, so this is the only way to get the extra fixup generated.
127  unsigned Opcode = MI.getOpcode();
128  if (Opcode == PPC::BL8_NOP_ELF_TLSGD || Opcode == PPC::BL8_NOP_ELF_TLSLD) {
129    const MCOperand &MO2 = MI.getOperand(OpNo+1);
130    Fixups.push_back(MCFixup::Create(0, MO2.getExpr(),
131                                     (MCFixupKind)PPC::fixup_ppc_nofixup));
132  }
133  return 0;
134}
135
136unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo,
137                                     SmallVectorImpl<MCFixup> &Fixups) const {
138  const MCOperand &MO = MI.getOperand(OpNo);
139  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
140
141  // Add a fixup for the branch target.
142  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
143                                   (MCFixupKind)PPC::fixup_ppc_brcond14));
144  return 0;
145}
146
147unsigned PPCMCCodeEmitter::getHA16Encoding(const MCInst &MI, unsigned OpNo,
148                                       SmallVectorImpl<MCFixup> &Fixups) const {
149  const MCOperand &MO = MI.getOperand(OpNo);
150  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
151
152  // Add a fixup for the branch target.
153  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
154                                   (MCFixupKind)PPC::fixup_ppc_ha16));
155  return 0;
156}
157
158unsigned PPCMCCodeEmitter::getLO16Encoding(const MCInst &MI, unsigned OpNo,
159                                       SmallVectorImpl<MCFixup> &Fixups) const {
160  const MCOperand &MO = MI.getOperand(OpNo);
161  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
162
163  // Add a fixup for the branch target.
164  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
165                                   (MCFixupKind)PPC::fixup_ppc_lo16));
166  return 0;
167}
168
169unsigned PPCMCCodeEmitter::getMemRIEncoding(const MCInst &MI, unsigned OpNo,
170                                            SmallVectorImpl<MCFixup> &Fixups) const {
171  // Encode (imm, reg) as a memri, which has the low 16-bits as the
172  // displacement and the next 5 bits as the register #.
173  assert(MI.getOperand(OpNo+1).isReg());
174  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups) << 16;
175
176  const MCOperand &MO = MI.getOperand(OpNo);
177  if (MO.isImm())
178    return (getMachineOpValue(MI, MO, Fixups) & 0xFFFF) | RegBits;
179
180  // Add a fixup for the displacement field.
181  if (isSVR4ABI() && is64BitMode())
182    Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
183                                     (MCFixupKind)PPC::fixup_ppc_toc16));
184  else
185    Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
186                                     (MCFixupKind)PPC::fixup_ppc_lo16));
187  return RegBits;
188}
189
190
191unsigned PPCMCCodeEmitter::getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
192                                       SmallVectorImpl<MCFixup> &Fixups) const {
193  // Encode (imm, reg) as a memrix, which has the low 14-bits as the
194  // displacement and the next 5 bits as the register #.
195  assert(MI.getOperand(OpNo+1).isReg());
196  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups) << 14;
197
198  const MCOperand &MO = MI.getOperand(OpNo);
199  if (MO.isImm())
200    return (getMachineOpValue(MI, MO, Fixups) & 0x3FFF) | RegBits;
201
202  // Add a fixup for the branch target.
203  if (isSVR4ABI() && is64BitMode())
204    Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
205                                     (MCFixupKind)PPC::fixup_ppc_toc16_ds));
206  else
207    Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
208                                     (MCFixupKind)PPC::fixup_ppc_lo14));
209  return RegBits;
210}
211
212
213unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
214                                       SmallVectorImpl<MCFixup> &Fixups) const {
215  const MCOperand &MO = MI.getOperand(OpNo);
216  if (MO.isReg()) return getMachineOpValue(MI, MO, Fixups);
217
218  // Add a fixup for the TLS register, which simply provides a relocation
219  // hint to the linker that this statement is part of a relocation sequence.
220  // Return the thread-pointer register's encoding.
221  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
222                                   (MCFixupKind)PPC::fixup_ppc_tlsreg));
223  return getPPCRegisterNumbering(PPC::X13);
224}
225
226unsigned PPCMCCodeEmitter::
227get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
228                    SmallVectorImpl<MCFixup> &Fixups) const {
229  const MCOperand &MO = MI.getOperand(OpNo);
230  assert((MI.getOpcode() == PPC::MTCRF ||
231          MI.getOpcode() == PPC::MFOCRF ||
232          MI.getOpcode() == PPC::MTCRF8) &&
233         (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
234  return 0x80 >> getPPCRegisterNumbering(MO.getReg());
235}
236
237
238unsigned PPCMCCodeEmitter::
239getMachineOpValue(const MCInst &MI, const MCOperand &MO,
240                  SmallVectorImpl<MCFixup> &Fixups) const {
241  if (MO.isReg()) {
242    // MTCRF/MFOCRF should go through get_crbitm_encoding for the CR operand.
243    // The GPR operand should come through here though.
244    assert((MI.getOpcode() != PPC::MTCRF && MI.getOpcode() != PPC::MFOCRF) ||
245           MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
246    return getPPCRegisterNumbering(MO.getReg());
247  }
248
249  assert(MO.isImm() &&
250         "Relocation required in an instruction that we cannot encode!");
251  return MO.getImm();
252}
253
254
255#include "PPCGenMCCodeEmitter.inc"
256