xref: /freebsd/contrib/llvm-project/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp (revision c2de0116c80176829406289da3b79b6e70855ea4)
1  //===-- M68kDisassembler.cpp - Disassembler for M68k ------------*- 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-exception
6  //
7  //===----------------------------------------------------------------------===//
8  //
9  // This file is part of the M68k Disassembler.
10  //
11  //===----------------------------------------------------------------------===//
12  
13  #include "M68k.h"
14  #include "M68kRegisterInfo.h"
15  #include "M68kSubtarget.h"
16  #include "MCTargetDesc/M68kMCCodeEmitter.h"
17  #include "MCTargetDesc/M68kMCTargetDesc.h"
18  #include "TargetInfo/M68kTargetInfo.h"
19  
20  #include "llvm/MC/MCAsmInfo.h"
21  #include "llvm/MC/MCContext.h"
22  #include "llvm/MC/MCDisassembler/MCDisassembler.h"
23  #include "llvm/MC/MCDecoderOps.h"
24  #include "llvm/MC/MCInst.h"
25  #include "llvm/MC/TargetRegistry.h"
26  #include "llvm/Support/Endian.h"
27  #include "llvm/Support/ErrorHandling.h"
28  
29  using namespace llvm;
30  
31  #define DEBUG_TYPE "m68k-disassembler"
32  
33  typedef MCDisassembler::DecodeStatus DecodeStatus;
34  
35  static const unsigned RegisterDecode[] = {
36      M68k::D0,    M68k::D1,  M68k::D2,  M68k::D3,  M68k::D4,  M68k::D5,
37      M68k::D6,    M68k::D7,  M68k::A0,  M68k::A1,  M68k::A2,  M68k::A3,
38      M68k::A4,    M68k::A5,  M68k::A6,  M68k::SP,  M68k::FP0, M68k::FP1,
39      M68k::FP2,   M68k::FP3, M68k::FP4, M68k::FP5, M68k::FP6, M68k::FP7,
40      M68k::FPIAR, M68k::FPS, M68k::FPC};
41  
42  static DecodeStatus DecodeRegisterClass(MCInst &Inst, uint64_t RegNo,
43                                          uint64_t Address, const void *Decoder) {
44    if (RegNo >= 24)
45      return DecodeStatus::Fail;
46    Inst.addOperand(MCOperand::createReg(RegisterDecode[RegNo]));
47    return DecodeStatus::Success;
48  }
49  
50  static DecodeStatus DecodeDR32RegisterClass(MCInst &Inst, uint64_t RegNo,
51                                              uint64_t Address,
52                                              const void *Decoder) {
53    return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
54  }
55  
56  static DecodeStatus DecodeDR16RegisterClass(MCInst &Inst, uint64_t RegNo,
57                                              uint64_t Address,
58                                              const void *Decoder) {
59    return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
60  }
61  
62  static DecodeStatus DecodeDR8RegisterClass(MCInst &Inst, uint64_t RegNo,
63                                             uint64_t Address,
64                                             const void *Decoder) {
65    return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
66  }
67  
68  static DecodeStatus DecodeAR32RegisterClass(MCInst &Inst, uint64_t RegNo,
69                                              uint64_t Address,
70                                              const void *Decoder) {
71    return DecodeRegisterClass(Inst, RegNo | 8ULL, Address, Decoder);
72  }
73  
74  static DecodeStatus DecodeAR16RegisterClass(MCInst &Inst, uint64_t RegNo,
75                                              uint64_t Address,
76                                              const void *Decoder) {
77    return DecodeRegisterClass(Inst, RegNo | 8ULL, Address, Decoder);
78  }
79  
80  static DecodeStatus DecodeXR32RegisterClass(MCInst &Inst, uint64_t RegNo,
81                                              uint64_t Address,
82                                              const void *Decoder) {
83    return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
84  }
85  
86  static DecodeStatus DecodeXR16RegisterClass(MCInst &Inst, uint64_t RegNo,
87                                              uint64_t Address,
88                                              const void *Decoder) {
89    return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
90  }
91  
92  static DecodeStatus DecodeFPDRRegisterClass(MCInst &Inst, uint64_t RegNo,
93                                              uint64_t Address,
94                                              const void *Decoder) {
95    return DecodeRegisterClass(Inst, RegNo | 16ULL, Address, Decoder);
96  }
97  #define DecodeFPDR32RegisterClass DecodeFPDRRegisterClass
98  #define DecodeFPDR64RegisterClass DecodeFPDRRegisterClass
99  #define DecodeFPDR80RegisterClass DecodeFPDRRegisterClass
100  
101  static DecodeStatus DecodeFPCSCRegisterClass(MCInst &Inst, uint64_t RegNo,
102                                               uint64_t Address,
103                                               const void *Decoder) {
104    return DecodeRegisterClass(Inst, (RegNo >> 1) + 24, Address, Decoder);
105  }
106  #define DecodeFPICRegisterClass DecodeFPCSCRegisterClass
107  
108  static DecodeStatus DecodeCCRCRegisterClass(MCInst &Inst, APInt &Insn,
109                                              uint64_t Address,
110                                              const void *Decoder) {
111    llvm_unreachable("unimplemented");
112  }
113  
114  static DecodeStatus DecodeImm32(MCInst &Inst, uint64_t Imm, uint64_t Address,
115                                  const void *Decoder) {
116    Inst.addOperand(MCOperand::createImm(M68k::swapWord<uint32_t>(Imm)));
117    return DecodeStatus::Success;
118  }
119  
120  #include "M68kGenDisassemblerTable.inc"
121  
122  #undef DecodeFPDR32RegisterClass
123  #undef DecodeFPDR64RegisterClass
124  #undef DecodeFPDR80RegisterClass
125  #undef DecodeFPICRegisterClass
126  
127  /// A disassembler class for M68k.
128  struct M68kDisassembler : public MCDisassembler {
129    M68kDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
130        : MCDisassembler(STI, Ctx) {}
131    virtual ~M68kDisassembler() {}
132  
133    DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
134                                ArrayRef<uint8_t> Bytes, uint64_t Address,
135                                raw_ostream &CStream) const override;
136  };
137  
138  DecodeStatus M68kDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
139                                                ArrayRef<uint8_t> Bytes,
140                                                uint64_t Address,
141                                                raw_ostream &CStream) const {
142    DecodeStatus Result;
143    auto MakeUp = [&](APInt &Insn, unsigned InstrBits) {
144      unsigned Idx = Insn.getBitWidth() >> 3;
145      unsigned RoundUp = alignTo(InstrBits, Align(16));
146      if (RoundUp > Insn.getBitWidth())
147        Insn = Insn.zext(RoundUp);
148      RoundUp = RoundUp >> 3;
149      for (; Idx < RoundUp; Idx += 2) {
150        Insn.insertBits(support::endian::read16be(&Bytes[Idx]), Idx * 8, 16);
151      }
152    };
153    APInt Insn(16, support::endian::read16be(Bytes.data()));
154    // 2 bytes of data are consumed, so set Size to 2
155    // If we don't do this, disassembler may generate result even
156    // the encoding is invalid. We need to let it fail correctly.
157    Size = 2;
158    Result = decodeInstruction(DecoderTable80, Instr, Insn, Address, this, STI,
159                               MakeUp);
160    if (Result == DecodeStatus::Success)
161      Size = InstrLenTable[Instr.getOpcode()] >> 3;
162    return Result;
163  }
164  
165  static MCDisassembler *createM68kDisassembler(const Target &T,
166                                                const MCSubtargetInfo &STI,
167                                                MCContext &Ctx) {
168    return new M68kDisassembler(STI, Ctx);
169  }
170  
171  extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kDisassembler() {
172    // Register the disassembler.
173    TargetRegistry::RegisterMCDisassembler(getTheM68kTarget(),
174                                           createM68kDisassembler);
175  }
176