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