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
19using namespace llvm;
20
21DEFINE_PPC_REGCLASSES
22
23#define DEBUG_TYPE "ppc-disassembler"
24
25typedef MCDisassembler::DecodeStatus DecodeStatus;
26
27namespace {
28class PPCDisassembler : public MCDisassembler {
29 bool IsLittleEndian;
30
31public:
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
42static MCDisassembler *createPPCDisassembler(const Target &T,
43 const MCSubtargetInfo &STI,
44 MCContext &Ctx) {
45 return new PPCDisassembler(STI, Ctx, /*IsLittleEndian=*/false);
46}
47
48static MCDisassembler *createPPCLEDisassembler(const Target &T,
49 const MCSubtargetInfo &STI,
50 MCContext &Ctx) {
51 return new PPCDisassembler(STI, Ctx, /*IsLittleEndian=*/true);
52}
53
54extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
55LLVMInitializePowerPCDisassembler() {
56 // Register the disassembler for each target.
57 TargetRegistry::RegisterMCDisassembler(T&: getThePPC32Target(),
58 Fn: createPPCDisassembler);
59 TargetRegistry::RegisterMCDisassembler(T&: getThePPC32LETarget(),
60 Fn: createPPCLEDisassembler);
61 TargetRegistry::RegisterMCDisassembler(T&: getThePPC64Target(),
62 Fn: createPPCDisassembler);
63 TargetRegistry::RegisterMCDisassembler(T&: getThePPC64LETarget(),
64 Fn: createPPCLEDisassembler);
65}
66
67static DecodeStatus decodeCondBrTarget(MCInst &Inst, unsigned Imm,
68 uint64_t /*Address*/,
69 const MCDisassembler * /*Decoder*/) {
70 Inst.addOperand(Op: MCOperand::createImm(Val: SignExtend32<14>(X: Imm)));
71 return MCDisassembler::Success;
72}
73
74static DecodeStatus decodeDirectBrTarget(MCInst &Inst, unsigned Imm,
75 uint64_t /*Address*/,
76 const MCDisassembler * /*Decoder*/) {
77 int32_t Offset = SignExtend32<24>(X: Imm);
78 Inst.addOperand(Op: MCOperand::createImm(Val: Offset));
79 return MCDisassembler::Success;
80}
81
82// FIXME: These can be generated by TableGen from the existing register
83// encoding values!
84
85template <std::size_t N>
86static DecodeStatus decodeRegisterClass(MCInst &Inst, uint64_t RegNo,
87 const MCPhysReg (&Regs)[N]) {
88 if (RegNo >= N)
89 return MCDisassembler::Fail;
90 Inst.addOperand(Op: MCOperand::createReg(Reg: Regs[RegNo]));
91 return MCDisassembler::Success;
92}
93
94static DecodeStatus DecodeCRRCRegisterClass(MCInst &Inst, uint64_t RegNo,
95 uint64_t Address,
96 const MCDisassembler *Decoder) {
97 return decodeRegisterClass(Inst, RegNo, Regs: CRRegs);
98}
99
100static DecodeStatus DecodeCRBITRCRegisterClass(MCInst &Inst, uint64_t RegNo,
101 uint64_t Address,
102 const MCDisassembler *Decoder) {
103 return decodeRegisterClass(Inst, RegNo, Regs: CRBITRegs);
104}
105
106static DecodeStatus DecodeF4RCRegisterClass(MCInst &Inst, uint64_t RegNo,
107 uint64_t Address,
108 const MCDisassembler *Decoder) {
109 return decodeRegisterClass(Inst, RegNo, Regs: FRegs);
110}
111
112static DecodeStatus DecodeF8RCRegisterClass(MCInst &Inst, uint64_t RegNo,
113 uint64_t Address,
114 const MCDisassembler *Decoder) {
115 return decodeRegisterClass(Inst, RegNo, Regs: FRegs);
116}
117
118static 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: RegNo >> 1, Regs: FpRegs);
124}
125
126static DecodeStatus DecodeVFRCRegisterClass(MCInst &Inst, uint64_t RegNo,
127 uint64_t Address,
128 const MCDisassembler *Decoder) {
129 return decodeRegisterClass(Inst, RegNo, Regs: VFRegs);
130}
131
132static DecodeStatus DecodeVRRCRegisterClass(MCInst &Inst, uint64_t RegNo,
133 uint64_t Address,
134 const MCDisassembler *Decoder) {
135 return decodeRegisterClass(Inst, RegNo, Regs: VRegs);
136}
137
138static DecodeStatus DecodeVSRCRegisterClass(MCInst &Inst, uint64_t RegNo,
139 uint64_t Address,
140 const MCDisassembler *Decoder) {
141 return decodeRegisterClass(Inst, RegNo, Regs: VSRegs);
142}
143
144static DecodeStatus DecodeVSFRCRegisterClass(MCInst &Inst, uint64_t RegNo,
145 uint64_t Address,
146 const MCDisassembler *Decoder) {
147 return decodeRegisterClass(Inst, RegNo, Regs: VSFRegs);
148}
149
150static DecodeStatus DecodeVSSRCRegisterClass(MCInst &Inst, uint64_t RegNo,
151 uint64_t Address,
152 const MCDisassembler *Decoder) {
153 return decodeRegisterClass(Inst, RegNo, Regs: VSSRegs);
154}
155
156static DecodeStatus DecodeGPRCRegisterClass(MCInst &Inst, uint64_t RegNo,
157 uint64_t Address,
158 const MCDisassembler *Decoder) {
159 return decodeRegisterClass(Inst, RegNo, Regs: RRegs);
160}
161
162static DecodeStatus
163DecodeGPRC_NOR0RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,
164 const MCDisassembler *Decoder) {
165 return decodeRegisterClass(Inst, RegNo, Regs: RRegsNoR0);
166}
167
168static DecodeStatus DecodeG8RCRegisterClass(MCInst &Inst, uint64_t RegNo,
169 uint64_t Address,
170 const MCDisassembler *Decoder) {
171 return decodeRegisterClass(Inst, RegNo, Regs: XRegs);
172}
173
174static DecodeStatus DecodeG8pRCRegisterClass(MCInst &Inst, uint64_t RegNo,
175 uint64_t Address,
176 const MCDisassembler *Decoder) {
177 return decodeRegisterClass(Inst, RegNo, Regs: XRegs);
178}
179
180static DecodeStatus
181DecodeG8RC_NOX0RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,
182 const MCDisassembler *Decoder) {
183 return decodeRegisterClass(Inst, RegNo, Regs: XRegsNoX0);
184}
185
186#define DecodePointerLikeRegClass0 DecodeGPRCRegisterClass
187#define DecodePointerLikeRegClass1 DecodeGPRC_NOR0RegisterClass
188
189static DecodeStatus DecodeSPERCRegisterClass(MCInst &Inst, uint64_t RegNo,
190 uint64_t Address,
191 const MCDisassembler *Decoder) {
192 return decodeRegisterClass(Inst, RegNo, Regs: SPERegs);
193}
194
195static DecodeStatus DecodeACCRCRegisterClass(MCInst &Inst, uint64_t RegNo,
196 uint64_t Address,
197 const MCDisassembler *Decoder) {
198 return decodeRegisterClass(Inst, RegNo, Regs: ACCRegs);
199}
200
201static DecodeStatus DecodeWACCRCRegisterClass(MCInst &Inst, uint64_t RegNo,
202 uint64_t Address,
203 const void *Decoder) {
204 return decodeRegisterClass(Inst, RegNo, Regs: WACCRegs);
205}
206
207static DecodeStatus DecodeWACC_HIRCRegisterClass(MCInst &Inst, uint64_t RegNo,
208 uint64_t Address,
209 const void *Decoder) {
210 return decodeRegisterClass(Inst, RegNo, Regs: WACC_HIRegs);
211}
212
213// TODO: Make this function static when the register class is used by a new
214// instruction.
215DecodeStatus DecodeDMRROWRCRegisterClass(MCInst &Inst, uint64_t RegNo,
216 uint64_t Address,
217 const void *Decoder) {
218 return decodeRegisterClass(Inst, RegNo, Regs: DMRROWRegs);
219}
220
221static DecodeStatus DecodeDMRROWpRCRegisterClass(MCInst &Inst, uint64_t RegNo,
222 uint64_t Address,
223 const void *Decoder) {
224 return decodeRegisterClass(Inst, RegNo, Regs: DMRROWpRegs);
225}
226
227static DecodeStatus DecodeDMRRCRegisterClass(MCInst &Inst, uint64_t RegNo,
228 uint64_t Address,
229 const void *Decoder) {
230 return decodeRegisterClass(Inst, RegNo, Regs: DMRRegs);
231}
232
233// TODO: Make this function static when the register class is used by a new
234// instruction.
235DecodeStatus DecodeDMRpRCRegisterClass(MCInst &Inst, uint64_t RegNo,
236 uint64_t Address, const void *Decoder) {
237 return decodeRegisterClass(Inst, RegNo, Regs: DMRpRegs);
238}
239
240static DecodeStatus DecodeVSRpRCRegisterClass(MCInst &Inst, uint64_t RegNo,
241 uint64_t Address,
242 const MCDisassembler *Decoder) {
243 return decodeRegisterClass(Inst, RegNo, Regs: VSRpRegs);
244}
245
246#define DecodeQSRCRegisterClass DecodeQFRCRegisterClass
247#define DecodeQBRCRegisterClass DecodeQFRCRegisterClass
248
249template <unsigned N>
250static 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(Op: MCOperand::createImm(Val: Imm));
256 return MCDisassembler::Success;
257}
258
259template <unsigned N>
260static 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(Op: MCOperand::createImm(Val: SignExtend64<N>(Imm)));
266 return MCDisassembler::Success;
267}
268
269static 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(Op: MCOperand::createImm(Val: Imm));
275 return MCDisassembler::Success;
276}
277
278static 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(Op: MCOperand::createReg(Reg: VSRpRegs[RegNo >> 1]));
284 return MCDisassembler::Success;
285}
286
287static 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(Op: MCOperand::createImm(Val: SignExtend64<16>(x: Imm << 2)));
292 return MCDisassembler::Success;
293}
294
295static 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>(x: (Imm & 0x3F) + 64) * 8;
303
304 Inst.addOperand(Op: MCOperand::createImm(Val: Disp));
305 return MCDisassembler::Success;
306}
307
308static 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(Op: MCOperand::createImm(Val: SignExtend64<16>(x: Imm << 4)));
313 return MCDisassembler::Success;
314}
315
316static 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(Op: MCOperand::createImm(Val: Disp << 3));
324 return MCDisassembler::Success;
325}
326
327static 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(Op: MCOperand::createImm(Val: Disp << 2));
335 return MCDisassembler::Success;
336}
337
338static 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(Op: MCOperand::createImm(Val: Disp << 1));
345 return MCDisassembler::Success;
346}
347
348static 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(Val: Imm);
354 if (Zeros >= 8)
355 return MCDisassembler::Fail;
356
357 Inst.addOperand(Op: MCOperand::createReg(Reg: CRRegs[7 - Zeros]));
358 return MCDisassembler::Success;
359}
360
361#include "PPCGenDisassemblerTables.inc"
362
363DecodeStatus 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(Feature: 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(DecodeTable: DecoderTable64, MI, insn: Inst, Address,
383 DisAsm: 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(Feature: PPC::FeatureSPE)) {
401 DecodeStatus result =
402 decodeInstruction(DecodeTable: DecoderTableSPE32, MI, insn: Inst, Address, DisAsm: this, STI);
403 if (result != MCDisassembler::Fail)
404 return result;
405 }
406
407 return decodeInstruction(DecodeTable: DecoderTable32, MI, insn: Inst, Address, DisAsm: this, STI);
408}
409