diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp b/contrib/llvm-project/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp new file mode 100644 index 000000000000..ffe4869e8fe5 --- /dev/null +++ b/contrib/llvm-project/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp @@ -0,0 +1,153 @@ +//===-- M68kDisassembler.cpp - Disassembler for M68k ------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is part of the M68k Disassembler. +// +//===----------------------------------------------------------------------===// + +#include "M68k.h" +#include "M68kRegisterInfo.h" +#include "M68kSubtarget.h" +#include "MCTargetDesc/M68kMCCodeEmitter.h" +#include "MCTargetDesc/M68kMCTargetDesc.h" +#include "TargetInfo/M68kTargetInfo.h" + +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" +#include "llvm/MC/MCDecoderOps.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/TargetRegistry.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +#define DEBUG_TYPE "m68k-disassembler" + +typedef MCDisassembler::DecodeStatus DecodeStatus; + +static const unsigned RegisterDecode[] = { + M68k::D0, M68k::D1, M68k::D2, M68k::D3, M68k::D4, M68k::D5, + M68k::D6, M68k::D7, M68k::A0, M68k::A1, M68k::A2, M68k::A3, + M68k::A4, M68k::A5, M68k::A6, M68k::SP, +}; + +static DecodeStatus DecodeRegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, const void *Decoder) { + if (RegNo >= 16) + return DecodeStatus::Fail; + Inst.addOperand(MCOperand::createReg(RegisterDecode[RegNo])); + return DecodeStatus::Success; +} + +static DecodeStatus DecodeDR32RegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + return DecodeRegisterClass(Inst, RegNo, Address, Decoder); +} + +static DecodeStatus DecodeDR16RegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + return DecodeRegisterClass(Inst, RegNo, Address, Decoder); +} + +static DecodeStatus DecodeDR8RegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + return DecodeRegisterClass(Inst, RegNo, Address, Decoder); +} + +static DecodeStatus DecodeAR32RegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + return DecodeRegisterClass(Inst, RegNo | 8ULL, Address, Decoder); +} + +static DecodeStatus DecodeAR16RegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + return DecodeRegisterClass(Inst, RegNo | 8ULL, Address, Decoder); +} + +static DecodeStatus DecodeXR32RegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + return DecodeRegisterClass(Inst, RegNo, Address, Decoder); +} + +static DecodeStatus DecodeXR16RegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + return DecodeRegisterClass(Inst, RegNo, Address, Decoder); +} + +static DecodeStatus DecodeCCRCRegisterClass(MCInst &Inst, APInt &Insn, + uint64_t Address, + const void *Decoder) { + llvm_unreachable("unimplemented"); +} + +static DecodeStatus DecodeImm32(MCInst &Inst, uint64_t Imm, uint64_t Address, + const void *Decoder) { + Inst.addOperand(MCOperand::createImm(M68k::swapWord<uint32_t>(Imm))); + return DecodeStatus::Success; +} + +#include "M68kGenDisassemblerTable.inc" + +/// A disassembler class for M68k. +struct M68kDisassembler : public MCDisassembler { + M68kDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) + : MCDisassembler(STI, Ctx) {} + virtual ~M68kDisassembler() {} + + DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, + ArrayRef<uint8_t> Bytes, uint64_t Address, + raw_ostream &CStream) const override; +}; + +DecodeStatus M68kDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, + ArrayRef<uint8_t> Bytes, + uint64_t Address, + raw_ostream &CStream) const { + DecodeStatus Result; + auto MakeUp = [&](APInt &Insn, unsigned InstrBits) { + unsigned Idx = Insn.getBitWidth() >> 3; + unsigned RoundUp = alignTo(InstrBits, Align(16)); + if (RoundUp > Insn.getBitWidth()) + Insn = Insn.zext(RoundUp); + RoundUp = RoundUp >> 3; + for (; Idx < RoundUp; Idx += 2) { + Insn.insertBits(support::endian::read16be(&Bytes[Idx]), Idx * 8, 16); + } + }; + APInt Insn(16, support::endian::read16be(Bytes.data())); + // 2 bytes of data are consumed, so set Size to 2 + // If we don't do this, disassembler may generate result even + // the encoding is invalid. We need to let it fail correctly. + Size = 2; + Result = decodeInstruction(DecoderTable80, Instr, Insn, Address, this, STI, + MakeUp); + if (Result == DecodeStatus::Success) + Size = InstrLenTable[Instr.getOpcode()] >> 3; + return Result; +} + +static MCDisassembler *createM68kDisassembler(const Target &T, + const MCSubtargetInfo &STI, + MCContext &Ctx) { + return new M68kDisassembler(STI, Ctx); +} + +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kDisassembler() { + // Register the disassembler. + TargetRegistry::RegisterMCDisassembler(getTheM68kTarget(), + createM68kDisassembler); +} |