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