1 | //===-- MipsSEInstrInfo.cpp - Mips32/64 Instruction Information -----------===// |
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 contains the Mips32/64 implementation of the TargetInstrInfo class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "MipsSEInstrInfo.h" |
14 | #include "MCTargetDesc/MipsInstPrinter.h" |
15 | #include "MipsAnalyzeImmediate.h" |
16 | #include "MipsMachineFunction.h" |
17 | #include "MipsTargetMachine.h" |
18 | #include "llvm/ADT/STLExtras.h" |
19 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
20 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
21 | #include "llvm/MC/TargetRegistry.h" |
22 | #include "llvm/Support/ErrorHandling.h" |
23 | #include "llvm/Support/MathExtras.h" |
24 | |
25 | using namespace llvm; |
26 | |
27 | static unsigned getUnconditionalBranch(const MipsSubtarget &STI) { |
28 | if (STI.inMicroMipsMode()) |
29 | return STI.isPositionIndependent() ? Mips::B_MM : Mips::J_MM; |
30 | return STI.isPositionIndependent() ? Mips::B : Mips::J; |
31 | } |
32 | |
33 | MipsSEInstrInfo::MipsSEInstrInfo(const MipsSubtarget &STI) |
34 | : MipsInstrInfo(STI, getUnconditionalBranch(STI)), RI() {} |
35 | |
36 | const MipsRegisterInfo &MipsSEInstrInfo::getRegisterInfo() const { |
37 | return RI; |
38 | } |
39 | |
40 | /// isLoadFromStackSlot - If the specified machine instruction is a direct |
41 | /// load from a stack slot, return the virtual or physical register number of |
42 | /// the destination along with the FrameIndex of the loaded stack slot. If |
43 | /// not, return 0. This predicate must return 0 if the instruction has |
44 | /// any side effects other than loading from the stack slot. |
45 | Register MipsSEInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, |
46 | int &FrameIndex) const { |
47 | unsigned Opc = MI.getOpcode(); |
48 | |
49 | if ((Opc == Mips::LW) || (Opc == Mips::LD) || |
50 | (Opc == Mips::LWC1) || (Opc == Mips::LDC1) || (Opc == Mips::LDC164)) { |
51 | if ((MI.getOperand(i: 1).isFI()) && // is a stack slot |
52 | (MI.getOperand(i: 2).isImm()) && // the imm is zero |
53 | (isZeroImm(op: MI.getOperand(i: 2)))) { |
54 | FrameIndex = MI.getOperand(i: 1).getIndex(); |
55 | return MI.getOperand(i: 0).getReg(); |
56 | } |
57 | } |
58 | |
59 | return 0; |
60 | } |
61 | |
62 | /// isStoreToStackSlot - If the specified machine instruction is a direct |
63 | /// store to a stack slot, return the virtual or physical register number of |
64 | /// the source reg along with the FrameIndex of the loaded stack slot. If |
65 | /// not, return 0. This predicate must return 0 if the instruction has |
66 | /// any side effects other than storing to the stack slot. |
67 | Register MipsSEInstrInfo::isStoreToStackSlot(const MachineInstr &MI, |
68 | int &FrameIndex) const { |
69 | unsigned Opc = MI.getOpcode(); |
70 | |
71 | if ((Opc == Mips::SW) || (Opc == Mips::SD) || |
72 | (Opc == Mips::SWC1) || (Opc == Mips::SDC1) || (Opc == Mips::SDC164)) { |
73 | if ((MI.getOperand(i: 1).isFI()) && // is a stack slot |
74 | (MI.getOperand(i: 2).isImm()) && // the imm is zero |
75 | (isZeroImm(op: MI.getOperand(i: 2)))) { |
76 | FrameIndex = MI.getOperand(i: 1).getIndex(); |
77 | return MI.getOperand(i: 0).getReg(); |
78 | } |
79 | } |
80 | return 0; |
81 | } |
82 | |
83 | void MipsSEInstrInfo::copyPhysReg(MachineBasicBlock &MBB, |
84 | MachineBasicBlock::iterator I, |
85 | const DebugLoc &DL, MCRegister DestReg, |
86 | MCRegister SrcReg, bool KillSrc) const { |
87 | unsigned Opc = 0, ZeroReg = 0; |
88 | bool isMicroMips = Subtarget.inMicroMipsMode(); |
89 | |
90 | if (Mips::GPR32RegClass.contains(Reg: DestReg)) { // Copy to CPU Reg. |
91 | if (Mips::GPR32RegClass.contains(Reg: SrcReg)) { |
92 | if (isMicroMips) |
93 | Opc = Mips::MOVE16_MM; |
94 | else |
95 | Opc = Mips::OR, ZeroReg = Mips::ZERO; |
96 | } else if (Mips::CCRRegClass.contains(Reg: SrcReg)) |
97 | Opc = Mips::CFC1; |
98 | else if (Mips::FGR32RegClass.contains(Reg: SrcReg)) |
99 | Opc = Mips::MFC1; |
100 | else if (Mips::HI32RegClass.contains(Reg: SrcReg)) { |
101 | Opc = isMicroMips ? Mips::MFHI16_MM : Mips::MFHI; |
102 | SrcReg = 0; |
103 | } else if (Mips::LO32RegClass.contains(Reg: SrcReg)) { |
104 | Opc = isMicroMips ? Mips::MFLO16_MM : Mips::MFLO; |
105 | SrcReg = 0; |
106 | } else if (Mips::HI32DSPRegClass.contains(Reg: SrcReg)) |
107 | Opc = Mips::MFHI_DSP; |
108 | else if (Mips::LO32DSPRegClass.contains(Reg: SrcReg)) |
109 | Opc = Mips::MFLO_DSP; |
110 | else if (Mips::DSPCCRegClass.contains(Reg: SrcReg)) { |
111 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: get(Opcode: Mips::RDDSP), DestReg).addImm(Val: 1 << 4) |
112 | .addReg(RegNo: SrcReg, flags: RegState::Implicit | getKillRegState(B: KillSrc)); |
113 | return; |
114 | } |
115 | else if (Mips::MSACtrlRegClass.contains(Reg: SrcReg)) |
116 | Opc = Mips::CFCMSA; |
117 | } |
118 | else if (Mips::GPR32RegClass.contains(Reg: SrcReg)) { // Copy from CPU Reg. |
119 | if (Mips::CCRRegClass.contains(Reg: DestReg)) |
120 | Opc = Mips::CTC1; |
121 | else if (Mips::FGR32RegClass.contains(Reg: DestReg)) |
122 | Opc = Mips::MTC1; |
123 | else if (Mips::HI32RegClass.contains(Reg: DestReg)) |
124 | Opc = Mips::MTHI, DestReg = 0; |
125 | else if (Mips::LO32RegClass.contains(Reg: DestReg)) |
126 | Opc = Mips::MTLO, DestReg = 0; |
127 | else if (Mips::HI32DSPRegClass.contains(Reg: DestReg)) |
128 | Opc = Mips::MTHI_DSP; |
129 | else if (Mips::LO32DSPRegClass.contains(Reg: DestReg)) |
130 | Opc = Mips::MTLO_DSP; |
131 | else if (Mips::DSPCCRegClass.contains(Reg: DestReg)) { |
132 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: get(Opcode: Mips::WRDSP)) |
133 | .addReg(RegNo: SrcReg, flags: getKillRegState(B: KillSrc)).addImm(Val: 1 << 4) |
134 | .addReg(RegNo: DestReg, flags: RegState::ImplicitDefine); |
135 | return; |
136 | } else if (Mips::MSACtrlRegClass.contains(Reg: DestReg)) { |
137 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: get(Opcode: Mips::CTCMSA)) |
138 | .addReg(RegNo: DestReg) |
139 | .addReg(RegNo: SrcReg, flags: getKillRegState(B: KillSrc)); |
140 | return; |
141 | } |
142 | } |
143 | else if (Mips::FGR32RegClass.contains(Reg1: DestReg, Reg2: SrcReg)) |
144 | Opc = Mips::FMOV_S; |
145 | else if (Mips::AFGR64RegClass.contains(Reg1: DestReg, Reg2: SrcReg)) |
146 | Opc = Mips::FMOV_D32; |
147 | else if (Mips::FGR64RegClass.contains(Reg1: DestReg, Reg2: SrcReg)) |
148 | Opc = Mips::FMOV_D64; |
149 | else if (Mips::GPR64RegClass.contains(Reg: DestReg)) { // Copy to CPU64 Reg. |
150 | if (Mips::GPR64RegClass.contains(Reg: SrcReg)) |
151 | Opc = Mips::OR64, ZeroReg = Mips::ZERO_64; |
152 | else if (Mips::HI64RegClass.contains(Reg: SrcReg)) |
153 | Opc = Mips::MFHI64, SrcReg = 0; |
154 | else if (Mips::LO64RegClass.contains(Reg: SrcReg)) |
155 | Opc = Mips::MFLO64, SrcReg = 0; |
156 | else if (Mips::FGR64RegClass.contains(Reg: SrcReg)) |
157 | Opc = Mips::DMFC1; |
158 | } |
159 | else if (Mips::GPR64RegClass.contains(Reg: SrcReg)) { // Copy from CPU64 Reg. |
160 | if (Mips::HI64RegClass.contains(Reg: DestReg)) |
161 | Opc = Mips::MTHI64, DestReg = 0; |
162 | else if (Mips::LO64RegClass.contains(Reg: DestReg)) |
163 | Opc = Mips::MTLO64, DestReg = 0; |
164 | else if (Mips::FGR64RegClass.contains(Reg: DestReg)) |
165 | Opc = Mips::DMTC1; |
166 | } |
167 | else if (Mips::MSA128BRegClass.contains(Reg: DestReg)) { // Copy to MSA reg |
168 | if (Mips::MSA128BRegClass.contains(Reg: SrcReg)) |
169 | Opc = Mips::MOVE_V; |
170 | } |
171 | |
172 | assert(Opc && "Cannot copy registers" ); |
173 | |
174 | MachineInstrBuilder MIB = BuildMI(BB&: MBB, I, MIMD: DL, MCID: get(Opcode: Opc)); |
175 | |
176 | if (DestReg) |
177 | MIB.addReg(RegNo: DestReg, flags: RegState::Define); |
178 | |
179 | if (SrcReg) |
180 | MIB.addReg(RegNo: SrcReg, flags: getKillRegState(B: KillSrc)); |
181 | |
182 | if (ZeroReg) |
183 | MIB.addReg(RegNo: ZeroReg); |
184 | } |
185 | |
186 | static bool isORCopyInst(const MachineInstr &MI) { |
187 | switch (MI.getOpcode()) { |
188 | default: |
189 | break; |
190 | case Mips::OR_MM: |
191 | case Mips::OR: |
192 | if (MI.getOperand(i: 2).getReg() == Mips::ZERO) |
193 | return true; |
194 | break; |
195 | case Mips::OR64: |
196 | if (MI.getOperand(i: 2).getReg() == Mips::ZERO_64) |
197 | return true; |
198 | break; |
199 | } |
200 | return false; |
201 | } |
202 | |
203 | /// We check for the common case of 'or', as it's MIPS' preferred instruction |
204 | /// for GPRs but we have to check the operands to ensure that is the case. |
205 | /// Other move instructions for MIPS are directly identifiable. |
206 | std::optional<DestSourcePair> |
207 | MipsSEInstrInfo::isCopyInstrImpl(const MachineInstr &MI) const { |
208 | if (MI.isMoveReg() || isORCopyInst(MI)) |
209 | return DestSourcePair{MI.getOperand(i: 0), MI.getOperand(i: 1)}; |
210 | |
211 | return std::nullopt; |
212 | } |
213 | |
214 | void MipsSEInstrInfo:: |
215 | storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, |
216 | Register SrcReg, bool isKill, int FI, |
217 | const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, |
218 | int64_t Offset) const { |
219 | DebugLoc DL; |
220 | MachineMemOperand *MMO = GetMemOperand(MBB, FI, Flags: MachineMemOperand::MOStore); |
221 | |
222 | unsigned Opc = 0; |
223 | |
224 | if (Mips::GPR32RegClass.hasSubClassEq(RC)) |
225 | Opc = Mips::SW; |
226 | else if (Mips::GPR64RegClass.hasSubClassEq(RC)) |
227 | Opc = Mips::SD; |
228 | else if (Mips::ACC64RegClass.hasSubClassEq(RC)) |
229 | Opc = Mips::STORE_ACC64; |
230 | else if (Mips::ACC64DSPRegClass.hasSubClassEq(RC)) |
231 | Opc = Mips::STORE_ACC64DSP; |
232 | else if (Mips::ACC128RegClass.hasSubClassEq(RC)) |
233 | Opc = Mips::STORE_ACC128; |
234 | else if (Mips::DSPCCRegClass.hasSubClassEq(RC)) |
235 | Opc = Mips::STORE_CCOND_DSP; |
236 | else if (Mips::FGR32RegClass.hasSubClassEq(RC)) |
237 | Opc = Mips::SWC1; |
238 | else if (Mips::AFGR64RegClass.hasSubClassEq(RC)) |
239 | Opc = Mips::SDC1; |
240 | else if (Mips::FGR64RegClass.hasSubClassEq(RC)) |
241 | Opc = Mips::SDC164; |
242 | else if (TRI->isTypeLegalForClass(RC: *RC, T: MVT::v16i8)) |
243 | Opc = Mips::ST_B; |
244 | else if (TRI->isTypeLegalForClass(RC: *RC, T: MVT::v8i16) || |
245 | TRI->isTypeLegalForClass(RC: *RC, T: MVT::v8f16)) |
246 | Opc = Mips::ST_H; |
247 | else if (TRI->isTypeLegalForClass(RC: *RC, T: MVT::v4i32) || |
248 | TRI->isTypeLegalForClass(RC: *RC, T: MVT::v4f32)) |
249 | Opc = Mips::ST_W; |
250 | else if (TRI->isTypeLegalForClass(RC: *RC, T: MVT::v2i64) || |
251 | TRI->isTypeLegalForClass(RC: *RC, T: MVT::v2f64)) |
252 | Opc = Mips::ST_D; |
253 | else if (Mips::LO32RegClass.hasSubClassEq(RC)) |
254 | Opc = Mips::SW; |
255 | else if (Mips::LO64RegClass.hasSubClassEq(RC)) |
256 | Opc = Mips::SD; |
257 | else if (Mips::HI32RegClass.hasSubClassEq(RC)) |
258 | Opc = Mips::SW; |
259 | else if (Mips::HI64RegClass.hasSubClassEq(RC)) |
260 | Opc = Mips::SD; |
261 | else if (Mips::DSPRRegClass.hasSubClassEq(RC)) |
262 | Opc = Mips::SWDSP; |
263 | |
264 | // Hi, Lo are normally caller save but they are callee save |
265 | // for interrupt handling. |
266 | const Function &Func = MBB.getParent()->getFunction(); |
267 | if (Func.hasFnAttribute(Kind: "interrupt" )) { |
268 | if (Mips::HI32RegClass.hasSubClassEq(RC)) { |
269 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: get(Opcode: Mips::MFHI), DestReg: Mips::K0); |
270 | SrcReg = Mips::K0; |
271 | } else if (Mips::HI64RegClass.hasSubClassEq(RC)) { |
272 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: get(Opcode: Mips::MFHI64), DestReg: Mips::K0_64); |
273 | SrcReg = Mips::K0_64; |
274 | } else if (Mips::LO32RegClass.hasSubClassEq(RC)) { |
275 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: get(Opcode: Mips::MFLO), DestReg: Mips::K0); |
276 | SrcReg = Mips::K0; |
277 | } else if (Mips::LO64RegClass.hasSubClassEq(RC)) { |
278 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: get(Opcode: Mips::MFLO64), DestReg: Mips::K0_64); |
279 | SrcReg = Mips::K0_64; |
280 | } |
281 | } |
282 | |
283 | assert(Opc && "Register class not handled!" ); |
284 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: get(Opcode: Opc)).addReg(RegNo: SrcReg, flags: getKillRegState(B: isKill)) |
285 | .addFrameIndex(Idx: FI).addImm(Val: Offset).addMemOperand(MMO); |
286 | } |
287 | |
288 | void MipsSEInstrInfo:: |
289 | loadRegFromStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, |
290 | Register DestReg, int FI, const TargetRegisterClass *RC, |
291 | const TargetRegisterInfo *TRI, int64_t Offset) const { |
292 | DebugLoc DL; |
293 | if (I != MBB.end()) DL = I->getDebugLoc(); |
294 | MachineMemOperand *MMO = GetMemOperand(MBB, FI, Flags: MachineMemOperand::MOLoad); |
295 | unsigned Opc = 0; |
296 | |
297 | const Function &Func = MBB.getParent()->getFunction(); |
298 | bool ReqIndirectLoad = Func.hasFnAttribute(Kind: "interrupt" ) && |
299 | (DestReg == Mips::LO0 || DestReg == Mips::LO0_64 || |
300 | DestReg == Mips::HI0 || DestReg == Mips::HI0_64); |
301 | |
302 | if (Mips::GPR32RegClass.hasSubClassEq(RC)) |
303 | Opc = Mips::LW; |
304 | else if (Mips::GPR64RegClass.hasSubClassEq(RC)) |
305 | Opc = Mips::LD; |
306 | else if (Mips::ACC64RegClass.hasSubClassEq(RC)) |
307 | Opc = Mips::LOAD_ACC64; |
308 | else if (Mips::ACC64DSPRegClass.hasSubClassEq(RC)) |
309 | Opc = Mips::LOAD_ACC64DSP; |
310 | else if (Mips::ACC128RegClass.hasSubClassEq(RC)) |
311 | Opc = Mips::LOAD_ACC128; |
312 | else if (Mips::DSPCCRegClass.hasSubClassEq(RC)) |
313 | Opc = Mips::LOAD_CCOND_DSP; |
314 | else if (Mips::FGR32RegClass.hasSubClassEq(RC)) |
315 | Opc = Mips::LWC1; |
316 | else if (Mips::AFGR64RegClass.hasSubClassEq(RC)) |
317 | Opc = Mips::LDC1; |
318 | else if (Mips::FGR64RegClass.hasSubClassEq(RC)) |
319 | Opc = Mips::LDC164; |
320 | else if (TRI->isTypeLegalForClass(RC: *RC, T: MVT::v16i8)) |
321 | Opc = Mips::LD_B; |
322 | else if (TRI->isTypeLegalForClass(RC: *RC, T: MVT::v8i16) || |
323 | TRI->isTypeLegalForClass(RC: *RC, T: MVT::v8f16)) |
324 | Opc = Mips::LD_H; |
325 | else if (TRI->isTypeLegalForClass(RC: *RC, T: MVT::v4i32) || |
326 | TRI->isTypeLegalForClass(RC: *RC, T: MVT::v4f32)) |
327 | Opc = Mips::LD_W; |
328 | else if (TRI->isTypeLegalForClass(RC: *RC, T: MVT::v2i64) || |
329 | TRI->isTypeLegalForClass(RC: *RC, T: MVT::v2f64)) |
330 | Opc = Mips::LD_D; |
331 | else if (Mips::HI32RegClass.hasSubClassEq(RC)) |
332 | Opc = Mips::LW; |
333 | else if (Mips::HI64RegClass.hasSubClassEq(RC)) |
334 | Opc = Mips::LD; |
335 | else if (Mips::LO32RegClass.hasSubClassEq(RC)) |
336 | Opc = Mips::LW; |
337 | else if (Mips::LO64RegClass.hasSubClassEq(RC)) |
338 | Opc = Mips::LD; |
339 | else if (Mips::DSPRRegClass.hasSubClassEq(RC)) |
340 | Opc = Mips::LWDSP; |
341 | |
342 | assert(Opc && "Register class not handled!" ); |
343 | |
344 | if (!ReqIndirectLoad) |
345 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: get(Opcode: Opc), DestReg) |
346 | .addFrameIndex(Idx: FI) |
347 | .addImm(Val: Offset) |
348 | .addMemOperand(MMO); |
349 | else { |
350 | // Load HI/LO through K0. Notably the DestReg is encoded into the |
351 | // instruction itself. |
352 | unsigned Reg = Mips::K0; |
353 | unsigned LdOp = Mips::MTLO; |
354 | if (DestReg == Mips::HI0) |
355 | LdOp = Mips::MTHI; |
356 | |
357 | if (Subtarget.getABI().ArePtrs64bit()) { |
358 | Reg = Mips::K0_64; |
359 | if (DestReg == Mips::HI0_64) |
360 | LdOp = Mips::MTHI64; |
361 | else |
362 | LdOp = Mips::MTLO64; |
363 | } |
364 | |
365 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: get(Opcode: Opc), DestReg: Reg) |
366 | .addFrameIndex(Idx: FI) |
367 | .addImm(Val: Offset) |
368 | .addMemOperand(MMO); |
369 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: get(Opcode: LdOp)).addReg(RegNo: Reg); |
370 | } |
371 | } |
372 | |
373 | bool MipsSEInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { |
374 | MachineBasicBlock &MBB = *MI.getParent(); |
375 | bool isMicroMips = Subtarget.inMicroMipsMode(); |
376 | unsigned Opc; |
377 | |
378 | switch (MI.getDesc().getOpcode()) { |
379 | default: |
380 | return false; |
381 | case Mips::RetRA: |
382 | expandRetRA(MBB, I: MI); |
383 | break; |
384 | case Mips::ERet: |
385 | expandERet(MBB, I: MI); |
386 | break; |
387 | case Mips::PseudoMFHI: |
388 | expandPseudoMFHiLo(MBB, I: MI, NewOpc: Mips::MFHI); |
389 | break; |
390 | case Mips::PseudoMFHI_MM: |
391 | expandPseudoMFHiLo(MBB, I: MI, NewOpc: Mips::MFHI16_MM); |
392 | break; |
393 | case Mips::PseudoMFLO: |
394 | expandPseudoMFHiLo(MBB, I: MI, NewOpc: Mips::MFLO); |
395 | break; |
396 | case Mips::PseudoMFLO_MM: |
397 | expandPseudoMFHiLo(MBB, I: MI, NewOpc: Mips::MFLO16_MM); |
398 | break; |
399 | case Mips::PseudoMFHI64: |
400 | expandPseudoMFHiLo(MBB, I: MI, NewOpc: Mips::MFHI64); |
401 | break; |
402 | case Mips::PseudoMFLO64: |
403 | expandPseudoMFHiLo(MBB, I: MI, NewOpc: Mips::MFLO64); |
404 | break; |
405 | case Mips::PseudoMTLOHI: |
406 | expandPseudoMTLoHi(MBB, I: MI, LoOpc: Mips::MTLO, HiOpc: Mips::MTHI, HasExplicitDef: false); |
407 | break; |
408 | case Mips::PseudoMTLOHI64: |
409 | expandPseudoMTLoHi(MBB, I: MI, LoOpc: Mips::MTLO64, HiOpc: Mips::MTHI64, HasExplicitDef: false); |
410 | break; |
411 | case Mips::PseudoMTLOHI_DSP: |
412 | expandPseudoMTLoHi(MBB, I: MI, LoOpc: Mips::MTLO_DSP, HiOpc: Mips::MTHI_DSP, HasExplicitDef: true); |
413 | break; |
414 | case Mips::PseudoMTLOHI_MM: |
415 | expandPseudoMTLoHi(MBB, I: MI, LoOpc: Mips::MTLO_MM, HiOpc: Mips::MTHI_MM, HasExplicitDef: false); |
416 | break; |
417 | case Mips::PseudoCVT_S_W: |
418 | expandCvtFPInt(MBB, I: MI, CvtOpc: Mips::CVT_S_W, MovOpc: Mips::MTC1, IsI64: false); |
419 | break; |
420 | case Mips::PseudoCVT_D32_W: |
421 | Opc = isMicroMips ? Mips::CVT_D32_W_MM : Mips::CVT_D32_W; |
422 | expandCvtFPInt(MBB, I: MI, CvtOpc: Opc, MovOpc: Mips::MTC1, IsI64: false); |
423 | break; |
424 | case Mips::PseudoCVT_S_L: |
425 | expandCvtFPInt(MBB, I: MI, CvtOpc: Mips::CVT_S_L, MovOpc: Mips::DMTC1, IsI64: true); |
426 | break; |
427 | case Mips::PseudoCVT_D64_W: |
428 | Opc = isMicroMips ? Mips::CVT_D64_W_MM : Mips::CVT_D64_W; |
429 | expandCvtFPInt(MBB, I: MI, CvtOpc: Opc, MovOpc: Mips::MTC1, IsI64: true); |
430 | break; |
431 | case Mips::PseudoCVT_D64_L: |
432 | expandCvtFPInt(MBB, I: MI, CvtOpc: Mips::CVT_D64_L, MovOpc: Mips::DMTC1, IsI64: true); |
433 | break; |
434 | case Mips::BuildPairF64: |
435 | expandBuildPairF64(MBB, I: MI, isMicroMips, FP64: false); |
436 | break; |
437 | case Mips::BuildPairF64_64: |
438 | expandBuildPairF64(MBB, I: MI, isMicroMips, FP64: true); |
439 | break; |
440 | case Mips::ExtractElementF64: |
441 | expandExtractElementF64(MBB, I: MI, isMicroMips, FP64: false); |
442 | break; |
443 | case Mips::ExtractElementF64_64: |
444 | expandExtractElementF64(MBB, I: MI, isMicroMips, FP64: true); |
445 | break; |
446 | case Mips::MIPSeh_return32: |
447 | case Mips::MIPSeh_return64: |
448 | expandEhReturn(MBB, I: MI); |
449 | break; |
450 | } |
451 | |
452 | MBB.erase(I: MI); |
453 | return true; |
454 | } |
455 | |
456 | /// isBranchWithImm - Return true if the branch contains an immediate |
457 | /// operand (\see lib/Target/Mips/MipsBranchExpansion.cpp). |
458 | bool MipsSEInstrInfo::isBranchWithImm(unsigned Opc) const { |
459 | switch (Opc) { |
460 | default: |
461 | return false; |
462 | case Mips::BBIT0: |
463 | case Mips::BBIT1: |
464 | case Mips::BBIT032: |
465 | case Mips::BBIT132: |
466 | return true; |
467 | } |
468 | } |
469 | |
470 | /// getOppositeBranchOpc - Return the inverse of the specified |
471 | /// opcode, e.g. turning BEQ to BNE. |
472 | unsigned MipsSEInstrInfo::getOppositeBranchOpc(unsigned Opc) const { |
473 | switch (Opc) { |
474 | default: llvm_unreachable("Illegal opcode!" ); |
475 | case Mips::BEQ: return Mips::BNE; |
476 | case Mips::BEQ_MM: return Mips::BNE_MM; |
477 | case Mips::BNE: return Mips::BEQ; |
478 | case Mips::BNE_MM: return Mips::BEQ_MM; |
479 | case Mips::BGTZ: return Mips::BLEZ; |
480 | case Mips::BGEZ: return Mips::BLTZ; |
481 | case Mips::BLTZ: return Mips::BGEZ; |
482 | case Mips::BLEZ: return Mips::BGTZ; |
483 | case Mips::BGTZ_MM: return Mips::BLEZ_MM; |
484 | case Mips::BGEZ_MM: return Mips::BLTZ_MM; |
485 | case Mips::BLTZ_MM: return Mips::BGEZ_MM; |
486 | case Mips::BLEZ_MM: return Mips::BGTZ_MM; |
487 | case Mips::BEQ64: return Mips::BNE64; |
488 | case Mips::BNE64: return Mips::BEQ64; |
489 | case Mips::BGTZ64: return Mips::BLEZ64; |
490 | case Mips::BGEZ64: return Mips::BLTZ64; |
491 | case Mips::BLTZ64: return Mips::BGEZ64; |
492 | case Mips::BLEZ64: return Mips::BGTZ64; |
493 | case Mips::BC1T: return Mips::BC1F; |
494 | case Mips::BC1F: return Mips::BC1T; |
495 | case Mips::BC1T_MM: return Mips::BC1F_MM; |
496 | case Mips::BC1F_MM: return Mips::BC1T_MM; |
497 | case Mips::BEQZ16_MM: return Mips::BNEZ16_MM; |
498 | case Mips::BNEZ16_MM: return Mips::BEQZ16_MM; |
499 | case Mips::BEQZC_MM: return Mips::BNEZC_MM; |
500 | case Mips::BNEZC_MM: return Mips::BEQZC_MM; |
501 | case Mips::BEQZC: return Mips::BNEZC; |
502 | case Mips::BNEZC: return Mips::BEQZC; |
503 | case Mips::BLEZC: return Mips::BGTZC; |
504 | case Mips::BGEZC: return Mips::BLTZC; |
505 | case Mips::BGEC: return Mips::BLTC; |
506 | case Mips::BGTZC: return Mips::BLEZC; |
507 | case Mips::BLTZC: return Mips::BGEZC; |
508 | case Mips::BLTC: return Mips::BGEC; |
509 | case Mips::BGEUC: return Mips::BLTUC; |
510 | case Mips::BLTUC: return Mips::BGEUC; |
511 | case Mips::BEQC: return Mips::BNEC; |
512 | case Mips::BNEC: return Mips::BEQC; |
513 | case Mips::BC1EQZ: return Mips::BC1NEZ; |
514 | case Mips::BC1NEZ: return Mips::BC1EQZ; |
515 | case Mips::BEQZC_MMR6: return Mips::BNEZC_MMR6; |
516 | case Mips::BNEZC_MMR6: return Mips::BEQZC_MMR6; |
517 | case Mips::BLEZC_MMR6: return Mips::BGTZC_MMR6; |
518 | case Mips::BGEZC_MMR6: return Mips::BLTZC_MMR6; |
519 | case Mips::BGEC_MMR6: return Mips::BLTC_MMR6; |
520 | case Mips::BGTZC_MMR6: return Mips::BLEZC_MMR6; |
521 | case Mips::BLTZC_MMR6: return Mips::BGEZC_MMR6; |
522 | case Mips::BLTC_MMR6: return Mips::BGEC_MMR6; |
523 | case Mips::BGEUC_MMR6: return Mips::BLTUC_MMR6; |
524 | case Mips::BLTUC_MMR6: return Mips::BGEUC_MMR6; |
525 | case Mips::BEQC_MMR6: return Mips::BNEC_MMR6; |
526 | case Mips::BNEC_MMR6: return Mips::BEQC_MMR6; |
527 | case Mips::BC1EQZC_MMR6: return Mips::BC1NEZC_MMR6; |
528 | case Mips::BC1NEZC_MMR6: return Mips::BC1EQZC_MMR6; |
529 | case Mips::BEQZC64: return Mips::BNEZC64; |
530 | case Mips::BNEZC64: return Mips::BEQZC64; |
531 | case Mips::BEQC64: return Mips::BNEC64; |
532 | case Mips::BNEC64: return Mips::BEQC64; |
533 | case Mips::BGEC64: return Mips::BLTC64; |
534 | case Mips::BGEUC64: return Mips::BLTUC64; |
535 | case Mips::BLTC64: return Mips::BGEC64; |
536 | case Mips::BLTUC64: return Mips::BGEUC64; |
537 | case Mips::BGTZC64: return Mips::BLEZC64; |
538 | case Mips::BGEZC64: return Mips::BLTZC64; |
539 | case Mips::BLTZC64: return Mips::BGEZC64; |
540 | case Mips::BLEZC64: return Mips::BGTZC64; |
541 | case Mips::BBIT0: return Mips::BBIT1; |
542 | case Mips::BBIT1: return Mips::BBIT0; |
543 | case Mips::BBIT032: return Mips::BBIT132; |
544 | case Mips::BBIT132: return Mips::BBIT032; |
545 | case Mips::BZ_B: return Mips::BNZ_B; |
546 | case Mips::BZ_H: return Mips::BNZ_H; |
547 | case Mips::BZ_W: return Mips::BNZ_W; |
548 | case Mips::BZ_D: return Mips::BNZ_D; |
549 | case Mips::BZ_V: return Mips::BNZ_V; |
550 | case Mips::BNZ_B: return Mips::BZ_B; |
551 | case Mips::BNZ_H: return Mips::BZ_H; |
552 | case Mips::BNZ_W: return Mips::BZ_W; |
553 | case Mips::BNZ_D: return Mips::BZ_D; |
554 | case Mips::BNZ_V: return Mips::BZ_V; |
555 | } |
556 | } |
557 | |
558 | /// Adjust SP by Amount bytes. |
559 | void MipsSEInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount, |
560 | MachineBasicBlock &MBB, |
561 | MachineBasicBlock::iterator I) const { |
562 | MipsABIInfo ABI = Subtarget.getABI(); |
563 | DebugLoc DL; |
564 | unsigned ADDiu = ABI.GetPtrAddiuOp(); |
565 | |
566 | if (Amount == 0) |
567 | return; |
568 | |
569 | if (isInt<16>(x: Amount)) { |
570 | // addi sp, sp, amount |
571 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: get(Opcode: ADDiu), DestReg: SP).addReg(RegNo: SP).addImm(Val: Amount); |
572 | } else { |
573 | // For numbers which are not 16bit integers we synthesize Amount inline |
574 | // then add or subtract it from sp. |
575 | unsigned Opc = ABI.GetPtrAdduOp(); |
576 | if (Amount < 0) { |
577 | Opc = ABI.GetPtrSubuOp(); |
578 | Amount = -Amount; |
579 | } |
580 | unsigned Reg = loadImmediate(Imm: Amount, MBB, II: I, DL, NewImm: nullptr); |
581 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: get(Opcode: Opc), DestReg: SP).addReg(RegNo: SP).addReg(RegNo: Reg, flags: RegState::Kill); |
582 | } |
583 | } |
584 | |
585 | /// This function generates the sequence of instructions needed to get the |
586 | /// result of adding register REG and immediate IMM. |
587 | unsigned MipsSEInstrInfo::loadImmediate(int64_t Imm, MachineBasicBlock &MBB, |
588 | MachineBasicBlock::iterator II, |
589 | const DebugLoc &DL, |
590 | unsigned *NewImm) const { |
591 | MipsAnalyzeImmediate AnalyzeImm; |
592 | const MipsSubtarget &STI = Subtarget; |
593 | MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo(); |
594 | unsigned Size = STI.isABI_N64() ? 64 : 32; |
595 | unsigned LUi = STI.isABI_N64() ? Mips::LUi64 : Mips::LUi; |
596 | unsigned ZEROReg = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; |
597 | const TargetRegisterClass *RC = STI.isABI_N64() ? |
598 | &Mips::GPR64RegClass : &Mips::GPR32RegClass; |
599 | bool LastInstrIsADDiu = NewImm; |
600 | |
601 | const MipsAnalyzeImmediate::InstSeq &Seq = |
602 | AnalyzeImm.Analyze(Imm, Size, LastInstrIsADDiu); |
603 | MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin(); |
604 | |
605 | assert(Seq.size() && (!LastInstrIsADDiu || (Seq.size() > 1))); |
606 | |
607 | // The first instruction can be a LUi, which is different from other |
608 | // instructions (ADDiu, ORI and SLL) in that it does not have a register |
609 | // operand. |
610 | Register Reg = RegInfo.createVirtualRegister(RegClass: RC); |
611 | |
612 | if (Inst->Opc == LUi) |
613 | BuildMI(BB&: MBB, I: II, MIMD: DL, MCID: get(Opcode: LUi), DestReg: Reg).addImm(Val: SignExtend64<16>(x: Inst->ImmOpnd)); |
614 | else |
615 | BuildMI(BB&: MBB, I: II, MIMD: DL, MCID: get(Opcode: Inst->Opc), DestReg: Reg).addReg(RegNo: ZEROReg) |
616 | .addImm(Val: SignExtend64<16>(x: Inst->ImmOpnd)); |
617 | |
618 | // Build the remaining instructions in Seq. |
619 | for (++Inst; Inst != Seq.end() - LastInstrIsADDiu; ++Inst) |
620 | BuildMI(BB&: MBB, I: II, MIMD: DL, MCID: get(Opcode: Inst->Opc), DestReg: Reg).addReg(RegNo: Reg, flags: RegState::Kill) |
621 | .addImm(Val: SignExtend64<16>(x: Inst->ImmOpnd)); |
622 | |
623 | if (LastInstrIsADDiu) |
624 | *NewImm = Inst->ImmOpnd; |
625 | |
626 | return Reg; |
627 | } |
628 | |
629 | unsigned MipsSEInstrInfo::getAnalyzableBrOpc(unsigned Opc) const { |
630 | return (Opc == Mips::BEQ || Opc == Mips::BEQ_MM || Opc == Mips::BNE || |
631 | Opc == Mips::BNE_MM || Opc == Mips::BGTZ || Opc == Mips::BGEZ || |
632 | Opc == Mips::BLTZ || Opc == Mips::BLEZ || Opc == Mips::BEQ64 || |
633 | Opc == Mips::BNE64 || Opc == Mips::BGTZ64 || Opc == Mips::BGEZ64 || |
634 | Opc == Mips::BLTZ64 || Opc == Mips::BLEZ64 || Opc == Mips::BC1T || |
635 | Opc == Mips::BC1F || Opc == Mips::B || Opc == Mips::J || |
636 | Opc == Mips::J_MM || Opc == Mips::B_MM || Opc == Mips::BEQZC_MM || |
637 | Opc == Mips::BNEZC_MM || Opc == Mips::BEQC || Opc == Mips::BNEC || |
638 | Opc == Mips::BLTC || Opc == Mips::BGEC || Opc == Mips::BLTUC || |
639 | Opc == Mips::BGEUC || Opc == Mips::BGTZC || Opc == Mips::BLEZC || |
640 | Opc == Mips::BGEZC || Opc == Mips::BLTZC || Opc == Mips::BEQZC || |
641 | Opc == Mips::BNEZC || Opc == Mips::BEQZC64 || Opc == Mips::BNEZC64 || |
642 | Opc == Mips::BEQC64 || Opc == Mips::BNEC64 || Opc == Mips::BGEC64 || |
643 | Opc == Mips::BGEUC64 || Opc == Mips::BLTC64 || Opc == Mips::BLTUC64 || |
644 | Opc == Mips::BGTZC64 || Opc == Mips::BGEZC64 || |
645 | Opc == Mips::BLTZC64 || Opc == Mips::BLEZC64 || Opc == Mips::BC || |
646 | Opc == Mips::BBIT0 || Opc == Mips::BBIT1 || Opc == Mips::BBIT032 || |
647 | Opc == Mips::BBIT132 || Opc == Mips::BC_MMR6 || |
648 | Opc == Mips::BEQC_MMR6 || Opc == Mips::BNEC_MMR6 || |
649 | Opc == Mips::BLTC_MMR6 || Opc == Mips::BGEC_MMR6 || |
650 | Opc == Mips::BLTUC_MMR6 || Opc == Mips::BGEUC_MMR6 || |
651 | Opc == Mips::BGTZC_MMR6 || Opc == Mips::BLEZC_MMR6 || |
652 | Opc == Mips::BGEZC_MMR6 || Opc == Mips::BLTZC_MMR6 || |
653 | Opc == Mips::BEQZC_MMR6 || Opc == Mips::BNEZC_MMR6) ? Opc : 0; |
654 | } |
655 | |
656 | void MipsSEInstrInfo::expandRetRA(MachineBasicBlock &MBB, |
657 | MachineBasicBlock::iterator I) const { |
658 | |
659 | MachineInstrBuilder MIB; |
660 | if (Subtarget.isGP64bit()) |
661 | MIB = BuildMI(BB&: MBB, I, MIMD: I->getDebugLoc(), MCID: get(Opcode: Mips::PseudoReturn64)) |
662 | .addReg(RegNo: Mips::RA_64, flags: RegState::Undef); |
663 | else |
664 | MIB = BuildMI(BB&: MBB, I, MIMD: I->getDebugLoc(), MCID: get(Opcode: Mips::PseudoReturn)) |
665 | .addReg(RegNo: Mips::RA, flags: RegState::Undef); |
666 | |
667 | // Retain any imp-use flags. |
668 | for (auto & MO : I->operands()) { |
669 | if (MO.isImplicit()) |
670 | MIB.add(MO); |
671 | } |
672 | } |
673 | |
674 | void MipsSEInstrInfo::expandERet(MachineBasicBlock &MBB, |
675 | MachineBasicBlock::iterator I) const { |
676 | BuildMI(BB&: MBB, I, MIMD: I->getDebugLoc(), MCID: get(Opcode: Mips::ERET)); |
677 | } |
678 | |
679 | std::pair<bool, bool> |
680 | MipsSEInstrInfo::compareOpndSize(unsigned Opc, |
681 | const MachineFunction &MF) const { |
682 | const MCInstrDesc &Desc = get(Opcode: Opc); |
683 | assert(Desc.NumOperands == 2 && "Unary instruction expected." ); |
684 | const MipsRegisterInfo *RI = &getRegisterInfo(); |
685 | unsigned DstRegSize = RI->getRegSizeInBits(RC: *getRegClass(MCID: Desc, OpNum: 0, TRI: RI, MF)); |
686 | unsigned SrcRegSize = RI->getRegSizeInBits(RC: *getRegClass(MCID: Desc, OpNum: 1, TRI: RI, MF)); |
687 | |
688 | return std::make_pair(x: DstRegSize > SrcRegSize, y: DstRegSize < SrcRegSize); |
689 | } |
690 | |
691 | void MipsSEInstrInfo::expandPseudoMFHiLo(MachineBasicBlock &MBB, |
692 | MachineBasicBlock::iterator I, |
693 | unsigned NewOpc) const { |
694 | BuildMI(BB&: MBB, I, MIMD: I->getDebugLoc(), MCID: get(Opcode: NewOpc), DestReg: I->getOperand(i: 0).getReg()); |
695 | } |
696 | |
697 | void MipsSEInstrInfo::expandPseudoMTLoHi(MachineBasicBlock &MBB, |
698 | MachineBasicBlock::iterator I, |
699 | unsigned LoOpc, |
700 | unsigned HiOpc, |
701 | bool HasExplicitDef) const { |
702 | // Expand |
703 | // lo_hi pseudomtlohi $gpr0, $gpr1 |
704 | // to these two instructions: |
705 | // mtlo $gpr0 |
706 | // mthi $gpr1 |
707 | |
708 | DebugLoc DL = I->getDebugLoc(); |
709 | const MachineOperand &SrcLo = I->getOperand(i: 1), &SrcHi = I->getOperand(i: 2); |
710 | MachineInstrBuilder LoInst = BuildMI(BB&: MBB, I, MIMD: DL, MCID: get(Opcode: LoOpc)); |
711 | MachineInstrBuilder HiInst = BuildMI(BB&: MBB, I, MIMD: DL, MCID: get(Opcode: HiOpc)); |
712 | |
713 | // Add lo/hi registers if the mtlo/hi instructions created have explicit |
714 | // def registers. |
715 | if (HasExplicitDef) { |
716 | Register DstReg = I->getOperand(i: 0).getReg(); |
717 | Register DstLo = getRegisterInfo().getSubReg(Reg: DstReg, Idx: Mips::sub_lo); |
718 | Register DstHi = getRegisterInfo().getSubReg(Reg: DstReg, Idx: Mips::sub_hi); |
719 | LoInst.addReg(RegNo: DstLo, flags: RegState::Define); |
720 | HiInst.addReg(RegNo: DstHi, flags: RegState::Define); |
721 | } |
722 | |
723 | LoInst.addReg(RegNo: SrcLo.getReg(), flags: getKillRegState(B: SrcLo.isKill())); |
724 | HiInst.addReg(RegNo: SrcHi.getReg(), flags: getKillRegState(B: SrcHi.isKill())); |
725 | } |
726 | |
727 | void MipsSEInstrInfo::expandCvtFPInt(MachineBasicBlock &MBB, |
728 | MachineBasicBlock::iterator I, |
729 | unsigned CvtOpc, unsigned MovOpc, |
730 | bool IsI64) const { |
731 | const MCInstrDesc &CvtDesc = get(Opcode: CvtOpc), &MovDesc = get(Opcode: MovOpc); |
732 | const MachineOperand &Dst = I->getOperand(i: 0), &Src = I->getOperand(i: 1); |
733 | unsigned DstReg = Dst.getReg(), SrcReg = Src.getReg(), TmpReg = DstReg; |
734 | unsigned KillSrc = getKillRegState(B: Src.isKill()); |
735 | DebugLoc DL = I->getDebugLoc(); |
736 | bool DstIsLarger, SrcIsLarger; |
737 | |
738 | std::tie(args&: DstIsLarger, args&: SrcIsLarger) = |
739 | compareOpndSize(Opc: CvtOpc, MF: *MBB.getParent()); |
740 | |
741 | if (DstIsLarger) |
742 | TmpReg = getRegisterInfo().getSubReg(Reg: DstReg, Idx: Mips::sub_lo); |
743 | |
744 | if (SrcIsLarger) |
745 | DstReg = getRegisterInfo().getSubReg(Reg: DstReg, Idx: Mips::sub_lo); |
746 | |
747 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: MovDesc, DestReg: TmpReg).addReg(RegNo: SrcReg, flags: KillSrc); |
748 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: CvtDesc, DestReg: DstReg).addReg(RegNo: TmpReg, flags: RegState::Kill); |
749 | } |
750 | |
751 | void MipsSEInstrInfo::expandExtractElementF64(MachineBasicBlock &MBB, |
752 | MachineBasicBlock::iterator I, |
753 | bool isMicroMips, |
754 | bool FP64) const { |
755 | Register DstReg = I->getOperand(i: 0).getReg(); |
756 | Register SrcReg = I->getOperand(i: 1).getReg(); |
757 | unsigned N = I->getOperand(i: 2).getImm(); |
758 | DebugLoc dl = I->getDebugLoc(); |
759 | |
760 | assert(N < 2 && "Invalid immediate" ); |
761 | unsigned SubIdx = N ? Mips::sub_hi : Mips::sub_lo; |
762 | Register SubReg = getRegisterInfo().getSubReg(Reg: SrcReg, Idx: SubIdx); |
763 | |
764 | // FPXX on MIPS-II or MIPS32r1 should have been handled with a spill/reload |
765 | // in MipsSEFrameLowering.cpp. |
766 | assert(!(Subtarget.isABI_FPXX() && !Subtarget.hasMips32r2())); |
767 | |
768 | // FP64A (FP64 with nooddspreg) should have been handled with a spill/reload |
769 | // in MipsSEFrameLowering.cpp. |
770 | assert(!(Subtarget.isFP64bit() && !Subtarget.useOddSPReg())); |
771 | |
772 | if (SubIdx == Mips::sub_hi && Subtarget.hasMTHC1()) { |
773 | // FIXME: Strictly speaking MFHC1 only reads the top 32-bits however, we |
774 | // claim to read the whole 64-bits as part of a white lie used to |
775 | // temporarily work around a widespread bug in the -mfp64 support. |
776 | // The problem is that none of the 32-bit fpu ops mention the fact |
777 | // that they clobber the upper 32-bits of the 64-bit FPR. Fixing that |
778 | // requires a major overhaul of the FPU implementation which can't |
779 | // be done right now due to time constraints. |
780 | // MFHC1 is one of two instructions that are affected since they are |
781 | // the only instructions that don't read the lower 32-bits. |
782 | // We therefore pretend that it reads the bottom 32-bits to |
783 | // artificially create a dependency and prevent the scheduler |
784 | // changing the behaviour of the code. |
785 | BuildMI(BB&: MBB, I, MIMD: dl, |
786 | MCID: get(Opcode: isMicroMips ? (FP64 ? Mips::MFHC1_D64_MM : Mips::MFHC1_D32_MM) |
787 | : (FP64 ? Mips::MFHC1_D64 : Mips::MFHC1_D32)), |
788 | DestReg: DstReg) |
789 | .addReg(RegNo: SrcReg); |
790 | } else |
791 | BuildMI(BB&: MBB, I, MIMD: dl, MCID: get(Opcode: Mips::MFC1), DestReg: DstReg).addReg(RegNo: SubReg); |
792 | } |
793 | |
794 | void MipsSEInstrInfo::expandBuildPairF64(MachineBasicBlock &MBB, |
795 | MachineBasicBlock::iterator I, |
796 | bool isMicroMips, bool FP64) const { |
797 | Register DstReg = I->getOperand(i: 0).getReg(); |
798 | unsigned LoReg = I->getOperand(i: 1).getReg(), HiReg = I->getOperand(i: 2).getReg(); |
799 | const MCInstrDesc& Mtc1Tdd = get(Opcode: Mips::MTC1); |
800 | DebugLoc dl = I->getDebugLoc(); |
801 | const TargetRegisterInfo &TRI = getRegisterInfo(); |
802 | |
803 | // When mthc1 is available, use: |
804 | // mtc1 Lo, $fp |
805 | // mthc1 Hi, $fp |
806 | // |
807 | // Otherwise, for O32 FPXX ABI: |
808 | // spill + reload via ldc1 |
809 | // This case is handled by the frame lowering code. |
810 | // |
811 | // Otherwise, for FP32: |
812 | // mtc1 Lo, $fp |
813 | // mtc1 Hi, $fp + 1 |
814 | // |
815 | // The case where dmtc1 is available doesn't need to be handled here |
816 | // because it never creates a BuildPairF64 node. |
817 | |
818 | // FPXX on MIPS-II or MIPS32r1 should have been handled with a spill/reload |
819 | // in MipsSEFrameLowering.cpp. |
820 | assert(!(Subtarget.isABI_FPXX() && !Subtarget.hasMips32r2())); |
821 | |
822 | // FP64A (FP64 with nooddspreg) should have been handled with a spill/reload |
823 | // in MipsSEFrameLowering.cpp. |
824 | assert(!(Subtarget.isFP64bit() && !Subtarget.useOddSPReg())); |
825 | |
826 | BuildMI(BB&: MBB, I, MIMD: dl, MCID: Mtc1Tdd, DestReg: TRI.getSubReg(Reg: DstReg, Idx: Mips::sub_lo)) |
827 | .addReg(RegNo: LoReg); |
828 | |
829 | if (Subtarget.hasMTHC1()) { |
830 | // FIXME: The .addReg(DstReg) is a white lie used to temporarily work |
831 | // around a widespread bug in the -mfp64 support. |
832 | // The problem is that none of the 32-bit fpu ops mention the fact |
833 | // that they clobber the upper 32-bits of the 64-bit FPR. Fixing that |
834 | // requires a major overhaul of the FPU implementation which can't |
835 | // be done right now due to time constraints. |
836 | // MTHC1 is one of two instructions that are affected since they are |
837 | // the only instructions that don't read the lower 32-bits. |
838 | // We therefore pretend that it reads the bottom 32-bits to |
839 | // artificially create a dependency and prevent the scheduler |
840 | // changing the behaviour of the code. |
841 | BuildMI(BB&: MBB, I, MIMD: dl, |
842 | MCID: get(Opcode: isMicroMips ? (FP64 ? Mips::MTHC1_D64_MM : Mips::MTHC1_D32_MM) |
843 | : (FP64 ? Mips::MTHC1_D64 : Mips::MTHC1_D32)), |
844 | DestReg: DstReg) |
845 | .addReg(RegNo: DstReg) |
846 | .addReg(RegNo: HiReg); |
847 | } else if (Subtarget.isABI_FPXX()) |
848 | llvm_unreachable("BuildPairF64 not expanded in frame lowering code!" ); |
849 | else |
850 | BuildMI(BB&: MBB, I, MIMD: dl, MCID: Mtc1Tdd, DestReg: TRI.getSubReg(Reg: DstReg, Idx: Mips::sub_hi)) |
851 | .addReg(RegNo: HiReg); |
852 | } |
853 | |
854 | void MipsSEInstrInfo::expandEhReturn(MachineBasicBlock &MBB, |
855 | MachineBasicBlock::iterator I) const { |
856 | // This pseudo instruction is generated as part of the lowering of |
857 | // ISD::EH_RETURN. We convert it to a stack increment by OffsetReg, and |
858 | // indirect jump to TargetReg |
859 | MipsABIInfo ABI = Subtarget.getABI(); |
860 | unsigned ADDU = ABI.GetPtrAdduOp(); |
861 | unsigned SP = Subtarget.isGP64bit() ? Mips::SP_64 : Mips::SP; |
862 | unsigned RA = Subtarget.isGP64bit() ? Mips::RA_64 : Mips::RA; |
863 | unsigned T9 = Subtarget.isGP64bit() ? Mips::T9_64 : Mips::T9; |
864 | unsigned ZERO = Subtarget.isGP64bit() ? Mips::ZERO_64 : Mips::ZERO; |
865 | Register OffsetReg = I->getOperand(i: 0).getReg(); |
866 | Register TargetReg = I->getOperand(i: 1).getReg(); |
867 | |
868 | // addu $ra, $v0, $zero |
869 | // addu $sp, $sp, $v1 |
870 | // jr $ra (via RetRA) |
871 | const TargetMachine &TM = MBB.getParent()->getTarget(); |
872 | if (TM.isPositionIndependent()) |
873 | BuildMI(BB&: MBB, I, MIMD: I->getDebugLoc(), MCID: get(Opcode: ADDU), DestReg: T9) |
874 | .addReg(RegNo: TargetReg) |
875 | .addReg(RegNo: ZERO); |
876 | BuildMI(BB&: MBB, I, MIMD: I->getDebugLoc(), MCID: get(Opcode: ADDU), DestReg: RA) |
877 | .addReg(RegNo: TargetReg) |
878 | .addReg(RegNo: ZERO); |
879 | BuildMI(BB&: MBB, I, MIMD: I->getDebugLoc(), MCID: get(Opcode: ADDU), DestReg: SP).addReg(RegNo: SP).addReg(RegNo: OffsetReg); |
880 | expandRetRA(MBB, I); |
881 | } |
882 | |
883 | const MipsInstrInfo *llvm::createMipsSEInstrInfo(const MipsSubtarget &STI) { |
884 | return new MipsSEInstrInfo(STI); |
885 | } |
886 | |