xref: /src/contrib/llvm-project/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
15ca98fd9SDimitry Andric //===------ PPCDisassembler.cpp - Disassembler for PowerPC ------*- C++ -*-===//
25ca98fd9SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ca98fd9SDimitry Andric //
75ca98fd9SDimitry Andric //===----------------------------------------------------------------------===//
85ca98fd9SDimitry Andric 
9d8e91e46SDimitry Andric #include "MCTargetDesc/PPCMCTargetDesc.h"
10e6d15924SDimitry Andric #include "TargetInfo/PowerPCTargetInfo.h"
11145449b1SDimitry Andric #include "llvm/MC/MCDecoderOps.h"
1201095a5dSDimitry Andric #include "llvm/MC/MCDisassembler/MCDisassembler.h"
135ca98fd9SDimitry Andric #include "llvm/MC/MCInst.h"
145ca98fd9SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
15c0981da4SDimitry Andric #include "llvm/MC/TargetRegistry.h"
1669156b4cSDimitry Andric #include "llvm/Support/Endian.h"
175ca98fd9SDimitry Andric 
185ca98fd9SDimitry Andric using namespace llvm;
195ca98fd9SDimitry Andric 
20e3b55780SDimitry Andric DEFINE_PPC_REGCLASSES
21d8e91e46SDimitry Andric 
225ca98fd9SDimitry Andric #define DEBUG_TYPE "ppc-disassembler"
235ca98fd9SDimitry Andric 
245ca98fd9SDimitry Andric typedef MCDisassembler::DecodeStatus DecodeStatus;
255ca98fd9SDimitry Andric 
265ca98fd9SDimitry Andric namespace {
275ca98fd9SDimitry Andric class PPCDisassembler : public MCDisassembler {
2869156b4cSDimitry Andric   bool IsLittleEndian;
2969156b4cSDimitry Andric 
305ca98fd9SDimitry Andric public:
PPCDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx,bool IsLittleEndian)3169156b4cSDimitry Andric   PPCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
3269156b4cSDimitry Andric                   bool IsLittleEndian)
3369156b4cSDimitry Andric       : MCDisassembler(STI, Ctx), IsLittleEndian(IsLittleEndian) {}
345ca98fd9SDimitry Andric 
3567c32a98SDimitry Andric   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
3667c32a98SDimitry Andric                               ArrayRef<uint8_t> Bytes, uint64_t Address,
3767c32a98SDimitry Andric                               raw_ostream &CStream) const override;
385ca98fd9SDimitry Andric };
395ca98fd9SDimitry Andric } // end anonymous namespace
405ca98fd9SDimitry Andric 
createPPCDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)415ca98fd9SDimitry Andric static MCDisassembler *createPPCDisassembler(const Target &T,
425ca98fd9SDimitry Andric                                              const MCSubtargetInfo &STI,
435ca98fd9SDimitry Andric                                              MCContext &Ctx) {
4469156b4cSDimitry Andric   return new PPCDisassembler(STI, Ctx, /*IsLittleEndian=*/false);
4569156b4cSDimitry Andric }
4669156b4cSDimitry Andric 
createPPCLEDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)4769156b4cSDimitry Andric static MCDisassembler *createPPCLEDisassembler(const Target &T,
4869156b4cSDimitry Andric                                                const MCSubtargetInfo &STI,
4969156b4cSDimitry Andric                                                MCContext &Ctx) {
5069156b4cSDimitry Andric   return new PPCDisassembler(STI, Ctx, /*IsLittleEndian=*/true);
515ca98fd9SDimitry Andric }
525ca98fd9SDimitry Andric 
LLVMInitializePowerPCDisassembler()53706b4fc4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCDisassembler() {
545ca98fd9SDimitry Andric   // Register the disassembler for each target.
55b915e9e0SDimitry Andric   TargetRegistry::RegisterMCDisassembler(getThePPC32Target(),
565ca98fd9SDimitry Andric                                          createPPCDisassembler);
57b60736ecSDimitry Andric   TargetRegistry::RegisterMCDisassembler(getThePPC32LETarget(),
58b60736ecSDimitry Andric                                          createPPCLEDisassembler);
59b915e9e0SDimitry Andric   TargetRegistry::RegisterMCDisassembler(getThePPC64Target(),
605ca98fd9SDimitry Andric                                          createPPCDisassembler);
61b915e9e0SDimitry Andric   TargetRegistry::RegisterMCDisassembler(getThePPC64LETarget(),
6269156b4cSDimitry Andric                                          createPPCLEDisassembler);
635ca98fd9SDimitry Andric }
645ca98fd9SDimitry Andric 
decodeCondBrTarget(MCInst & Inst,unsigned Imm,uint64_t,const MCDisassembler *)65cfca06d7SDimitry Andric static DecodeStatus decodeCondBrTarget(MCInst &Inst, unsigned Imm,
66cfca06d7SDimitry Andric                                        uint64_t /*Address*/,
67145449b1SDimitry Andric                                        const MCDisassembler * /*Decoder*/) {
68cfca06d7SDimitry Andric   Inst.addOperand(MCOperand::createImm(SignExtend32<14>(Imm)));
69cfca06d7SDimitry Andric   return MCDisassembler::Success;
70cfca06d7SDimitry Andric }
71cfca06d7SDimitry Andric 
decodeDirectBrTarget(MCInst & Inst,unsigned Imm,uint64_t,const MCDisassembler *)72cfca06d7SDimitry Andric static DecodeStatus decodeDirectBrTarget(MCInst &Inst, unsigned Imm,
73cfca06d7SDimitry Andric                                          uint64_t /*Address*/,
74145449b1SDimitry Andric                                          const MCDisassembler * /*Decoder*/) {
75e6d15924SDimitry Andric   int32_t Offset = SignExtend32<24>(Imm);
76e6d15924SDimitry Andric   Inst.addOperand(MCOperand::createImm(Offset));
77e6d15924SDimitry Andric   return MCDisassembler::Success;
78e6d15924SDimitry Andric }
79e6d15924SDimitry Andric 
805ca98fd9SDimitry Andric // FIXME: These can be generated by TableGen from the existing register
815ca98fd9SDimitry Andric // encoding values!
825ca98fd9SDimitry Andric 
835ca98fd9SDimitry Andric template <std::size_t N>
decodeRegisterClass(MCInst & Inst,uint64_t RegNo,const MCPhysReg (& Regs)[N])845ca98fd9SDimitry Andric static DecodeStatus decodeRegisterClass(MCInst &Inst, uint64_t RegNo,
85d8e91e46SDimitry Andric                                         const MCPhysReg (&Regs)[N]) {
867fa27ce4SDimitry Andric   if (RegNo >= N)
877fa27ce4SDimitry Andric     return MCDisassembler::Fail;
885a5ac124SDimitry Andric   Inst.addOperand(MCOperand::createReg(Regs[RegNo]));
895ca98fd9SDimitry Andric   return MCDisassembler::Success;
905ca98fd9SDimitry Andric }
915ca98fd9SDimitry Andric 
DecodeCRRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)925ca98fd9SDimitry Andric static DecodeStatus DecodeCRRCRegisterClass(MCInst &Inst, uint64_t RegNo,
935ca98fd9SDimitry Andric                                             uint64_t Address,
94145449b1SDimitry Andric                                             const MCDisassembler *Decoder) {
955ca98fd9SDimitry Andric   return decodeRegisterClass(Inst, RegNo, CRRegs);
965ca98fd9SDimitry Andric }
975ca98fd9SDimitry Andric 
DecodeCRBITRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)985ca98fd9SDimitry Andric static DecodeStatus DecodeCRBITRCRegisterClass(MCInst &Inst, uint64_t RegNo,
995ca98fd9SDimitry Andric                                                uint64_t Address,
100145449b1SDimitry Andric                                                const MCDisassembler *Decoder) {
1015ca98fd9SDimitry Andric   return decodeRegisterClass(Inst, RegNo, CRBITRegs);
1025ca98fd9SDimitry Andric }
1035ca98fd9SDimitry Andric 
DecodeF4RCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1045ca98fd9SDimitry Andric static DecodeStatus DecodeF4RCRegisterClass(MCInst &Inst, uint64_t RegNo,
1055ca98fd9SDimitry Andric                                             uint64_t Address,
106145449b1SDimitry Andric                                             const MCDisassembler *Decoder) {
1075ca98fd9SDimitry Andric   return decodeRegisterClass(Inst, RegNo, FRegs);
1085ca98fd9SDimitry Andric }
1095ca98fd9SDimitry Andric 
DecodeF8RCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1105ca98fd9SDimitry Andric static DecodeStatus DecodeF8RCRegisterClass(MCInst &Inst, uint64_t RegNo,
1115ca98fd9SDimitry Andric                                             uint64_t Address,
112145449b1SDimitry Andric                                             const MCDisassembler *Decoder) {
1135ca98fd9SDimitry Andric   return decodeRegisterClass(Inst, RegNo, FRegs);
1145ca98fd9SDimitry Andric }
1155ca98fd9SDimitry Andric 
DecodeFpRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1167fa27ce4SDimitry Andric static DecodeStatus DecodeFpRCRegisterClass(MCInst &Inst, uint64_t RegNo,
1177fa27ce4SDimitry Andric                                             uint64_t Address,
1187fa27ce4SDimitry Andric                                             const MCDisassembler *Decoder) {
1197fa27ce4SDimitry Andric   if (RegNo > 30 || (RegNo & 1))
1207fa27ce4SDimitry Andric     return MCDisassembler::Fail;
1217fa27ce4SDimitry Andric   return decodeRegisterClass(Inst, RegNo >> 1, FpRegs);
1227fa27ce4SDimitry Andric }
1237fa27ce4SDimitry Andric 
DecodeVFRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)124b915e9e0SDimitry Andric static DecodeStatus DecodeVFRCRegisterClass(MCInst &Inst, uint64_t RegNo,
125b915e9e0SDimitry Andric                                             uint64_t Address,
126145449b1SDimitry Andric                                             const MCDisassembler *Decoder) {
127b915e9e0SDimitry Andric   return decodeRegisterClass(Inst, RegNo, VFRegs);
128b915e9e0SDimitry Andric }
129b915e9e0SDimitry Andric 
DecodeVRRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1305ca98fd9SDimitry Andric static DecodeStatus DecodeVRRCRegisterClass(MCInst &Inst, uint64_t RegNo,
1315ca98fd9SDimitry Andric                                             uint64_t Address,
132145449b1SDimitry Andric                                             const MCDisassembler *Decoder) {
1335ca98fd9SDimitry Andric   return decodeRegisterClass(Inst, RegNo, VRegs);
1345ca98fd9SDimitry Andric }
1355ca98fd9SDimitry Andric 
DecodeVSRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1365ca98fd9SDimitry Andric static DecodeStatus DecodeVSRCRegisterClass(MCInst &Inst, uint64_t RegNo,
1375ca98fd9SDimitry Andric                                             uint64_t Address,
138145449b1SDimitry Andric                                             const MCDisassembler *Decoder) {
1395ca98fd9SDimitry Andric   return decodeRegisterClass(Inst, RegNo, VSRegs);
1405ca98fd9SDimitry Andric }
1415ca98fd9SDimitry Andric 
DecodeVSFRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1425ca98fd9SDimitry Andric static DecodeStatus DecodeVSFRCRegisterClass(MCInst &Inst, uint64_t RegNo,
1435ca98fd9SDimitry Andric                                              uint64_t Address,
144145449b1SDimitry Andric                                              const MCDisassembler *Decoder) {
1455ca98fd9SDimitry Andric   return decodeRegisterClass(Inst, RegNo, VSFRegs);
1465ca98fd9SDimitry Andric }
1475ca98fd9SDimitry Andric 
DecodeVSSRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1485a5ac124SDimitry Andric static DecodeStatus DecodeVSSRCRegisterClass(MCInst &Inst, uint64_t RegNo,
1495a5ac124SDimitry Andric                                              uint64_t Address,
150145449b1SDimitry Andric                                              const MCDisassembler *Decoder) {
1515a5ac124SDimitry Andric   return decodeRegisterClass(Inst, RegNo, VSSRegs);
1525a5ac124SDimitry Andric }
1535a5ac124SDimitry Andric 
DecodeGPRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1545ca98fd9SDimitry Andric static DecodeStatus DecodeGPRCRegisterClass(MCInst &Inst, uint64_t RegNo,
1555ca98fd9SDimitry Andric                                             uint64_t Address,
156145449b1SDimitry Andric                                             const MCDisassembler *Decoder) {
157d8e91e46SDimitry Andric   return decodeRegisterClass(Inst, RegNo, RRegs);
1585ca98fd9SDimitry Andric }
1595ca98fd9SDimitry Andric 
160145449b1SDimitry Andric static DecodeStatus
DecodeGPRC_NOR0RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)161145449b1SDimitry Andric DecodeGPRC_NOR0RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,
162145449b1SDimitry Andric                              const MCDisassembler *Decoder) {
163d8e91e46SDimitry Andric   return decodeRegisterClass(Inst, RegNo, RRegsNoR0);
1645ca98fd9SDimitry Andric }
1655ca98fd9SDimitry Andric 
DecodeG8RCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1665ca98fd9SDimitry Andric static DecodeStatus DecodeG8RCRegisterClass(MCInst &Inst, uint64_t RegNo,
1675ca98fd9SDimitry Andric                                             uint64_t Address,
168145449b1SDimitry Andric                                             const MCDisassembler *Decoder) {
169d8e91e46SDimitry Andric   return decodeRegisterClass(Inst, RegNo, XRegs);
1705ca98fd9SDimitry Andric }
1715ca98fd9SDimitry Andric 
DecodeG8pRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)172344a3780SDimitry Andric static DecodeStatus DecodeG8pRCRegisterClass(MCInst &Inst, uint64_t RegNo,
173344a3780SDimitry Andric                                              uint64_t Address,
174145449b1SDimitry Andric                                              const MCDisassembler *Decoder) {
175344a3780SDimitry Andric   return decodeRegisterClass(Inst, RegNo, XRegs);
176344a3780SDimitry Andric }
177344a3780SDimitry Andric 
178145449b1SDimitry Andric static DecodeStatus
DecodeG8RC_NOX0RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)179145449b1SDimitry Andric DecodeG8RC_NOX0RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,
180145449b1SDimitry Andric                              const MCDisassembler *Decoder) {
181d8e91e46SDimitry Andric   return decodeRegisterClass(Inst, RegNo, XRegsNoX0);
1826b3f41edSDimitry Andric }
1836b3f41edSDimitry Andric 
1845ca98fd9SDimitry Andric #define DecodePointerLikeRegClass0 DecodeGPRCRegisterClass
1855ca98fd9SDimitry Andric #define DecodePointerLikeRegClass1 DecodeGPRC_NOR0RegisterClass
1865ca98fd9SDimitry Andric 
DecodeSPERCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)187eb11fae6SDimitry Andric static DecodeStatus DecodeSPERCRegisterClass(MCInst &Inst, uint64_t RegNo,
188eb11fae6SDimitry Andric                                              uint64_t Address,
189145449b1SDimitry Andric                                              const MCDisassembler *Decoder) {
190eb11fae6SDimitry Andric   return decodeRegisterClass(Inst, RegNo, SPERegs);
191eb11fae6SDimitry Andric }
192eb11fae6SDimitry Andric 
DecodeACCRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)193b60736ecSDimitry Andric static DecodeStatus DecodeACCRCRegisterClass(MCInst &Inst, uint64_t RegNo,
194b60736ecSDimitry Andric                                              uint64_t Address,
195145449b1SDimitry Andric                                              const MCDisassembler *Decoder) {
196b60736ecSDimitry Andric   return decodeRegisterClass(Inst, RegNo, ACCRegs);
197b60736ecSDimitry Andric }
198b60736ecSDimitry Andric 
DecodeWACCRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)199e3b55780SDimitry Andric static DecodeStatus DecodeWACCRCRegisterClass(MCInst &Inst, uint64_t RegNo,
200e3b55780SDimitry Andric                                               uint64_t Address,
201e3b55780SDimitry Andric                                               const void *Decoder) {
202e3b55780SDimitry Andric   return decodeRegisterClass(Inst, RegNo, WACCRegs);
203e3b55780SDimitry Andric }
204e3b55780SDimitry Andric 
DecodeWACC_HIRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)205e3b55780SDimitry Andric static DecodeStatus DecodeWACC_HIRCRegisterClass(MCInst &Inst, uint64_t RegNo,
206e3b55780SDimitry Andric                                                  uint64_t Address,
207e3b55780SDimitry Andric                                                  const void *Decoder) {
208e3b55780SDimitry Andric   return decodeRegisterClass(Inst, RegNo, WACC_HIRegs);
209e3b55780SDimitry Andric }
210e3b55780SDimitry Andric 
211e3b55780SDimitry Andric // TODO: Make this function static when the register class is used by a new
212e3b55780SDimitry Andric //       instruction.
DecodeDMRROWRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)213e3b55780SDimitry Andric DecodeStatus DecodeDMRROWRCRegisterClass(MCInst &Inst, uint64_t RegNo,
214e3b55780SDimitry Andric                                          uint64_t Address,
215e3b55780SDimitry Andric                                          const void *Decoder) {
216e3b55780SDimitry Andric   return decodeRegisterClass(Inst, RegNo, DMRROWRegs);
217e3b55780SDimitry Andric }
218e3b55780SDimitry Andric 
DecodeDMRROWpRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)219e3b55780SDimitry Andric static DecodeStatus DecodeDMRROWpRCRegisterClass(MCInst &Inst, uint64_t RegNo,
220e3b55780SDimitry Andric                                                  uint64_t Address,
221e3b55780SDimitry Andric                                                  const void *Decoder) {
222e3b55780SDimitry Andric   return decodeRegisterClass(Inst, RegNo, DMRROWpRegs);
223e3b55780SDimitry Andric }
224e3b55780SDimitry Andric 
DecodeDMRRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)225e3b55780SDimitry Andric static DecodeStatus DecodeDMRRCRegisterClass(MCInst &Inst, uint64_t RegNo,
226e3b55780SDimitry Andric                                              uint64_t Address,
227e3b55780SDimitry Andric                                              const void *Decoder) {
228e3b55780SDimitry Andric   return decodeRegisterClass(Inst, RegNo, DMRRegs);
229e3b55780SDimitry Andric }
230e3b55780SDimitry Andric 
231e3b55780SDimitry Andric // TODO: Make this function static when the register class is used by a new
232e3b55780SDimitry Andric //       instruction.
DecodeDMRpRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)233e3b55780SDimitry Andric DecodeStatus DecodeDMRpRCRegisterClass(MCInst &Inst, uint64_t RegNo,
234e3b55780SDimitry Andric                                        uint64_t Address, const void *Decoder) {
235e3b55780SDimitry Andric   return decodeRegisterClass(Inst, RegNo, DMRpRegs);
236e3b55780SDimitry Andric }
237e3b55780SDimitry Andric 
DecodeVSRpRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)238b60736ecSDimitry Andric static DecodeStatus DecodeVSRpRCRegisterClass(MCInst &Inst, uint64_t RegNo,
239b60736ecSDimitry Andric                                               uint64_t Address,
240145449b1SDimitry Andric                                               const MCDisassembler *Decoder) {
241b60736ecSDimitry Andric   return decodeRegisterClass(Inst, RegNo, VSRpRegs);
242b60736ecSDimitry Andric }
243b60736ecSDimitry Andric 
2445a5ac124SDimitry Andric #define DecodeQSRCRegisterClass DecodeQFRCRegisterClass
2455a5ac124SDimitry Andric #define DecodeQBRCRegisterClass DecodeQFRCRegisterClass
2465a5ac124SDimitry Andric 
2475ca98fd9SDimitry Andric template <unsigned N>
decodeUImmOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)2485ca98fd9SDimitry Andric static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm,
249145449b1SDimitry Andric                                       int64_t Address,
250145449b1SDimitry Andric                                       const MCDisassembler *Decoder) {
2517fa27ce4SDimitry Andric   if (!isUInt<N>(Imm))
2527fa27ce4SDimitry Andric     return MCDisassembler::Fail;
2535a5ac124SDimitry Andric   Inst.addOperand(MCOperand::createImm(Imm));
2545ca98fd9SDimitry Andric   return MCDisassembler::Success;
2555ca98fd9SDimitry Andric }
2565ca98fd9SDimitry Andric 
2575ca98fd9SDimitry Andric template <unsigned N>
decodeSImmOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)2585ca98fd9SDimitry Andric static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm,
259145449b1SDimitry Andric                                       int64_t Address,
260145449b1SDimitry Andric                                       const MCDisassembler *Decoder) {
2617fa27ce4SDimitry Andric   if (!isUInt<N>(Imm))
2627fa27ce4SDimitry Andric     return MCDisassembler::Fail;
2635a5ac124SDimitry Andric   Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm)));
2645ca98fd9SDimitry Andric   return MCDisassembler::Success;
2655ca98fd9SDimitry Andric }
2665ca98fd9SDimitry Andric 
decodeImmZeroOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)267cfca06d7SDimitry Andric static DecodeStatus decodeImmZeroOperand(MCInst &Inst, uint64_t Imm,
268145449b1SDimitry Andric                                          int64_t Address,
269145449b1SDimitry Andric                                          const MCDisassembler *Decoder) {
270cfca06d7SDimitry Andric   if (Imm != 0)
271cfca06d7SDimitry Andric     return MCDisassembler::Fail;
272cfca06d7SDimitry Andric   Inst.addOperand(MCOperand::createImm(Imm));
273cfca06d7SDimitry Andric   return MCDisassembler::Success;
274cfca06d7SDimitry Andric }
275cfca06d7SDimitry Andric 
decodeVSRpEvenOperands(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)276b60736ecSDimitry Andric static DecodeStatus decodeVSRpEvenOperands(MCInst &Inst, uint64_t RegNo,
277b60736ecSDimitry Andric                                            uint64_t Address,
278145449b1SDimitry Andric                                            const MCDisassembler *Decoder) {
279b60736ecSDimitry Andric   if (RegNo & 1)
280b60736ecSDimitry Andric     return MCDisassembler::Fail;
281b60736ecSDimitry Andric   Inst.addOperand(MCOperand::createReg(VSRpRegs[RegNo >> 1]));
282b60736ecSDimitry Andric   return MCDisassembler::Success;
283b60736ecSDimitry Andric }
284b60736ecSDimitry Andric 
decodeDispRIXOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)2857fa27ce4SDimitry Andric static DecodeStatus decodeDispRIXOperand(MCInst &Inst, uint64_t Imm,
286145449b1SDimitry Andric                                          int64_t Address,
287145449b1SDimitry Andric                                          const MCDisassembler *Decoder) {
2887fa27ce4SDimitry Andric   // The rix displacement is an immediate shifted by 2
2897fa27ce4SDimitry Andric   Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Imm << 2)));
2905ca98fd9SDimitry Andric   return MCDisassembler::Success;
2915ca98fd9SDimitry Andric }
2925ca98fd9SDimitry Andric 
decodeDispRIHashOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)2937fa27ce4SDimitry Andric static DecodeStatus decodeDispRIHashOperand(MCInst &Inst, uint64_t Imm,
294145449b1SDimitry Andric                                             int64_t Address,
295145449b1SDimitry Andric                                             const MCDisassembler *Decoder) {
2967fa27ce4SDimitry Andric   // Decode the disp field for a hash store or hash check operation.
2977fa27ce4SDimitry Andric   // The field is composed of an immediate value that is 6 bits
298344a3780SDimitry Andric   // and covers the range -8 to -512. The immediate is always negative and 2s
299344a3780SDimitry Andric   // complement which is why we sign extend a 7 bit value.
300344a3780SDimitry Andric   const int64_t Disp = SignExtend64<7>((Imm & 0x3F) + 64) * 8;
301344a3780SDimitry Andric 
302344a3780SDimitry Andric   Inst.addOperand(MCOperand::createImm(Disp));
303344a3780SDimitry Andric   return MCDisassembler::Success;
304344a3780SDimitry Andric }
305344a3780SDimitry Andric 
decodeDispRIX16Operand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)3067fa27ce4SDimitry Andric static DecodeStatus decodeDispRIX16Operand(MCInst &Inst, uint64_t Imm,
307145449b1SDimitry Andric                                            int64_t Address,
308145449b1SDimitry Andric                                            const MCDisassembler *Decoder) {
3097fa27ce4SDimitry Andric   // The rix16 displacement has 12-bits which are shifted by 4.
3107fa27ce4SDimitry Andric   Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Imm << 4)));
31101095a5dSDimitry Andric   return MCDisassembler::Success;
31201095a5dSDimitry Andric }
31301095a5dSDimitry Andric 
decodeDispSPE8Operand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)3147fa27ce4SDimitry Andric static DecodeStatus decodeDispSPE8Operand(MCInst &Inst, uint64_t Imm,
315cfca06d7SDimitry Andric                                           int64_t Address,
316145449b1SDimitry Andric                                           const MCDisassembler *Decoder) {
3177fa27ce4SDimitry Andric   // Decode the dispSPE8 field, which has 5-bits, 8-byte aligned.
318cfca06d7SDimitry Andric 
319eb11fae6SDimitry Andric   uint64_t Disp = Imm & 0x1F;
320eb11fae6SDimitry Andric 
321eb11fae6SDimitry Andric   Inst.addOperand(MCOperand::createImm(Disp << 3));
322eb11fae6SDimitry Andric   return MCDisassembler::Success;
323eb11fae6SDimitry Andric }
324eb11fae6SDimitry Andric 
decodeDispSPE4Operand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)3257fa27ce4SDimitry Andric static DecodeStatus decodeDispSPE4Operand(MCInst &Inst, uint64_t Imm,
326145449b1SDimitry Andric                                           int64_t Address,
327145449b1SDimitry Andric                                           const MCDisassembler *Decoder) {
3287fa27ce4SDimitry Andric   // Decode the dispSPE8 field, which has 5-bits, 4-byte aligned.
329eb11fae6SDimitry Andric 
330eb11fae6SDimitry Andric   uint64_t Disp = Imm & 0x1F;
331eb11fae6SDimitry Andric 
332eb11fae6SDimitry Andric   Inst.addOperand(MCOperand::createImm(Disp << 2));
333eb11fae6SDimitry Andric   return MCDisassembler::Success;
334eb11fae6SDimitry Andric }
335eb11fae6SDimitry Andric 
decodeDispSPE2Operand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)3367fa27ce4SDimitry Andric static DecodeStatus decodeDispSPE2Operand(MCInst &Inst, uint64_t Imm,
337145449b1SDimitry Andric                                           int64_t Address,
338145449b1SDimitry Andric                                           const MCDisassembler *Decoder) {
3397fa27ce4SDimitry Andric   // Decode the dispSPE8 field, which has 5-bits, 2-byte aligned.
340eb11fae6SDimitry Andric 
341eb11fae6SDimitry Andric   uint64_t Disp = Imm & 0x1F;
342eb11fae6SDimitry Andric   Inst.addOperand(MCOperand::createImm(Disp << 1));
343eb11fae6SDimitry Andric   return MCDisassembler::Success;
344eb11fae6SDimitry Andric }
345eb11fae6SDimitry Andric 
decodeCRBitMOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)3465ca98fd9SDimitry Andric static DecodeStatus decodeCRBitMOperand(MCInst &Inst, uint64_t Imm,
347145449b1SDimitry Andric                                         int64_t Address,
348145449b1SDimitry Andric                                         const MCDisassembler *Decoder) {
3495ca98fd9SDimitry Andric   // The cr bit encoding is 0x80 >> cr_reg_num.
3505ca98fd9SDimitry Andric 
3517fa27ce4SDimitry Andric   unsigned Zeros = llvm::countr_zero(Imm);
3527fa27ce4SDimitry Andric   if (Zeros >= 8)
3537fa27ce4SDimitry Andric     return MCDisassembler::Fail;
3545ca98fd9SDimitry Andric 
3555a5ac124SDimitry Andric   Inst.addOperand(MCOperand::createReg(CRRegs[7 - Zeros]));
3565ca98fd9SDimitry Andric   return MCDisassembler::Success;
3575ca98fd9SDimitry Andric }
3585ca98fd9SDimitry Andric 
3595ca98fd9SDimitry Andric #include "PPCGenDisassemblerTables.inc"
3605ca98fd9SDimitry Andric 
getInstruction(MCInst & MI,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & CS) const3615ca98fd9SDimitry Andric DecodeStatus PPCDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
36267c32a98SDimitry Andric                                              ArrayRef<uint8_t> Bytes,
363706b4fc4SDimitry Andric                                              uint64_t Address,
36467c32a98SDimitry Andric                                              raw_ostream &CS) const {
365cfca06d7SDimitry Andric   auto *ReadFunc = IsLittleEndian ? support::endian::read32le
366cfca06d7SDimitry Andric                                   : support::endian::read32be;
367cfca06d7SDimitry Andric 
368cfca06d7SDimitry Andric   // If this is an 8-byte prefixed instruction, handle it here.
369cfca06d7SDimitry Andric   // Note: prefixed instructions aren't technically 8-byte entities - the prefix
370cfca06d7SDimitry Andric   //       appears in memory at an address 4 bytes prior to that of the base
371cfca06d7SDimitry Andric   //       instruction regardless of endianness. So we read the two pieces and
372cfca06d7SDimitry Andric   //       rebuild the 8-byte instruction.
373cfca06d7SDimitry Andric   // TODO: In this function we call decodeInstruction several times with
374cfca06d7SDimitry Andric   //       different decoder tables. It may be possible to only call once by
375cfca06d7SDimitry Andric   //       looking at the top 6 bits of the instruction.
3767fa27ce4SDimitry Andric   if (STI.hasFeature(PPC::FeaturePrefixInstrs) && Bytes.size() >= 8) {
377cfca06d7SDimitry Andric     uint32_t Prefix = ReadFunc(Bytes.data());
378cfca06d7SDimitry Andric     uint32_t BaseInst = ReadFunc(Bytes.data() + 4);
379cfca06d7SDimitry Andric     uint64_t Inst = BaseInst | (uint64_t)Prefix << 32;
380cfca06d7SDimitry Andric     DecodeStatus result = decodeInstruction(DecoderTable64, MI, Inst, Address,
381cfca06d7SDimitry Andric                                             this, STI);
382cfca06d7SDimitry Andric     if (result != MCDisassembler::Fail) {
383cfca06d7SDimitry Andric       Size = 8;
384cfca06d7SDimitry Andric       return result;
385cfca06d7SDimitry Andric     }
386cfca06d7SDimitry Andric   }
387cfca06d7SDimitry Andric 
3885ca98fd9SDimitry Andric   // Get the four bytes of the instruction.
3895ca98fd9SDimitry Andric   Size = 4;
39067c32a98SDimitry Andric   if (Bytes.size() < 4) {
3915ca98fd9SDimitry Andric     Size = 0;
3925ca98fd9SDimitry Andric     return MCDisassembler::Fail;
3935ca98fd9SDimitry Andric   }
3945ca98fd9SDimitry Andric 
39569156b4cSDimitry Andric   // Read the instruction in the proper endianness.
396cfca06d7SDimitry Andric   uint64_t Inst = ReadFunc(Bytes.data());
3975ca98fd9SDimitry Andric 
3987fa27ce4SDimitry Andric   if (STI.hasFeature(PPC::FeatureSPE)) {
399eb11fae6SDimitry Andric     DecodeStatus result =
400eb11fae6SDimitry Andric         decodeInstruction(DecoderTableSPE32, MI, Inst, Address, this, STI);
401eb11fae6SDimitry Andric     if (result != MCDisassembler::Fail)
402eb11fae6SDimitry Andric       return result;
4035a5ac124SDimitry Andric   }
4045a5ac124SDimitry Andric 
4055ca98fd9SDimitry Andric   return decodeInstruction(DecoderTable32, MI, Inst, Address, this, STI);
4065ca98fd9SDimitry Andric }
407