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