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, 39 }; 40 41 static DecodeStatus DecodeRegisterClass(MCInst &Inst, uint64_t RegNo, 42 uint64_t Address, const void *Decoder) { 43 if (RegNo >= 16) 44 return DecodeStatus::Fail; 45 Inst.addOperand(MCOperand::createReg(RegisterDecode[RegNo])); 46 return DecodeStatus::Success; 47 } 48 49 static DecodeStatus DecodeDR32RegisterClass(MCInst &Inst, uint64_t RegNo, 50 uint64_t Address, 51 const void *Decoder) { 52 return DecodeRegisterClass(Inst, RegNo, Address, Decoder); 53 } 54 55 static DecodeStatus DecodeDR16RegisterClass(MCInst &Inst, uint64_t RegNo, 56 uint64_t Address, 57 const void *Decoder) { 58 return DecodeRegisterClass(Inst, RegNo, Address, Decoder); 59 } 60 61 static DecodeStatus DecodeDR8RegisterClass(MCInst &Inst, uint64_t RegNo, 62 uint64_t Address, 63 const void *Decoder) { 64 return DecodeRegisterClass(Inst, RegNo, Address, Decoder); 65 } 66 67 static DecodeStatus DecodeAR32RegisterClass(MCInst &Inst, uint64_t RegNo, 68 uint64_t Address, 69 const void *Decoder) { 70 return DecodeRegisterClass(Inst, RegNo | 8ULL, Address, Decoder); 71 } 72 73 static DecodeStatus DecodeAR16RegisterClass(MCInst &Inst, uint64_t RegNo, 74 uint64_t Address, 75 const void *Decoder) { 76 return DecodeRegisterClass(Inst, RegNo | 8ULL, Address, Decoder); 77 } 78 79 static DecodeStatus DecodeXR32RegisterClass(MCInst &Inst, uint64_t RegNo, 80 uint64_t Address, 81 const void *Decoder) { 82 return DecodeRegisterClass(Inst, RegNo, Address, Decoder); 83 } 84 85 static DecodeStatus DecodeXR16RegisterClass(MCInst &Inst, uint64_t RegNo, 86 uint64_t Address, 87 const void *Decoder) { 88 return DecodeRegisterClass(Inst, RegNo, Address, Decoder); 89 } 90 91 static DecodeStatus DecodeCCRCRegisterClass(MCInst &Inst, APInt &Insn, 92 uint64_t Address, 93 const void *Decoder) { 94 llvm_unreachable("unimplemented"); 95 } 96 97 static DecodeStatus DecodeImm32(MCInst &Inst, uint64_t Imm, uint64_t Address, 98 const void *Decoder) { 99 Inst.addOperand(MCOperand::createImm(M68k::swapWord<uint32_t>(Imm))); 100 return DecodeStatus::Success; 101 } 102 103 #include "M68kGenDisassemblerTable.inc" 104 105 /// A disassembler class for M68k. 106 struct M68kDisassembler : public MCDisassembler { 107 M68kDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) 108 : MCDisassembler(STI, Ctx) {} 109 virtual ~M68kDisassembler() {} 110 111 DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, 112 ArrayRef<uint8_t> Bytes, uint64_t Address, 113 raw_ostream &CStream) const override; 114 }; 115 116 DecodeStatus M68kDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, 117 ArrayRef<uint8_t> Bytes, 118 uint64_t Address, 119 raw_ostream &CStream) const { 120 DecodeStatus Result; 121 auto MakeUp = [&](APInt &Insn, unsigned InstrBits) { 122 unsigned Idx = Insn.getBitWidth() >> 3; 123 unsigned RoundUp = alignTo(InstrBits, Align(16)); 124 if (RoundUp > Insn.getBitWidth()) 125 Insn = Insn.zext(RoundUp); 126 RoundUp = RoundUp >> 3; 127 for (; Idx < RoundUp; Idx += 2) { 128 Insn.insertBits(support::endian::read16be(&Bytes[Idx]), Idx * 8, 16); 129 } 130 }; 131 APInt Insn(16, support::endian::read16be(Bytes.data())); 132 // 2 bytes of data are consumed, so set Size to 2 133 // If we don't do this, disassembler may generate result even 134 // the encoding is invalid. We need to let it fail correctly. 135 Size = 2; 136 Result = decodeInstruction(DecoderTable80, Instr, Insn, Address, this, STI, 137 MakeUp); 138 if (Result == DecodeStatus::Success) 139 Size = InstrLenTable[Instr.getOpcode()] >> 3; 140 return Result; 141 } 142 143 static MCDisassembler *createM68kDisassembler(const Target &T, 144 const MCSubtargetInfo &STI, 145 MCContext &Ctx) { 146 return new M68kDisassembler(STI, Ctx); 147 } 148 149 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kDisassembler() { 150 // Register the disassembler. 151 TargetRegistry::RegisterMCDisassembler(getTheM68kTarget(), 152 createM68kDisassembler); 153 } 154