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