xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- MipsMCTargetDesc.cpp - Mips Target Descriptions -------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file provides Mips specific target descriptions.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "MipsMCTargetDesc.h"
140b57cec5SDimitry Andric #include "MipsAsmBackend.h"
15480093f4SDimitry Andric #include "MipsBaseInfo.h"
160b57cec5SDimitry Andric #include "MipsELFStreamer.h"
170b57cec5SDimitry Andric #include "MipsInstPrinter.h"
180b57cec5SDimitry Andric #include "MipsMCAsmInfo.h"
190b57cec5SDimitry Andric #include "MipsMCNaCl.h"
200b57cec5SDimitry Andric #include "MipsTargetStreamer.h"
210b57cec5SDimitry Andric #include "TargetInfo/MipsTargetInfo.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCELFStreamer.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCInstrAnalysis.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
300b57cec5SDimitry Andric #include "llvm/MC/MachineLocation.h"
31349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
320b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
330b57cec5SDimitry Andric #include "llvm/Support/FormattedStream.h"
3406c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric using namespace llvm;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric #define GET_INSTRINFO_MC_DESC
39753f127fSDimitry Andric #define ENABLE_INSTR_PREDICATE_VERIFIER
400b57cec5SDimitry Andric #include "MipsGenInstrInfo.inc"
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric #define GET_SUBTARGETINFO_MC_DESC
430b57cec5SDimitry Andric #include "MipsGenSubtargetInfo.inc"
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric #define GET_REGINFO_MC_DESC
460b57cec5SDimitry Andric #include "MipsGenRegisterInfo.inc"
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric /// Select the Mips CPU for the given triple and cpu name.
selectMipsCPU(const Triple & TT,StringRef CPU)490b57cec5SDimitry Andric StringRef MIPS_MC::selectMipsCPU(const Triple &TT, StringRef CPU) {
500b57cec5SDimitry Andric   if (CPU.empty() || CPU == "generic") {
510b57cec5SDimitry Andric     if (TT.getSubArch() == llvm::Triple::MipsSubArch_r6) {
520b57cec5SDimitry Andric       if (TT.isMIPS32())
530b57cec5SDimitry Andric         CPU = "mips32r6";
540b57cec5SDimitry Andric       else
550b57cec5SDimitry Andric         CPU = "mips64r6";
560b57cec5SDimitry Andric     } else {
570b57cec5SDimitry Andric       if (TT.isMIPS32())
580b57cec5SDimitry Andric         CPU = "mips32";
590b57cec5SDimitry Andric       else
600b57cec5SDimitry Andric         CPU = "mips64";
610b57cec5SDimitry Andric     }
620b57cec5SDimitry Andric   }
630b57cec5SDimitry Andric   return CPU;
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
createMipsMCInstrInfo()660b57cec5SDimitry Andric static MCInstrInfo *createMipsMCInstrInfo() {
670b57cec5SDimitry Andric   MCInstrInfo *X = new MCInstrInfo();
680b57cec5SDimitry Andric   InitMipsMCInstrInfo(X);
690b57cec5SDimitry Andric   return X;
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric 
createMipsMCRegisterInfo(const Triple & TT)720b57cec5SDimitry Andric static MCRegisterInfo *createMipsMCRegisterInfo(const Triple &TT) {
730b57cec5SDimitry Andric   MCRegisterInfo *X = new MCRegisterInfo();
740b57cec5SDimitry Andric   InitMipsMCRegisterInfo(X, Mips::RA);
750b57cec5SDimitry Andric   return X;
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric 
createMipsMCSubtargetInfo(const Triple & TT,StringRef CPU,StringRef FS)780b57cec5SDimitry Andric static MCSubtargetInfo *createMipsMCSubtargetInfo(const Triple &TT,
790b57cec5SDimitry Andric                                                   StringRef CPU, StringRef FS) {
800b57cec5SDimitry Andric   CPU = MIPS_MC::selectMipsCPU(TT, CPU);
81e8d8bef9SDimitry Andric   return createMipsMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS);
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric 
createMipsMCAsmInfo(const MCRegisterInfo & MRI,const Triple & TT,const MCTargetOptions & Options)840b57cec5SDimitry Andric static MCAsmInfo *createMipsMCAsmInfo(const MCRegisterInfo &MRI,
85480093f4SDimitry Andric                                       const Triple &TT,
86480093f4SDimitry Andric                                       const MCTargetOptions &Options) {
87480093f4SDimitry Andric   MCAsmInfo *MAI = new MipsMCAsmInfo(TT, Options);
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   unsigned SP = MRI.getDwarfRegNum(Mips::SP, true);
900b57cec5SDimitry Andric   MCCFIInstruction Inst = MCCFIInstruction::createDefCfaRegister(nullptr, SP);
910b57cec5SDimitry Andric   MAI->addInitialFrameState(Inst);
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   return MAI;
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric 
createMipsMCInstPrinter(const Triple & T,unsigned SyntaxVariant,const MCAsmInfo & MAI,const MCInstrInfo & MII,const MCRegisterInfo & MRI)960b57cec5SDimitry Andric static MCInstPrinter *createMipsMCInstPrinter(const Triple &T,
970b57cec5SDimitry Andric                                               unsigned SyntaxVariant,
980b57cec5SDimitry Andric                                               const MCAsmInfo &MAI,
990b57cec5SDimitry Andric                                               const MCInstrInfo &MII,
1000b57cec5SDimitry Andric                                               const MCRegisterInfo &MRI) {
1010b57cec5SDimitry Andric   return new MipsInstPrinter(MAI, MII, MRI);
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric 
createMCStreamer(const Triple & T,MCContext & Context,std::unique_ptr<MCAsmBackend> && MAB,std::unique_ptr<MCObjectWriter> && OW,std::unique_ptr<MCCodeEmitter> && Emitter)1040b57cec5SDimitry Andric static MCStreamer *createMCStreamer(const Triple &T, MCContext &Context,
1050b57cec5SDimitry Andric                                     std::unique_ptr<MCAsmBackend> &&MAB,
1060b57cec5SDimitry Andric                                     std::unique_ptr<MCObjectWriter> &&OW,
107*0fca6ea1SDimitry Andric                                     std::unique_ptr<MCCodeEmitter> &&Emitter) {
1080b57cec5SDimitry Andric   MCStreamer *S;
1090b57cec5SDimitry Andric   if (!T.isOSNaCl())
1100b57cec5SDimitry Andric     S = createMipsELFStreamer(Context, std::move(MAB), std::move(OW),
111*0fca6ea1SDimitry Andric                               std::move(Emitter));
1120b57cec5SDimitry Andric   else
1130b57cec5SDimitry Andric     S = createMipsNaClELFStreamer(Context, std::move(MAB), std::move(OW),
114*0fca6ea1SDimitry Andric                                   std::move(Emitter));
1150b57cec5SDimitry Andric   return S;
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
createMipsAsmTargetStreamer(MCStreamer & S,formatted_raw_ostream & OS,MCInstPrinter * InstPrint)1180b57cec5SDimitry Andric static MCTargetStreamer *createMipsAsmTargetStreamer(MCStreamer &S,
1190b57cec5SDimitry Andric                                                      formatted_raw_ostream &OS,
120*0fca6ea1SDimitry Andric                                                      MCInstPrinter *InstPrint) {
1210b57cec5SDimitry Andric   return new MipsTargetAsmStreamer(S, OS);
1220b57cec5SDimitry Andric }
1230b57cec5SDimitry Andric 
createMipsNullTargetStreamer(MCStreamer & S)1240b57cec5SDimitry Andric static MCTargetStreamer *createMipsNullTargetStreamer(MCStreamer &S) {
1250b57cec5SDimitry Andric   return new MipsTargetStreamer(S);
1260b57cec5SDimitry Andric }
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric static MCTargetStreamer *
createMipsObjectTargetStreamer(MCStreamer & S,const MCSubtargetInfo & STI)1290b57cec5SDimitry Andric createMipsObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
1300b57cec5SDimitry Andric   return new MipsTargetELFStreamer(S, STI);
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric namespace {
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric class MipsMCInstrAnalysis : public MCInstrAnalysis {
1360b57cec5SDimitry Andric public:
MipsMCInstrAnalysis(const MCInstrInfo * Info)1370b57cec5SDimitry Andric   MipsMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}
1380b57cec5SDimitry Andric 
evaluateBranch(const MCInst & Inst,uint64_t Addr,uint64_t Size,uint64_t & Target) const1390b57cec5SDimitry Andric   bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
1400b57cec5SDimitry Andric                       uint64_t &Target) const override {
1410b57cec5SDimitry Andric     unsigned NumOps = Inst.getNumOperands();
1420b57cec5SDimitry Andric     if (NumOps == 0)
1430b57cec5SDimitry Andric       return false;
144bdd1243dSDimitry Andric     switch (Info->get(Inst.getOpcode()).operands()[NumOps - 1].OperandType) {
1450b57cec5SDimitry Andric     case MCOI::OPERAND_UNKNOWN:
1468bcb0991SDimitry Andric     case MCOI::OPERAND_IMMEDIATE: {
1478bcb0991SDimitry Andric       // j, jal, jalx, jals
1488bcb0991SDimitry Andric       // Absolute branch within the current 256 MB-aligned region
1498bcb0991SDimitry Andric       uint64_t Region = Addr & ~uint64_t(0xfffffff);
1508bcb0991SDimitry Andric       Target = Region + Inst.getOperand(NumOps - 1).getImm();
1510b57cec5SDimitry Andric       return true;
1528bcb0991SDimitry Andric     }
1530b57cec5SDimitry Andric     case MCOI::OPERAND_PCREL:
1548bcb0991SDimitry Andric       // b, beq ...
1550b57cec5SDimitry Andric       Target = Addr + Inst.getOperand(NumOps - 1).getImm();
1560b57cec5SDimitry Andric       return true;
1570b57cec5SDimitry Andric     default:
1580b57cec5SDimitry Andric       return false;
1590b57cec5SDimitry Andric     }
1600b57cec5SDimitry Andric   }
1610b57cec5SDimitry Andric };
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric 
createMipsMCInstrAnalysis(const MCInstrInfo * Info)1640b57cec5SDimitry Andric static MCInstrAnalysis *createMipsMCInstrAnalysis(const MCInstrInfo *Info) {
1650b57cec5SDimitry Andric   return new MipsMCInstrAnalysis(Info);
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric 
LLVMInitializeMipsTargetMC()168480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsTargetMC() {
1690b57cec5SDimitry Andric   for (Target *T : {&getTheMipsTarget(), &getTheMipselTarget(),
1700b57cec5SDimitry Andric                     &getTheMips64Target(), &getTheMips64elTarget()}) {
1710b57cec5SDimitry Andric     // Register the MC asm info.
1720b57cec5SDimitry Andric     RegisterMCAsmInfoFn X(*T, createMipsMCAsmInfo);
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric     // Register the MC instruction info.
1750b57cec5SDimitry Andric     TargetRegistry::RegisterMCInstrInfo(*T, createMipsMCInstrInfo);
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric     // Register the MC register info.
1780b57cec5SDimitry Andric     TargetRegistry::RegisterMCRegInfo(*T, createMipsMCRegisterInfo);
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric     // Register the elf streamer.
1810b57cec5SDimitry Andric     TargetRegistry::RegisterELFStreamer(*T, createMCStreamer);
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric     // Register the asm target streamer.
1840b57cec5SDimitry Andric     TargetRegistry::RegisterAsmTargetStreamer(*T, createMipsAsmTargetStreamer);
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric     TargetRegistry::RegisterNullTargetStreamer(*T,
1870b57cec5SDimitry Andric                                                createMipsNullTargetStreamer);
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric     // Register the MC subtarget info.
1900b57cec5SDimitry Andric     TargetRegistry::RegisterMCSubtargetInfo(*T, createMipsMCSubtargetInfo);
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric     // Register the MC instruction analyzer.
1930b57cec5SDimitry Andric     TargetRegistry::RegisterMCInstrAnalysis(*T, createMipsMCInstrAnalysis);
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric     // Register the MCInstPrinter.
1960b57cec5SDimitry Andric     TargetRegistry::RegisterMCInstPrinter(*T, createMipsMCInstPrinter);
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric     TargetRegistry::RegisterObjectTargetStreamer(
1990b57cec5SDimitry Andric         *T, createMipsObjectTargetStreamer);
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric     // Register the asm backend.
2020b57cec5SDimitry Andric     TargetRegistry::RegisterMCAsmBackend(*T, createMipsAsmBackend);
2030b57cec5SDimitry Andric   }
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric   // Register the MC Code Emitter
2060b57cec5SDimitry Andric   for (Target *T : {&getTheMipsTarget(), &getTheMips64Target()})
2070b57cec5SDimitry Andric     TargetRegistry::RegisterMCCodeEmitter(*T, createMipsMCCodeEmitterEB);
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric   for (Target *T : {&getTheMipselTarget(), &getTheMips64elTarget()})
2100b57cec5SDimitry Andric     TargetRegistry::RegisterMCCodeEmitter(*T, createMipsMCCodeEmitterEL);
2110b57cec5SDimitry Andric }
212