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
DecodeRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)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
DecodeDR32RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)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
DecodeDR16RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)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
DecodeDR8RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)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
DecodeAR32RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)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
DecodeAR16RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)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
DecodeXR32RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)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
DecodeXR16RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)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
DecodeFPDRRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)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
DecodeFPCSCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)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
DecodeCCRCRegisterClass(MCInst & Inst,APInt & Insn,uint64_t Address,const void * Decoder)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
DecodeImm32(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)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 {
M68kDisassemblerM68kDisassembler12981ad6265SDimitry Andric M68kDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
13081ad6265SDimitry Andric : MCDisassembler(STI, Ctx) {}
~M68kDisassemblerM68kDisassembler131fe6060f1SDimitry 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
getInstruction(MCInst & Instr,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & CStream) const138fe6060f1SDimitry 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
createM68kDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)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
LLVMInitializeM68kDisassembler()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