12345347eSHal Finkel //===------ PPCDisassembler.cpp - Disassembler for PowerPC ------*- C++ -*-===//
22345347eSHal Finkel //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62345347eSHal Finkel //
72345347eSHal Finkel //===----------------------------------------------------------------------===//
82345347eSHal Finkel
927c769d2SBenjamin Kramer #include "MCTargetDesc/PPCMCTargetDesc.h"
10ee6ced19SRichard Trieu #include "TargetInfo/PowerPCTargetInfo.h"
11*c644488aSSheng #include "llvm/MC/MCDecoderOps.h"
12f57c1977SBenjamin Kramer #include "llvm/MC/MCDisassembler/MCDisassembler.h"
132345347eSHal Finkel #include "llvm/MC/MCInst.h"
142345347eSHal Finkel #include "llvm/MC/MCSubtargetInfo.h"
1589b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
16c11fd3e7SBenjamin Kramer #include "llvm/Support/Endian.h"
172345347eSHal Finkel
182345347eSHal Finkel using namespace llvm;
192345347eSHal Finkel
200dad994aSNemanja Ivanovic DEFINE_PPC_REGCLASSES;
210dad994aSNemanja Ivanovic
22e96dd897SChandler Carruth #define DEBUG_TYPE "ppc-disassembler"
23e96dd897SChandler Carruth
242345347eSHal Finkel typedef MCDisassembler::DecodeStatus DecodeStatus;
252345347eSHal Finkel
262345347eSHal Finkel namespace {
272345347eSHal Finkel class PPCDisassembler : public MCDisassembler {
28c11fd3e7SBenjamin Kramer bool IsLittleEndian;
29c11fd3e7SBenjamin Kramer
302345347eSHal Finkel public:
PPCDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx,bool IsLittleEndian)31c11fd3e7SBenjamin Kramer PPCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
32c11fd3e7SBenjamin Kramer bool IsLittleEndian)
33c11fd3e7SBenjamin Kramer : MCDisassembler(STI, Ctx), IsLittleEndian(IsLittleEndian) {}
342345347eSHal Finkel
354aa6bea7SRafael Espindola DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
367fc5b874SRafael Espindola ArrayRef<uint8_t> Bytes, uint64_t Address,
374aa6bea7SRafael Espindola raw_ostream &CStream) const override;
382345347eSHal Finkel };
392345347eSHal Finkel } // end anonymous namespace
402345347eSHal Finkel
createPPCDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)412345347eSHal Finkel static MCDisassembler *createPPCDisassembler(const Target &T,
42a1bc0f56SLang Hames const MCSubtargetInfo &STI,
43a1bc0f56SLang Hames MCContext &Ctx) {
44c11fd3e7SBenjamin Kramer return new PPCDisassembler(STI, Ctx, /*IsLittleEndian=*/false);
45c11fd3e7SBenjamin Kramer }
46c11fd3e7SBenjamin Kramer
createPPCLEDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)47c11fd3e7SBenjamin Kramer static MCDisassembler *createPPCLEDisassembler(const Target &T,
48c11fd3e7SBenjamin Kramer const MCSubtargetInfo &STI,
49c11fd3e7SBenjamin Kramer MCContext &Ctx) {
50c11fd3e7SBenjamin Kramer return new PPCDisassembler(STI, Ctx, /*IsLittleEndian=*/true);
512345347eSHal Finkel }
522345347eSHal Finkel
LLVMInitializePowerPCDisassembler()530dbcb363STom Stellard extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCDisassembler() {
542345347eSHal Finkel // Register the disassembler for each target.
55f42454b9SMehdi Amini TargetRegistry::RegisterMCDisassembler(getThePPC32Target(),
562345347eSHal Finkel createPPCDisassembler);
578f004471SBrandon Bergren TargetRegistry::RegisterMCDisassembler(getThePPC32LETarget(),
588f004471SBrandon Bergren createPPCLEDisassembler);
59f42454b9SMehdi Amini TargetRegistry::RegisterMCDisassembler(getThePPC64Target(),
602345347eSHal Finkel createPPCDisassembler);
61f42454b9SMehdi Amini TargetRegistry::RegisterMCDisassembler(getThePPC64LETarget(),
62c11fd3e7SBenjamin Kramer createPPCLEDisassembler);
632345347eSHal Finkel }
642345347eSHal Finkel
decodeCondBrTarget(MCInst & Inst,unsigned Imm,uint64_t,const MCDisassembler *)654af7560bSFangrui Song static DecodeStatus decodeCondBrTarget(MCInst &Inst, unsigned Imm,
664af7560bSFangrui Song uint64_t /*Address*/,
674ae9745aSMaksim Panchenko const MCDisassembler * /*Decoder*/) {
684af7560bSFangrui Song Inst.addOperand(MCOperand::createImm(SignExtend32<14>(Imm)));
694af7560bSFangrui Song return MCDisassembler::Success;
704af7560bSFangrui Song }
714af7560bSFangrui Song
decodeDirectBrTarget(MCInst & Inst,unsigned Imm,uint64_t,const MCDisassembler *)7285adce3dSFangrui Song static DecodeStatus decodeDirectBrTarget(MCInst &Inst, unsigned Imm,
7385adce3dSFangrui Song uint64_t /*Address*/,
744ae9745aSMaksim Panchenko const MCDisassembler * /*Decoder*/) {
75c0694520SSean Fertile int32_t Offset = SignExtend32<24>(Imm);
76c0694520SSean Fertile Inst.addOperand(MCOperand::createImm(Offset));
77c0694520SSean Fertile return MCDisassembler::Success;
78c0694520SSean Fertile }
79c0694520SSean Fertile
802345347eSHal Finkel // FIXME: These can be generated by TableGen from the existing register
812345347eSHal Finkel // encoding values!
822345347eSHal Finkel
832345347eSHal Finkel template <std::size_t N>
decodeRegisterClass(MCInst & Inst,uint64_t RegNo,const MCPhysReg (& Regs)[N])842345347eSHal Finkel static DecodeStatus decodeRegisterClass(MCInst &Inst, uint64_t RegNo,
850dad994aSNemanja Ivanovic const MCPhysReg (&Regs)[N]) {
862345347eSHal Finkel assert(RegNo < N && "Invalid register number");
87e9119e41SJim Grosbach Inst.addOperand(MCOperand::createReg(Regs[RegNo]));
882345347eSHal Finkel return MCDisassembler::Success;
892345347eSHal Finkel }
902345347eSHal Finkel
DecodeCRRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)912345347eSHal Finkel static DecodeStatus DecodeCRRCRegisterClass(MCInst &Inst, uint64_t RegNo,
922345347eSHal Finkel uint64_t Address,
934ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
942345347eSHal Finkel return decodeRegisterClass(Inst, RegNo, CRRegs);
952345347eSHal Finkel }
962345347eSHal Finkel
DecodeCRBITRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)972345347eSHal Finkel static DecodeStatus DecodeCRBITRCRegisterClass(MCInst &Inst, uint64_t RegNo,
982345347eSHal Finkel uint64_t Address,
994ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1002345347eSHal Finkel return decodeRegisterClass(Inst, RegNo, CRBITRegs);
1012345347eSHal Finkel }
1022345347eSHal Finkel
DecodeF4RCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1032345347eSHal Finkel static DecodeStatus DecodeF4RCRegisterClass(MCInst &Inst, uint64_t RegNo,
1042345347eSHal Finkel uint64_t Address,
1054ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1062345347eSHal Finkel return decodeRegisterClass(Inst, RegNo, FRegs);
1072345347eSHal Finkel }
1082345347eSHal Finkel
DecodeF8RCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1092345347eSHal Finkel static DecodeStatus DecodeF8RCRegisterClass(MCInst &Inst, uint64_t RegNo,
1102345347eSHal Finkel uint64_t Address,
1114ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1122345347eSHal Finkel return decodeRegisterClass(Inst, RegNo, FRegs);
1132345347eSHal Finkel }
1142345347eSHal Finkel
DecodeVFRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)11511049f8fSNemanja Ivanovic static DecodeStatus DecodeVFRCRegisterClass(MCInst &Inst, uint64_t RegNo,
11611049f8fSNemanja Ivanovic uint64_t Address,
1174ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
11811049f8fSNemanja Ivanovic return decodeRegisterClass(Inst, RegNo, VFRegs);
11911049f8fSNemanja Ivanovic }
12011049f8fSNemanja Ivanovic
DecodeVRRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1212345347eSHal Finkel static DecodeStatus DecodeVRRCRegisterClass(MCInst &Inst, uint64_t RegNo,
1222345347eSHal Finkel uint64_t Address,
1234ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1242345347eSHal Finkel return decodeRegisterClass(Inst, RegNo, VRegs);
1252345347eSHal Finkel }
1262345347eSHal Finkel
DecodeVSRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)12727774d92SHal Finkel static DecodeStatus DecodeVSRCRegisterClass(MCInst &Inst, uint64_t RegNo,
12827774d92SHal Finkel uint64_t Address,
1294ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
13027774d92SHal Finkel return decodeRegisterClass(Inst, RegNo, VSRegs);
13127774d92SHal Finkel }
13227774d92SHal Finkel
DecodeVSFRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)13319be506aSHal Finkel static DecodeStatus DecodeVSFRCRegisterClass(MCInst &Inst, uint64_t RegNo,
13419be506aSHal Finkel uint64_t Address,
1354ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
13619be506aSHal Finkel return decodeRegisterClass(Inst, RegNo, VSFRegs);
13719be506aSHal Finkel }
13819be506aSHal Finkel
DecodeVSSRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)139f3c94b1eSNemanja Ivanovic static DecodeStatus DecodeVSSRCRegisterClass(MCInst &Inst, uint64_t RegNo,
140f3c94b1eSNemanja Ivanovic uint64_t Address,
1414ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
142f3c94b1eSNemanja Ivanovic return decodeRegisterClass(Inst, RegNo, VSSRegs);
143f3c94b1eSNemanja Ivanovic }
144f3c94b1eSNemanja Ivanovic
DecodeGPRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1452345347eSHal Finkel static DecodeStatus DecodeGPRCRegisterClass(MCInst &Inst, uint64_t RegNo,
1462345347eSHal Finkel uint64_t Address,
1474ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1480dad994aSNemanja Ivanovic return decodeRegisterClass(Inst, RegNo, RRegs);
1492345347eSHal Finkel }
1502345347eSHal Finkel
1514ae9745aSMaksim Panchenko static DecodeStatus
DecodeGPRC_NOR0RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1524ae9745aSMaksim Panchenko DecodeGPRC_NOR0RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,
1534ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1540dad994aSNemanja Ivanovic return decodeRegisterClass(Inst, RegNo, RRegsNoR0);
1552345347eSHal Finkel }
1562345347eSHal Finkel
DecodeG8RCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1572345347eSHal Finkel static DecodeStatus DecodeG8RCRegisterClass(MCInst &Inst, uint64_t RegNo,
1582345347eSHal Finkel uint64_t Address,
1594ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1600dad994aSNemanja Ivanovic return decodeRegisterClass(Inst, RegNo, XRegs);
1612345347eSHal Finkel }
1622345347eSHal Finkel
DecodeG8pRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1631c450c3dSKai Luo static DecodeStatus DecodeG8pRCRegisterClass(MCInst &Inst, uint64_t RegNo,
1641c450c3dSKai Luo uint64_t Address,
1654ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1661c450c3dSKai Luo return decodeRegisterClass(Inst, RegNo, XRegs);
1671c450c3dSKai Luo }
1681c450c3dSKai Luo
1694ae9745aSMaksim Panchenko static DecodeStatus
DecodeG8RC_NOX0RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1704ae9745aSMaksim Panchenko DecodeG8RC_NOX0RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,
1714ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1720dad994aSNemanja Ivanovic return decodeRegisterClass(Inst, RegNo, XRegsNoX0);
17322e7da95SGuozhi Wei }
17422e7da95SGuozhi Wei
1752345347eSHal Finkel #define DecodePointerLikeRegClass0 DecodeGPRCRegisterClass
1762345347eSHal Finkel #define DecodePointerLikeRegClass1 DecodeGPRC_NOR0RegisterClass
1772345347eSHal Finkel
DecodeSPERCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)178d52990c7SJustin Hibbits static DecodeStatus DecodeSPERCRegisterClass(MCInst &Inst, uint64_t RegNo,
179d52990c7SJustin Hibbits uint64_t Address,
1804ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
181d52990c7SJustin Hibbits return decodeRegisterClass(Inst, RegNo, SPERegs);
182d52990c7SJustin Hibbits }
183d52990c7SJustin Hibbits
DecodeACCRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1849b86b700SBaptiste Saleil static DecodeStatus DecodeACCRCRegisterClass(MCInst &Inst, uint64_t RegNo,
1859b86b700SBaptiste Saleil uint64_t Address,
1864ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1879b86b700SBaptiste Saleil return decodeRegisterClass(Inst, RegNo, ACCRegs);
1889b86b700SBaptiste Saleil }
1899b86b700SBaptiste Saleil
DecodeVSRpRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1901372e23cSBaptiste Saleil static DecodeStatus DecodeVSRpRCRegisterClass(MCInst &Inst, uint64_t RegNo,
1911372e23cSBaptiste Saleil uint64_t Address,
1924ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1931372e23cSBaptiste Saleil return decodeRegisterClass(Inst, RegNo, VSRpRegs);
1941372e23cSBaptiste Saleil }
1951372e23cSBaptiste Saleil
196c93a9a2cSHal Finkel #define DecodeQSRCRegisterClass DecodeQFRCRegisterClass
197c93a9a2cSHal Finkel #define DecodeQBRCRegisterClass DecodeQFRCRegisterClass
198c93a9a2cSHal Finkel
1992345347eSHal Finkel template <unsigned N>
decodeUImmOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)2002345347eSHal Finkel static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm,
2014ae9745aSMaksim Panchenko int64_t Address,
2024ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
2032345347eSHal Finkel assert(isUInt<N>(Imm) && "Invalid immediate");
204e9119e41SJim Grosbach Inst.addOperand(MCOperand::createImm(Imm));
2052345347eSHal Finkel return MCDisassembler::Success;
2062345347eSHal Finkel }
2072345347eSHal Finkel
2082345347eSHal Finkel template <unsigned N>
decodeSImmOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)2092345347eSHal Finkel static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm,
2104ae9745aSMaksim Panchenko int64_t Address,
2114ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
2122345347eSHal Finkel assert(isUInt<N>(Imm) && "Invalid immediate");
213e9119e41SJim Grosbach Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm)));
2142345347eSHal Finkel return MCDisassembler::Success;
2152345347eSHal Finkel }
2162345347eSHal Finkel
decodeImmZeroOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)2175cee3401SVictor Huang static DecodeStatus decodeImmZeroOperand(MCInst &Inst, uint64_t Imm,
2184ae9745aSMaksim Panchenko int64_t Address,
2194ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
2205cee3401SVictor Huang if (Imm != 0)
2215cee3401SVictor Huang return MCDisassembler::Fail;
2225cee3401SVictor Huang Inst.addOperand(MCOperand::createImm(Imm));
2235cee3401SVictor Huang return MCDisassembler::Success;
2245cee3401SVictor Huang }
2255cee3401SVictor Huang
decodeVSRpEvenOperands(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)22666d2e3f4SAhsan Saghir static DecodeStatus decodeVSRpEvenOperands(MCInst &Inst, uint64_t RegNo,
22766d2e3f4SAhsan Saghir uint64_t Address,
2284ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
22966d2e3f4SAhsan Saghir if (RegNo & 1)
23066d2e3f4SAhsan Saghir return MCDisassembler::Fail;
23166d2e3f4SAhsan Saghir Inst.addOperand(MCOperand::createReg(VSRpRegs[RegNo >> 1]));
23266d2e3f4SAhsan Saghir return MCDisassembler::Success;
23366d2e3f4SAhsan Saghir }
23466d2e3f4SAhsan Saghir
decodeMemRIOperands(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)2352345347eSHal Finkel static DecodeStatus decodeMemRIOperands(MCInst &Inst, uint64_t Imm,
2364ae9745aSMaksim Panchenko int64_t Address,
2374ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
2382345347eSHal Finkel // Decode the memri field (imm, reg), which has the low 16-bits as the
2392345347eSHal Finkel // displacement and the next 5 bits as the register #.
2402345347eSHal Finkel
2412345347eSHal Finkel uint64_t Base = Imm >> 16;
2422345347eSHal Finkel uint64_t Disp = Imm & 0xFFFF;
2432345347eSHal Finkel
2442345347eSHal Finkel assert(Base < 32 && "Invalid base register");
2452345347eSHal Finkel
2462345347eSHal Finkel switch (Inst.getOpcode()) {
2472345347eSHal Finkel default: break;
2482345347eSHal Finkel case PPC::LBZU:
2492345347eSHal Finkel case PPC::LHAU:
2502345347eSHal Finkel case PPC::LHZU:
2512345347eSHal Finkel case PPC::LWZU:
2522345347eSHal Finkel case PPC::LFSU:
2532345347eSHal Finkel case PPC::LFDU:
2542345347eSHal Finkel // Add the tied output operand.
2550dad994aSNemanja Ivanovic Inst.addOperand(MCOperand::createReg(RRegsNoR0[Base]));
2562345347eSHal Finkel break;
2572345347eSHal Finkel case PPC::STBU:
2582345347eSHal Finkel case PPC::STHU:
2592345347eSHal Finkel case PPC::STWU:
2602345347eSHal Finkel case PPC::STFSU:
2612345347eSHal Finkel case PPC::STFDU:
2620dad994aSNemanja Ivanovic Inst.insert(Inst.begin(), MCOperand::createReg(RRegsNoR0[Base]));
2632345347eSHal Finkel break;
2642345347eSHal Finkel }
2652345347eSHal Finkel
266e9119e41SJim Grosbach Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Disp)));
2670dad994aSNemanja Ivanovic Inst.addOperand(MCOperand::createReg(RRegsNoR0[Base]));
2682345347eSHal Finkel return MCDisassembler::Success;
2692345347eSHal Finkel }
2702345347eSHal Finkel
decodeMemRIXOperands(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)2712345347eSHal Finkel static DecodeStatus decodeMemRIXOperands(MCInst &Inst, uint64_t Imm,
2724ae9745aSMaksim Panchenko int64_t Address,
2734ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
2742345347eSHal Finkel // Decode the memrix field (imm, reg), which has the low 14-bits as the
2752345347eSHal Finkel // displacement and the next 5 bits as the register #.
2762345347eSHal Finkel
2772345347eSHal Finkel uint64_t Base = Imm >> 14;
2782345347eSHal Finkel uint64_t Disp = Imm & 0x3FFF;
2792345347eSHal Finkel
2802345347eSHal Finkel assert(Base < 32 && "Invalid base register");
2812345347eSHal Finkel
2822345347eSHal Finkel if (Inst.getOpcode() == PPC::LDU)
2832345347eSHal Finkel // Add the tied output operand.
2840dad994aSNemanja Ivanovic Inst.addOperand(MCOperand::createReg(RRegsNoR0[Base]));
2852345347eSHal Finkel else if (Inst.getOpcode() == PPC::STDU)
2860dad994aSNemanja Ivanovic Inst.insert(Inst.begin(), MCOperand::createReg(RRegsNoR0[Base]));
2872345347eSHal Finkel
288e9119e41SJim Grosbach Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Disp << 2)));
2890dad994aSNemanja Ivanovic Inst.addOperand(MCOperand::createReg(RRegsNoR0[Base]));
2902345347eSHal Finkel return MCDisassembler::Success;
2912345347eSHal Finkel }
2922345347eSHal Finkel
decodeMemRIHashOperands(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)293f28cb01bSStefan Pintilie static DecodeStatus decodeMemRIHashOperands(MCInst &Inst, uint64_t Imm,
294f28cb01bSStefan Pintilie int64_t Address,
2954ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
296f28cb01bSStefan Pintilie // Decode the memrix field for a hash store or hash check operation.
297f28cb01bSStefan Pintilie // The field is composed of a register and an immediate value that is 6 bits
298f28cb01bSStefan Pintilie // and covers the range -8 to -512. The immediate is always negative and 2s
299f28cb01bSStefan Pintilie // complement which is why we sign extend a 7 bit value.
300f28cb01bSStefan Pintilie const uint64_t Base = Imm >> 6;
301f28cb01bSStefan Pintilie const int64_t Disp = SignExtend64<7>((Imm & 0x3F) + 64) * 8;
302f28cb01bSStefan Pintilie
303f28cb01bSStefan Pintilie assert(Base < 32 && "Invalid base register");
304f28cb01bSStefan Pintilie
305f28cb01bSStefan Pintilie Inst.addOperand(MCOperand::createImm(Disp));
306f28cb01bSStefan Pintilie Inst.addOperand(MCOperand::createReg(RRegs[Base]));
307f28cb01bSStefan Pintilie return MCDisassembler::Success;
308f28cb01bSStefan Pintilie }
309f28cb01bSStefan Pintilie
decodeMemRIX16Operands(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)310ba532dc8SKit Barton static DecodeStatus decodeMemRIX16Operands(MCInst &Inst, uint64_t Imm,
3114ae9745aSMaksim Panchenko int64_t Address,
3124ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
313ba532dc8SKit Barton // Decode the memrix16 field (imm, reg), which has the low 12-bits as the
314ba532dc8SKit Barton // displacement with 16-byte aligned, and the next 5 bits as the register #.
315ba532dc8SKit Barton
316ba532dc8SKit Barton uint64_t Base = Imm >> 12;
317ba532dc8SKit Barton uint64_t Disp = Imm & 0xFFF;
318ba532dc8SKit Barton
319ba532dc8SKit Barton assert(Base < 32 && "Invalid base register");
320ba532dc8SKit Barton
321ba532dc8SKit Barton Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Disp << 4)));
3220dad994aSNemanja Ivanovic Inst.addOperand(MCOperand::createReg(RRegsNoR0[Base]));
323ba532dc8SKit Barton return MCDisassembler::Success;
324ba532dc8SKit Barton }
325ba532dc8SKit Barton
decodeMemRI34PCRelOperands(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)3264b414d9aSVictor Huang static DecodeStatus decodeMemRI34PCRelOperands(MCInst &Inst, uint64_t Imm,
3274b414d9aSVictor Huang int64_t Address,
3284ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
3294b414d9aSVictor Huang // Decode the memri34_pcrel field (imm, reg), which has the low 34-bits as the
3304b414d9aSVictor Huang // displacement, and the next 5 bits as an immediate 0.
3314b414d9aSVictor Huang uint64_t Base = Imm >> 34;
3324b414d9aSVictor Huang uint64_t Disp = Imm & 0x3FFFFFFFFUL;
3334b414d9aSVictor Huang
3344b414d9aSVictor Huang assert(Base < 32 && "Invalid base register");
3354b414d9aSVictor Huang
3364b414d9aSVictor Huang Inst.addOperand(MCOperand::createImm(SignExtend64<34>(Disp)));
3374b414d9aSVictor Huang return decodeImmZeroOperand(Inst, Base, Address, Decoder);
3384b414d9aSVictor Huang }
3394b414d9aSVictor Huang
decodeMemRI34Operands(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)3404b414d9aSVictor Huang static DecodeStatus decodeMemRI34Operands(MCInst &Inst, uint64_t Imm,
3414b414d9aSVictor Huang int64_t Address,
3424ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
3434b414d9aSVictor Huang // Decode the memri34 field (imm, reg), which has the low 34-bits as the
3444b414d9aSVictor Huang // displacement, and the next 5 bits as the register #.
3454b414d9aSVictor Huang uint64_t Base = Imm >> 34;
3464b414d9aSVictor Huang uint64_t Disp = Imm & 0x3FFFFFFFFUL;
3474b414d9aSVictor Huang
3484b414d9aSVictor Huang assert(Base < 32 && "Invalid base register");
3494b414d9aSVictor Huang
3504b414d9aSVictor Huang Inst.addOperand(MCOperand::createImm(SignExtend64<34>(Disp)));
3514b414d9aSVictor Huang Inst.addOperand(MCOperand::createReg(RRegsNoR0[Base]));
3524b414d9aSVictor Huang return MCDisassembler::Success;
3534b414d9aSVictor Huang }
3544b414d9aSVictor Huang
decodeSPE8Operands(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)3554fa4fa6aSJustin Hibbits static DecodeStatus decodeSPE8Operands(MCInst &Inst, uint64_t Imm,
3564ae9745aSMaksim Panchenko int64_t Address,
3574ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
3584fa4fa6aSJustin Hibbits // Decode the spe8disp field (imm, reg), which has the low 5-bits as the
3594fa4fa6aSJustin Hibbits // displacement with 8-byte aligned, and the next 5 bits as the register #.
3604fa4fa6aSJustin Hibbits
3614fa4fa6aSJustin Hibbits uint64_t Base = Imm >> 5;
3624fa4fa6aSJustin Hibbits uint64_t Disp = Imm & 0x1F;
3634fa4fa6aSJustin Hibbits
3644fa4fa6aSJustin Hibbits assert(Base < 32 && "Invalid base register");
3654fa4fa6aSJustin Hibbits
3664fa4fa6aSJustin Hibbits Inst.addOperand(MCOperand::createImm(Disp << 3));
3670dad994aSNemanja Ivanovic Inst.addOperand(MCOperand::createReg(RRegsNoR0[Base]));
3684fa4fa6aSJustin Hibbits return MCDisassembler::Success;
3694fa4fa6aSJustin Hibbits }
3704fa4fa6aSJustin Hibbits
decodeSPE4Operands(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)3714fa4fa6aSJustin Hibbits static DecodeStatus decodeSPE4Operands(MCInst &Inst, uint64_t Imm,
3724ae9745aSMaksim Panchenko int64_t Address,
3734ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
3744fa4fa6aSJustin Hibbits // Decode the spe4disp field (imm, reg), which has the low 5-bits as the
3754fa4fa6aSJustin Hibbits // displacement with 4-byte aligned, and the next 5 bits as the register #.
3764fa4fa6aSJustin Hibbits
3774fa4fa6aSJustin Hibbits uint64_t Base = Imm >> 5;
3784fa4fa6aSJustin Hibbits uint64_t Disp = Imm & 0x1F;
3794fa4fa6aSJustin Hibbits
3804fa4fa6aSJustin Hibbits assert(Base < 32 && "Invalid base register");
3814fa4fa6aSJustin Hibbits
3824fa4fa6aSJustin Hibbits Inst.addOperand(MCOperand::createImm(Disp << 2));
3830dad994aSNemanja Ivanovic Inst.addOperand(MCOperand::createReg(RRegsNoR0[Base]));
3844fa4fa6aSJustin Hibbits return MCDisassembler::Success;
3854fa4fa6aSJustin Hibbits }
3864fa4fa6aSJustin Hibbits
decodeSPE2Operands(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)3874fa4fa6aSJustin Hibbits static DecodeStatus decodeSPE2Operands(MCInst &Inst, uint64_t Imm,
3884ae9745aSMaksim Panchenko int64_t Address,
3894ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
3904fa4fa6aSJustin Hibbits // Decode the spe2disp field (imm, reg), which has the low 5-bits as the
3914fa4fa6aSJustin Hibbits // displacement with 2-byte aligned, and the next 5 bits as the register #.
3924fa4fa6aSJustin Hibbits
3934fa4fa6aSJustin Hibbits uint64_t Base = Imm >> 5;
3944fa4fa6aSJustin Hibbits uint64_t Disp = Imm & 0x1F;
3954fa4fa6aSJustin Hibbits
3964fa4fa6aSJustin Hibbits assert(Base < 32 && "Invalid base register");
3974fa4fa6aSJustin Hibbits
3984fa4fa6aSJustin Hibbits Inst.addOperand(MCOperand::createImm(Disp << 1));
3990dad994aSNemanja Ivanovic Inst.addOperand(MCOperand::createReg(RRegsNoR0[Base]));
4004fa4fa6aSJustin Hibbits return MCDisassembler::Success;
4014fa4fa6aSJustin Hibbits }
4024fa4fa6aSJustin Hibbits
decodeCRBitMOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)4032345347eSHal Finkel static DecodeStatus decodeCRBitMOperand(MCInst &Inst, uint64_t Imm,
4044ae9745aSMaksim Panchenko int64_t Address,
4054ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
4062345347eSHal Finkel // The cr bit encoding is 0x80 >> cr_reg_num.
4072345347eSHal Finkel
4082345347eSHal Finkel unsigned Zeros = countTrailingZeros(Imm);
4092345347eSHal Finkel assert(Zeros < 8 && "Invalid CR bit value");
4102345347eSHal Finkel
411e9119e41SJim Grosbach Inst.addOperand(MCOperand::createReg(CRRegs[7 - Zeros]));
4122345347eSHal Finkel return MCDisassembler::Success;
4132345347eSHal Finkel }
4142345347eSHal Finkel
4152345347eSHal Finkel #include "PPCGenDisassemblerTables.inc"
4162345347eSHal Finkel
getInstruction(MCInst & MI,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & CS) const4172345347eSHal Finkel DecodeStatus PPCDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
4187fc5b874SRafael Espindola ArrayRef<uint8_t> Bytes,
4196fdd6a7bSFangrui Song uint64_t Address,
4204aa6bea7SRafael Espindola raw_ostream &CS) const {
4215cee3401SVictor Huang auto *ReadFunc = IsLittleEndian ? support::endian::read32le
4225cee3401SVictor Huang : support::endian::read32be;
4235cee3401SVictor Huang
4245cee3401SVictor Huang // If this is an 8-byte prefixed instruction, handle it here.
4255cee3401SVictor Huang // Note: prefixed instructions aren't technically 8-byte entities - the prefix
4265cee3401SVictor Huang // appears in memory at an address 4 bytes prior to that of the base
4275cee3401SVictor Huang // instruction regardless of endianness. So we read the two pieces and
4285cee3401SVictor Huang // rebuild the 8-byte instruction.
4295cee3401SVictor Huang // TODO: In this function we call decodeInstruction several times with
4305cee3401SVictor Huang // different decoder tables. It may be possible to only call once by
4315cee3401SVictor Huang // looking at the top 6 bits of the instruction.
4325cee3401SVictor Huang if (STI.getFeatureBits()[PPC::FeaturePrefixInstrs] && Bytes.size() >= 8) {
4335cee3401SVictor Huang uint32_t Prefix = ReadFunc(Bytes.data());
4345cee3401SVictor Huang uint32_t BaseInst = ReadFunc(Bytes.data() + 4);
4355cee3401SVictor Huang uint64_t Inst = BaseInst | (uint64_t)Prefix << 32;
4365cee3401SVictor Huang DecodeStatus result = decodeInstruction(DecoderTable64, MI, Inst, Address,
4375cee3401SVictor Huang this, STI);
4385cee3401SVictor Huang if (result != MCDisassembler::Fail) {
4395cee3401SVictor Huang Size = 8;
4405cee3401SVictor Huang return result;
4415cee3401SVictor Huang }
4425cee3401SVictor Huang }
4435cee3401SVictor Huang
4442345347eSHal Finkel // Get the four bytes of the instruction.
4452345347eSHal Finkel Size = 4;
4467fc5b874SRafael Espindola if (Bytes.size() < 4) {
4472345347eSHal Finkel Size = 0;
4482345347eSHal Finkel return MCDisassembler::Fail;
4492345347eSHal Finkel }
4502345347eSHal Finkel
451c11fd3e7SBenjamin Kramer // Read the instruction in the proper endianness.
4525cee3401SVictor Huang uint64_t Inst = ReadFunc(Bytes.data());
4532345347eSHal Finkel
454d28f8672SJinsong Ji if (STI.getFeatureBits()[PPC::FeatureSPE]) {
4554fa4fa6aSJustin Hibbits DecodeStatus result =
4564fa4fa6aSJustin Hibbits decodeInstruction(DecoderTableSPE32, MI, Inst, Address, this, STI);
4574fa4fa6aSJustin Hibbits if (result != MCDisassembler::Fail)
4584fa4fa6aSJustin Hibbits return result;
459c93a9a2cSHal Finkel }
460c93a9a2cSHal Finkel
4612345347eSHal Finkel return decodeInstruction(DecoderTable32, MI, Inst, Address, this, STI);
4622345347eSHal Finkel }
463