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