Path: blob/main/contrib/llvm-project/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
39606 views
//===------ PPCDisassembler.cpp - Disassembler for PowerPC ------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "MCTargetDesc/PPCMCTargetDesc.h"9#include "TargetInfo/PowerPCTargetInfo.h"10#include "llvm/MC/MCDecoderOps.h"11#include "llvm/MC/MCDisassembler/MCDisassembler.h"12#include "llvm/MC/MCInst.h"13#include "llvm/MC/MCSubtargetInfo.h"14#include "llvm/MC/TargetRegistry.h"15#include "llvm/Support/Endian.h"1617using namespace llvm;1819DEFINE_PPC_REGCLASSES2021#define DEBUG_TYPE "ppc-disassembler"2223typedef MCDisassembler::DecodeStatus DecodeStatus;2425namespace {26class PPCDisassembler : public MCDisassembler {27bool IsLittleEndian;2829public:30PPCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,31bool IsLittleEndian)32: MCDisassembler(STI, Ctx), IsLittleEndian(IsLittleEndian) {}3334DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,35ArrayRef<uint8_t> Bytes, uint64_t Address,36raw_ostream &CStream) const override;37};38} // end anonymous namespace3940static MCDisassembler *createPPCDisassembler(const Target &T,41const MCSubtargetInfo &STI,42MCContext &Ctx) {43return new PPCDisassembler(STI, Ctx, /*IsLittleEndian=*/false);44}4546static MCDisassembler *createPPCLEDisassembler(const Target &T,47const MCSubtargetInfo &STI,48MCContext &Ctx) {49return new PPCDisassembler(STI, Ctx, /*IsLittleEndian=*/true);50}5152extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCDisassembler() {53// Register the disassembler for each target.54TargetRegistry::RegisterMCDisassembler(getThePPC32Target(),55createPPCDisassembler);56TargetRegistry::RegisterMCDisassembler(getThePPC32LETarget(),57createPPCLEDisassembler);58TargetRegistry::RegisterMCDisassembler(getThePPC64Target(),59createPPCDisassembler);60TargetRegistry::RegisterMCDisassembler(getThePPC64LETarget(),61createPPCLEDisassembler);62}6364static DecodeStatus decodeCondBrTarget(MCInst &Inst, unsigned Imm,65uint64_t /*Address*/,66const MCDisassembler * /*Decoder*/) {67Inst.addOperand(MCOperand::createImm(SignExtend32<14>(Imm)));68return MCDisassembler::Success;69}7071static DecodeStatus decodeDirectBrTarget(MCInst &Inst, unsigned Imm,72uint64_t /*Address*/,73const MCDisassembler * /*Decoder*/) {74int32_t Offset = SignExtend32<24>(Imm);75Inst.addOperand(MCOperand::createImm(Offset));76return MCDisassembler::Success;77}7879// FIXME: These can be generated by TableGen from the existing register80// encoding values!8182template <std::size_t N>83static DecodeStatus decodeRegisterClass(MCInst &Inst, uint64_t RegNo,84const MCPhysReg (&Regs)[N]) {85if (RegNo >= N)86return MCDisassembler::Fail;87Inst.addOperand(MCOperand::createReg(Regs[RegNo]));88return MCDisassembler::Success;89}9091static DecodeStatus DecodeCRRCRegisterClass(MCInst &Inst, uint64_t RegNo,92uint64_t Address,93const MCDisassembler *Decoder) {94return decodeRegisterClass(Inst, RegNo, CRRegs);95}9697static DecodeStatus DecodeCRBITRCRegisterClass(MCInst &Inst, uint64_t RegNo,98uint64_t Address,99const MCDisassembler *Decoder) {100return decodeRegisterClass(Inst, RegNo, CRBITRegs);101}102103static DecodeStatus DecodeF4RCRegisterClass(MCInst &Inst, uint64_t RegNo,104uint64_t Address,105const MCDisassembler *Decoder) {106return decodeRegisterClass(Inst, RegNo, FRegs);107}108109static DecodeStatus DecodeF8RCRegisterClass(MCInst &Inst, uint64_t RegNo,110uint64_t Address,111const MCDisassembler *Decoder) {112return decodeRegisterClass(Inst, RegNo, FRegs);113}114115static DecodeStatus DecodeFpRCRegisterClass(MCInst &Inst, uint64_t RegNo,116uint64_t Address,117const MCDisassembler *Decoder) {118if (RegNo > 30 || (RegNo & 1))119return MCDisassembler::Fail;120return decodeRegisterClass(Inst, RegNo >> 1, FpRegs);121}122123static DecodeStatus DecodeVFRCRegisterClass(MCInst &Inst, uint64_t RegNo,124uint64_t Address,125const MCDisassembler *Decoder) {126return decodeRegisterClass(Inst, RegNo, VFRegs);127}128129static DecodeStatus DecodeVRRCRegisterClass(MCInst &Inst, uint64_t RegNo,130uint64_t Address,131const MCDisassembler *Decoder) {132return decodeRegisterClass(Inst, RegNo, VRegs);133}134135static DecodeStatus DecodeVSRCRegisterClass(MCInst &Inst, uint64_t RegNo,136uint64_t Address,137const MCDisassembler *Decoder) {138return decodeRegisterClass(Inst, RegNo, VSRegs);139}140141static DecodeStatus DecodeVSFRCRegisterClass(MCInst &Inst, uint64_t RegNo,142uint64_t Address,143const MCDisassembler *Decoder) {144return decodeRegisterClass(Inst, RegNo, VSFRegs);145}146147static DecodeStatus DecodeVSSRCRegisterClass(MCInst &Inst, uint64_t RegNo,148uint64_t Address,149const MCDisassembler *Decoder) {150return decodeRegisterClass(Inst, RegNo, VSSRegs);151}152153static DecodeStatus DecodeGPRCRegisterClass(MCInst &Inst, uint64_t RegNo,154uint64_t Address,155const MCDisassembler *Decoder) {156return decodeRegisterClass(Inst, RegNo, RRegs);157}158159static DecodeStatus160DecodeGPRC_NOR0RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,161const MCDisassembler *Decoder) {162return decodeRegisterClass(Inst, RegNo, RRegsNoR0);163}164165static DecodeStatus DecodeG8RCRegisterClass(MCInst &Inst, uint64_t RegNo,166uint64_t Address,167const MCDisassembler *Decoder) {168return decodeRegisterClass(Inst, RegNo, XRegs);169}170171static DecodeStatus DecodeG8pRCRegisterClass(MCInst &Inst, uint64_t RegNo,172uint64_t Address,173const MCDisassembler *Decoder) {174return decodeRegisterClass(Inst, RegNo, XRegs);175}176177static DecodeStatus178DecodeG8RC_NOX0RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,179const MCDisassembler *Decoder) {180return decodeRegisterClass(Inst, RegNo, XRegsNoX0);181}182183#define DecodePointerLikeRegClass0 DecodeGPRCRegisterClass184#define DecodePointerLikeRegClass1 DecodeGPRC_NOR0RegisterClass185186static DecodeStatus DecodeSPERCRegisterClass(MCInst &Inst, uint64_t RegNo,187uint64_t Address,188const MCDisassembler *Decoder) {189return decodeRegisterClass(Inst, RegNo, SPERegs);190}191192static DecodeStatus DecodeACCRCRegisterClass(MCInst &Inst, uint64_t RegNo,193uint64_t Address,194const MCDisassembler *Decoder) {195return decodeRegisterClass(Inst, RegNo, ACCRegs);196}197198static DecodeStatus DecodeWACCRCRegisterClass(MCInst &Inst, uint64_t RegNo,199uint64_t Address,200const void *Decoder) {201return decodeRegisterClass(Inst, RegNo, WACCRegs);202}203204static DecodeStatus DecodeWACC_HIRCRegisterClass(MCInst &Inst, uint64_t RegNo,205uint64_t Address,206const void *Decoder) {207return decodeRegisterClass(Inst, RegNo, WACC_HIRegs);208}209210// TODO: Make this function static when the register class is used by a new211// instruction.212DecodeStatus DecodeDMRROWRCRegisterClass(MCInst &Inst, uint64_t RegNo,213uint64_t Address,214const void *Decoder) {215return decodeRegisterClass(Inst, RegNo, DMRROWRegs);216}217218static DecodeStatus DecodeDMRROWpRCRegisterClass(MCInst &Inst, uint64_t RegNo,219uint64_t Address,220const void *Decoder) {221return decodeRegisterClass(Inst, RegNo, DMRROWpRegs);222}223224static DecodeStatus DecodeDMRRCRegisterClass(MCInst &Inst, uint64_t RegNo,225uint64_t Address,226const void *Decoder) {227return decodeRegisterClass(Inst, RegNo, DMRRegs);228}229230// TODO: Make this function static when the register class is used by a new231// instruction.232DecodeStatus DecodeDMRpRCRegisterClass(MCInst &Inst, uint64_t RegNo,233uint64_t Address, const void *Decoder) {234return decodeRegisterClass(Inst, RegNo, DMRpRegs);235}236237static DecodeStatus DecodeVSRpRCRegisterClass(MCInst &Inst, uint64_t RegNo,238uint64_t Address,239const MCDisassembler *Decoder) {240return decodeRegisterClass(Inst, RegNo, VSRpRegs);241}242243#define DecodeQSRCRegisterClass DecodeQFRCRegisterClass244#define DecodeQBRCRegisterClass DecodeQFRCRegisterClass245246template <unsigned N>247static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm,248int64_t Address,249const MCDisassembler *Decoder) {250if (!isUInt<N>(Imm))251return MCDisassembler::Fail;252Inst.addOperand(MCOperand::createImm(Imm));253return MCDisassembler::Success;254}255256template <unsigned N>257static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm,258int64_t Address,259const MCDisassembler *Decoder) {260if (!isUInt<N>(Imm))261return MCDisassembler::Fail;262Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm)));263return MCDisassembler::Success;264}265266static DecodeStatus decodeImmZeroOperand(MCInst &Inst, uint64_t Imm,267int64_t Address,268const MCDisassembler *Decoder) {269if (Imm != 0)270return MCDisassembler::Fail;271Inst.addOperand(MCOperand::createImm(Imm));272return MCDisassembler::Success;273}274275static DecodeStatus decodeVSRpEvenOperands(MCInst &Inst, uint64_t RegNo,276uint64_t Address,277const MCDisassembler *Decoder) {278if (RegNo & 1)279return MCDisassembler::Fail;280Inst.addOperand(MCOperand::createReg(VSRpRegs[RegNo >> 1]));281return MCDisassembler::Success;282}283284static DecodeStatus decodeDispRIXOperand(MCInst &Inst, uint64_t Imm,285int64_t Address,286const MCDisassembler *Decoder) {287// The rix displacement is an immediate shifted by 2288Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Imm << 2)));289return MCDisassembler::Success;290}291292static DecodeStatus decodeDispRIHashOperand(MCInst &Inst, uint64_t Imm,293int64_t Address,294const MCDisassembler *Decoder) {295// Decode the disp field for a hash store or hash check operation.296// The field is composed of an immediate value that is 6 bits297// and covers the range -8 to -512. The immediate is always negative and 2s298// complement which is why we sign extend a 7 bit value.299const int64_t Disp = SignExtend64<7>((Imm & 0x3F) + 64) * 8;300301Inst.addOperand(MCOperand::createImm(Disp));302return MCDisassembler::Success;303}304305static DecodeStatus decodeDispRIX16Operand(MCInst &Inst, uint64_t Imm,306int64_t Address,307const MCDisassembler *Decoder) {308// The rix16 displacement has 12-bits which are shifted by 4.309Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Imm << 4)));310return MCDisassembler::Success;311}312313static DecodeStatus decodeDispSPE8Operand(MCInst &Inst, uint64_t Imm,314int64_t Address,315const MCDisassembler *Decoder) {316// Decode the dispSPE8 field, which has 5-bits, 8-byte aligned.317318uint64_t Disp = Imm & 0x1F;319320Inst.addOperand(MCOperand::createImm(Disp << 3));321return MCDisassembler::Success;322}323324static DecodeStatus decodeDispSPE4Operand(MCInst &Inst, uint64_t Imm,325int64_t Address,326const MCDisassembler *Decoder) {327// Decode the dispSPE8 field, which has 5-bits, 4-byte aligned.328329uint64_t Disp = Imm & 0x1F;330331Inst.addOperand(MCOperand::createImm(Disp << 2));332return MCDisassembler::Success;333}334335static DecodeStatus decodeDispSPE2Operand(MCInst &Inst, uint64_t Imm,336int64_t Address,337const MCDisassembler *Decoder) {338// Decode the dispSPE8 field, which has 5-bits, 2-byte aligned.339340uint64_t Disp = Imm & 0x1F;341Inst.addOperand(MCOperand::createImm(Disp << 1));342return MCDisassembler::Success;343}344345static DecodeStatus decodeCRBitMOperand(MCInst &Inst, uint64_t Imm,346int64_t Address,347const MCDisassembler *Decoder) {348// The cr bit encoding is 0x80 >> cr_reg_num.349350unsigned Zeros = llvm::countr_zero(Imm);351if (Zeros >= 8)352return MCDisassembler::Fail;353354Inst.addOperand(MCOperand::createReg(CRRegs[7 - Zeros]));355return MCDisassembler::Success;356}357358#include "PPCGenDisassemblerTables.inc"359360DecodeStatus PPCDisassembler::getInstruction(MCInst &MI, uint64_t &Size,361ArrayRef<uint8_t> Bytes,362uint64_t Address,363raw_ostream &CS) const {364auto *ReadFunc = IsLittleEndian ? support::endian::read32le365: support::endian::read32be;366367// If this is an 8-byte prefixed instruction, handle it here.368// Note: prefixed instructions aren't technically 8-byte entities - the prefix369// appears in memory at an address 4 bytes prior to that of the base370// instruction regardless of endianness. So we read the two pieces and371// rebuild the 8-byte instruction.372// TODO: In this function we call decodeInstruction several times with373// different decoder tables. It may be possible to only call once by374// looking at the top 6 bits of the instruction.375if (STI.hasFeature(PPC::FeaturePrefixInstrs) && Bytes.size() >= 8) {376uint32_t Prefix = ReadFunc(Bytes.data());377uint32_t BaseInst = ReadFunc(Bytes.data() + 4);378uint64_t Inst = BaseInst | (uint64_t)Prefix << 32;379DecodeStatus result = decodeInstruction(DecoderTable64, MI, Inst, Address,380this, STI);381if (result != MCDisassembler::Fail) {382Size = 8;383return result;384}385}386387// Get the four bytes of the instruction.388Size = 4;389if (Bytes.size() < 4) {390Size = 0;391return MCDisassembler::Fail;392}393394// Read the instruction in the proper endianness.395uint64_t Inst = ReadFunc(Bytes.data());396397if (STI.hasFeature(PPC::FeatureSPE)) {398DecodeStatus result =399decodeInstruction(DecoderTableSPE32, MI, Inst, Address, this, STI);400if (result != MCDisassembler::Fail)401return result;402}403404return decodeInstruction(DecoderTable32, MI, Inst, Address, this, STI);405}406407408