//===-- W65816MCTargetDesc.cpp - W65816 Target Descriptions ---------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file provides W65816 specific target descriptions.
//
//===----------------------------------------------------------------------===//

#include "W65816MCTargetDesc.h"
#include "W65816InstPrinter.h"
#include "W65816MCAsmInfo.h"
#include "TargetInfo/W65816TargetInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/Compiler.h"

using namespace llvm;

#define GET_INSTRINFO_MC_DESC
#define ENABLE_INSTR_PREDICATE_VERIFIER
#include "W65816GenInstrInfo.inc"

#define GET_SUBTARGETINFO_MC_DESC
#include "W65816GenSubtargetInfo.inc"

#define GET_REGINFO_MC_DESC
#include "W65816GenRegisterInfo.inc"

static MCInstrInfo *createW65816MCInstrInfo() {
  MCInstrInfo *X = new MCInstrInfo();
  InitW65816MCInstrInfo(X);
  return X;
}

static MCRegisterInfo *createW65816MCRegisterInfo(const Triple &TT) {
  MCRegisterInfo *X = new MCRegisterInfo();
  InitW65816MCRegisterInfo(X, W65816::PC);
  return X;
}

static MCAsmInfo *createW65816MCAsmInfo(const MCRegisterInfo &MRI,
                                        const Triple &TT,
                                        const MCTargetOptions &Options) {
  // Initial DWARF CFI frame state is deliberately omitted for the skeleton;
  // it will be added once frame lowering is fully described.
  return new W65816MCAsmInfo(TT);
}

static MCSubtargetInfo *
createW65816MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
  // Default CPU to "w65816" when none is given, so the Proc's default
  // features (FeatureMLow + FeatureXLow, matching the C ABI) are applied
  // to the MC-layer Subtarget — without this, both llvm-mc and the
  // disassembler start with an empty feature mask, which makes the
  // Predicated `_Imm16` instruction defs (LDA/LDX/LDY/CMP/CPX/CPY/ADC/SBC
  // /AND/ORA/EOR/BIT) invisible to both the AsmMatcher and the Decoder.
  StringRef CPUName = CPU.empty() ? StringRef("w65816") : CPU;
  return createW65816MCSubtargetInfoImpl(TT, CPUName, /*TuneCPU=*/CPUName, FS);
}

static MCInstPrinter *createW65816MCInstPrinter(const Triple &T,
                                                unsigned SyntaxVariant,
                                                const MCAsmInfo &MAI,
                                                const MCInstrInfo &MII,
                                                const MCRegisterInfo &MRI) {
  if (SyntaxVariant == 0)
    return new W65816InstPrinter(MAI, MII, MRI);
  return nullptr;
}

extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
LLVMInitializeW65816TargetMC() {
  Target &T = getTheW65816Target();

  TargetRegistry::RegisterMCAsmInfo(T, createW65816MCAsmInfo);
  TargetRegistry::RegisterMCInstrInfo(T, createW65816MCInstrInfo);
  TargetRegistry::RegisterMCRegInfo(T, createW65816MCRegisterInfo);
  TargetRegistry::RegisterMCSubtargetInfo(T, createW65816MCSubtargetInfo);
  TargetRegistry::RegisterMCInstPrinter(T, createW65816MCInstPrinter);
  TargetRegistry::RegisterMCCodeEmitter(T, createW65816MCCodeEmitter);
  TargetRegistry::RegisterMCAsmBackend(T, createW65816MCAsmBackend);
  TargetRegistry::RegisterObjectTargetStreamer(
      T, createW65816ObjectTargetStreamer);
}
