[ARM] MVE integer min and max
[llvm-complete.git] / lib / Target / PowerPC / MCTargetDesc / PPCMCCodeEmitter.cpp
blob676efc5004553644dfa76b2d949e71fdf05efb6c
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.
11 //===----------------------------------------------------------------------===//
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>
30 using namespace llvm;
32 #define DEBUG_TYPE "mccodeemitter"
34 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
36 MCCodeEmitter *llvm::createPPCMCCodeEmitter(const MCInstrInfo &MCII,
37 const MCRegisterInfo &MRI,
38 MCContext &Ctx) {
39 return new PPCMCCodeEmitter(MCII, Ctx);
42 unsigned PPCMCCodeEmitter::
43 getDirectBrEncoding(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);
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;
55 unsigned 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);
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;
67 unsigned PPCMCCodeEmitter::
68 getAbsDirectBrEncoding(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);
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;
80 unsigned PPCMCCodeEmitter::
81 getAbsCondBrEncoding(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);
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;
93 unsigned 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);
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;
105 unsigned 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;
113 const MCOperand &MO = MI.getOperand(OpNo);
114 if (MO.isImm())
115 return (getMachineOpValue(MI, MO, Fixups, STI) & 0xFFFF) | RegBits;
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;
123 unsigned 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;
131 const MCOperand &MO = MI.getOperand(OpNo);
132 if (MO.isImm())
133 return ((getMachineOpValue(MI, MO, Fixups, STI) >> 2) & 0x3FFF) | RegBits;
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;
141 unsigned 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;
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;
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;
162 unsigned 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;
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;
177 unsigned 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;
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;
192 unsigned 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;
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;
207 unsigned 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);
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);
223 unsigned 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);
235 unsigned PPCMCCodeEmitter::
236 get_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());
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.
250 static 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;
256 llvm_unreachable("This operand is not part of this instruction");
257 return ~0U; // Silence any warnings about no return.
260 unsigned PPCMCCodeEmitter::
261 getMachineOpValue(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);
277 assert(MO.isImm() &&
278 "Relocation required in an instruction that we cannot encode!");
279 return MO.getImm();
282 void PPCMCCodeEmitter::encodeInstruction(
283 const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups,
284 const MCSubtargetInfo &STI) const {
285 verifyInstructionPredicates(MI,
286 computeAvailableFeatures(STI.getFeatureBits()));
288 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
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");
309 ++MCNumEmitted; // Keep track of the # of mi's emitted.
312 // Get the number of bytes used to encode the given MCInst.
313 unsigned PPCMCCodeEmitter::getInstSizeInBytes(const MCInst &MI) const {
314 unsigned Opcode = MI.getOpcode();
315 const MCInstrDesc &Desc = MCII.get(Opcode);
316 return Desc.getSize();
319 #define ENABLE_INSTR_PREDICATE_VERIFIER
320 #include "PPCGenMCCodeEmitter.inc"