Path: blob/main/contrib/llvm-project/llvm/lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp
35293 views
//===-- SystemZDisassembler.cpp - Disassembler for SystemZ ------*- 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/SystemZMCTargetDesc.h"9#include "SystemZ.h"10#include "TargetInfo/SystemZTargetInfo.h"11#include "llvm/MC/MCDecoderOps.h"12#include "llvm/MC/MCDisassembler/MCDisassembler.h"13#include "llvm/MC/MCInst.h"14#include "llvm/MC/MCSubtargetInfo.h"15#include "llvm/MC/TargetRegistry.h"16#include "llvm/Support/MathExtras.h"17#include <cassert>18#include <cstdint>1920using namespace llvm;2122#define DEBUG_TYPE "systemz-disassembler"2324typedef MCDisassembler::DecodeStatus DecodeStatus;2526namespace {2728class SystemZDisassembler : public MCDisassembler {29public:30SystemZDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)31: MCDisassembler(STI, Ctx) {}32~SystemZDisassembler() override = default;3334DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,35ArrayRef<uint8_t> Bytes, uint64_t Address,36raw_ostream &CStream) const override;37};3839} // end anonymous namespace4041static MCDisassembler *createSystemZDisassembler(const Target &T,42const MCSubtargetInfo &STI,43MCContext &Ctx) {44return new SystemZDisassembler(STI, Ctx);45}4647// NOLINTNEXTLINE(readability-identifier-naming)48extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZDisassembler() {49// Register the disassembler.50TargetRegistry::RegisterMCDisassembler(getTheSystemZTarget(),51createSystemZDisassembler);52}5354/// tryAddingSymbolicOperand - trys to add a symbolic operand in place of the55/// immediate Value in the MCInst.56///57/// @param Value - The immediate Value, has had any PC adjustment made by58/// the caller.59/// @param isBranch - If the instruction is a branch instruction60/// @param Address - The starting address of the instruction61/// @param Offset - The byte offset to this immediate in the instruction62/// @param Width - The byte width of this immediate in the instruction63///64/// If the getOpInfo() function was set when setupForSymbolicDisassembly() was65/// called then that function is called to get any symbolic information for the66/// immediate in the instruction using the Address, Offset and Width. If that67/// returns non-zero then the symbolic information it returns is used to create68/// an MCExpr and that is added as an operand to the MCInst. If getOpInfo()69/// returns zero and isBranch is true then a symbol look up for immediate Value70/// is done and if a symbol is found an MCExpr is created with that, else71/// an MCExpr with the immediate Value is created. This function returns true72/// if it adds an operand to the MCInst and false otherwise.73static bool tryAddingSymbolicOperand(int64_t Value, bool IsBranch,74uint64_t Address, uint64_t Offset,75uint64_t Width, MCInst &MI,76const MCDisassembler *Decoder) {77return Decoder->tryAddingSymbolicOperand(MI, Value, Address, IsBranch, Offset,78Width, /*InstSize=*/0);79}8081static DecodeStatus decodeRegisterClass(MCInst &Inst, uint64_t RegNo,82const unsigned *Regs, unsigned Size,83bool IsAddr = false) {84assert(RegNo < Size && "Invalid register");85if (IsAddr && RegNo == 0) {86RegNo = SystemZ::NoRegister;87} else {88RegNo = Regs[RegNo];89if (RegNo == 0)90return MCDisassembler::Fail;91}92Inst.addOperand(MCOperand::createReg(RegNo));93return MCDisassembler::Success;94}9596static DecodeStatus DecodeGR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,97uint64_t Address,98const MCDisassembler *Decoder) {99return decodeRegisterClass(Inst, RegNo, SystemZMC::GR32Regs, 16);100}101102static DecodeStatus DecodeGRH32BitRegisterClass(MCInst &Inst, uint64_t RegNo,103uint64_t Address,104const MCDisassembler *Decoder) {105return decodeRegisterClass(Inst, RegNo, SystemZMC::GRH32Regs, 16);106}107108static DecodeStatus DecodeGR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,109uint64_t Address,110const MCDisassembler *Decoder) {111return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs, 16);112}113114static DecodeStatus DecodeGR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,115uint64_t Address,116const MCDisassembler *Decoder) {117return decodeRegisterClass(Inst, RegNo, SystemZMC::GR128Regs, 16);118}119120static DecodeStatus121DecodeADDR32BitRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,122const MCDisassembler *Decoder) {123return decodeRegisterClass(Inst, RegNo, SystemZMC::GR32Regs, 16, true);124}125126static DecodeStatus127DecodeADDR64BitRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,128const MCDisassembler *Decoder) {129return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs, 16, true);130}131132static DecodeStatus DecodeFP32BitRegisterClass(MCInst &Inst, uint64_t RegNo,133uint64_t Address,134const MCDisassembler *Decoder) {135return decodeRegisterClass(Inst, RegNo, SystemZMC::FP32Regs, 16);136}137138static DecodeStatus DecodeFP64BitRegisterClass(MCInst &Inst, uint64_t RegNo,139uint64_t Address,140const MCDisassembler *Decoder) {141return decodeRegisterClass(Inst, RegNo, SystemZMC::FP64Regs, 16);142}143144static DecodeStatus DecodeFP128BitRegisterClass(MCInst &Inst, uint64_t RegNo,145uint64_t Address,146const MCDisassembler *Decoder) {147return decodeRegisterClass(Inst, RegNo, SystemZMC::FP128Regs, 16);148}149150static DecodeStatus DecodeVR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,151uint64_t Address,152const MCDisassembler *Decoder) {153return decodeRegisterClass(Inst, RegNo, SystemZMC::VR32Regs, 32);154}155156static DecodeStatus DecodeVR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,157uint64_t Address,158const MCDisassembler *Decoder) {159return decodeRegisterClass(Inst, RegNo, SystemZMC::VR64Regs, 32);160}161162static DecodeStatus DecodeVR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,163uint64_t Address,164const MCDisassembler *Decoder) {165return decodeRegisterClass(Inst, RegNo, SystemZMC::VR128Regs, 32);166}167168static DecodeStatus DecodeAR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,169uint64_t Address,170const MCDisassembler *Decoder) {171return decodeRegisterClass(Inst, RegNo, SystemZMC::AR32Regs, 16);172}173174static DecodeStatus DecodeCR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,175uint64_t Address,176const MCDisassembler *Decoder) {177return decodeRegisterClass(Inst, RegNo, SystemZMC::CR64Regs, 16);178}179180template<unsigned N>181static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm) {182if (!isUInt<N>(Imm))183return MCDisassembler::Fail;184Inst.addOperand(MCOperand::createImm(Imm));185return MCDisassembler::Success;186}187188template<unsigned N>189static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm) {190if (!isUInt<N>(Imm))191return MCDisassembler::Fail;192Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm)));193return MCDisassembler::Success;194}195196static DecodeStatus decodeU1ImmOperand(MCInst &Inst, uint64_t Imm,197uint64_t Address,198const MCDisassembler *Decoder) {199return decodeUImmOperand<1>(Inst, Imm);200}201202static DecodeStatus decodeU2ImmOperand(MCInst &Inst, uint64_t Imm,203uint64_t Address,204const MCDisassembler *Decoder) {205return decodeUImmOperand<2>(Inst, Imm);206}207208static DecodeStatus decodeU3ImmOperand(MCInst &Inst, uint64_t Imm,209uint64_t Address,210const MCDisassembler *Decoder) {211return decodeUImmOperand<3>(Inst, Imm);212}213214static DecodeStatus decodeU4ImmOperand(MCInst &Inst, uint64_t Imm,215uint64_t Address,216const MCDisassembler *Decoder) {217return decodeUImmOperand<4>(Inst, Imm);218}219220static DecodeStatus decodeU8ImmOperand(MCInst &Inst, uint64_t Imm,221uint64_t Address,222const MCDisassembler *Decoder) {223return decodeUImmOperand<8>(Inst, Imm);224}225226static DecodeStatus decodeU12ImmOperand(MCInst &Inst, uint64_t Imm,227uint64_t Address,228const MCDisassembler *Decoder) {229return decodeUImmOperand<12>(Inst, Imm);230}231232static DecodeStatus decodeU16ImmOperand(MCInst &Inst, uint64_t Imm,233uint64_t Address,234const MCDisassembler *Decoder) {235return decodeUImmOperand<16>(Inst, Imm);236}237238static DecodeStatus decodeU32ImmOperand(MCInst &Inst, uint64_t Imm,239uint64_t Address,240const MCDisassembler *Decoder) {241return decodeUImmOperand<32>(Inst, Imm);242}243244static DecodeStatus decodeS8ImmOperand(MCInst &Inst, uint64_t Imm,245uint64_t Address,246const MCDisassembler *Decoder) {247return decodeSImmOperand<8>(Inst, Imm);248}249250static DecodeStatus decodeS16ImmOperand(MCInst &Inst, uint64_t Imm,251uint64_t Address,252const MCDisassembler *Decoder) {253return decodeSImmOperand<16>(Inst, Imm);254}255256static DecodeStatus decodeS20ImmOperand(MCInst &Inst, uint64_t Imm,257uint64_t Address,258const MCDisassembler *Decoder) {259return decodeSImmOperand<20>(Inst, Imm);260}261262static DecodeStatus decodeS32ImmOperand(MCInst &Inst, uint64_t Imm,263uint64_t Address,264const MCDisassembler *Decoder) {265return decodeSImmOperand<32>(Inst, Imm);266}267268template <unsigned N>269static DecodeStatus decodeLenOperand(MCInst &Inst, uint64_t Imm,270uint64_t Address,271const MCDisassembler *Decoder) {272if (!isUInt<N>(Imm))273return MCDisassembler::Fail;274Inst.addOperand(MCOperand::createImm(Imm + 1));275return MCDisassembler::Success;276}277278template <unsigned N>279static DecodeStatus decodePCDBLOperand(MCInst &Inst, uint64_t Imm,280uint64_t Address, bool isBranch,281const MCDisassembler *Decoder) {282assert(isUInt<N>(Imm) && "Invalid PC-relative offset");283uint64_t Value = SignExtend64<N>(Imm) * 2 + Address;284285if (!tryAddingSymbolicOperand(Value, isBranch, Address, 2, N / 8,286Inst, Decoder))287Inst.addOperand(MCOperand::createImm(Value));288289return MCDisassembler::Success;290}291292static DecodeStatus decodePC12DBLBranchOperand(MCInst &Inst, uint64_t Imm,293uint64_t Address,294const MCDisassembler *Decoder) {295return decodePCDBLOperand<12>(Inst, Imm, Address, true, Decoder);296}297298static DecodeStatus decodePC16DBLBranchOperand(MCInst &Inst, uint64_t Imm,299uint64_t Address,300const MCDisassembler *Decoder) {301return decodePCDBLOperand<16>(Inst, Imm, Address, true, Decoder);302}303304static DecodeStatus decodePC24DBLBranchOperand(MCInst &Inst, uint64_t Imm,305uint64_t Address,306const MCDisassembler *Decoder) {307return decodePCDBLOperand<24>(Inst, Imm, Address, true, Decoder);308}309310static DecodeStatus decodePC32DBLBranchOperand(MCInst &Inst, uint64_t Imm,311uint64_t Address,312const MCDisassembler *Decoder) {313return decodePCDBLOperand<32>(Inst, Imm, Address, true, Decoder);314}315316static DecodeStatus decodePC32DBLOperand(MCInst &Inst, uint64_t Imm,317uint64_t Address,318const MCDisassembler *Decoder) {319return decodePCDBLOperand<32>(Inst, Imm, Address, false, Decoder);320}321322#include "SystemZGenDisassemblerTables.inc"323324DecodeStatus SystemZDisassembler::getInstruction(MCInst &MI, uint64_t &Size,325ArrayRef<uint8_t> Bytes,326uint64_t Address,327raw_ostream &CS) const {328// Get the first two bytes of the instruction.329Size = 0;330if (Bytes.size() < 2)331return MCDisassembler::Fail;332333// The top 2 bits of the first byte specify the size.334const uint8_t *Table;335if (Bytes[0] < 0x40) {336Size = 2;337Table = DecoderTable16;338} else if (Bytes[0] < 0xc0) {339Size = 4;340Table = DecoderTable32;341} else {342Size = 6;343Table = DecoderTable48;344}345346// Read any remaining bytes.347if (Bytes.size() < Size) {348Size = Bytes.size();349return MCDisassembler::Fail;350}351352// Construct the instruction.353uint64_t Inst = 0;354for (uint64_t I = 0; I < Size; ++I)355Inst = (Inst << 8) | Bytes[I];356357return decodeInstruction(Table, MI, Inst, Address, this, STI);358}359360361