xref: /llvm-project/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp (revision a0d77492110cce44d563166ed7ce21fdb3670f64)
16bf22ae4SJim Lin //===-- M68kDisassembler.cpp - Disassembler for M68k ------------*- C++ -*-===//
222211857SRicky Taylor //
322211857SRicky Taylor // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
422211857SRicky Taylor // See https://llvm.org/LICENSE.txt for license information.
522211857SRicky Taylor // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
622211857SRicky Taylor //
722211857SRicky Taylor //===----------------------------------------------------------------------===//
822211857SRicky Taylor //
922211857SRicky Taylor // This file is part of the M68k Disassembler.
1022211857SRicky Taylor //
1122211857SRicky Taylor //===----------------------------------------------------------------------===//
1222211857SRicky Taylor 
1322211857SRicky Taylor #include "M68k.h"
1422211857SRicky Taylor #include "M68kRegisterInfo.h"
1522211857SRicky Taylor #include "M68kSubtarget.h"
1622211857SRicky Taylor #include "MCTargetDesc/M68kMCCodeEmitter.h"
1722211857SRicky Taylor #include "MCTargetDesc/M68kMCTargetDesc.h"
1822211857SRicky Taylor #include "TargetInfo/M68kTargetInfo.h"
1922211857SRicky Taylor 
2022211857SRicky Taylor #include "llvm/MC/MCAsmInfo.h"
2122211857SRicky Taylor #include "llvm/MC/MCContext.h"
22cf0b6df6SSheng #include "llvm/MC/MCDecoderOps.h"
234cce1074Sknickish #include "llvm/MC/MCDisassembler/MCDisassembler.h"
2422211857SRicky Taylor #include "llvm/MC/MCInst.h"
2589b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
26cf0b6df6SSheng #include "llvm/Support/Endian.h"
27cf0b6df6SSheng #include "llvm/Support/ErrorHandling.h"
2822211857SRicky Taylor 
2922211857SRicky Taylor using namespace llvm;
3022211857SRicky Taylor 
3122211857SRicky Taylor #define DEBUG_TYPE "m68k-disassembler"
3222211857SRicky Taylor 
3322211857SRicky Taylor typedef MCDisassembler::DecodeStatus DecodeStatus;
3422211857SRicky Taylor 
35cf0b6df6SSheng static const unsigned RegisterDecode[] = {
36cf0b6df6SSheng     M68k::D0,    M68k::D1,  M68k::D2,  M68k::D3,  M68k::D4,  M68k::D5,
37cf0b6df6SSheng     M68k::D6,    M68k::D7,  M68k::A0,  M68k::A1,  M68k::A2,  M68k::A3,
387486b7b6SMin-Yih Hsu     M68k::A4,    M68k::A5,  M68k::A6,  M68k::SP,  M68k::FP0, M68k::FP1,
39d2672a55SMin-Yih Hsu     M68k::FP2,   M68k::FP3, M68k::FP4, M68k::FP5, M68k::FP6, M68k::FP7,
40d2672a55SMin-Yih Hsu     M68k::FPIAR, M68k::FPS, M68k::FPC};
4122211857SRicky Taylor 
42cf0b6df6SSheng static DecodeStatus DecodeRegisterClass(MCInst &Inst, uint64_t RegNo,
43cf0b6df6SSheng                                         uint64_t Address, const void *Decoder) {
447486b7b6SMin-Yih Hsu   if (RegNo >= 24)
45cf0b6df6SSheng     return DecodeStatus::Fail;
46cf0b6df6SSheng   Inst.addOperand(MCOperand::createReg(RegisterDecode[RegNo]));
47cf0b6df6SSheng   return DecodeStatus::Success;
4822211857SRicky Taylor }
4922211857SRicky Taylor 
50cf0b6df6SSheng static DecodeStatus DecodeDR32RegisterClass(MCInst &Inst, uint64_t RegNo,
51cf0b6df6SSheng                                             uint64_t Address,
52cf0b6df6SSheng                                             const void *Decoder) {
53cf0b6df6SSheng   return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
5422211857SRicky Taylor }
5522211857SRicky Taylor 
56cf0b6df6SSheng static DecodeStatus DecodeDR16RegisterClass(MCInst &Inst, uint64_t RegNo,
57cf0b6df6SSheng                                             uint64_t Address,
58cf0b6df6SSheng                                             const void *Decoder) {
59cf0b6df6SSheng   return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
60cf0b6df6SSheng }
61cf0b6df6SSheng 
62cf0b6df6SSheng static DecodeStatus DecodeDR8RegisterClass(MCInst &Inst, uint64_t RegNo,
63cf0b6df6SSheng                                            uint64_t Address,
64cf0b6df6SSheng                                            const void *Decoder) {
65cf0b6df6SSheng   return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
66cf0b6df6SSheng }
67cf0b6df6SSheng 
68cf0b6df6SSheng static DecodeStatus DecodeAR32RegisterClass(MCInst &Inst, uint64_t RegNo,
69cf0b6df6SSheng                                             uint64_t Address,
70cf0b6df6SSheng                                             const void *Decoder) {
71cf0b6df6SSheng   return DecodeRegisterClass(Inst, RegNo | 8ULL, Address, Decoder);
72cf0b6df6SSheng }
73cf0b6df6SSheng 
74cf0b6df6SSheng static DecodeStatus DecodeAR16RegisterClass(MCInst &Inst, uint64_t RegNo,
75cf0b6df6SSheng                                             uint64_t Address,
76cf0b6df6SSheng                                             const void *Decoder) {
77cf0b6df6SSheng   return DecodeRegisterClass(Inst, RegNo | 8ULL, Address, Decoder);
78cf0b6df6SSheng }
79cf0b6df6SSheng 
80cf0b6df6SSheng static DecodeStatus DecodeXR32RegisterClass(MCInst &Inst, uint64_t RegNo,
81cf0b6df6SSheng                                             uint64_t Address,
82cf0b6df6SSheng                                             const void *Decoder) {
83cf0b6df6SSheng   return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
84cf0b6df6SSheng }
85cf0b6df6SSheng 
864cce1074Sknickish static DecodeStatus DecodeXR32RegisterClass(MCInst &Inst, APInt RegNo,
874cce1074Sknickish                                             uint64_t Address,
884cce1074Sknickish                                             const void *Decoder) {
894cce1074Sknickish   return DecodeRegisterClass(Inst, RegNo.getZExtValue(), Address, Decoder);
904cce1074Sknickish }
914cce1074Sknickish 
92cf0b6df6SSheng static DecodeStatus DecodeXR16RegisterClass(MCInst &Inst, uint64_t RegNo,
93cf0b6df6SSheng                                             uint64_t Address,
94cf0b6df6SSheng                                             const void *Decoder) {
95cf0b6df6SSheng   return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
96cf0b6df6SSheng }
97cf0b6df6SSheng 
987486b7b6SMin-Yih Hsu static DecodeStatus DecodeFPDRRegisterClass(MCInst &Inst, uint64_t RegNo,
997486b7b6SMin-Yih Hsu                                             uint64_t Address,
1007486b7b6SMin-Yih Hsu                                             const void *Decoder) {
1017486b7b6SMin-Yih Hsu   return DecodeRegisterClass(Inst, RegNo | 16ULL, Address, Decoder);
1027486b7b6SMin-Yih Hsu }
1037486b7b6SMin-Yih Hsu #define DecodeFPDR32RegisterClass DecodeFPDRRegisterClass
1047486b7b6SMin-Yih Hsu #define DecodeFPDR64RegisterClass DecodeFPDRRegisterClass
1057486b7b6SMin-Yih Hsu #define DecodeFPDR80RegisterClass DecodeFPDRRegisterClass
1067486b7b6SMin-Yih Hsu 
107d2672a55SMin-Yih Hsu static DecodeStatus DecodeFPCSCRegisterClass(MCInst &Inst, uint64_t RegNo,
108d2672a55SMin-Yih Hsu                                              uint64_t Address,
109d2672a55SMin-Yih Hsu                                              const void *Decoder) {
110d2672a55SMin-Yih Hsu   return DecodeRegisterClass(Inst, (RegNo >> 1) + 24, Address, Decoder);
111d2672a55SMin-Yih Hsu }
112d2672a55SMin-Yih Hsu #define DecodeFPICRegisterClass DecodeFPCSCRegisterClass
113d2672a55SMin-Yih Hsu 
114cf0b6df6SSheng static DecodeStatus DecodeCCRCRegisterClass(MCInst &Inst, APInt &Insn,
115cf0b6df6SSheng                                             uint64_t Address,
116cf0b6df6SSheng                                             const void *Decoder) {
117cf0b6df6SSheng   llvm_unreachable("unimplemented");
118cf0b6df6SSheng }
119cf0b6df6SSheng 
120*a0d77492SJanis Heims static DecodeStatus DecodeSRCRegisterClass(MCInst &Inst, APInt &Insn,
121*a0d77492SJanis Heims                                            uint64_t Address,
122*a0d77492SJanis Heims                                            const void *Decoder) {
123*a0d77492SJanis Heims   llvm_unreachable("unimplemented");
124*a0d77492SJanis Heims }
125*a0d77492SJanis Heims 
126c40b158eSMin-Yih Hsu static DecodeStatus DecodeImm32(MCInst &Inst, uint64_t Imm, uint64_t Address,
127c40b158eSMin-Yih Hsu                                 const void *Decoder) {
128c40b158eSMin-Yih Hsu   Inst.addOperand(MCOperand::createImm(M68k::swapWord<uint32_t>(Imm)));
129c40b158eSMin-Yih Hsu   return DecodeStatus::Success;
130c40b158eSMin-Yih Hsu }
131c40b158eSMin-Yih Hsu 
132cf0b6df6SSheng #include "M68kGenDisassemblerTable.inc"
13322211857SRicky Taylor 
1347486b7b6SMin-Yih Hsu #undef DecodeFPDR32RegisterClass
1357486b7b6SMin-Yih Hsu #undef DecodeFPDR64RegisterClass
1367486b7b6SMin-Yih Hsu #undef DecodeFPDR80RegisterClass
137d2672a55SMin-Yih Hsu #undef DecodeFPICRegisterClass
1387486b7b6SMin-Yih Hsu 
13922211857SRicky Taylor /// A disassembler class for M68k.
14052d509f3SMin-Yih Hsu struct M68kDisassembler : public MCDisassembler {
14152d509f3SMin-Yih Hsu   M68kDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
14252d509f3SMin-Yih Hsu       : MCDisassembler(STI, Ctx) {}
14322211857SRicky Taylor   virtual ~M68kDisassembler() {}
14422211857SRicky Taylor 
14522211857SRicky Taylor   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
14622211857SRicky Taylor                               ArrayRef<uint8_t> Bytes, uint64_t Address,
14722211857SRicky Taylor                               raw_ostream &CStream) const override;
14822211857SRicky Taylor };
14922211857SRicky Taylor 
15022211857SRicky Taylor DecodeStatus M68kDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
15122211857SRicky Taylor                                               ArrayRef<uint8_t> Bytes,
15222211857SRicky Taylor                                               uint64_t Address,
15322211857SRicky Taylor                                               raw_ostream &CStream) const {
154cf0b6df6SSheng   DecodeStatus Result;
155cf0b6df6SSheng   auto MakeUp = [&](APInt &Insn, unsigned InstrBits) {
156cf0b6df6SSheng     unsigned Idx = Insn.getBitWidth() >> 3;
157cf0b6df6SSheng     unsigned RoundUp = alignTo(InstrBits, Align(16));
158df25f0d5SSheng     if (RoundUp > Insn.getBitWidth())
159017c9827SSheng       Insn = Insn.zext(RoundUp);
160cf0b6df6SSheng     RoundUp = RoundUp >> 3;
161cf0b6df6SSheng     for (; Idx < RoundUp; Idx += 2) {
162cf0b6df6SSheng       Insn.insertBits(support::endian::read16be(&Bytes[Idx]), Idx * 8, 16);
16322211857SRicky Taylor     }
16422211857SRicky Taylor   };
165cf0b6df6SSheng   APInt Insn(16, support::endian::read16be(Bytes.data()));
166a5d618b3SSheng   // 2 bytes of data are consumed, so set Size to 2
167a5d618b3SSheng   // If we don't do this, disassembler may generate result even
168a5d618b3SSheng   // the encoding is invalid. We need to let it fail correctly.
169a5d618b3SSheng   Size = 2;
170cf0b6df6SSheng   Result = decodeInstruction(DecoderTable80, Instr, Insn, Address, this, STI,
171cf0b6df6SSheng                              MakeUp);
172cf0b6df6SSheng   if (Result == DecodeStatus::Success)
173cf0b6df6SSheng     Size = InstrLenTable[Instr.getOpcode()] >> 3;
174cf0b6df6SSheng   return Result;
17522211857SRicky Taylor }
17622211857SRicky Taylor 
17722211857SRicky Taylor static MCDisassembler *createM68kDisassembler(const Target &T,
17822211857SRicky Taylor                                               const MCSubtargetInfo &STI,
17922211857SRicky Taylor                                               MCContext &Ctx) {
18052d509f3SMin-Yih Hsu   return new M68kDisassembler(STI, Ctx);
18122211857SRicky Taylor }
18222211857SRicky Taylor 
18322211857SRicky Taylor extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kDisassembler() {
18422211857SRicky Taylor   // Register the disassembler.
18522211857SRicky Taylor   TargetRegistry::RegisterMCDisassembler(getTheM68kTarget(),
18622211857SRicky Taylor                                          createM68kDisassembler);
18722211857SRicky Taylor }
188