PPCMCCodeEmitter.cpp revision 23a72c8f7e46618ff8dbdbba4e8c1a2c4e44e3df
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"
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  const MCContext &CTX;
37  Triple TT;
38
39public:
40  PPCMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
41                   MCContext &ctx)
42    : STI(sti), CTX(ctx), TT(STI.getTargetTriple()) {
43  }
44
45  ~PPCMCCodeEmitter() {}
46
47  unsigned getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
48                               SmallVectorImpl<MCFixup> &Fixups) const;
49  unsigned getCondBrEncoding(const MCInst &MI, unsigned OpNo,
50                             SmallVectorImpl<MCFixup> &Fixups) const;
51  unsigned getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo,
52                                  SmallVectorImpl<MCFixup> &Fixups) const;
53  unsigned getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo,
54                                SmallVectorImpl<MCFixup> &Fixups) const;
55  unsigned getImm16Encoding(const MCInst &MI, unsigned OpNo,
56                             SmallVectorImpl<MCFixup> &Fixups) const;
57  unsigned getMemRIEncoding(const MCInst &MI, unsigned OpNo,
58                            SmallVectorImpl<MCFixup> &Fixups) const;
59  unsigned getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
60                             SmallVectorImpl<MCFixup> &Fixups) const;
61  unsigned getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
62                             SmallVectorImpl<MCFixup> &Fixups) const;
63  unsigned getTLSCallEncoding(const MCInst &MI, unsigned OpNo,
64                              SmallVectorImpl<MCFixup> &Fixups) const;
65  unsigned get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
66                               SmallVectorImpl<MCFixup> &Fixups) const;
67
68  /// getMachineOpValue - Return binary encoding of operand. If the machine
69  /// operand requires relocation, record the relocation and return zero.
70  unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
71                             SmallVectorImpl<MCFixup> &Fixups) const;
72
73  // getBinaryCodeForInstr - TableGen'erated function for getting the
74  // binary encoding for an instruction.
75  uint64_t getBinaryCodeForInstr(const MCInst &MI,
76                                 SmallVectorImpl<MCFixup> &Fixups) const;
77  void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
78                         SmallVectorImpl<MCFixup> &Fixups) const {
79    uint64_t Bits = getBinaryCodeForInstr(MI, Fixups);
80
81    // BL8_NOP etc. all have a size of 8 because of the following 'nop'.
82    unsigned Size = 4; // FIXME: Have Desc.getSize() return the correct value!
83    unsigned Opcode = MI.getOpcode();
84    if (Opcode == PPC::BL8_NOP || Opcode == PPC::BLA8_NOP ||
85        Opcode == PPC::BL8_NOP_TLS)
86      Size = 8;
87
88    // Output the constant in big endian byte order.
89    int ShiftValue = (Size * 8) - 8;
90    for (unsigned i = 0; i != Size; ++i) {
91      OS << (char)(Bits >> ShiftValue);
92      Bits <<= 8;
93    }
94
95    ++MCNumEmitted;  // Keep track of the # of mi's emitted.
96  }
97
98};
99
100} // end anonymous namespace
101
102MCCodeEmitter *llvm::createPPCMCCodeEmitter(const MCInstrInfo &MCII,
103                                            const MCRegisterInfo &MRI,
104                                            const MCSubtargetInfo &STI,
105                                            MCContext &Ctx) {
106  return new PPCMCCodeEmitter(MCII, STI, Ctx);
107}
108
109unsigned PPCMCCodeEmitter::
110getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
111                    SmallVectorImpl<MCFixup> &Fixups) const {
112  const MCOperand &MO = MI.getOperand(OpNo);
113  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
114
115  // Add a fixup for the branch target.
116  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
117                                   (MCFixupKind)PPC::fixup_ppc_br24));
118  return 0;
119}
120
121unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo,
122                                     SmallVectorImpl<MCFixup> &Fixups) const {
123  const MCOperand &MO = MI.getOperand(OpNo);
124  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
125
126  // Add a fixup for the branch target.
127  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
128                                   (MCFixupKind)PPC::fixup_ppc_brcond14));
129  return 0;
130}
131
132unsigned PPCMCCodeEmitter::
133getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo,
134                       SmallVectorImpl<MCFixup> &Fixups) const {
135  const MCOperand &MO = MI.getOperand(OpNo);
136  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
137
138  // Add a fixup for the branch target.
139  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
140                                   (MCFixupKind)PPC::fixup_ppc_br24abs));
141  return 0;
142}
143
144unsigned PPCMCCodeEmitter::
145getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo,
146                     SmallVectorImpl<MCFixup> &Fixups) const {
147  const MCOperand &MO = MI.getOperand(OpNo);
148  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
149
150  // Add a fixup for the branch target.
151  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
152                                   (MCFixupKind)PPC::fixup_ppc_brcond14abs));
153  return 0;
154}
155
156unsigned PPCMCCodeEmitter::getImm16Encoding(const MCInst &MI, unsigned OpNo,
157                                       SmallVectorImpl<MCFixup> &Fixups) const {
158  const MCOperand &MO = MI.getOperand(OpNo);
159  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
160
161  // Add a fixup for the immediate field.
162  Fixups.push_back(MCFixup::Create(2, MO.getExpr(),
163                                   (MCFixupKind)PPC::fixup_ppc_half16));
164  return 0;
165}
166
167unsigned PPCMCCodeEmitter::getMemRIEncoding(const MCInst &MI, unsigned OpNo,
168                                            SmallVectorImpl<MCFixup> &Fixups) const {
169  // Encode (imm, reg) as a memri, which has the low 16-bits as the
170  // displacement and the next 5 bits as the register #.
171  assert(MI.getOperand(OpNo+1).isReg());
172  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups) << 16;
173
174  const MCOperand &MO = MI.getOperand(OpNo);
175  if (MO.isImm())
176    return (getMachineOpValue(MI, MO, Fixups) & 0xFFFF) | RegBits;
177
178  // Add a fixup for the displacement field.
179  Fixups.push_back(MCFixup::Create(2, MO.getExpr(),
180                                   (MCFixupKind)PPC::fixup_ppc_half16));
181  return RegBits;
182}
183
184
185unsigned PPCMCCodeEmitter::getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
186                                       SmallVectorImpl<MCFixup> &Fixups) const {
187  // Encode (imm, reg) as a memrix, which has the low 14-bits as the
188  // displacement and the next 5 bits as the register #.
189  assert(MI.getOperand(OpNo+1).isReg());
190  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups) << 14;
191
192  const MCOperand &MO = MI.getOperand(OpNo);
193  if (MO.isImm())
194    return ((getMachineOpValue(MI, MO, Fixups) >> 2) & 0x3FFF) | RegBits;
195
196  // Add a fixup for the displacement field.
197  Fixups.push_back(MCFixup::Create(2, MO.getExpr(),
198                                   (MCFixupKind)PPC::fixup_ppc_half16ds));
199  return RegBits;
200}
201
202
203unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
204                                       SmallVectorImpl<MCFixup> &Fixups) const {
205  const MCOperand &MO = MI.getOperand(OpNo);
206  if (MO.isReg()) return getMachineOpValue(MI, MO, Fixups);
207
208  // Add a fixup for the TLS register, which simply provides a relocation
209  // hint to the linker that this statement is part of a relocation sequence.
210  // Return the thread-pointer register's encoding.
211  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
212                                   (MCFixupKind)PPC::fixup_ppc_nofixup));
213  return CTX.getRegisterInfo()->getEncodingValue(PPC::X13);
214}
215
216unsigned PPCMCCodeEmitter::getTLSCallEncoding(const MCInst &MI, unsigned OpNo,
217                                       SmallVectorImpl<MCFixup> &Fixups) const {
218  // For special TLS calls, we need two fixups; one for the branch target
219  // (__tls_get_addr), which we create via getDirectBrEncoding as usual,
220  // and one for the TLSGD or TLSLD symbol, which is emitted here.
221  const MCOperand &MO = MI.getOperand(OpNo+1);
222  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
223                                   (MCFixupKind)PPC::fixup_ppc_nofixup));
224  return getDirectBrEncoding(MI, OpNo, Fixups);
225}
226
227unsigned PPCMCCodeEmitter::
228get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
229                    SmallVectorImpl<MCFixup> &Fixups) const {
230  const MCOperand &MO = MI.getOperand(OpNo);
231  assert((MI.getOpcode() == PPC::MTOCRF || MI.getOpcode() == PPC::MTOCRF8 ||
232          MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) &&
233         (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
234  return 0x80 >> CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
235}
236
237
238unsigned PPCMCCodeEmitter::
239getMachineOpValue(const MCInst &MI, const MCOperand &MO,
240                  SmallVectorImpl<MCFixup> &Fixups) const {
241  if (MO.isReg()) {
242    // MTOCRF/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::MTOCRF && MI.getOpcode() != PPC::MTOCRF8 &&
245            MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) ||
246           MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
247    return CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
248  }
249
250  assert(MO.isImm() &&
251         "Relocation required in an instruction that we cannot encode!");
252  return MO.getImm();
253}
254
255
256#include "PPCGenMCCodeEmitter.inc"
257