1 | //===-- MipsMCTargetDesc.cpp - Mips Target Descriptions -------------------===// |
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 provides Mips specific target descriptions. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "MipsMCTargetDesc.h" |
14 | #include "MipsAsmBackend.h" |
15 | #include "MipsBaseInfo.h" |
16 | #include "MipsELFStreamer.h" |
17 | #include "MipsInstPrinter.h" |
18 | #include "MipsMCAsmInfo.h" |
19 | #include "MipsMCNaCl.h" |
20 | #include "MipsTargetStreamer.h" |
21 | #include "TargetInfo/MipsTargetInfo.h" |
22 | #include "llvm/MC/MCCodeEmitter.h" |
23 | #include "llvm/MC/MCELFStreamer.h" |
24 | #include "llvm/MC/MCInstrAnalysis.h" |
25 | #include "llvm/MC/MCInstrInfo.h" |
26 | #include "llvm/MC/MCObjectWriter.h" |
27 | #include "llvm/MC/MCRegisterInfo.h" |
28 | #include "llvm/MC/MCSubtargetInfo.h" |
29 | #include "llvm/MC/MCSymbol.h" |
30 | #include "llvm/MC/MachineLocation.h" |
31 | #include "llvm/MC/TargetRegistry.h" |
32 | #include "llvm/Support/ErrorHandling.h" |
33 | #include "llvm/Support/FormattedStream.h" |
34 | #include "llvm/TargetParser/Triple.h" |
35 | |
36 | using namespace llvm; |
37 | |
38 | #define GET_INSTRINFO_MC_DESC |
39 | #define ENABLE_INSTR_PREDICATE_VERIFIER |
40 | #include "MipsGenInstrInfo.inc" |
41 | |
42 | #define GET_SUBTARGETINFO_MC_DESC |
43 | #include "MipsGenSubtargetInfo.inc" |
44 | |
45 | #define GET_REGINFO_MC_DESC |
46 | #include "MipsGenRegisterInfo.inc" |
47 | |
48 | /// Select the Mips CPU for the given triple and cpu name. |
49 | StringRef MIPS_MC::selectMipsCPU(const Triple &TT, StringRef CPU) { |
50 | if (CPU.empty() || CPU == "generic" ) { |
51 | if (TT.getSubArch() == llvm::Triple::MipsSubArch_r6) { |
52 | if (TT.isMIPS32()) |
53 | CPU = "mips32r6" ; |
54 | else |
55 | CPU = "mips64r6" ; |
56 | } else { |
57 | if (TT.isMIPS32()) |
58 | CPU = "mips32" ; |
59 | else |
60 | CPU = "mips64" ; |
61 | } |
62 | } |
63 | return CPU; |
64 | } |
65 | |
66 | static MCInstrInfo *createMipsMCInstrInfo() { |
67 | MCInstrInfo *X = new MCInstrInfo(); |
68 | InitMipsMCInstrInfo(II: X); |
69 | return X; |
70 | } |
71 | |
72 | static MCRegisterInfo *createMipsMCRegisterInfo(const Triple &TT) { |
73 | MCRegisterInfo *X = new MCRegisterInfo(); |
74 | InitMipsMCRegisterInfo(RI: X, RA: Mips::RA); |
75 | return X; |
76 | } |
77 | |
78 | static MCSubtargetInfo *createMipsMCSubtargetInfo(const Triple &TT, |
79 | StringRef CPU, StringRef FS) { |
80 | CPU = MIPS_MC::selectMipsCPU(TT, CPU); |
81 | return createMipsMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS); |
82 | } |
83 | |
84 | static MCAsmInfo *createMipsMCAsmInfo(const MCRegisterInfo &MRI, |
85 | const Triple &TT, |
86 | const MCTargetOptions &Options) { |
87 | MCAsmInfo *MAI = new MipsMCAsmInfo(TT, Options); |
88 | |
89 | unsigned SP = MRI.getDwarfRegNum(RegNum: Mips::SP, isEH: true); |
90 | MCCFIInstruction Inst = MCCFIInstruction::createDefCfaRegister(L: nullptr, Register: SP); |
91 | MAI->addInitialFrameState(Inst); |
92 | |
93 | return MAI; |
94 | } |
95 | |
96 | static MCInstPrinter *createMipsMCInstPrinter(const Triple &T, |
97 | unsigned SyntaxVariant, |
98 | const MCAsmInfo &MAI, |
99 | const MCInstrInfo &MII, |
100 | const MCRegisterInfo &MRI) { |
101 | return new MipsInstPrinter(MAI, MII, MRI); |
102 | } |
103 | |
104 | static MCStreamer *createMCStreamer(const Triple &T, MCContext &Context, |
105 | std::unique_ptr<MCAsmBackend> &&MAB, |
106 | std::unique_ptr<MCObjectWriter> &&OW, |
107 | std::unique_ptr<MCCodeEmitter> &&Emitter) { |
108 | MCStreamer *S; |
109 | if (!T.isOSNaCl()) |
110 | S = createMipsELFStreamer(Context, MAB: std::move(MAB), OW: std::move(OW), |
111 | Emitter: std::move(Emitter)); |
112 | else |
113 | S = createMipsNaClELFStreamer(Context, TAB: std::move(MAB), OW: std::move(OW), |
114 | Emitter: std::move(Emitter)); |
115 | return S; |
116 | } |
117 | |
118 | static MCTargetStreamer *createMipsAsmTargetStreamer(MCStreamer &S, |
119 | formatted_raw_ostream &OS, |
120 | MCInstPrinter *InstPrint) { |
121 | return new MipsTargetAsmStreamer(S, OS); |
122 | } |
123 | |
124 | static MCTargetStreamer *createMipsNullTargetStreamer(MCStreamer &S) { |
125 | return new MipsTargetStreamer(S); |
126 | } |
127 | |
128 | static MCTargetStreamer * |
129 | createMipsObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { |
130 | return new MipsTargetELFStreamer(S, STI); |
131 | } |
132 | |
133 | namespace { |
134 | |
135 | class MipsMCInstrAnalysis : public MCInstrAnalysis { |
136 | public: |
137 | MipsMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} |
138 | |
139 | bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, |
140 | uint64_t &Target) const override { |
141 | unsigned NumOps = Inst.getNumOperands(); |
142 | if (NumOps == 0) |
143 | return false; |
144 | switch (Info->get(Opcode: Inst.getOpcode()).operands()[NumOps - 1].OperandType) { |
145 | case MCOI::OPERAND_UNKNOWN: |
146 | case MCOI::OPERAND_IMMEDIATE: { |
147 | // j, jal, jalx, jals |
148 | // Absolute branch within the current 256 MB-aligned region |
149 | uint64_t Region = Addr & ~uint64_t(0xfffffff); |
150 | Target = Region + Inst.getOperand(i: NumOps - 1).getImm(); |
151 | return true; |
152 | } |
153 | case MCOI::OPERAND_PCREL: |
154 | // b, beq ... |
155 | Target = Addr + Inst.getOperand(i: NumOps - 1).getImm(); |
156 | return true; |
157 | default: |
158 | return false; |
159 | } |
160 | } |
161 | }; |
162 | } |
163 | |
164 | static MCInstrAnalysis *createMipsMCInstrAnalysis(const MCInstrInfo *Info) { |
165 | return new MipsMCInstrAnalysis(Info); |
166 | } |
167 | |
168 | extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsTargetMC() { |
169 | for (Target *T : {&getTheMipsTarget(), &getTheMipselTarget(), |
170 | &getTheMips64Target(), &getTheMips64elTarget()}) { |
171 | // Register the MC asm info. |
172 | RegisterMCAsmInfoFn X(*T, createMipsMCAsmInfo); |
173 | |
174 | // Register the MC instruction info. |
175 | TargetRegistry::RegisterMCInstrInfo(T&: *T, Fn: createMipsMCInstrInfo); |
176 | |
177 | // Register the MC register info. |
178 | TargetRegistry::RegisterMCRegInfo(T&: *T, Fn: createMipsMCRegisterInfo); |
179 | |
180 | // Register the elf streamer. |
181 | TargetRegistry::RegisterELFStreamer(T&: *T, Fn: createMCStreamer); |
182 | |
183 | // Register the asm target streamer. |
184 | TargetRegistry::RegisterAsmTargetStreamer(T&: *T, Fn: createMipsAsmTargetStreamer); |
185 | |
186 | TargetRegistry::RegisterNullTargetStreamer(T&: *T, |
187 | Fn: createMipsNullTargetStreamer); |
188 | |
189 | // Register the MC subtarget info. |
190 | TargetRegistry::RegisterMCSubtargetInfo(T&: *T, Fn: createMipsMCSubtargetInfo); |
191 | |
192 | // Register the MC instruction analyzer. |
193 | TargetRegistry::RegisterMCInstrAnalysis(T&: *T, Fn: createMipsMCInstrAnalysis); |
194 | |
195 | // Register the MCInstPrinter. |
196 | TargetRegistry::RegisterMCInstPrinter(T&: *T, Fn: createMipsMCInstPrinter); |
197 | |
198 | TargetRegistry::RegisterObjectTargetStreamer( |
199 | T&: *T, Fn: createMipsObjectTargetStreamer); |
200 | |
201 | // Register the asm backend. |
202 | TargetRegistry::RegisterMCAsmBackend(T&: *T, Fn: createMipsAsmBackend); |
203 | } |
204 | |
205 | // Register the MC Code Emitter |
206 | for (Target *T : {&getTheMipsTarget(), &getTheMips64Target()}) |
207 | TargetRegistry::RegisterMCCodeEmitter(T&: *T, Fn: createMipsMCCodeEmitterEB); |
208 | |
209 | for (Target *T : {&getTheMipselTarget(), &getTheMips64elTarget()}) |
210 | TargetRegistry::RegisterMCCodeEmitter(T&: *T, Fn: createMipsMCCodeEmitterEL); |
211 | } |
212 | |