brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.3 KiB · 70e619c Raw
408 lines · cpp
1//===------ PPCDisassembler.cpp - Disassembler for PowerPC ------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "MCTargetDesc/PPCMCTargetDesc.h"10#include "TargetInfo/PowerPCTargetInfo.h"11#include "llvm/MC/MCDecoder.h"12#include "llvm/MC/MCDecoderOps.h"13#include "llvm/MC/MCDisassembler/MCDisassembler.h"14#include "llvm/MC/MCInst.h"15#include "llvm/MC/MCSubtargetInfo.h"16#include "llvm/MC/TargetRegistry.h"17#include "llvm/Support/Compiler.h"18#include "llvm/Support/Endian.h"19 20using namespace llvm;21using namespace llvm::MCD;22 23DEFINE_PPC_REGCLASSES24 25#define DEBUG_TYPE "ppc-disassembler"26 27typedef MCDisassembler::DecodeStatus DecodeStatus;28 29namespace {30class PPCDisassembler : public MCDisassembler {31  bool IsLittleEndian;32 33public:34  PPCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,35                  bool IsLittleEndian)36      : MCDisassembler(STI, Ctx), IsLittleEndian(IsLittleEndian) {}37 38  DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,39                              ArrayRef<uint8_t> Bytes, uint64_t Address,40                              raw_ostream &CStream) const override;41};42} // end anonymous namespace43 44static MCDisassembler *createPPCDisassembler(const Target &T,45                                             const MCSubtargetInfo &STI,46                                             MCContext &Ctx) {47  return new PPCDisassembler(STI, Ctx, /*IsLittleEndian=*/false);48}49 50static MCDisassembler *createPPCLEDisassembler(const Target &T,51                                               const MCSubtargetInfo &STI,52                                               MCContext &Ctx) {53  return new PPCDisassembler(STI, Ctx, /*IsLittleEndian=*/true);54}55 56extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void57LLVMInitializePowerPCDisassembler() {58  // Register the disassembler for each target.59  TargetRegistry::RegisterMCDisassembler(getThePPC32Target(),60                                         createPPCDisassembler);61  TargetRegistry::RegisterMCDisassembler(getThePPC32LETarget(),62                                         createPPCLEDisassembler);63  TargetRegistry::RegisterMCDisassembler(getThePPC64Target(),64                                         createPPCDisassembler);65  TargetRegistry::RegisterMCDisassembler(getThePPC64LETarget(),66                                         createPPCLEDisassembler);67}68 69static DecodeStatus decodeCondBrTarget(MCInst &Inst, unsigned Imm,70                                       uint64_t /*Address*/,71                                       const MCDisassembler * /*Decoder*/) {72  Inst.addOperand(MCOperand::createImm(SignExtend32<14>(Imm)));73  return MCDisassembler::Success;74}75 76static DecodeStatus decodeDirectBrTarget(MCInst &Inst, unsigned Imm,77                                         uint64_t /*Address*/,78                                         const MCDisassembler * /*Decoder*/) {79  int32_t Offset = SignExtend32<24>(Imm);80  Inst.addOperand(MCOperand::createImm(Offset));81  return MCDisassembler::Success;82}83 84// FIXME: These can be generated by TableGen from the existing register85// encoding values!86 87template <std::size_t N>88static DecodeStatus decodeRegisterClass(MCInst &Inst, uint64_t RegNo,89                                        const MCPhysReg (&Regs)[N]) {90  if (RegNo >= N)91    return MCDisassembler::Fail;92  Inst.addOperand(MCOperand::createReg(Regs[RegNo]));93  return MCDisassembler::Success;94}95 96static DecodeStatus DecodeCRRCRegisterClass(MCInst &Inst, uint64_t RegNo,97                                            uint64_t Address,98                                            const MCDisassembler *Decoder) {99  return decodeRegisterClass(Inst, RegNo, CRRegs);100}101 102static DecodeStatus DecodeCRBITRCRegisterClass(MCInst &Inst, uint64_t RegNo,103                                               uint64_t Address,104                                               const MCDisassembler *Decoder) {105  return decodeRegisterClass(Inst, RegNo, CRBITRegs);106}107 108static DecodeStatus DecodeF4RCRegisterClass(MCInst &Inst, uint64_t RegNo,109                                            uint64_t Address,110                                            const MCDisassembler *Decoder) {111  return decodeRegisterClass(Inst, RegNo, FRegs);112}113 114static DecodeStatus DecodeF8RCRegisterClass(MCInst &Inst, uint64_t RegNo,115                                            uint64_t Address,116                                            const MCDisassembler *Decoder) {117  return decodeRegisterClass(Inst, RegNo, FRegs);118}119 120static DecodeStatus DecodeFpRCRegisterClass(MCInst &Inst, uint64_t RegNo,121                                            uint64_t Address,122                                            const MCDisassembler *Decoder) {123  if (RegNo > 30 || (RegNo & 1))124    return MCDisassembler::Fail;125  return decodeRegisterClass(Inst, RegNo >> 1, FpRegs);126}127 128static DecodeStatus DecodeVFRCRegisterClass(MCInst &Inst, uint64_t RegNo,129                                            uint64_t Address,130                                            const MCDisassembler *Decoder) {131  return decodeRegisterClass(Inst, RegNo, VFRegs);132}133 134static DecodeStatus DecodeVRRCRegisterClass(MCInst &Inst, uint64_t RegNo,135                                            uint64_t Address,136                                            const MCDisassembler *Decoder) {137  return decodeRegisterClass(Inst, RegNo, VRegs);138}139 140static DecodeStatus DecodeVSRCRegisterClass(MCInst &Inst, uint64_t RegNo,141                                            uint64_t Address,142                                            const MCDisassembler *Decoder) {143  return decodeRegisterClass(Inst, RegNo, VSRegs);144}145 146static DecodeStatus DecodeVSFRCRegisterClass(MCInst &Inst, uint64_t RegNo,147                                             uint64_t Address,148                                             const MCDisassembler *Decoder) {149  return decodeRegisterClass(Inst, RegNo, VSFRegs);150}151 152static DecodeStatus DecodeVSSRCRegisterClass(MCInst &Inst, uint64_t RegNo,153                                             uint64_t Address,154                                             const MCDisassembler *Decoder) {155  return decodeRegisterClass(Inst, RegNo, VSSRegs);156}157 158static DecodeStatus DecodeGPRCRegisterClass(MCInst &Inst, uint64_t RegNo,159                                            uint64_t Address,160                                            const MCDisassembler *Decoder) {161  return decodeRegisterClass(Inst, RegNo, RRegs);162}163 164static DecodeStatus165DecodeGPRC_NOR0RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,166                             const MCDisassembler *Decoder) {167  return decodeRegisterClass(Inst, RegNo, RRegsNoR0);168}169 170static DecodeStatus DecodeG8RCRegisterClass(MCInst &Inst, uint64_t RegNo,171                                            uint64_t Address,172                                            const MCDisassembler *Decoder) {173  return decodeRegisterClass(Inst, RegNo, XRegs);174}175 176static DecodeStatus DecodeG8pRCRegisterClass(MCInst &Inst, uint64_t RegNo,177                                             uint64_t Address,178                                             const MCDisassembler *Decoder) {179  return decodeRegisterClass(Inst, RegNo, XRegs);180}181 182static DecodeStatus183DecodeG8RC_NOX0RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,184                             const MCDisassembler *Decoder) {185  return decodeRegisterClass(Inst, RegNo, XRegsNoX0);186}187 188static DecodeStatus DecodeSPERCRegisterClass(MCInst &Inst, uint64_t RegNo,189                                             uint64_t Address,190                                             const MCDisassembler *Decoder) {191  return decodeRegisterClass(Inst, RegNo, SPERegs);192}193 194static DecodeStatus DecodeACCRCRegisterClass(MCInst &Inst, uint64_t RegNo,195                                             uint64_t Address,196                                             const MCDisassembler *Decoder) {197  return decodeRegisterClass(Inst, RegNo, ACCRegs);198}199 200static DecodeStatus DecodeWACCRCRegisterClass(MCInst &Inst, uint64_t RegNo,201                                              uint64_t Address,202                                              const void *Decoder) {203  return decodeRegisterClass(Inst, RegNo, WACCRegs);204}205 206static DecodeStatus DecodeWACC_HIRCRegisterClass(MCInst &Inst, uint64_t RegNo,207                                                 uint64_t Address,208                                                 const void *Decoder) {209  return decodeRegisterClass(Inst, RegNo, WACC_HIRegs);210}211 212// TODO: Make this function static when the register class is used by a new213//       instruction.214DecodeStatus DecodeDMRROWRCRegisterClass(MCInst &Inst, uint64_t RegNo,215                                         uint64_t Address,216                                         const void *Decoder) {217  return decodeRegisterClass(Inst, RegNo, DMRROWRegs);218}219 220static DecodeStatus DecodeDMRROWpRCRegisterClass(MCInst &Inst, uint64_t RegNo,221                                                 uint64_t Address,222                                                 const void *Decoder) {223  return decodeRegisterClass(Inst, RegNo, DMRROWpRegs);224}225 226static DecodeStatus DecodeDMRRCRegisterClass(MCInst &Inst, uint64_t RegNo,227                                             uint64_t Address,228                                             const void *Decoder) {229  return decodeRegisterClass(Inst, RegNo, DMRRegs);230}231 232// TODO: Make this function static when the register class is used by a new233//       instruction.234DecodeStatus DecodeDMRpRCRegisterClass(MCInst &Inst, uint64_t RegNo,235                                       uint64_t Address, const void *Decoder) {236  return decodeRegisterClass(Inst, RegNo, DMRpRegs);237}238 239static DecodeStatus DecodeVSRpRCRegisterClass(MCInst &Inst, uint64_t RegNo,240                                              uint64_t Address,241                                              const MCDisassembler *Decoder) {242  return decodeRegisterClass(Inst, RegNo, VSRpRegs);243}244 245#define DecodeQSRCRegisterClass DecodeQFRCRegisterClass246#define DecodeQBRCRegisterClass DecodeQFRCRegisterClass247 248template <unsigned N>249static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm,250                                      int64_t Address,251                                      const MCDisassembler *Decoder) {252  if (!isUInt<N>(Imm))253    return MCDisassembler::Fail;254  Inst.addOperand(MCOperand::createImm(Imm));255  return MCDisassembler::Success;256}257 258template <unsigned N>259static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm,260                                      int64_t Address,261                                      const MCDisassembler *Decoder) {262  if (!isUInt<N>(Imm))263    return MCDisassembler::Fail;264  Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm)));265  return MCDisassembler::Success;266}267 268static DecodeStatus decodeImmZeroOperand(MCInst &Inst, uint64_t Imm,269                                         int64_t Address,270                                         const MCDisassembler *Decoder) {271  if (Imm != 0)272    return MCDisassembler::Fail;273  Inst.addOperand(MCOperand::createImm(Imm));274  return MCDisassembler::Success;275}276 277static DecodeStatus decodeVSRpEvenOperands(MCInst &Inst, uint64_t RegNo,278                                           uint64_t Address,279                                           const MCDisassembler *Decoder) {280  if (RegNo & 1)281    return MCDisassembler::Fail;282  Inst.addOperand(MCOperand::createReg(VSRpRegs[RegNo >> 1]));283  return MCDisassembler::Success;284}285 286static DecodeStatus decodeDispRIXOperand(MCInst &Inst, uint64_t Imm,287                                         int64_t Address,288                                         const MCDisassembler *Decoder) {289  // The rix displacement is an immediate shifted by 2290  Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Imm << 2)));291  return MCDisassembler::Success;292}293 294static DecodeStatus decodeDispRIHashOperand(MCInst &Inst, uint64_t Imm,295                                            int64_t Address,296                                            const MCDisassembler *Decoder) {297  // Decode the disp field for a hash store or hash check operation.298  // The field is composed of an immediate value that is 6 bits299  // and covers the range -8 to -512. The immediate is always negative and 2s300  // complement which is why we sign extend a 7 bit value.301  const int64_t Disp = SignExtend64<7>((Imm & 0x3F) + 64) * 8;302 303  Inst.addOperand(MCOperand::createImm(Disp));304  return MCDisassembler::Success;305}306 307static DecodeStatus decodeDispRIX16Operand(MCInst &Inst, uint64_t Imm,308                                           int64_t Address,309                                           const MCDisassembler *Decoder) {310  // The rix16 displacement has 12-bits which are shifted by 4.311  Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Imm << 4)));312  return MCDisassembler::Success;313}314 315static DecodeStatus decodeDispSPE8Operand(MCInst &Inst, uint64_t Imm,316                                          int64_t Address,317                                          const MCDisassembler *Decoder) {318  // Decode the dispSPE8 field, which has 5-bits, 8-byte aligned.319 320  uint64_t Disp = Imm & 0x1F;321 322  Inst.addOperand(MCOperand::createImm(Disp << 3));323  return MCDisassembler::Success;324}325 326static DecodeStatus decodeDispSPE4Operand(MCInst &Inst, uint64_t Imm,327                                          int64_t Address,328                                          const MCDisassembler *Decoder) {329  // Decode the dispSPE8 field, which has 5-bits, 4-byte aligned.330 331  uint64_t Disp = Imm & 0x1F;332 333  Inst.addOperand(MCOperand::createImm(Disp << 2));334  return MCDisassembler::Success;335}336 337static DecodeStatus decodeDispSPE2Operand(MCInst &Inst, uint64_t Imm,338                                          int64_t Address,339                                          const MCDisassembler *Decoder) {340  // Decode the dispSPE8 field, which has 5-bits, 2-byte aligned.341 342  uint64_t Disp = Imm & 0x1F;343  Inst.addOperand(MCOperand::createImm(Disp << 1));344  return MCDisassembler::Success;345}346 347static DecodeStatus decodeCRBitMOperand(MCInst &Inst, uint64_t Imm,348                                        int64_t Address,349                                        const MCDisassembler *Decoder) {350  // The cr bit encoding is 0x80 >> cr_reg_num.351 352  unsigned Zeros = llvm::countr_zero(Imm);353  if (Zeros >= 8)354    return MCDisassembler::Fail;355 356  Inst.addOperand(MCOperand::createReg(CRRegs[7 - Zeros]));357  return MCDisassembler::Success;358}359 360#include "PPCGenDisassemblerTables.inc"361 362DecodeStatus PPCDisassembler::getInstruction(MCInst &MI, uint64_t &Size,363                                             ArrayRef<uint8_t> Bytes,364                                             uint64_t Address,365                                             raw_ostream &CS) const {366  auto *ReadFunc = IsLittleEndian ? support::endian::read32le367                                  : support::endian::read32be;368 369  // If this is an 8-byte prefixed instruction, handle it here.370  // Note: prefixed instructions aren't technically 8-byte entities - the prefix371  //       appears in memory at an address 4 bytes prior to that of the base372  //       instruction regardless of endianness. So we read the two pieces and373  //       rebuild the 8-byte instruction.374  // TODO: In this function we call decodeInstruction several times with375  //       different decoder tables. It may be possible to only call once by376  //       looking at the top 6 bits of the instruction.377  if (STI.hasFeature(PPC::FeaturePrefixInstrs) && Bytes.size() >= 8) {378    uint32_t Prefix = ReadFunc(Bytes.data());379    uint32_t BaseInst = ReadFunc(Bytes.data() + 4);380    uint64_t Inst = BaseInst | (uint64_t)Prefix << 32;381    DecodeStatus result = decodeInstruction(DecoderTable64, MI, Inst, Address,382                                            this, STI);383    if (result != MCDisassembler::Fail) {384      Size = 8;385      return result;386    }387  }388 389  // Get the four bytes of the instruction.390  Size = 4;391  if (Bytes.size() < 4) {392    Size = 0;393    return MCDisassembler::Fail;394  }395 396  // Read the instruction in the proper endianness.397  uint64_t Inst = ReadFunc(Bytes.data());398 399  if (STI.hasFeature(PPC::FeatureSPE)) {400    DecodeStatus result =401        decodeInstruction(DecoderTableSPE32, MI, Inst, Address, this, STI);402    if (result != MCDisassembler::Fail)403      return result;404  }405 406  return decodeInstruction(DecoderTable32, MI, Inst, Address, this, STI);407}408