104eeddc0SDimitry Andric //===-- M68kDisassembler.cpp - Disassembler for M68k ------------*- C++ -*-===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric // 9fe6060f1SDimitry Andric // This file is part of the M68k Disassembler. 10fe6060f1SDimitry Andric // 11fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 12fe6060f1SDimitry Andric 13fe6060f1SDimitry Andric #include "M68k.h" 14fe6060f1SDimitry Andric #include "M68kRegisterInfo.h" 15fe6060f1SDimitry Andric #include "M68kSubtarget.h" 16fe6060f1SDimitry Andric #include "MCTargetDesc/M68kMCCodeEmitter.h" 17fe6060f1SDimitry Andric #include "MCTargetDesc/M68kMCTargetDesc.h" 18fe6060f1SDimitry Andric #include "TargetInfo/M68kTargetInfo.h" 19fe6060f1SDimitry Andric 20fe6060f1SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 21fe6060f1SDimitry Andric #include "llvm/MC/MCContext.h" 22fe6060f1SDimitry Andric #include "llvm/MC/MCDisassembler/MCDisassembler.h" 2381ad6265SDimitry Andric #include "llvm/MC/MCDecoderOps.h" 24fe6060f1SDimitry Andric #include "llvm/MC/MCInst.h" 25349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 2681ad6265SDimitry Andric #include "llvm/Support/Endian.h" 2781ad6265SDimitry Andric #include "llvm/Support/ErrorHandling.h" 28fe6060f1SDimitry Andric 29fe6060f1SDimitry Andric using namespace llvm; 30fe6060f1SDimitry Andric 31fe6060f1SDimitry Andric #define DEBUG_TYPE "m68k-disassembler" 32fe6060f1SDimitry Andric 33fe6060f1SDimitry Andric typedef MCDisassembler::DecodeStatus DecodeStatus; 34fe6060f1SDimitry Andric 3581ad6265SDimitry Andric static const unsigned RegisterDecode[] = { 3681ad6265SDimitry Andric M68k::D0, M68k::D1, M68k::D2, M68k::D3, M68k::D4, M68k::D5, 3781ad6265SDimitry Andric M68k::D6, M68k::D7, M68k::A0, M68k::A1, M68k::A2, M68k::A3, 3806c3fb27SDimitry Andric M68k::A4, M68k::A5, M68k::A6, M68k::SP, M68k::FP0, M68k::FP1, 39*5f757f3fSDimitry Andric M68k::FP2, M68k::FP3, M68k::FP4, M68k::FP5, M68k::FP6, M68k::FP7, 40*5f757f3fSDimitry Andric M68k::FPIAR, M68k::FPS, M68k::FPC}; 41fe6060f1SDimitry Andric 4281ad6265SDimitry Andric static DecodeStatus DecodeRegisterClass(MCInst &Inst, uint64_t RegNo, 4381ad6265SDimitry Andric uint64_t Address, const void *Decoder) { 4406c3fb27SDimitry Andric if (RegNo >= 24) 4581ad6265SDimitry Andric return DecodeStatus::Fail; 4681ad6265SDimitry Andric Inst.addOperand(MCOperand::createReg(RegisterDecode[RegNo])); 4781ad6265SDimitry Andric return DecodeStatus::Success; 48fe6060f1SDimitry Andric } 49fe6060f1SDimitry Andric 5081ad6265SDimitry Andric static DecodeStatus DecodeDR32RegisterClass(MCInst &Inst, uint64_t RegNo, 5181ad6265SDimitry Andric uint64_t Address, 5281ad6265SDimitry Andric const void *Decoder) { 5381ad6265SDimitry Andric return DecodeRegisterClass(Inst, RegNo, Address, Decoder); 54fe6060f1SDimitry Andric } 55fe6060f1SDimitry Andric 5681ad6265SDimitry Andric static DecodeStatus DecodeDR16RegisterClass(MCInst &Inst, uint64_t RegNo, 5781ad6265SDimitry Andric uint64_t Address, 5881ad6265SDimitry Andric const void *Decoder) { 5981ad6265SDimitry Andric return DecodeRegisterClass(Inst, RegNo, Address, Decoder); 6081ad6265SDimitry Andric } 6181ad6265SDimitry Andric 6281ad6265SDimitry Andric static DecodeStatus DecodeDR8RegisterClass(MCInst &Inst, uint64_t RegNo, 6381ad6265SDimitry Andric uint64_t Address, 6481ad6265SDimitry Andric const void *Decoder) { 6581ad6265SDimitry Andric return DecodeRegisterClass(Inst, RegNo, Address, Decoder); 6681ad6265SDimitry Andric } 6781ad6265SDimitry Andric 6881ad6265SDimitry Andric static DecodeStatus DecodeAR32RegisterClass(MCInst &Inst, uint64_t RegNo, 6981ad6265SDimitry Andric uint64_t Address, 7081ad6265SDimitry Andric const void *Decoder) { 7181ad6265SDimitry Andric return DecodeRegisterClass(Inst, RegNo | 8ULL, Address, Decoder); 7281ad6265SDimitry Andric } 7381ad6265SDimitry Andric 7481ad6265SDimitry Andric static DecodeStatus DecodeAR16RegisterClass(MCInst &Inst, uint64_t RegNo, 7581ad6265SDimitry Andric uint64_t Address, 7681ad6265SDimitry Andric const void *Decoder) { 7781ad6265SDimitry Andric return DecodeRegisterClass(Inst, RegNo | 8ULL, Address, Decoder); 7881ad6265SDimitry Andric } 7981ad6265SDimitry Andric 8081ad6265SDimitry Andric static DecodeStatus DecodeXR32RegisterClass(MCInst &Inst, uint64_t RegNo, 8181ad6265SDimitry Andric uint64_t Address, 8281ad6265SDimitry Andric const void *Decoder) { 8381ad6265SDimitry Andric return DecodeRegisterClass(Inst, RegNo, Address, Decoder); 8481ad6265SDimitry Andric } 8581ad6265SDimitry Andric 8681ad6265SDimitry Andric static DecodeStatus DecodeXR16RegisterClass(MCInst &Inst, uint64_t RegNo, 8781ad6265SDimitry Andric uint64_t Address, 8881ad6265SDimitry Andric const void *Decoder) { 8981ad6265SDimitry Andric return DecodeRegisterClass(Inst, RegNo, Address, Decoder); 9081ad6265SDimitry Andric } 9181ad6265SDimitry Andric 9206c3fb27SDimitry Andric static DecodeStatus DecodeFPDRRegisterClass(MCInst &Inst, uint64_t RegNo, 9306c3fb27SDimitry Andric uint64_t Address, 9406c3fb27SDimitry Andric const void *Decoder) { 9506c3fb27SDimitry Andric return DecodeRegisterClass(Inst, RegNo | 16ULL, Address, Decoder); 9606c3fb27SDimitry Andric } 9706c3fb27SDimitry Andric #define DecodeFPDR32RegisterClass DecodeFPDRRegisterClass 9806c3fb27SDimitry Andric #define DecodeFPDR64RegisterClass DecodeFPDRRegisterClass 9906c3fb27SDimitry Andric #define DecodeFPDR80RegisterClass DecodeFPDRRegisterClass 10006c3fb27SDimitry Andric 101*5f757f3fSDimitry Andric static DecodeStatus DecodeFPCSCRegisterClass(MCInst &Inst, uint64_t RegNo, 102*5f757f3fSDimitry Andric uint64_t Address, 103*5f757f3fSDimitry Andric const void *Decoder) { 104*5f757f3fSDimitry Andric return DecodeRegisterClass(Inst, (RegNo >> 1) + 24, Address, Decoder); 105*5f757f3fSDimitry Andric } 106*5f757f3fSDimitry Andric #define DecodeFPICRegisterClass DecodeFPCSCRegisterClass 107*5f757f3fSDimitry Andric 10881ad6265SDimitry Andric static DecodeStatus DecodeCCRCRegisterClass(MCInst &Inst, APInt &Insn, 10981ad6265SDimitry Andric uint64_t Address, 11081ad6265SDimitry Andric const void *Decoder) { 11181ad6265SDimitry Andric llvm_unreachable("unimplemented"); 11281ad6265SDimitry Andric } 11381ad6265SDimitry Andric 114bdd1243dSDimitry Andric static DecodeStatus DecodeImm32(MCInst &Inst, uint64_t Imm, uint64_t Address, 115bdd1243dSDimitry Andric const void *Decoder) { 116bdd1243dSDimitry Andric Inst.addOperand(MCOperand::createImm(M68k::swapWord<uint32_t>(Imm))); 117bdd1243dSDimitry Andric return DecodeStatus::Success; 118bdd1243dSDimitry Andric } 119bdd1243dSDimitry Andric 12081ad6265SDimitry Andric #include "M68kGenDisassemblerTable.inc" 121fe6060f1SDimitry Andric 12206c3fb27SDimitry Andric #undef DecodeFPDR32RegisterClass 12306c3fb27SDimitry Andric #undef DecodeFPDR64RegisterClass 12406c3fb27SDimitry Andric #undef DecodeFPDR80RegisterClass 125*5f757f3fSDimitry Andric #undef DecodeFPICRegisterClass 12606c3fb27SDimitry Andric 127fe6060f1SDimitry Andric /// A disassembler class for M68k. 12881ad6265SDimitry Andric struct M68kDisassembler : public MCDisassembler { 12981ad6265SDimitry Andric M68kDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) 13081ad6265SDimitry Andric : MCDisassembler(STI, Ctx) {} 131fe6060f1SDimitry Andric virtual ~M68kDisassembler() {} 132fe6060f1SDimitry Andric 133fe6060f1SDimitry Andric DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, 134fe6060f1SDimitry Andric ArrayRef<uint8_t> Bytes, uint64_t Address, 135fe6060f1SDimitry Andric raw_ostream &CStream) const override; 136fe6060f1SDimitry Andric }; 137fe6060f1SDimitry Andric 138fe6060f1SDimitry Andric DecodeStatus M68kDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, 139fe6060f1SDimitry Andric ArrayRef<uint8_t> Bytes, 140fe6060f1SDimitry Andric uint64_t Address, 141fe6060f1SDimitry Andric raw_ostream &CStream) const { 14281ad6265SDimitry Andric DecodeStatus Result; 14381ad6265SDimitry Andric auto MakeUp = [&](APInt &Insn, unsigned InstrBits) { 14481ad6265SDimitry Andric unsigned Idx = Insn.getBitWidth() >> 3; 14581ad6265SDimitry Andric unsigned RoundUp = alignTo(InstrBits, Align(16)); 14681ad6265SDimitry Andric if (RoundUp > Insn.getBitWidth()) 14781ad6265SDimitry Andric Insn = Insn.zext(RoundUp); 14881ad6265SDimitry Andric RoundUp = RoundUp >> 3; 14981ad6265SDimitry Andric for (; Idx < RoundUp; Idx += 2) { 15081ad6265SDimitry Andric Insn.insertBits(support::endian::read16be(&Bytes[Idx]), Idx * 8, 16); 151fe6060f1SDimitry Andric } 152fe6060f1SDimitry Andric }; 15381ad6265SDimitry Andric APInt Insn(16, support::endian::read16be(Bytes.data())); 15481ad6265SDimitry Andric // 2 bytes of data are consumed, so set Size to 2 15581ad6265SDimitry Andric // If we don't do this, disassembler may generate result even 15681ad6265SDimitry Andric // the encoding is invalid. We need to let it fail correctly. 15781ad6265SDimitry Andric Size = 2; 15881ad6265SDimitry Andric Result = decodeInstruction(DecoderTable80, Instr, Insn, Address, this, STI, 15981ad6265SDimitry Andric MakeUp); 16081ad6265SDimitry Andric if (Result == DecodeStatus::Success) 16181ad6265SDimitry Andric Size = InstrLenTable[Instr.getOpcode()] >> 3; 16281ad6265SDimitry Andric return Result; 163fe6060f1SDimitry Andric } 164fe6060f1SDimitry Andric 165fe6060f1SDimitry Andric static MCDisassembler *createM68kDisassembler(const Target &T, 166fe6060f1SDimitry Andric const MCSubtargetInfo &STI, 167fe6060f1SDimitry Andric MCContext &Ctx) { 16881ad6265SDimitry Andric return new M68kDisassembler(STI, Ctx); 169fe6060f1SDimitry Andric } 170fe6060f1SDimitry Andric 171fe6060f1SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kDisassembler() { 172fe6060f1SDimitry Andric // Register the disassembler. 173fe6060f1SDimitry Andric TargetRegistry::RegisterMCDisassembler(getTheM68kTarget(), 174fe6060f1SDimitry Andric createM68kDisassembler); 175fe6060f1SDimitry Andric } 176