1//===-- PPCMCCodeEmitter.cpp - Convert PPC code to machine code -----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the PPCMCCodeEmitter class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "MCTargetDesc/PPCFixupKinds.h"
14#include "PPCInstrInfo.h"
15#include "PPCMCCodeEmitter.h"
16#include "llvm/ADT/SmallVector.h"
17#include "llvm/ADT/Statistic.h"
18#include "llvm/ADT/Triple.h"
19#include "llvm/MC/MCFixup.h"
20#include "llvm/MC/MCInstrDesc.h"
21#include "llvm/MC/MCRegisterInfo.h"
22#include "llvm/Support/Endian.h"
23#include "llvm/Support/EndianStream.h"
24#include "llvm/Support/ErrorHandling.h"
25#include "llvm/Support/MathExtras.h"
26#include "llvm/Support/raw_ostream.h"
27#include <cassert>
28#include <cstdint>
29
30using namespace llvm;
31
32#define DEBUG_TYPE "mccodeemitter"
33
34STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
35
36MCCodeEmitter *llvm::createPPCMCCodeEmitter(const MCInstrInfo &MCII,
37                                            const MCRegisterInfo &MRI,
38                                            MCContext &Ctx) {
39  return new PPCMCCodeEmitter(MCII, Ctx);
40}
41
42unsigned PPCMCCodeEmitter::
43getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
44                    SmallVectorImpl<MCFixup> &Fixups,
45                    const MCSubtargetInfo &STI) const {
46  const MCOperand &MO = MI.getOperand(OpNo);
47  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
48
49  // Add a fixup for the branch target.
50  Fixups.push_back(MCFixup::create(0, MO.getExpr(),
51                                   (MCFixupKind)PPC::fixup_ppc_br24));
52  return 0;
53}
54
55unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo,
56                                     SmallVectorImpl<MCFixup> &Fixups,
57                                     const MCSubtargetInfo &STI) const {
58  const MCOperand &MO = MI.getOperand(OpNo);
59  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
60
61  // Add a fixup for the branch target.
62  Fixups.push_back(MCFixup::create(0, MO.getExpr(),
63                                   (MCFixupKind)PPC::fixup_ppc_brcond14));
64  return 0;
65}
66
67unsigned PPCMCCodeEmitter::
68getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo,
69                       SmallVectorImpl<MCFixup> &Fixups,
70                       const MCSubtargetInfo &STI) const {
71  const MCOperand &MO = MI.getOperand(OpNo);
72  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
73
74  // Add a fixup for the branch target.
75  Fixups.push_back(MCFixup::create(0, MO.getExpr(),
76                                   (MCFixupKind)PPC::fixup_ppc_br24abs));
77  return 0;
78}
79
80unsigned PPCMCCodeEmitter::
81getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo,
82                     SmallVectorImpl<MCFixup> &Fixups,
83                     const MCSubtargetInfo &STI) const {
84  const MCOperand &MO = MI.getOperand(OpNo);
85  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
86
87  // Add a fixup for the branch target.
88  Fixups.push_back(MCFixup::create(0, MO.getExpr(),
89                                   (MCFixupKind)PPC::fixup_ppc_brcond14abs));
90  return 0;
91}
92
93unsigned PPCMCCodeEmitter::getImm16Encoding(const MCInst &MI, unsigned OpNo,
94                                       SmallVectorImpl<MCFixup> &Fixups,
95                                       const MCSubtargetInfo &STI) const {
96  const MCOperand &MO = MI.getOperand(OpNo);
97  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
98
99  // Add a fixup for the immediate field.
100  Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
101                                   (MCFixupKind)PPC::fixup_ppc_half16));
102  return 0;
103}
104
105unsigned PPCMCCodeEmitter::getMemRIEncoding(const MCInst &MI, unsigned OpNo,
106                                            SmallVectorImpl<MCFixup> &Fixups,
107                                            const MCSubtargetInfo &STI) const {
108  // Encode (imm, reg) as a memri, which has the low 16-bits as the
109  // displacement and the next 5 bits as the register #.
110  assert(MI.getOperand(OpNo+1).isReg());
111  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 16;
112
113  const MCOperand &MO = MI.getOperand(OpNo);
114  if (MO.isImm())
115    return (getMachineOpValue(MI, MO, Fixups, STI) & 0xFFFF) | RegBits;
116
117  // Add a fixup for the displacement field.
118  Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
119                                   (MCFixupKind)PPC::fixup_ppc_half16));
120  return RegBits;
121}
122
123unsigned PPCMCCodeEmitter::getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
124                                       SmallVectorImpl<MCFixup> &Fixups,
125                                       const MCSubtargetInfo &STI) const {
126  // Encode (imm, reg) as a memrix, which has the low 14-bits as the
127  // displacement and the next 5 bits as the register #.
128  assert(MI.getOperand(OpNo+1).isReg());
129  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 14;
130
131  const MCOperand &MO = MI.getOperand(OpNo);
132  if (MO.isImm())
133    return ((getMachineOpValue(MI, MO, Fixups, STI) >> 2) & 0x3FFF) | RegBits;
134
135  // Add a fixup for the displacement field.
136  Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
137                                   (MCFixupKind)PPC::fixup_ppc_half16ds));
138  return RegBits;
139}
140
141unsigned PPCMCCodeEmitter::getMemRIX16Encoding(const MCInst &MI, unsigned OpNo,
142                                       SmallVectorImpl<MCFixup> &Fixups,
143                                       const MCSubtargetInfo &STI) const {
144  // Encode (imm, reg) as a memrix16, which has the low 12-bits as the
145  // displacement and the next 5 bits as the register #.
146  assert(MI.getOperand(OpNo+1).isReg());
147  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 12;
148
149  const MCOperand &MO = MI.getOperand(OpNo);
150  if (MO.isImm()) {
151    assert(!(MO.getImm() % 16) &&
152           "Expecting an immediate that is a multiple of 16");
153    return ((getMachineOpValue(MI, MO, Fixups, STI) >> 4) & 0xFFF) | RegBits;
154  }
155
156  // Otherwise add a fixup for the displacement field.
157  Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
158                                   (MCFixupKind)PPC::fixup_ppc_half16ds));
159  return RegBits;
160}
161
162unsigned PPCMCCodeEmitter::getSPE8DisEncoding(const MCInst &MI, unsigned OpNo,
163                                              SmallVectorImpl<MCFixup> &Fixups,
164                                              const MCSubtargetInfo &STI)
165                                              const {
166  // Encode (imm, reg) as a spe8dis, which has the low 5-bits of (imm / 8)
167  // as the displacement and the next 5 bits as the register #.
168  assert(MI.getOperand(OpNo+1).isReg());
169  uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
170
171  const MCOperand &MO = MI.getOperand(OpNo);
172  assert(MO.isImm());
173  uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 3;
174  return reverseBits(Imm | RegBits) >> 22;
175}
176
177unsigned PPCMCCodeEmitter::getSPE4DisEncoding(const MCInst &MI, unsigned OpNo,
178                                              SmallVectorImpl<MCFixup> &Fixups,
179                                              const MCSubtargetInfo &STI)
180                                              const {
181  // Encode (imm, reg) as a spe4dis, which has the low 5-bits of (imm / 4)
182  // as the displacement and the next 5 bits as the register #.
183  assert(MI.getOperand(OpNo+1).isReg());
184  uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
185
186  const MCOperand &MO = MI.getOperand(OpNo);
187  assert(MO.isImm());
188  uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 2;
189  return reverseBits(Imm | RegBits) >> 22;
190}
191
192unsigned PPCMCCodeEmitter::getSPE2DisEncoding(const MCInst &MI, unsigned OpNo,
193                                              SmallVectorImpl<MCFixup> &Fixups,
194                                              const MCSubtargetInfo &STI)
195                                              const {
196  // Encode (imm, reg) as a spe2dis, which has the low 5-bits of (imm / 2)
197  // as the displacement and the next 5 bits as the register #.
198  assert(MI.getOperand(OpNo+1).isReg());
199  uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
200
201  const MCOperand &MO = MI.getOperand(OpNo);
202  assert(MO.isImm());
203  uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 1;
204  return reverseBits(Imm | RegBits) >> 22;
205}
206
207unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
208                                       SmallVectorImpl<MCFixup> &Fixups,
209                                       const MCSubtargetInfo &STI) const {
210  const MCOperand &MO = MI.getOperand(OpNo);
211  if (MO.isReg()) return getMachineOpValue(MI, MO, Fixups, STI);
212
213  // Add a fixup for the TLS register, which simply provides a relocation
214  // hint to the linker that this statement is part of a relocation sequence.
215  // Return the thread-pointer register's encoding.
216  Fixups.push_back(MCFixup::create(0, MO.getExpr(),
217                                   (MCFixupKind)PPC::fixup_ppc_nofixup));
218  const Triple &TT = STI.getTargetTriple();
219  bool isPPC64 = TT.isPPC64();
220  return CTX.getRegisterInfo()->getEncodingValue(isPPC64 ? PPC::X13 : PPC::R2);
221}
222
223unsigned PPCMCCodeEmitter::getTLSCallEncoding(const MCInst &MI, unsigned OpNo,
224                                       SmallVectorImpl<MCFixup> &Fixups,
225                                       const MCSubtargetInfo &STI) const {
226  // For special TLS calls, we need two fixups; one for the branch target
227  // (__tls_get_addr), which we create via getDirectBrEncoding as usual,
228  // and one for the TLSGD or TLSLD symbol, which is emitted here.
229  const MCOperand &MO = MI.getOperand(OpNo+1);
230  Fixups.push_back(MCFixup::create(0, MO.getExpr(),
231                                   (MCFixupKind)PPC::fixup_ppc_nofixup));
232  return getDirectBrEncoding(MI, OpNo, Fixups, STI);
233}
234
235unsigned PPCMCCodeEmitter::
236get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
237                    SmallVectorImpl<MCFixup> &Fixups,
238                    const MCSubtargetInfo &STI) const {
239  const MCOperand &MO = MI.getOperand(OpNo);
240  assert((MI.getOpcode() == PPC::MTOCRF || MI.getOpcode() == PPC::MTOCRF8 ||
241          MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) &&
242         (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
243  return 0x80 >> CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
244}
245
246// Get the index for this operand in this instruction. This is needed for
247// computing the register number in PPCInstrInfo::getRegNumForOperand() for
248// any instructions that use a different numbering scheme for registers in
249// different operands.
250static unsigned getOpIdxForMO(const MCInst &MI, const MCOperand &MO) {
251  for (unsigned i = 0; i < MI.getNumOperands(); i++) {
252    const MCOperand &Op = MI.getOperand(i);
253    if (&Op == &MO)
254      return i;
255  }
256  llvm_unreachable("This operand is not part of this instruction");
257  return ~0U; // Silence any warnings about no return.
258}
259
260unsigned PPCMCCodeEmitter::
261getMachineOpValue(const MCInst &MI, const MCOperand &MO,
262                  SmallVectorImpl<MCFixup> &Fixups,
263                  const MCSubtargetInfo &STI) const {
264  if (MO.isReg()) {
265    // MTOCRF/MFOCRF should go through get_crbitm_encoding for the CR operand.
266    // The GPR operand should come through here though.
267    assert((MI.getOpcode() != PPC::MTOCRF && MI.getOpcode() != PPC::MTOCRF8 &&
268            MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) ||
269           MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
270    unsigned OpNo = getOpIdxForMO(MI, MO);
271    unsigned Reg =
272      PPCInstrInfo::getRegNumForOperand(MCII.get(MI.getOpcode()),
273                                        MO.getReg(), OpNo);
274    return CTX.getRegisterInfo()->getEncodingValue(Reg);
275  }
276
277  assert(MO.isImm() &&
278         "Relocation required in an instruction that we cannot encode!");
279  return MO.getImm();
280}
281
282void PPCMCCodeEmitter::encodeInstruction(
283    const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups,
284    const MCSubtargetInfo &STI) const {
285  verifyInstructionPredicates(MI,
286                              computeAvailableFeatures(STI.getFeatureBits()));
287
288  uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
289
290  // Output the constant in big/little endian byte order.
291  unsigned Size = getInstSizeInBytes(MI);
292  support::endianness E = IsLittleEndian ? support::little : support::big;
293  switch (Size) {
294  case 0:
295    break;
296  case 4:
297    support::endian::write<uint32_t>(OS, Bits, E);
298    break;
299  case 8:
300    // If we emit a pair of instructions, the first one is
301    // always in the top 32 bits, even on little-endian.
302    support::endian::write<uint32_t>(OS, Bits >> 32, E);
303    support::endian::write<uint32_t>(OS, Bits, E);
304    break;
305  default:
306    llvm_unreachable("Invalid instruction size");
307  }
308
309  ++MCNumEmitted; // Keep track of the # of mi's emitted.
310}
311
312// Get the number of bytes used to encode the given MCInst.
313unsigned PPCMCCodeEmitter::getInstSizeInBytes(const MCInst &MI) const {
314  unsigned Opcode = MI.getOpcode();
315  const MCInstrDesc &Desc = MCII.get(Opcode);
316  return Desc.getSize();
317}
318
319#define ENABLE_INSTR_PREDICATE_VERIFIER
320#include "PPCGenMCCodeEmitter.inc"
321