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/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 using namespace llvm;
26 
27 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
28 
29 namespace {
30 class PPCMCCodeEmitter : public MCCodeEmitter {
31   PPCMCCodeEmitter(const PPCMCCodeEmitter &) LLVM_DELETED_FUNCTION;
32   void operator=(const PPCMCCodeEmitter &) LLVM_DELETED_FUNCTION;
33 
34   const MCSubtargetInfo &STI;
35   Triple TT;
36 
37 public:
38   PPCMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
39                    MCContext &ctx)
40     : STI(sti), TT(STI.getTargetTriple()) {
41   }
42 
43   ~PPCMCCodeEmitter() {}
44 
45   bool is64BitMode() const {
46     return (STI.getFeatureBits() & PPC::Feature64Bit) != 0;
47   }
48 
49   bool isSVR4ABI() const {
50     return TT.isMacOSX() == 0;
51   }
52 
53   unsigned getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
54                                SmallVectorImpl<MCFixup> &Fixups) const;
55   unsigned getCondBrEncoding(const MCInst &MI, unsigned OpNo,
56                              SmallVectorImpl<MCFixup> &Fixups) const;
57   unsigned getHA16Encoding(const MCInst &MI, unsigned OpNo,
58                            SmallVectorImpl<MCFixup> &Fixups) const;
59   unsigned getLO16Encoding(const MCInst &MI, unsigned OpNo,
60                            SmallVectorImpl<MCFixup> &Fixups) const;
61   unsigned getMemRIEncoding(const MCInst &MI, unsigned OpNo,
62                             SmallVectorImpl<MCFixup> &Fixups) const;
63   unsigned getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
64                              SmallVectorImpl<MCFixup> &Fixups) const;
65   unsigned getTLSOffsetEncoding(const MCInst &MI, unsigned OpNo,
66                                 SmallVectorImpl<MCFixup> &Fixups) const;
67   unsigned getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
68                              SmallVectorImpl<MCFixup> &Fixups) const;
69   unsigned get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
70                                SmallVectorImpl<MCFixup> &Fixups) const;
71 
72   /// getMachineOpValue - Return binary encoding of operand. If the machine
73   /// operand requires relocation, record the relocation and return zero.
74   unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
75                              SmallVectorImpl<MCFixup> &Fixups) const;
76 
77   // getBinaryCodeForInstr - TableGen'erated function for getting the
78   // binary encoding for an instruction.
79   uint64_t getBinaryCodeForInstr(const MCInst &MI,
80                                  SmallVectorImpl<MCFixup> &Fixups) const;
81   void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
82                          SmallVectorImpl<MCFixup> &Fixups) const {
83     uint64_t Bits = getBinaryCodeForInstr(MI, Fixups);
84 
85     // BL8_NOPELF and BLA8_NOP_ELF is both size of 8 bacause of the
86     // following 'nop'.
87     unsigned Size = 4; // FIXME: Have Desc.getSize() return the correct value!
88     unsigned Opcode = MI.getOpcode();
89     if (Opcode == PPC::BL8_NOP_ELF || Opcode == PPC::BLA8_NOP_ELF)
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 
106 MCCodeEmitter *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 
113 unsigned PPCMCCodeEmitter::
114 getDirectBrEncoding(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   return 0;
123 }
124 
125 unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo,
126                                      SmallVectorImpl<MCFixup> &Fixups) const {
127   const MCOperand &MO = MI.getOperand(OpNo);
128   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
129 
130   // Add a fixup for the branch target.
131   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
132                                    (MCFixupKind)PPC::fixup_ppc_brcond14));
133   return 0;
134 }
135 
136 unsigned PPCMCCodeEmitter::getHA16Encoding(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_ha16));
144   return 0;
145 }
146 
147 unsigned PPCMCCodeEmitter::getLO16Encoding(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_lo16));
155   return 0;
156 }
157 
158 unsigned PPCMCCodeEmitter::getMemRIEncoding(const MCInst &MI, unsigned OpNo,
159                                             SmallVectorImpl<MCFixup> &Fixups) const {
160   // Encode (imm, reg) as a memri, which has the low 16-bits as the
161   // displacement and the next 5 bits as the register #.
162   assert(MI.getOperand(OpNo+1).isReg());
163   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups) << 16;
164 
165   const MCOperand &MO = MI.getOperand(OpNo);
166   if (MO.isImm())
167     return (getMachineOpValue(MI, MO, Fixups) & 0xFFFF) | RegBits;
168 
169   // Add a fixup for the displacement field.
170   if (isSVR4ABI() && is64BitMode())
171     Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
172                                      (MCFixupKind)PPC::fixup_ppc_toc16));
173   else
174     Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
175                                      (MCFixupKind)PPC::fixup_ppc_lo16));
176   return RegBits;
177 }
178 
179 
180 unsigned PPCMCCodeEmitter::getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
181                                        SmallVectorImpl<MCFixup> &Fixups) const {
182   // Encode (imm, reg) as a memrix, which has the low 14-bits as the
183   // displacement and the next 5 bits as the register #.
184   assert(MI.getOperand(OpNo+1).isReg());
185   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups) << 14;
186 
187   const MCOperand &MO = MI.getOperand(OpNo);
188   if (MO.isImm())
189     return (getMachineOpValue(MI, MO, Fixups) & 0x3FFF) | RegBits;
190 
191   // Add a fixup for the branch target.
192   if (isSVR4ABI() && is64BitMode())
193     Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
194                                      (MCFixupKind)PPC::fixup_ppc_toc16_ds));
195   else
196     Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
197                                      (MCFixupKind)PPC::fixup_ppc_lo14));
198   return RegBits;
199 }
200 
201 
202 unsigned PPCMCCodeEmitter::getTLSOffsetEncoding(const MCInst &MI, unsigned OpNo,
203                                        SmallVectorImpl<MCFixup> &Fixups) const {
204   const MCOperand &MO = MI.getOperand(OpNo);
205 
206   // Add a fixup for the GOT displacement to the TLS block offset.
207   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
208                                    (MCFixupKind)PPC::fixup_ppc_toc16_ds));
209   return 0;
210 }
211 
212 
213 unsigned 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 
226 
227 unsigned PPCMCCodeEmitter::
228 get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
229                     SmallVectorImpl<MCFixup> &Fixups) const {
230   const MCOperand &MO = MI.getOperand(OpNo);
231   assert((MI.getOpcode() == PPC::MTCRF ||
232           MI.getOpcode() == PPC::MFOCRF ||
233           MI.getOpcode() == PPC::MTCRF8) &&
234          (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
235   return 0x80 >> getPPCRegisterNumbering(MO.getReg());
236 }
237 
238 
239 unsigned PPCMCCodeEmitter::
240 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
241                   SmallVectorImpl<MCFixup> &Fixups) const {
242   if (MO.isReg()) {
243     // MTCRF/MFOCRF should go through get_crbitm_encoding for the CR operand.
244     // The GPR operand should come through here though.
245     assert((MI.getOpcode() != PPC::MTCRF && MI.getOpcode() != PPC::MFOCRF) ||
246            MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
247     return getPPCRegisterNumbering(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