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(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 | |
67 | static 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 | |
74 | static 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 | |
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(Op: MCOperand::createReg(Reg: 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, Regs: 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, Regs: 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, Regs: 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, Regs: 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: RegNo >> 1, Regs: 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, Regs: 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, Regs: 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, Regs: 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, Regs: 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, Regs: 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, Regs: 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, Regs: 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, Regs: 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, Regs: 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, Regs: 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, Regs: 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, Regs: 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, Regs: 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, Regs: 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, Regs: 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, Regs: 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, Regs: 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, Regs: 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, Regs: 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(Op: MCOperand::createImm(Val: 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(Op: MCOperand::createImm(Val: 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(Op: MCOperand::createImm(Val: 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(Op: MCOperand::createReg(Reg: 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(Op: MCOperand::createImm(Val: SignExtend64<16>(x: 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>(x: (Imm & 0x3F) + 64) * 8; |
303 | |
304 | Inst.addOperand(Op: MCOperand::createImm(Val: 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(Op: MCOperand::createImm(Val: SignExtend64<16>(x: 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(Op: MCOperand::createImm(Val: 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(Op: MCOperand::createImm(Val: 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(Op: MCOperand::createImm(Val: 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(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 | |
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(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 | |