xref: /freebsd/contrib/llvm-project/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
1 //===------ PPCDisassembler.cpp - Disassembler for PowerPC ------*- C++ -*-===//
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 #include "MCTargetDesc/PPCMCTargetDesc.h"
10 #include "TargetInfo/PowerPCTargetInfo.h"
11 #include "llvm/MC/MCDecoderOps.h"
12 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
13 #include "llvm/MC/MCInst.h"
14 #include "llvm/MC/MCSubtargetInfo.h"
15 #include "llvm/MC/TargetRegistry.h"
16 #include "llvm/Support/Compiler.h"
17 #include "llvm/Support/Endian.h"
18 
19 using namespace llvm;
20 
21 DEFINE_PPC_REGCLASSES
22 
23 #define DEBUG_TYPE "ppc-disassembler"
24 
25 typedef MCDisassembler::DecodeStatus DecodeStatus;
26 
27 namespace {
28 class PPCDisassembler : public MCDisassembler {
29   bool IsLittleEndian;
30 
31 public:
32   PPCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
33                   bool IsLittleEndian)
34       : MCDisassembler(STI, Ctx), IsLittleEndian(IsLittleEndian) {}
35 
36   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
37                               ArrayRef<uint8_t> Bytes, uint64_t Address,
38                               raw_ostream &CStream) const override;
39 };
40 } // end anonymous namespace
41 
42 static MCDisassembler *createPPCDisassembler(const Target &T,
43                                              const MCSubtargetInfo &STI,
44                                              MCContext &Ctx) {
45   return new PPCDisassembler(STI, Ctx, /*IsLittleEndian=*/false);
46 }
47 
48 static MCDisassembler *createPPCLEDisassembler(const Target &T,
49                                                const MCSubtargetInfo &STI,
50                                                MCContext &Ctx) {
51   return new PPCDisassembler(STI, Ctx, /*IsLittleEndian=*/true);
52 }
53 
54 extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
55 LLVMInitializePowerPCDisassembler() {
56   // Register the disassembler for each target.
57   TargetRegistry::RegisterMCDisassembler(getThePPC32Target(),
58                                          createPPCDisassembler);
59   TargetRegistry::RegisterMCDisassembler(getThePPC32LETarget(),
60                                          createPPCLEDisassembler);
61   TargetRegistry::RegisterMCDisassembler(getThePPC64Target(),
62                                          createPPCDisassembler);
63   TargetRegistry::RegisterMCDisassembler(getThePPC64LETarget(),
64                                          createPPCLEDisassembler);
65 }
66 
67 static DecodeStatus decodeCondBrTarget(MCInst &Inst, unsigned Imm,
68                                        uint64_t /*Address*/,
69                                        const MCDisassembler * /*Decoder*/) {
70   Inst.addOperand(MCOperand::createImm(SignExtend32<14>(Imm)));
71   return MCDisassembler::Success;
72 }
73 
74 static DecodeStatus decodeDirectBrTarget(MCInst &Inst, unsigned Imm,
75                                          uint64_t /*Address*/,
76                                          const MCDisassembler * /*Decoder*/) {
77   int32_t Offset = SignExtend32<24>(Imm);
78   Inst.addOperand(MCOperand::createImm(Offset));
79   return MCDisassembler::Success;
80 }
81 
82 // FIXME: These can be generated by TableGen from the existing register
83 // encoding values!
84 
85 template <std::size_t N>
86 static DecodeStatus decodeRegisterClass(MCInst &Inst, uint64_t RegNo,
87                                         const MCPhysReg (&Regs)[N]) {
88   if (RegNo >= N)
89     return MCDisassembler::Fail;
90   Inst.addOperand(MCOperand::createReg(Regs[RegNo]));
91   return MCDisassembler::Success;
92 }
93 
94 static DecodeStatus DecodeCRRCRegisterClass(MCInst &Inst, uint64_t RegNo,
95                                             uint64_t Address,
96                                             const MCDisassembler *Decoder) {
97   return decodeRegisterClass(Inst, RegNo, CRRegs);
98 }
99 
100 static DecodeStatus DecodeCRBITRCRegisterClass(MCInst &Inst, uint64_t RegNo,
101                                                uint64_t Address,
102                                                const MCDisassembler *Decoder) {
103   return decodeRegisterClass(Inst, RegNo, CRBITRegs);
104 }
105 
106 static DecodeStatus DecodeF4RCRegisterClass(MCInst &Inst, uint64_t RegNo,
107                                             uint64_t Address,
108                                             const MCDisassembler *Decoder) {
109   return decodeRegisterClass(Inst, RegNo, FRegs);
110 }
111 
112 static DecodeStatus DecodeF8RCRegisterClass(MCInst &Inst, uint64_t RegNo,
113                                             uint64_t Address,
114                                             const MCDisassembler *Decoder) {
115   return decodeRegisterClass(Inst, RegNo, FRegs);
116 }
117 
118 static DecodeStatus DecodeFpRCRegisterClass(MCInst &Inst, uint64_t RegNo,
119                                             uint64_t Address,
120                                             const MCDisassembler *Decoder) {
121   if (RegNo > 30 || (RegNo & 1))
122     return MCDisassembler::Fail;
123   return decodeRegisterClass(Inst, RegNo >> 1, FpRegs);
124 }
125 
126 static DecodeStatus DecodeVFRCRegisterClass(MCInst &Inst, uint64_t RegNo,
127                                             uint64_t Address,
128                                             const MCDisassembler *Decoder) {
129   return decodeRegisterClass(Inst, RegNo, VFRegs);
130 }
131 
132 static DecodeStatus DecodeVRRCRegisterClass(MCInst &Inst, uint64_t RegNo,
133                                             uint64_t Address,
134                                             const MCDisassembler *Decoder) {
135   return decodeRegisterClass(Inst, RegNo, VRegs);
136 }
137 
138 static DecodeStatus DecodeVSRCRegisterClass(MCInst &Inst, uint64_t RegNo,
139                                             uint64_t Address,
140                                             const MCDisassembler *Decoder) {
141   return decodeRegisterClass(Inst, RegNo, VSRegs);
142 }
143 
144 static DecodeStatus DecodeVSFRCRegisterClass(MCInst &Inst, uint64_t RegNo,
145                                              uint64_t Address,
146                                              const MCDisassembler *Decoder) {
147   return decodeRegisterClass(Inst, RegNo, VSFRegs);
148 }
149 
150 static DecodeStatus DecodeVSSRCRegisterClass(MCInst &Inst, uint64_t RegNo,
151                                              uint64_t Address,
152                                              const MCDisassembler *Decoder) {
153   return decodeRegisterClass(Inst, RegNo, VSSRegs);
154 }
155 
156 static DecodeStatus DecodeGPRCRegisterClass(MCInst &Inst, uint64_t RegNo,
157                                             uint64_t Address,
158                                             const MCDisassembler *Decoder) {
159   return decodeRegisterClass(Inst, RegNo, RRegs);
160 }
161 
162 static DecodeStatus
163 DecodeGPRC_NOR0RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,
164                              const MCDisassembler *Decoder) {
165   return decodeRegisterClass(Inst, RegNo, RRegsNoR0);
166 }
167 
168 static DecodeStatus DecodeG8RCRegisterClass(MCInst &Inst, uint64_t RegNo,
169                                             uint64_t Address,
170                                             const MCDisassembler *Decoder) {
171   return decodeRegisterClass(Inst, RegNo, XRegs);
172 }
173 
174 static DecodeStatus DecodeG8pRCRegisterClass(MCInst &Inst, uint64_t RegNo,
175                                              uint64_t Address,
176                                              const MCDisassembler *Decoder) {
177   return decodeRegisterClass(Inst, RegNo, XRegs);
178 }
179 
180 static DecodeStatus
181 DecodeG8RC_NOX0RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,
182                              const MCDisassembler *Decoder) {
183   return decodeRegisterClass(Inst, RegNo, XRegsNoX0);
184 }
185 
186 #define DecodePointerLikeRegClass0 DecodeGPRCRegisterClass
187 #define DecodePointerLikeRegClass1 DecodeGPRC_NOR0RegisterClass
188 
189 static DecodeStatus DecodeSPERCRegisterClass(MCInst &Inst, uint64_t RegNo,
190                                              uint64_t Address,
191                                              const MCDisassembler *Decoder) {
192   return decodeRegisterClass(Inst, RegNo, SPERegs);
193 }
194 
195 static DecodeStatus DecodeACCRCRegisterClass(MCInst &Inst, uint64_t RegNo,
196                                              uint64_t Address,
197                                              const MCDisassembler *Decoder) {
198   return decodeRegisterClass(Inst, RegNo, ACCRegs);
199 }
200 
201 static DecodeStatus DecodeWACCRCRegisterClass(MCInst &Inst, uint64_t RegNo,
202                                               uint64_t Address,
203                                               const void *Decoder) {
204   return decodeRegisterClass(Inst, RegNo, WACCRegs);
205 }
206 
207 static DecodeStatus DecodeWACC_HIRCRegisterClass(MCInst &Inst, uint64_t RegNo,
208                                                  uint64_t Address,
209                                                  const void *Decoder) {
210   return decodeRegisterClass(Inst, RegNo, WACC_HIRegs);
211 }
212 
213 // TODO: Make this function static when the register class is used by a new
214 //       instruction.
215 DecodeStatus DecodeDMRROWRCRegisterClass(MCInst &Inst, uint64_t RegNo,
216                                          uint64_t Address,
217                                          const void *Decoder) {
218   return decodeRegisterClass(Inst, RegNo, DMRROWRegs);
219 }
220 
221 static DecodeStatus DecodeDMRROWpRCRegisterClass(MCInst &Inst, uint64_t RegNo,
222                                                  uint64_t Address,
223                                                  const void *Decoder) {
224   return decodeRegisterClass(Inst, RegNo, DMRROWpRegs);
225 }
226 
227 static DecodeStatus DecodeDMRRCRegisterClass(MCInst &Inst, uint64_t RegNo,
228                                              uint64_t Address,
229                                              const void *Decoder) {
230   return decodeRegisterClass(Inst, RegNo, DMRRegs);
231 }
232 
233 // TODO: Make this function static when the register class is used by a new
234 //       instruction.
235 DecodeStatus DecodeDMRpRCRegisterClass(MCInst &Inst, uint64_t RegNo,
236                                        uint64_t Address, const void *Decoder) {
237   return decodeRegisterClass(Inst, RegNo, DMRpRegs);
238 }
239 
240 static DecodeStatus DecodeVSRpRCRegisterClass(MCInst &Inst, uint64_t RegNo,
241                                               uint64_t Address,
242                                               const MCDisassembler *Decoder) {
243   return decodeRegisterClass(Inst, RegNo, VSRpRegs);
244 }
245 
246 #define DecodeQSRCRegisterClass DecodeQFRCRegisterClass
247 #define DecodeQBRCRegisterClass DecodeQFRCRegisterClass
248 
249 template <unsigned N>
250 static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm,
251                                       int64_t Address,
252                                       const MCDisassembler *Decoder) {
253   if (!isUInt<N>(Imm))
254     return MCDisassembler::Fail;
255   Inst.addOperand(MCOperand::createImm(Imm));
256   return MCDisassembler::Success;
257 }
258 
259 template <unsigned N>
260 static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm,
261                                       int64_t Address,
262                                       const MCDisassembler *Decoder) {
263   if (!isUInt<N>(Imm))
264     return MCDisassembler::Fail;
265   Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm)));
266   return MCDisassembler::Success;
267 }
268 
269 static DecodeStatus decodeImmZeroOperand(MCInst &Inst, uint64_t Imm,
270                                          int64_t Address,
271                                          const MCDisassembler *Decoder) {
272   if (Imm != 0)
273     return MCDisassembler::Fail;
274   Inst.addOperand(MCOperand::createImm(Imm));
275   return MCDisassembler::Success;
276 }
277 
278 static DecodeStatus decodeVSRpEvenOperands(MCInst &Inst, uint64_t RegNo,
279                                            uint64_t Address,
280                                            const MCDisassembler *Decoder) {
281   if (RegNo & 1)
282     return MCDisassembler::Fail;
283   Inst.addOperand(MCOperand::createReg(VSRpRegs[RegNo >> 1]));
284   return MCDisassembler::Success;
285 }
286 
287 static DecodeStatus decodeDispRIXOperand(MCInst &Inst, uint64_t Imm,
288                                          int64_t Address,
289                                          const MCDisassembler *Decoder) {
290   // The rix displacement is an immediate shifted by 2
291   Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Imm << 2)));
292   return MCDisassembler::Success;
293 }
294 
295 static DecodeStatus decodeDispRIHashOperand(MCInst &Inst, uint64_t Imm,
296                                             int64_t Address,
297                                             const MCDisassembler *Decoder) {
298   // Decode the disp field for a hash store or hash check operation.
299   // The field is composed of an immediate value that is 6 bits
300   // and covers the range -8 to -512. The immediate is always negative and 2s
301   // complement which is why we sign extend a 7 bit value.
302   const int64_t Disp = SignExtend64<7>((Imm & 0x3F) + 64) * 8;
303 
304   Inst.addOperand(MCOperand::createImm(Disp));
305   return MCDisassembler::Success;
306 }
307 
308 static DecodeStatus decodeDispRIX16Operand(MCInst &Inst, uint64_t Imm,
309                                            int64_t Address,
310                                            const MCDisassembler *Decoder) {
311   // The rix16 displacement has 12-bits which are shifted by 4.
312   Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Imm << 4)));
313   return MCDisassembler::Success;
314 }
315 
316 static DecodeStatus decodeDispSPE8Operand(MCInst &Inst, uint64_t Imm,
317                                           int64_t Address,
318                                           const MCDisassembler *Decoder) {
319   // Decode the dispSPE8 field, which has 5-bits, 8-byte aligned.
320 
321   uint64_t Disp = Imm & 0x1F;
322 
323   Inst.addOperand(MCOperand::createImm(Disp << 3));
324   return MCDisassembler::Success;
325 }
326 
327 static DecodeStatus decodeDispSPE4Operand(MCInst &Inst, uint64_t Imm,
328                                           int64_t Address,
329                                           const MCDisassembler *Decoder) {
330   // Decode the dispSPE8 field, which has 5-bits, 4-byte aligned.
331 
332   uint64_t Disp = Imm & 0x1F;
333 
334   Inst.addOperand(MCOperand::createImm(Disp << 2));
335   return MCDisassembler::Success;
336 }
337 
338 static DecodeStatus decodeDispSPE2Operand(MCInst &Inst, uint64_t Imm,
339                                           int64_t Address,
340                                           const MCDisassembler *Decoder) {
341   // Decode the dispSPE8 field, which has 5-bits, 2-byte aligned.
342 
343   uint64_t Disp = Imm & 0x1F;
344   Inst.addOperand(MCOperand::createImm(Disp << 1));
345   return MCDisassembler::Success;
346 }
347 
348 static DecodeStatus decodeCRBitMOperand(MCInst &Inst, uint64_t Imm,
349                                         int64_t Address,
350                                         const MCDisassembler *Decoder) {
351   // The cr bit encoding is 0x80 >> cr_reg_num.
352 
353   unsigned Zeros = llvm::countr_zero(Imm);
354   if (Zeros >= 8)
355     return MCDisassembler::Fail;
356 
357   Inst.addOperand(MCOperand::createReg(CRRegs[7 - Zeros]));
358   return MCDisassembler::Success;
359 }
360 
361 #include "PPCGenDisassemblerTables.inc"
362 
363 DecodeStatus PPCDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
364                                              ArrayRef<uint8_t> Bytes,
365                                              uint64_t Address,
366                                              raw_ostream &CS) const {
367   auto *ReadFunc = IsLittleEndian ? support::endian::read32le
368                                   : support::endian::read32be;
369 
370   // If this is an 8-byte prefixed instruction, handle it here.
371   // Note: prefixed instructions aren't technically 8-byte entities - the prefix
372   //       appears in memory at an address 4 bytes prior to that of the base
373   //       instruction regardless of endianness. So we read the two pieces and
374   //       rebuild the 8-byte instruction.
375   // TODO: In this function we call decodeInstruction several times with
376   //       different decoder tables. It may be possible to only call once by
377   //       looking at the top 6 bits of the instruction.
378   if (STI.hasFeature(PPC::FeaturePrefixInstrs) && Bytes.size() >= 8) {
379     uint32_t Prefix = ReadFunc(Bytes.data());
380     uint32_t BaseInst = ReadFunc(Bytes.data() + 4);
381     uint64_t Inst = BaseInst | (uint64_t)Prefix << 32;
382     DecodeStatus result = decodeInstruction(DecoderTable64, MI, Inst, Address,
383                                             this, STI);
384     if (result != MCDisassembler::Fail) {
385       Size = 8;
386       return result;
387     }
388   }
389 
390   // Get the four bytes of the instruction.
391   Size = 4;
392   if (Bytes.size() < 4) {
393     Size = 0;
394     return MCDisassembler::Fail;
395   }
396 
397   // Read the instruction in the proper endianness.
398   uint64_t Inst = ReadFunc(Bytes.data());
399 
400   if (STI.hasFeature(PPC::FeatureSPE)) {
401     DecodeStatus result =
402         decodeInstruction(DecoderTableSPE32, MI, Inst, Address, this, STI);
403     if (result != MCDisassembler::Fail)
404       return result;
405   }
406 
407   return decodeInstruction(DecoderTable32, MI, Inst, Address, this, STI);
408 }
409