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