181ad6265SDimitry Andric //===-- LoongArchMCTargetDesc.cpp - LoongArch Target Descriptions ---------===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric // 981ad6265SDimitry Andric // This file provides LoongArch specific target descriptions. 1081ad6265SDimitry Andric // 1181ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1281ad6265SDimitry Andric 1381ad6265SDimitry Andric #include "LoongArchMCTargetDesc.h" 1481ad6265SDimitry Andric #include "LoongArchBaseInfo.h" 15bdd1243dSDimitry Andric #include "LoongArchELFStreamer.h" 1681ad6265SDimitry Andric #include "LoongArchInstPrinter.h" 1781ad6265SDimitry Andric #include "LoongArchMCAsmInfo.h" 1881ad6265SDimitry Andric #include "TargetInfo/LoongArchTargetInfo.h" 19bdd1243dSDimitry Andric #include "llvm/MC/MCAsmBackend.h" 2081ad6265SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 21bdd1243dSDimitry Andric #include "llvm/MC/MCCodeEmitter.h" 2281ad6265SDimitry Andric #include "llvm/MC/MCDwarf.h" 2381ad6265SDimitry Andric #include "llvm/MC/MCInstrAnalysis.h" 2481ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h" 25bdd1243dSDimitry Andric #include "llvm/MC/MCObjectWriter.h" 2681ad6265SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 2781ad6265SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 2881ad6265SDimitry Andric #include "llvm/MC/TargetRegistry.h" 2981ad6265SDimitry Andric #include "llvm/Support/Compiler.h" 3081ad6265SDimitry Andric 3181ad6265SDimitry Andric #define GET_INSTRINFO_MC_DESC 32753f127fSDimitry Andric #define ENABLE_INSTR_PREDICATE_VERIFIER 3381ad6265SDimitry Andric #include "LoongArchGenInstrInfo.inc" 3481ad6265SDimitry Andric 3581ad6265SDimitry Andric #define GET_REGINFO_MC_DESC 3681ad6265SDimitry Andric #include "LoongArchGenRegisterInfo.inc" 3781ad6265SDimitry Andric 3881ad6265SDimitry Andric #define GET_SUBTARGETINFO_MC_DESC 3981ad6265SDimitry Andric #include "LoongArchGenSubtargetInfo.inc" 4081ad6265SDimitry Andric 4181ad6265SDimitry Andric using namespace llvm; 4281ad6265SDimitry Andric 4381ad6265SDimitry Andric static MCRegisterInfo *createLoongArchMCRegisterInfo(const Triple &TT) { 4481ad6265SDimitry Andric MCRegisterInfo *X = new MCRegisterInfo(); 4581ad6265SDimitry Andric InitLoongArchMCRegisterInfo(X, LoongArch::R1); 4681ad6265SDimitry Andric return X; 4781ad6265SDimitry Andric } 4881ad6265SDimitry Andric 4981ad6265SDimitry Andric static MCInstrInfo *createLoongArchMCInstrInfo() { 5081ad6265SDimitry Andric MCInstrInfo *X = new MCInstrInfo(); 5181ad6265SDimitry Andric InitLoongArchMCInstrInfo(X); 5281ad6265SDimitry Andric return X; 5381ad6265SDimitry Andric } 5481ad6265SDimitry Andric 5581ad6265SDimitry Andric static MCSubtargetInfo * 5681ad6265SDimitry Andric createLoongArchMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) { 57bdd1243dSDimitry Andric if (CPU.empty() || CPU == "generic") 58*71ac745dSDimitry Andric CPU = TT.isArch64Bit() ? "generic-la64" : "generic-la32"; 5981ad6265SDimitry Andric return createLoongArchMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS); 6081ad6265SDimitry Andric } 6181ad6265SDimitry Andric 6281ad6265SDimitry Andric static MCAsmInfo *createLoongArchMCAsmInfo(const MCRegisterInfo &MRI, 6381ad6265SDimitry Andric const Triple &TT, 6481ad6265SDimitry Andric const MCTargetOptions &Options) { 6581ad6265SDimitry Andric MCAsmInfo *MAI = new LoongArchMCAsmInfo(TT); 6681ad6265SDimitry Andric 6781ad6265SDimitry Andric // Initial state of the frame pointer is sp(r3). 6881ad6265SDimitry Andric MCRegister SP = MRI.getDwarfRegNum(LoongArch::R3, true); 6981ad6265SDimitry Andric MCCFIInstruction Inst = MCCFIInstruction::cfiDefCfa(nullptr, SP, 0); 7081ad6265SDimitry Andric MAI->addInitialFrameState(Inst); 7181ad6265SDimitry Andric 7281ad6265SDimitry Andric return MAI; 7381ad6265SDimitry Andric } 7481ad6265SDimitry Andric 7581ad6265SDimitry Andric static MCInstPrinter *createLoongArchMCInstPrinter(const Triple &T, 7681ad6265SDimitry Andric unsigned SyntaxVariant, 7781ad6265SDimitry Andric const MCAsmInfo &MAI, 7881ad6265SDimitry Andric const MCInstrInfo &MII, 7981ad6265SDimitry Andric const MCRegisterInfo &MRI) { 8081ad6265SDimitry Andric return new LoongArchInstPrinter(MAI, MII, MRI); 8181ad6265SDimitry Andric } 8281ad6265SDimitry Andric 83bdd1243dSDimitry Andric static MCTargetStreamer * 84bdd1243dSDimitry Andric createLoongArchObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { 85bdd1243dSDimitry Andric return STI.getTargetTriple().isOSBinFormatELF() 86bdd1243dSDimitry Andric ? new LoongArchTargetELFStreamer(S, STI) 87bdd1243dSDimitry Andric : nullptr; 88bdd1243dSDimitry Andric } 89bdd1243dSDimitry Andric 9081ad6265SDimitry Andric namespace { 9181ad6265SDimitry Andric 9281ad6265SDimitry Andric class LoongArchMCInstrAnalysis : public MCInstrAnalysis { 9381ad6265SDimitry Andric public: 9481ad6265SDimitry Andric explicit LoongArchMCInstrAnalysis(const MCInstrInfo *Info) 9581ad6265SDimitry Andric : MCInstrAnalysis(Info) {} 9681ad6265SDimitry Andric 9781ad6265SDimitry Andric bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, 9881ad6265SDimitry Andric uint64_t &Target) const override { 9981ad6265SDimitry Andric unsigned NumOps = Inst.getNumOperands(); 1005f757f3fSDimitry Andric if ((isBranch(Inst) && !isIndirectBranch(Inst)) || 1015f757f3fSDimitry Andric Inst.getOpcode() == LoongArch::BL) { 10281ad6265SDimitry Andric Target = Addr + Inst.getOperand(NumOps - 1).getImm(); 10381ad6265SDimitry Andric return true; 10481ad6265SDimitry Andric } 10581ad6265SDimitry Andric 10681ad6265SDimitry Andric return false; 10781ad6265SDimitry Andric } 1085f757f3fSDimitry Andric 1095f757f3fSDimitry Andric bool isTerminator(const MCInst &Inst) const override { 1105f757f3fSDimitry Andric if (MCInstrAnalysis::isTerminator(Inst)) 1115f757f3fSDimitry Andric return true; 1125f757f3fSDimitry Andric 1135f757f3fSDimitry Andric switch (Inst.getOpcode()) { 1145f757f3fSDimitry Andric default: 1155f757f3fSDimitry Andric return false; 1165f757f3fSDimitry Andric case LoongArch::JIRL: 1175f757f3fSDimitry Andric return Inst.getOperand(0).getReg() == LoongArch::R0; 1185f757f3fSDimitry Andric } 1195f757f3fSDimitry Andric } 1205f757f3fSDimitry Andric 1215f757f3fSDimitry Andric bool isCall(const MCInst &Inst) const override { 1225f757f3fSDimitry Andric if (MCInstrAnalysis::isCall(Inst)) 1235f757f3fSDimitry Andric return true; 1245f757f3fSDimitry Andric 1255f757f3fSDimitry Andric switch (Inst.getOpcode()) { 1265f757f3fSDimitry Andric default: 1275f757f3fSDimitry Andric return false; 1285f757f3fSDimitry Andric case LoongArch::JIRL: 1295f757f3fSDimitry Andric return Inst.getOperand(0).getReg() != LoongArch::R0; 1305f757f3fSDimitry Andric } 1315f757f3fSDimitry Andric } 1325f757f3fSDimitry Andric 1335f757f3fSDimitry Andric bool isReturn(const MCInst &Inst) const override { 1345f757f3fSDimitry Andric if (MCInstrAnalysis::isReturn(Inst)) 1355f757f3fSDimitry Andric return true; 1365f757f3fSDimitry Andric 1375f757f3fSDimitry Andric switch (Inst.getOpcode()) { 1385f757f3fSDimitry Andric default: 1395f757f3fSDimitry Andric return false; 1405f757f3fSDimitry Andric case LoongArch::JIRL: 1415f757f3fSDimitry Andric return Inst.getOperand(0).getReg() == LoongArch::R0 && 1425f757f3fSDimitry Andric Inst.getOperand(1).getReg() == LoongArch::R1; 1435f757f3fSDimitry Andric } 1445f757f3fSDimitry Andric } 1455f757f3fSDimitry Andric 1465f757f3fSDimitry Andric bool isBranch(const MCInst &Inst) const override { 1475f757f3fSDimitry Andric if (MCInstrAnalysis::isBranch(Inst)) 1485f757f3fSDimitry Andric return true; 1495f757f3fSDimitry Andric 1505f757f3fSDimitry Andric switch (Inst.getOpcode()) { 1515f757f3fSDimitry Andric default: 1525f757f3fSDimitry Andric return false; 1535f757f3fSDimitry Andric case LoongArch::JIRL: 1545f757f3fSDimitry Andric return Inst.getOperand(0).getReg() == LoongArch::R0 && 1555f757f3fSDimitry Andric Inst.getOperand(1).getReg() != LoongArch::R1; 1565f757f3fSDimitry Andric } 1575f757f3fSDimitry Andric } 1585f757f3fSDimitry Andric 1595f757f3fSDimitry Andric bool isUnconditionalBranch(const MCInst &Inst) const override { 1605f757f3fSDimitry Andric if (MCInstrAnalysis::isUnconditionalBranch(Inst)) 1615f757f3fSDimitry Andric return true; 1625f757f3fSDimitry Andric 1635f757f3fSDimitry Andric switch (Inst.getOpcode()) { 1645f757f3fSDimitry Andric default: 1655f757f3fSDimitry Andric return false; 1665f757f3fSDimitry Andric case LoongArch::JIRL: 1675f757f3fSDimitry Andric return Inst.getOperand(0).getReg() == LoongArch::R0 && 1685f757f3fSDimitry Andric Inst.getOperand(1).getReg() != LoongArch::R1; 1695f757f3fSDimitry Andric } 1705f757f3fSDimitry Andric } 1715f757f3fSDimitry Andric 1725f757f3fSDimitry Andric bool isIndirectBranch(const MCInst &Inst) const override { 1735f757f3fSDimitry Andric if (MCInstrAnalysis::isIndirectBranch(Inst)) 1745f757f3fSDimitry Andric return true; 1755f757f3fSDimitry Andric 1765f757f3fSDimitry Andric switch (Inst.getOpcode()) { 1775f757f3fSDimitry Andric default: 1785f757f3fSDimitry Andric return false; 1795f757f3fSDimitry Andric case LoongArch::JIRL: 1805f757f3fSDimitry Andric return Inst.getOperand(0).getReg() == LoongArch::R0 && 1815f757f3fSDimitry Andric Inst.getOperand(1).getReg() != LoongArch::R1; 1825f757f3fSDimitry Andric } 1835f757f3fSDimitry Andric } 18481ad6265SDimitry Andric }; 18581ad6265SDimitry Andric 186972a253aSDimitry Andric } // end namespace 18781ad6265SDimitry Andric 18881ad6265SDimitry Andric static MCInstrAnalysis *createLoongArchInstrAnalysis(const MCInstrInfo *Info) { 18981ad6265SDimitry Andric return new LoongArchMCInstrAnalysis(Info); 19081ad6265SDimitry Andric } 19181ad6265SDimitry Andric 192bdd1243dSDimitry Andric namespace { 193bdd1243dSDimitry Andric MCStreamer *createLoongArchELFStreamer(const Triple &T, MCContext &Context, 194bdd1243dSDimitry Andric std::unique_ptr<MCAsmBackend> &&MAB, 195bdd1243dSDimitry Andric std::unique_ptr<MCObjectWriter> &&MOW, 1960fca6ea1SDimitry Andric std::unique_ptr<MCCodeEmitter> &&MCE) { 197bdd1243dSDimitry Andric return createLoongArchELFStreamer(Context, std::move(MAB), std::move(MOW), 1980fca6ea1SDimitry Andric std::move(MCE)); 199bdd1243dSDimitry Andric } 200bdd1243dSDimitry Andric } // end namespace 201bdd1243dSDimitry Andric 20281ad6265SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTargetMC() { 20381ad6265SDimitry Andric for (Target *T : {&getTheLoongArch32Target(), &getTheLoongArch64Target()}) { 20481ad6265SDimitry Andric TargetRegistry::RegisterMCRegInfo(*T, createLoongArchMCRegisterInfo); 20581ad6265SDimitry Andric TargetRegistry::RegisterMCInstrInfo(*T, createLoongArchMCInstrInfo); 20681ad6265SDimitry Andric TargetRegistry::RegisterMCSubtargetInfo(*T, createLoongArchMCSubtargetInfo); 20781ad6265SDimitry Andric TargetRegistry::RegisterMCAsmInfo(*T, createLoongArchMCAsmInfo); 20881ad6265SDimitry Andric TargetRegistry::RegisterMCCodeEmitter(*T, createLoongArchMCCodeEmitter); 20981ad6265SDimitry Andric TargetRegistry::RegisterMCAsmBackend(*T, createLoongArchAsmBackend); 21081ad6265SDimitry Andric TargetRegistry::RegisterMCInstPrinter(*T, createLoongArchMCInstPrinter); 21181ad6265SDimitry Andric TargetRegistry::RegisterMCInstrAnalysis(*T, createLoongArchInstrAnalysis); 212bdd1243dSDimitry Andric TargetRegistry::RegisterELFStreamer(*T, createLoongArchELFStreamer); 213bdd1243dSDimitry Andric TargetRegistry::RegisterObjectTargetStreamer( 214bdd1243dSDimitry Andric *T, createLoongArchObjectTargetStreamer); 21581ad6265SDimitry Andric } 21681ad6265SDimitry Andric } 217