365 lines · cpp
1//===-- SystemZDisassembler.cpp - Disassembler for SystemZ ------*- 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/SystemZMCTargetDesc.h"10#include "TargetInfo/SystemZTargetInfo.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/MathExtras.h"19#include <cassert>20#include <cstdint>21 22using namespace llvm;23using namespace llvm::MCD;24 25#define DEBUG_TYPE "systemz-disassembler"26 27typedef MCDisassembler::DecodeStatus DecodeStatus;28 29namespace {30 31class SystemZDisassembler : public MCDisassembler {32public:33 SystemZDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)34 : MCDisassembler(STI, Ctx) {}35 ~SystemZDisassembler() override = default;36 37 DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,38 ArrayRef<uint8_t> Bytes, uint64_t Address,39 raw_ostream &CStream) const override;40};41 42} // end anonymous namespace43 44static MCDisassembler *createSystemZDisassembler(const Target &T,45 const MCSubtargetInfo &STI,46 MCContext &Ctx) {47 return new SystemZDisassembler(STI, Ctx);48}49 50// NOLINTNEXTLINE(readability-identifier-naming)51extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void52LLVMInitializeSystemZDisassembler() {53 // Register the disassembler.54 TargetRegistry::RegisterMCDisassembler(getTheSystemZTarget(),55 createSystemZDisassembler);56}57 58/// tryAddingSymbolicOperand - trys to add a symbolic operand in place of the59/// immediate Value in the MCInst.60///61/// @param Value - The immediate Value, has had any PC adjustment made by62/// the caller.63/// @param isBranch - If the instruction is a branch instruction64/// @param Address - The starting address of the instruction65/// @param Offset - The byte offset to this immediate in the instruction66/// @param Width - The byte width of this immediate in the instruction67///68/// If the getOpInfo() function was set when setupForSymbolicDisassembly() was69/// called then that function is called to get any symbolic information for the70/// immediate in the instruction using the Address, Offset and Width. If that71/// returns non-zero then the symbolic information it returns is used to create72/// an MCExpr and that is added as an operand to the MCInst. If getOpInfo()73/// returns zero and isBranch is true then a symbol look up for immediate Value74/// is done and if a symbol is found an MCExpr is created with that, else75/// an MCExpr with the immediate Value is created. This function returns true76/// if it adds an operand to the MCInst and false otherwise.77static bool tryAddingSymbolicOperand(int64_t Value, bool IsBranch,78 uint64_t Address, uint64_t Offset,79 uint64_t Width, MCInst &MI,80 const MCDisassembler *Decoder) {81 return Decoder->tryAddingSymbolicOperand(MI, Value, Address, IsBranch, Offset,82 Width, /*InstSize=*/0);83}84 85static DecodeStatus decodeRegisterClass(MCInst &Inst, uint64_t RegNo,86 const unsigned *Regs, unsigned Size,87 bool IsAddr = false) {88 assert(RegNo < Size && "Invalid register");89 if (IsAddr && RegNo == 0) {90 RegNo = SystemZ::NoRegister;91 } else {92 RegNo = Regs[RegNo];93 if (RegNo == 0)94 return MCDisassembler::Fail;95 }96 Inst.addOperand(MCOperand::createReg(RegNo));97 return MCDisassembler::Success;98}99 100static DecodeStatus DecodeGR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,101 uint64_t Address,102 const MCDisassembler *Decoder) {103 return decodeRegisterClass(Inst, RegNo, SystemZMC::GR32Regs, 16);104}105 106static DecodeStatus DecodeGRH32BitRegisterClass(MCInst &Inst, uint64_t RegNo,107 uint64_t Address,108 const MCDisassembler *Decoder) {109 return decodeRegisterClass(Inst, RegNo, SystemZMC::GRH32Regs, 16);110}111 112static DecodeStatus DecodeGR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,113 uint64_t Address,114 const MCDisassembler *Decoder) {115 return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs, 16);116}117 118static DecodeStatus DecodeGR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,119 uint64_t Address,120 const MCDisassembler *Decoder) {121 return decodeRegisterClass(Inst, RegNo, SystemZMC::GR128Regs, 16);122}123 124static DecodeStatus125DecodeADDR32BitRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,126 const MCDisassembler *Decoder) {127 return decodeRegisterClass(Inst, RegNo, SystemZMC::GR32Regs, 16, true);128}129 130static DecodeStatus131DecodeADDR64BitRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,132 const MCDisassembler *Decoder) {133 return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs, 16, true);134}135 136static DecodeStatus DecodeFP32BitRegisterClass(MCInst &Inst, uint64_t RegNo,137 uint64_t Address,138 const MCDisassembler *Decoder) {139 return decodeRegisterClass(Inst, RegNo, SystemZMC::FP32Regs, 16);140}141 142static DecodeStatus DecodeFP64BitRegisterClass(MCInst &Inst, uint64_t RegNo,143 uint64_t Address,144 const MCDisassembler *Decoder) {145 return decodeRegisterClass(Inst, RegNo, SystemZMC::FP64Regs, 16);146}147 148static DecodeStatus DecodeFP128BitRegisterClass(MCInst &Inst, uint64_t RegNo,149 uint64_t Address,150 const MCDisassembler *Decoder) {151 return decodeRegisterClass(Inst, RegNo, SystemZMC::FP128Regs, 16);152}153 154static DecodeStatus DecodeVR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,155 uint64_t Address,156 const MCDisassembler *Decoder) {157 return decodeRegisterClass(Inst, RegNo, SystemZMC::VR32Regs, 32);158}159 160static DecodeStatus DecodeVR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,161 uint64_t Address,162 const MCDisassembler *Decoder) {163 return decodeRegisterClass(Inst, RegNo, SystemZMC::VR64Regs, 32);164}165 166static DecodeStatus DecodeVR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,167 uint64_t Address,168 const MCDisassembler *Decoder) {169 return decodeRegisterClass(Inst, RegNo, SystemZMC::VR128Regs, 32);170}171 172static DecodeStatus DecodeAR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,173 uint64_t Address,174 const MCDisassembler *Decoder) {175 return decodeRegisterClass(Inst, RegNo, SystemZMC::AR32Regs, 16);176}177 178static DecodeStatus DecodeCR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,179 uint64_t Address,180 const MCDisassembler *Decoder) {181 return decodeRegisterClass(Inst, RegNo, SystemZMC::CR64Regs, 16);182}183 184template<unsigned N>185static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm) {186 if (!isUInt<N>(Imm))187 return MCDisassembler::Fail;188 Inst.addOperand(MCOperand::createImm(Imm));189 return MCDisassembler::Success;190}191 192template<unsigned N>193static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm) {194 if (!isUInt<N>(Imm))195 return MCDisassembler::Fail;196 Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm)));197 return MCDisassembler::Success;198}199 200static DecodeStatus decodeU1ImmOperand(MCInst &Inst, uint64_t Imm,201 uint64_t Address,202 const MCDisassembler *Decoder) {203 return decodeUImmOperand<1>(Inst, Imm);204}205 206static DecodeStatus decodeU2ImmOperand(MCInst &Inst, uint64_t Imm,207 uint64_t Address,208 const MCDisassembler *Decoder) {209 return decodeUImmOperand<2>(Inst, Imm);210}211 212static DecodeStatus decodeU3ImmOperand(MCInst &Inst, uint64_t Imm,213 uint64_t Address,214 const MCDisassembler *Decoder) {215 return decodeUImmOperand<3>(Inst, Imm);216}217 218static DecodeStatus decodeU4ImmOperand(MCInst &Inst, uint64_t Imm,219 uint64_t Address,220 const MCDisassembler *Decoder) {221 return decodeUImmOperand<4>(Inst, Imm);222}223 224static DecodeStatus decodeU8ImmOperand(MCInst &Inst, uint64_t Imm,225 uint64_t Address,226 const MCDisassembler *Decoder) {227 return decodeUImmOperand<8>(Inst, Imm);228}229 230static DecodeStatus decodeU12ImmOperand(MCInst &Inst, uint64_t Imm,231 uint64_t Address,232 const MCDisassembler *Decoder) {233 return decodeUImmOperand<12>(Inst, Imm);234}235 236static DecodeStatus decodeU16ImmOperand(MCInst &Inst, uint64_t Imm,237 uint64_t Address,238 const MCDisassembler *Decoder) {239 return decodeUImmOperand<16>(Inst, Imm);240}241 242static DecodeStatus decodeU32ImmOperand(MCInst &Inst, uint64_t Imm,243 uint64_t Address,244 const MCDisassembler *Decoder) {245 return decodeUImmOperand<32>(Inst, Imm);246}247 248static DecodeStatus decodeS8ImmOperand(MCInst &Inst, uint64_t Imm,249 uint64_t Address,250 const MCDisassembler *Decoder) {251 return decodeSImmOperand<8>(Inst, Imm);252}253 254static DecodeStatus decodeS16ImmOperand(MCInst &Inst, uint64_t Imm,255 uint64_t Address,256 const MCDisassembler *Decoder) {257 return decodeSImmOperand<16>(Inst, Imm);258}259 260static DecodeStatus decodeS20ImmOperand(MCInst &Inst, uint64_t Imm,261 uint64_t Address,262 const MCDisassembler *Decoder) {263 return decodeSImmOperand<20>(Inst, Imm);264}265 266static DecodeStatus decodeS32ImmOperand(MCInst &Inst, uint64_t Imm,267 uint64_t Address,268 const MCDisassembler *Decoder) {269 return decodeSImmOperand<32>(Inst, Imm);270}271 272template <unsigned N>273static DecodeStatus decodeLenOperand(MCInst &Inst, uint64_t Imm,274 uint64_t Address,275 const MCDisassembler *Decoder) {276 if (!isUInt<N>(Imm))277 return MCDisassembler::Fail;278 Inst.addOperand(MCOperand::createImm(Imm + 1));279 return MCDisassembler::Success;280}281 282template <unsigned N>283static DecodeStatus decodePCDBLOperand(MCInst &Inst, uint64_t Imm,284 uint64_t Address, bool isBranch,285 const MCDisassembler *Decoder) {286 assert(isUInt<N>(Imm) && "Invalid PC-relative offset");287 uint64_t Value = SignExtend64<N>(Imm) * 2;288 289 if (!tryAddingSymbolicOperand(Value + Address, isBranch, Address, 2, N / 8,290 Inst, Decoder))291 Inst.addOperand(MCOperand::createImm(Value));292 293 return MCDisassembler::Success;294}295 296static DecodeStatus decodePC12DBLBranchOperand(MCInst &Inst, uint64_t Imm,297 uint64_t Address,298 const MCDisassembler *Decoder) {299 return decodePCDBLOperand<12>(Inst, Imm, Address, true, Decoder);300}301 302static DecodeStatus decodePC16DBLBranchOperand(MCInst &Inst, uint64_t Imm,303 uint64_t Address,304 const MCDisassembler *Decoder) {305 return decodePCDBLOperand<16>(Inst, Imm, Address, true, Decoder);306}307 308static DecodeStatus decodePC24DBLBranchOperand(MCInst &Inst, uint64_t Imm,309 uint64_t Address,310 const MCDisassembler *Decoder) {311 return decodePCDBLOperand<24>(Inst, Imm, Address, true, Decoder);312}313 314static DecodeStatus decodePC32DBLBranchOperand(MCInst &Inst, uint64_t Imm,315 uint64_t Address,316 const MCDisassembler *Decoder) {317 return decodePCDBLOperand<32>(Inst, Imm, Address, true, Decoder);318}319 320static DecodeStatus decodePC32DBLOperand(MCInst &Inst, uint64_t Imm,321 uint64_t Address,322 const MCDisassembler *Decoder) {323 return decodePCDBLOperand<32>(Inst, Imm, Address, false, Decoder);324}325 326#include "SystemZGenDisassemblerTables.inc"327 328DecodeStatus SystemZDisassembler::getInstruction(MCInst &MI, uint64_t &Size,329 ArrayRef<uint8_t> Bytes,330 uint64_t Address,331 raw_ostream &CS) const {332 CommentStream = &CS;333 334 // Get the first two bytes of the instruction.335 Size = 0;336 if (Bytes.size() < 2)337 return MCDisassembler::Fail;338 339 // The top 2 bits of the first byte specify the size.340 const uint8_t *Table;341 if (Bytes[0] < 0x40) {342 Size = 2;343 Table = DecoderTable16;344 } else if (Bytes[0] < 0xc0) {345 Size = 4;346 Table = DecoderTable32;347 } else {348 Size = 6;349 Table = DecoderTable48;350 }351 352 // Read any remaining bytes.353 if (Bytes.size() < Size) {354 Size = Bytes.size();355 return MCDisassembler::Fail;356 }357 358 // Construct the instruction.359 uint64_t Inst = 0;360 for (uint64_t I = 0; I < Size; ++I)361 Inst = (Inst << 8) | Bytes[I];362 363 return decodeInstruction(Table, MI, Inst, Address, this, STI);364}365