10b57cec5SDimitry Andric //===-- BPFMCTargetDesc.cpp - BPF 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 BPF specific target descriptions. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "MCTargetDesc/BPFMCTargetDesc.h" 140b57cec5SDimitry Andric #include "MCTargetDesc/BPFInstPrinter.h" 150b57cec5SDimitry Andric #include "MCTargetDesc/BPFMCAsmInfo.h" 160b57cec5SDimitry Andric #include "TargetInfo/BPFTargetInfo.h" 170b57cec5SDimitry Andric #include "llvm/MC/MCInstrAnalysis.h" 180b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h" 190b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 200b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 21349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 2206c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric #define GET_INSTRINFO_MC_DESC 25753f127fSDimitry Andric #define ENABLE_INSTR_PREDICATE_VERIFIER 260b57cec5SDimitry Andric #include "BPFGenInstrInfo.inc" 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric #define GET_SUBTARGETINFO_MC_DESC 290b57cec5SDimitry Andric #include "BPFGenSubtargetInfo.inc" 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric #define GET_REGINFO_MC_DESC 320b57cec5SDimitry Andric #include "BPFGenRegisterInfo.inc" 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric using namespace llvm; 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric static MCInstrInfo *createBPFMCInstrInfo() { 370b57cec5SDimitry Andric MCInstrInfo *X = new MCInstrInfo(); 380b57cec5SDimitry Andric InitBPFMCInstrInfo(X); 390b57cec5SDimitry Andric return X; 400b57cec5SDimitry Andric } 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric static MCRegisterInfo *createBPFMCRegisterInfo(const Triple &TT) { 430b57cec5SDimitry Andric MCRegisterInfo *X = new MCRegisterInfo(); 440b57cec5SDimitry Andric InitBPFMCRegisterInfo(X, BPF::R11 /* RAReg doesn't exist */); 450b57cec5SDimitry Andric return X; 460b57cec5SDimitry Andric } 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric static MCSubtargetInfo *createBPFMCSubtargetInfo(const Triple &TT, 490b57cec5SDimitry Andric StringRef CPU, StringRef FS) { 50e8d8bef9SDimitry Andric return createBPFMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS); 510b57cec5SDimitry Andric } 520b57cec5SDimitry Andric 53*0fca6ea1SDimitry Andric static MCStreamer * 54*0fca6ea1SDimitry Andric createBPFMCStreamer(const Triple &T, MCContext &Ctx, 550b57cec5SDimitry Andric std::unique_ptr<MCAsmBackend> &&MAB, 560b57cec5SDimitry Andric std::unique_ptr<MCObjectWriter> &&OW, 57*0fca6ea1SDimitry Andric std::unique_ptr<MCCodeEmitter> &&Emitter) { 58*0fca6ea1SDimitry Andric return createELFStreamer(Ctx, std::move(MAB), std::move(OW), 59*0fca6ea1SDimitry Andric std::move(Emitter)); 600b57cec5SDimitry Andric } 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric static MCInstPrinter *createBPFMCInstPrinter(const Triple &T, 630b57cec5SDimitry Andric unsigned SyntaxVariant, 640b57cec5SDimitry Andric const MCAsmInfo &MAI, 650b57cec5SDimitry Andric const MCInstrInfo &MII, 660b57cec5SDimitry Andric const MCRegisterInfo &MRI) { 670b57cec5SDimitry Andric if (SyntaxVariant == 0) 680b57cec5SDimitry Andric return new BPFInstPrinter(MAI, MII, MRI); 690b57cec5SDimitry Andric return nullptr; 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric namespace { 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric class BPFMCInstrAnalysis : public MCInstrAnalysis { 750b57cec5SDimitry Andric public: 760b57cec5SDimitry Andric explicit BPFMCInstrAnalysis(const MCInstrInfo *Info) 770b57cec5SDimitry Andric : MCInstrAnalysis(Info) {} 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, 800b57cec5SDimitry Andric uint64_t &Target) const override { 810b57cec5SDimitry Andric // The target is the 3rd operand of cond inst and the 1st of uncond inst. 825f757f3fSDimitry Andric int32_t Imm; 830b57cec5SDimitry Andric if (isConditionalBranch(Inst)) { 84*0fca6ea1SDimitry Andric if (Inst.getOpcode() == BPF::JCOND) 85*0fca6ea1SDimitry Andric Imm = (short)Inst.getOperand(0).getImm(); 86*0fca6ea1SDimitry Andric else 875f757f3fSDimitry Andric Imm = (short)Inst.getOperand(2).getImm(); 885f757f3fSDimitry Andric } else if (isUnconditionalBranch(Inst)) { 895f757f3fSDimitry Andric if (Inst.getOpcode() == BPF::JMP) 905f757f3fSDimitry Andric Imm = (short)Inst.getOperand(0).getImm(); 910b57cec5SDimitry Andric else 925f757f3fSDimitry Andric Imm = (int)Inst.getOperand(0).getImm(); 935f757f3fSDimitry Andric } else 940b57cec5SDimitry Andric return false; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric Target = Addr + Size + Imm * Size; 970b57cec5SDimitry Andric return true; 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric }; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric } // end anonymous namespace 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric static MCInstrAnalysis *createBPFInstrAnalysis(const MCInstrInfo *Info) { 1040b57cec5SDimitry Andric return new BPFMCInstrAnalysis(Info); 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric 107480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFTargetMC() { 1080b57cec5SDimitry Andric for (Target *T : 1090b57cec5SDimitry Andric {&getTheBPFleTarget(), &getTheBPFbeTarget(), &getTheBPFTarget()}) { 1100b57cec5SDimitry Andric // Register the MC asm info. 1110b57cec5SDimitry Andric RegisterMCAsmInfo<BPFMCAsmInfo> X(*T); 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric // Register the MC instruction info. 1140b57cec5SDimitry Andric TargetRegistry::RegisterMCInstrInfo(*T, createBPFMCInstrInfo); 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric // Register the MC register info. 1170b57cec5SDimitry Andric TargetRegistry::RegisterMCRegInfo(*T, createBPFMCRegisterInfo); 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric // Register the MC subtarget info. 1200b57cec5SDimitry Andric TargetRegistry::RegisterMCSubtargetInfo(*T, 1210b57cec5SDimitry Andric createBPFMCSubtargetInfo); 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric // Register the object streamer 1240b57cec5SDimitry Andric TargetRegistry::RegisterELFStreamer(*T, createBPFMCStreamer); 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric // Register the MCInstPrinter. 1270b57cec5SDimitry Andric TargetRegistry::RegisterMCInstPrinter(*T, createBPFMCInstPrinter); 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric // Register the MC instruction analyzer. 1300b57cec5SDimitry Andric TargetRegistry::RegisterMCInstrAnalysis(*T, createBPFInstrAnalysis); 1310b57cec5SDimitry Andric } 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric // Register the MC code emitter 1340b57cec5SDimitry Andric TargetRegistry::RegisterMCCodeEmitter(getTheBPFleTarget(), 1350b57cec5SDimitry Andric createBPFMCCodeEmitter); 1360b57cec5SDimitry Andric TargetRegistry::RegisterMCCodeEmitter(getTheBPFbeTarget(), 1370b57cec5SDimitry Andric createBPFbeMCCodeEmitter); 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric // Register the ASM Backend 1400b57cec5SDimitry Andric TargetRegistry::RegisterMCAsmBackend(getTheBPFleTarget(), 1410b57cec5SDimitry Andric createBPFAsmBackend); 1420b57cec5SDimitry Andric TargetRegistry::RegisterMCAsmBackend(getTheBPFbeTarget(), 1430b57cec5SDimitry Andric createBPFbeAsmBackend); 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric if (sys::IsLittleEndianHost) { 1460b57cec5SDimitry Andric TargetRegistry::RegisterMCCodeEmitter(getTheBPFTarget(), 1470b57cec5SDimitry Andric createBPFMCCodeEmitter); 1480b57cec5SDimitry Andric TargetRegistry::RegisterMCAsmBackend(getTheBPFTarget(), 1490b57cec5SDimitry Andric createBPFAsmBackend); 1500b57cec5SDimitry Andric } else { 1510b57cec5SDimitry Andric TargetRegistry::RegisterMCCodeEmitter(getTheBPFTarget(), 1520b57cec5SDimitry Andric createBPFbeMCCodeEmitter); 1530b57cec5SDimitry Andric TargetRegistry::RegisterMCAsmBackend(getTheBPFTarget(), 1540b57cec5SDimitry Andric createBPFbeAsmBackend); 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric } 158