2012-08-01 05:49:49 +08:00
|
|
|
//===-- MipsSEInstrInfo.cpp - Mips32/64 Instruction Information -----------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file contains the Mips32/64 implementation of the TargetInstrInfo class.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "MipsSEInstrInfo.h"
|
|
|
|
#include "InstPrinter/MipsInstPrinter.h"
|
2016-04-18 17:17:29 +08:00
|
|
|
#include "MipsAnalyzeImmediate.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "MipsMachineFunction.h"
|
|
|
|
#include "MipsTargetMachine.h"
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2012-08-01 05:49:49 +08:00
|
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2016-06-14 21:39:43 +08:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2012-08-01 05:49:49 +08:00
|
|
|
#include "llvm/Support/TargetRegistry.h"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2014-07-19 07:25:00 +08:00
|
|
|
MipsSEInstrInfo::MipsSEInstrInfo(const MipsSubtarget &STI)
|
2016-06-28 22:33:28 +08:00
|
|
|
: MipsInstrInfo(STI, STI.isPositionIndependent() ? Mips::B : Mips::J),
|
2015-03-12 13:43:57 +08:00
|
|
|
RI() {}
|
2012-08-01 05:49:49 +08:00
|
|
|
|
2012-08-01 07:41:32 +08:00
|
|
|
const MipsRegisterInfo &MipsSEInstrInfo::getRegisterInfo() const {
|
|
|
|
return RI;
|
|
|
|
}
|
|
|
|
|
2012-08-01 05:49:49 +08:00
|
|
|
/// isLoadFromStackSlot - If the specified machine instruction is a direct
|
|
|
|
/// load from a stack slot, return the virtual or physical register number of
|
|
|
|
/// the destination along with the FrameIndex of the loaded stack slot. If
|
|
|
|
/// not, return 0. This predicate must return 0 if the instruction has
|
|
|
|
/// any side effects other than loading from the stack slot.
|
2016-06-30 08:01:54 +08:00
|
|
|
unsigned MipsSEInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
|
2015-01-09 02:18:53 +08:00
|
|
|
int &FrameIndex) const {
|
2016-06-30 08:01:54 +08:00
|
|
|
unsigned Opc = MI.getOpcode();
|
2012-08-01 05:49:49 +08:00
|
|
|
|
2013-08-21 05:08:22 +08:00
|
|
|
if ((Opc == Mips::LW) || (Opc == Mips::LD) ||
|
|
|
|
(Opc == Mips::LWC1) || (Opc == Mips::LDC1) || (Opc == Mips::LDC164)) {
|
2016-06-30 08:01:54 +08:00
|
|
|
if ((MI.getOperand(1).isFI()) && // is a stack slot
|
|
|
|
(MI.getOperand(2).isImm()) && // the imm is zero
|
|
|
|
(isZeroImm(MI.getOperand(2)))) {
|
|
|
|
FrameIndex = MI.getOperand(1).getIndex();
|
|
|
|
return MI.getOperand(0).getReg();
|
2012-08-01 05:49:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// isStoreToStackSlot - If the specified machine instruction is a direct
|
|
|
|
/// store to a stack slot, return the virtual or physical register number of
|
|
|
|
/// the source reg along with the FrameIndex of the loaded stack slot. If
|
|
|
|
/// not, return 0. This predicate must return 0 if the instruction has
|
|
|
|
/// any side effects other than storing to the stack slot.
|
2016-06-30 08:01:54 +08:00
|
|
|
unsigned MipsSEInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
|
2015-01-09 02:18:53 +08:00
|
|
|
int &FrameIndex) const {
|
2016-06-30 08:01:54 +08:00
|
|
|
unsigned Opc = MI.getOpcode();
|
2012-08-01 05:49:49 +08:00
|
|
|
|
2013-08-21 05:08:22 +08:00
|
|
|
if ((Opc == Mips::SW) || (Opc == Mips::SD) ||
|
|
|
|
(Opc == Mips::SWC1) || (Opc == Mips::SDC1) || (Opc == Mips::SDC164)) {
|
2016-06-30 08:01:54 +08:00
|
|
|
if ((MI.getOperand(1).isFI()) && // is a stack slot
|
|
|
|
(MI.getOperand(2).isImm()) && // the imm is zero
|
|
|
|
(isZeroImm(MI.getOperand(2)))) {
|
|
|
|
FrameIndex = MI.getOperand(1).getIndex();
|
|
|
|
return MI.getOperand(0).getReg();
|
2012-08-01 05:49:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MipsSEInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
2016-06-12 23:39:02 +08:00
|
|
|
MachineBasicBlock::iterator I,
|
|
|
|
const DebugLoc &DL, unsigned DestReg,
|
|
|
|
unsigned SrcReg, bool KillSrc) const {
|
2012-08-01 05:49:49 +08:00
|
|
|
unsigned Opc = 0, ZeroReg = 0;
|
2014-07-19 07:25:00 +08:00
|
|
|
bool isMicroMips = Subtarget.inMicroMipsMode();
|
2012-08-01 05:49:49 +08:00
|
|
|
|
2013-08-07 07:08:38 +08:00
|
|
|
if (Mips::GPR32RegClass.contains(DestReg)) { // Copy to CPU Reg.
|
2014-03-20 18:18:24 +08:00
|
|
|
if (Mips::GPR32RegClass.contains(SrcReg)) {
|
|
|
|
if (isMicroMips)
|
|
|
|
Opc = Mips::MOVE16_MM;
|
|
|
|
else
|
2015-08-11 16:56:25 +08:00
|
|
|
Opc = Mips::OR, ZeroReg = Mips::ZERO;
|
2014-03-20 18:18:24 +08:00
|
|
|
} else if (Mips::CCRRegClass.contains(SrcReg))
|
2012-08-01 05:49:49 +08:00
|
|
|
Opc = Mips::CFC1;
|
|
|
|
else if (Mips::FGR32RegClass.contains(SrcReg))
|
|
|
|
Opc = Mips::MFC1;
|
2014-04-03 20:47:34 +08:00
|
|
|
else if (Mips::HI32RegClass.contains(SrcReg)) {
|
|
|
|
Opc = isMicroMips ? Mips::MFHI16_MM : Mips::MFHI;
|
|
|
|
SrcReg = 0;
|
|
|
|
} else if (Mips::LO32RegClass.contains(SrcReg)) {
|
|
|
|
Opc = isMicroMips ? Mips::MFLO16_MM : Mips::MFLO;
|
|
|
|
SrcReg = 0;
|
|
|
|
} else if (Mips::HI32DSPRegClass.contains(SrcReg))
|
2013-05-01 07:22:09 +08:00
|
|
|
Opc = Mips::MFHI_DSP;
|
2013-08-14 08:47:08 +08:00
|
|
|
else if (Mips::LO32DSPRegClass.contains(SrcReg))
|
2013-05-01 07:22:09 +08:00
|
|
|
Opc = Mips::MFLO_DSP;
|
2013-05-03 07:07:05 +08:00
|
|
|
else if (Mips::DSPCCRegClass.contains(SrcReg)) {
|
|
|
|
BuildMI(MBB, I, DL, get(Mips::RDDSP), DestReg).addImm(1 << 4)
|
|
|
|
.addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
|
|
|
|
return;
|
|
|
|
}
|
2013-08-28 18:26:24 +08:00
|
|
|
else if (Mips::MSACtrlRegClass.contains(SrcReg))
|
|
|
|
Opc = Mips::CFCMSA;
|
2012-08-01 05:49:49 +08:00
|
|
|
}
|
2013-08-07 07:08:38 +08:00
|
|
|
else if (Mips::GPR32RegClass.contains(SrcReg)) { // Copy from CPU Reg.
|
2012-08-01 05:49:49 +08:00
|
|
|
if (Mips::CCRRegClass.contains(DestReg))
|
|
|
|
Opc = Mips::CTC1;
|
|
|
|
else if (Mips::FGR32RegClass.contains(DestReg))
|
|
|
|
Opc = Mips::MTC1;
|
2013-08-14 08:47:08 +08:00
|
|
|
else if (Mips::HI32RegClass.contains(DestReg))
|
2012-08-01 05:49:49 +08:00
|
|
|
Opc = Mips::MTHI, DestReg = 0;
|
2013-08-14 08:47:08 +08:00
|
|
|
else if (Mips::LO32RegClass.contains(DestReg))
|
2012-08-01 05:49:49 +08:00
|
|
|
Opc = Mips::MTLO, DestReg = 0;
|
2013-08-14 08:47:08 +08:00
|
|
|
else if (Mips::HI32DSPRegClass.contains(DestReg))
|
2013-05-01 07:22:09 +08:00
|
|
|
Opc = Mips::MTHI_DSP;
|
2013-08-14 08:47:08 +08:00
|
|
|
else if (Mips::LO32DSPRegClass.contains(DestReg))
|
2013-05-01 07:22:09 +08:00
|
|
|
Opc = Mips::MTLO_DSP;
|
2013-05-03 07:07:05 +08:00
|
|
|
else if (Mips::DSPCCRegClass.contains(DestReg)) {
|
|
|
|
BuildMI(MBB, I, DL, get(Mips::WRDSP))
|
|
|
|
.addReg(SrcReg, getKillRegState(KillSrc)).addImm(1 << 4)
|
|
|
|
.addReg(DestReg, RegState::ImplicitDefine);
|
|
|
|
return;
|
2016-06-14 17:11:33 +08:00
|
|
|
} else if (Mips::MSACtrlRegClass.contains(DestReg)) {
|
|
|
|
BuildMI(MBB, I, DL, get(Mips::CTCMSA))
|
|
|
|
.addReg(DestReg)
|
|
|
|
.addReg(SrcReg, getKillRegState(KillSrc));
|
|
|
|
return;
|
2013-05-03 07:07:05 +08:00
|
|
|
}
|
2012-08-01 05:49:49 +08:00
|
|
|
}
|
|
|
|
else if (Mips::FGR32RegClass.contains(DestReg, SrcReg))
|
|
|
|
Opc = Mips::FMOV_S;
|
|
|
|
else if (Mips::AFGR64RegClass.contains(DestReg, SrcReg))
|
|
|
|
Opc = Mips::FMOV_D32;
|
|
|
|
else if (Mips::FGR64RegClass.contains(DestReg, SrcReg))
|
|
|
|
Opc = Mips::FMOV_D64;
|
2013-08-07 07:08:38 +08:00
|
|
|
else if (Mips::GPR64RegClass.contains(DestReg)) { // Copy to CPU64 Reg.
|
|
|
|
if (Mips::GPR64RegClass.contains(SrcReg))
|
2015-08-11 16:56:25 +08:00
|
|
|
Opc = Mips::OR64, ZeroReg = Mips::ZERO_64;
|
2013-08-14 08:47:08 +08:00
|
|
|
else if (Mips::HI64RegClass.contains(SrcReg))
|
2012-08-01 05:49:49 +08:00
|
|
|
Opc = Mips::MFHI64, SrcReg = 0;
|
2013-08-14 08:47:08 +08:00
|
|
|
else if (Mips::LO64RegClass.contains(SrcReg))
|
2012-08-01 05:49:49 +08:00
|
|
|
Opc = Mips::MFLO64, SrcReg = 0;
|
|
|
|
else if (Mips::FGR64RegClass.contains(SrcReg))
|
|
|
|
Opc = Mips::DMFC1;
|
|
|
|
}
|
2013-08-07 07:08:38 +08:00
|
|
|
else if (Mips::GPR64RegClass.contains(SrcReg)) { // Copy from CPU64 Reg.
|
2013-08-14 08:47:08 +08:00
|
|
|
if (Mips::HI64RegClass.contains(DestReg))
|
2012-08-01 05:49:49 +08:00
|
|
|
Opc = Mips::MTHI64, DestReg = 0;
|
2013-08-14 08:47:08 +08:00
|
|
|
else if (Mips::LO64RegClass.contains(DestReg))
|
2012-08-01 05:49:49 +08:00
|
|
|
Opc = Mips::MTLO64, DestReg = 0;
|
|
|
|
else if (Mips::FGR64RegClass.contains(DestReg))
|
|
|
|
Opc = Mips::DMTC1;
|
|
|
|
}
|
2013-09-27 20:03:51 +08:00
|
|
|
else if (Mips::MSA128BRegClass.contains(DestReg)) { // Copy to MSA reg
|
|
|
|
if (Mips::MSA128BRegClass.contains(SrcReg))
|
|
|
|
Opc = Mips::MOVE_V;
|
|
|
|
}
|
2012-08-01 05:49:49 +08:00
|
|
|
|
|
|
|
assert(Opc && "Cannot copy registers");
|
|
|
|
|
|
|
|
MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opc));
|
|
|
|
|
|
|
|
if (DestReg)
|
|
|
|
MIB.addReg(DestReg, RegState::Define);
|
|
|
|
|
|
|
|
if (SrcReg)
|
|
|
|
MIB.addReg(SrcReg, getKillRegState(KillSrc));
|
2012-12-20 12:06:06 +08:00
|
|
|
|
|
|
|
if (ZeroReg)
|
|
|
|
MIB.addReg(ZeroReg);
|
2012-08-01 05:49:49 +08:00
|
|
|
}
|
|
|
|
|
2018-05-23 23:28:28 +08:00
|
|
|
static bool isORCopyInst(const MachineInstr &MI) {
|
|
|
|
switch (MI.getOpcode()) {
|
2018-06-07 21:06:06 +08:00
|
|
|
default:
|
|
|
|
break;
|
2018-05-23 23:28:28 +08:00
|
|
|
case Mips::OR_MM:
|
|
|
|
case Mips::OR:
|
|
|
|
if (MI.getOperand(2).getReg() == Mips::ZERO)
|
|
|
|
return true;
|
2018-06-07 21:06:06 +08:00
|
|
|
break;
|
2018-05-23 23:28:28 +08:00
|
|
|
case Mips::OR64:
|
|
|
|
if (MI.getOperand(2).getReg() == Mips::ZERO_64)
|
|
|
|
return true;
|
2018-06-07 21:06:06 +08:00
|
|
|
break;
|
2018-05-23 23:28:28 +08:00
|
|
|
}
|
2018-06-07 21:06:06 +08:00
|
|
|
return false;
|
2018-05-23 23:28:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// If @MI is WRDSP/RRDSP instruction return true with @isWrite set to true
|
|
|
|
/// if it is WRDSP instruction.
|
2018-06-07 21:06:06 +08:00
|
|
|
static bool isReadOrWriteToDSPReg(const MachineInstr &MI, bool &isWrite) {
|
2018-05-23 23:28:28 +08:00
|
|
|
switch (MI.getOpcode()) {
|
2018-06-07 21:06:06 +08:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
case Mips::WRDSP:
|
|
|
|
case Mips::WRDSP_MM:
|
|
|
|
isWrite = true;
|
|
|
|
break;
|
|
|
|
case Mips::RDDSP:
|
|
|
|
case Mips::RDDSP_MM:
|
|
|
|
isWrite = false;
|
|
|
|
break;
|
2018-05-23 23:28:28 +08:00
|
|
|
}
|
2018-06-07 21:06:06 +08:00
|
|
|
return true;
|
2018-05-23 23:28:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// We check for the common case of 'or', as it's MIPS' preferred instruction
|
|
|
|
/// for GPRs but we have to check the operands to ensure that is the case.
|
|
|
|
/// Other move instructions for MIPS are directly identifiable.
|
2018-06-07 00:36:30 +08:00
|
|
|
bool MipsSEInstrInfo::isCopyInstr(const MachineInstr &MI,
|
|
|
|
const MachineOperand *&Src,
|
|
|
|
const MachineOperand *&Dest) const {
|
2018-05-23 23:28:28 +08:00
|
|
|
bool isDSPControlWrite = false;
|
|
|
|
// Condition is made to match the creation of WRDSP/RDDSP copy instruction
|
|
|
|
// from copyPhysReg function.
|
2018-06-07 21:06:06 +08:00
|
|
|
if (isReadOrWriteToDSPReg(MI, isDSPControlWrite)) {
|
2018-06-07 00:36:30 +08:00
|
|
|
if (!MI.getOperand(1).isImm() || MI.getOperand(1).getImm() != (1<<4))
|
2018-05-23 23:28:28 +08:00
|
|
|
return false;
|
|
|
|
else if (isDSPControlWrite) {
|
2018-06-07 00:36:30 +08:00
|
|
|
Src = &MI.getOperand(0);
|
|
|
|
Dest = &MI.getOperand(2);
|
2018-05-23 23:28:28 +08:00
|
|
|
} else {
|
2018-06-07 00:36:30 +08:00
|
|
|
Dest = &MI.getOperand(0);
|
|
|
|
Src = &MI.getOperand(2);
|
2018-05-23 23:28:28 +08:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} else if (MI.isMoveReg() || isORCopyInst(MI)) {
|
2018-06-07 00:36:30 +08:00
|
|
|
Dest = &MI.getOperand(0);
|
|
|
|
Src = &MI.getOperand(1);
|
2018-05-23 23:28:28 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-08-01 05:49:49 +08:00
|
|
|
void MipsSEInstrInfo::
|
2013-03-29 10:14:12 +08:00
|
|
|
storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
|
|
|
unsigned SrcReg, bool isKill, int FI,
|
|
|
|
const TargetRegisterClass *RC, const TargetRegisterInfo *TRI,
|
|
|
|
int64_t Offset) const {
|
2012-08-01 05:49:49 +08:00
|
|
|
DebugLoc DL;
|
|
|
|
MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOStore);
|
|
|
|
|
|
|
|
unsigned Opc = 0;
|
|
|
|
|
2013-08-07 07:08:38 +08:00
|
|
|
if (Mips::GPR32RegClass.hasSubClassEq(RC))
|
2013-08-21 05:08:22 +08:00
|
|
|
Opc = Mips::SW;
|
2013-08-07 07:08:38 +08:00
|
|
|
else if (Mips::GPR64RegClass.hasSubClassEq(RC))
|
2013-08-21 05:08:22 +08:00
|
|
|
Opc = Mips::SD;
|
2013-08-09 05:54:26 +08:00
|
|
|
else if (Mips::ACC64RegClass.hasSubClassEq(RC))
|
2013-08-21 05:08:22 +08:00
|
|
|
Opc = Mips::STORE_ACC64;
|
2013-08-09 05:54:26 +08:00
|
|
|
else if (Mips::ACC64DSPRegClass.hasSubClassEq(RC))
|
2013-08-21 05:08:22 +08:00
|
|
|
Opc = Mips::STORE_ACC64DSP;
|
2013-08-09 05:54:26 +08:00
|
|
|
else if (Mips::ACC128RegClass.hasSubClassEq(RC))
|
2013-08-21 05:08:22 +08:00
|
|
|
Opc = Mips::STORE_ACC128;
|
2013-05-03 07:07:05 +08:00
|
|
|
else if (Mips::DSPCCRegClass.hasSubClassEq(RC))
|
2013-08-21 05:08:22 +08:00
|
|
|
Opc = Mips::STORE_CCOND_DSP;
|
2012-08-01 05:49:49 +08:00
|
|
|
else if (Mips::FGR32RegClass.hasSubClassEq(RC))
|
2013-08-21 05:08:22 +08:00
|
|
|
Opc = Mips::SWC1;
|
2012-08-01 05:49:49 +08:00
|
|
|
else if (Mips::AFGR64RegClass.hasSubClassEq(RC))
|
|
|
|
Opc = Mips::SDC1;
|
|
|
|
else if (Mips::FGR64RegClass.hasSubClassEq(RC))
|
2013-08-21 05:08:22 +08:00
|
|
|
Opc = Mips::SDC164;
|
2017-04-25 03:51:12 +08:00
|
|
|
else if (TRI->isTypeLegalForClass(*RC, MVT::v16i8))
|
2013-08-27 18:04:21 +08:00
|
|
|
Opc = Mips::ST_B;
|
2017-04-25 03:51:12 +08:00
|
|
|
else if (TRI->isTypeLegalForClass(*RC, MVT::v8i16) ||
|
|
|
|
TRI->isTypeLegalForClass(*RC, MVT::v8f16))
|
2013-08-27 18:04:21 +08:00
|
|
|
Opc = Mips::ST_H;
|
2017-04-25 03:51:12 +08:00
|
|
|
else if (TRI->isTypeLegalForClass(*RC, MVT::v4i32) ||
|
|
|
|
TRI->isTypeLegalForClass(*RC, MVT::v4f32))
|
2013-08-27 18:04:21 +08:00
|
|
|
Opc = Mips::ST_W;
|
2017-04-25 03:51:12 +08:00
|
|
|
else if (TRI->isTypeLegalForClass(*RC, MVT::v2i64) ||
|
|
|
|
TRI->isTypeLegalForClass(*RC, MVT::v2f64))
|
2013-08-27 18:04:21 +08:00
|
|
|
Opc = Mips::ST_D;
|
2015-10-26 20:38:43 +08:00
|
|
|
else if (Mips::LO32RegClass.hasSubClassEq(RC))
|
|
|
|
Opc = Mips::SW;
|
|
|
|
else if (Mips::LO64RegClass.hasSubClassEq(RC))
|
|
|
|
Opc = Mips::SD;
|
|
|
|
else if (Mips::HI32RegClass.hasSubClassEq(RC))
|
|
|
|
Opc = Mips::SW;
|
|
|
|
else if (Mips::HI64RegClass.hasSubClassEq(RC))
|
|
|
|
Opc = Mips::SD;
|
2017-10-03 21:45:49 +08:00
|
|
|
else if (Mips::DSPRRegClass.hasSubClassEq(RC))
|
|
|
|
Opc = Mips::SWDSP;
|
2015-10-26 20:38:43 +08:00
|
|
|
|
|
|
|
// Hi, Lo are normally caller save but they are callee save
|
|
|
|
// for interrupt handling.
|
2017-12-16 06:22:58 +08:00
|
|
|
const Function &Func = MBB.getParent()->getFunction();
|
|
|
|
if (Func.hasFnAttribute("interrupt")) {
|
2015-10-26 20:38:43 +08:00
|
|
|
if (Mips::HI32RegClass.hasSubClassEq(RC)) {
|
|
|
|
BuildMI(MBB, I, DL, get(Mips::MFHI), Mips::K0);
|
|
|
|
SrcReg = Mips::K0;
|
|
|
|
} else if (Mips::HI64RegClass.hasSubClassEq(RC)) {
|
|
|
|
BuildMI(MBB, I, DL, get(Mips::MFHI64), Mips::K0_64);
|
|
|
|
SrcReg = Mips::K0_64;
|
|
|
|
} else if (Mips::LO32RegClass.hasSubClassEq(RC)) {
|
|
|
|
BuildMI(MBB, I, DL, get(Mips::MFLO), Mips::K0);
|
|
|
|
SrcReg = Mips::K0;
|
|
|
|
} else if (Mips::LO64RegClass.hasSubClassEq(RC)) {
|
|
|
|
BuildMI(MBB, I, DL, get(Mips::MFLO64), Mips::K0_64);
|
|
|
|
SrcReg = Mips::K0_64;
|
|
|
|
}
|
|
|
|
}
|
2012-08-01 05:49:49 +08:00
|
|
|
|
|
|
|
assert(Opc && "Register class not handled!");
|
|
|
|
BuildMI(MBB, I, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill))
|
2013-03-29 10:14:12 +08:00
|
|
|
.addFrameIndex(FI).addImm(Offset).addMemOperand(MMO);
|
2012-08-01 05:49:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void MipsSEInstrInfo::
|
2013-03-29 10:14:12 +08:00
|
|
|
loadRegFromStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
|
|
|
unsigned DestReg, int FI, const TargetRegisterClass *RC,
|
|
|
|
const TargetRegisterInfo *TRI, int64_t Offset) const {
|
2012-08-01 05:49:49 +08:00
|
|
|
DebugLoc DL;
|
|
|
|
if (I != MBB.end()) DL = I->getDebugLoc();
|
|
|
|
MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOLoad);
|
|
|
|
unsigned Opc = 0;
|
|
|
|
|
2017-12-16 06:22:58 +08:00
|
|
|
const Function &Func = MBB.getParent()->getFunction();
|
|
|
|
bool ReqIndirectLoad = Func.hasFnAttribute("interrupt") &&
|
2015-10-26 20:38:43 +08:00
|
|
|
(DestReg == Mips::LO0 || DestReg == Mips::LO0_64 ||
|
|
|
|
DestReg == Mips::HI0 || DestReg == Mips::HI0_64);
|
|
|
|
|
2013-08-07 07:08:38 +08:00
|
|
|
if (Mips::GPR32RegClass.hasSubClassEq(RC))
|
2013-08-21 05:08:22 +08:00
|
|
|
Opc = Mips::LW;
|
2013-08-07 07:08:38 +08:00
|
|
|
else if (Mips::GPR64RegClass.hasSubClassEq(RC))
|
2013-08-21 05:08:22 +08:00
|
|
|
Opc = Mips::LD;
|
2013-08-09 05:54:26 +08:00
|
|
|
else if (Mips::ACC64RegClass.hasSubClassEq(RC))
|
2013-08-21 05:08:22 +08:00
|
|
|
Opc = Mips::LOAD_ACC64;
|
2013-08-09 05:54:26 +08:00
|
|
|
else if (Mips::ACC64DSPRegClass.hasSubClassEq(RC))
|
2013-08-21 05:08:22 +08:00
|
|
|
Opc = Mips::LOAD_ACC64DSP;
|
2013-08-09 05:54:26 +08:00
|
|
|
else if (Mips::ACC128RegClass.hasSubClassEq(RC))
|
2013-08-21 05:08:22 +08:00
|
|
|
Opc = Mips::LOAD_ACC128;
|
2013-05-03 07:07:05 +08:00
|
|
|
else if (Mips::DSPCCRegClass.hasSubClassEq(RC))
|
2013-08-21 05:08:22 +08:00
|
|
|
Opc = Mips::LOAD_CCOND_DSP;
|
2012-08-01 05:49:49 +08:00
|
|
|
else if (Mips::FGR32RegClass.hasSubClassEq(RC))
|
2013-08-21 05:08:22 +08:00
|
|
|
Opc = Mips::LWC1;
|
2012-08-01 05:49:49 +08:00
|
|
|
else if (Mips::AFGR64RegClass.hasSubClassEq(RC))
|
|
|
|
Opc = Mips::LDC1;
|
|
|
|
else if (Mips::FGR64RegClass.hasSubClassEq(RC))
|
2013-08-21 05:08:22 +08:00
|
|
|
Opc = Mips::LDC164;
|
2017-04-25 03:51:12 +08:00
|
|
|
else if (TRI->isTypeLegalForClass(*RC, MVT::v16i8))
|
2013-08-27 18:04:21 +08:00
|
|
|
Opc = Mips::LD_B;
|
2017-04-25 03:51:12 +08:00
|
|
|
else if (TRI->isTypeLegalForClass(*RC, MVT::v8i16) ||
|
|
|
|
TRI->isTypeLegalForClass(*RC, MVT::v8f16))
|
2013-08-27 18:04:21 +08:00
|
|
|
Opc = Mips::LD_H;
|
2017-04-25 03:51:12 +08:00
|
|
|
else if (TRI->isTypeLegalForClass(*RC, MVT::v4i32) ||
|
|
|
|
TRI->isTypeLegalForClass(*RC, MVT::v4f32))
|
2013-08-27 18:04:21 +08:00
|
|
|
Opc = Mips::LD_W;
|
2017-04-25 03:51:12 +08:00
|
|
|
else if (TRI->isTypeLegalForClass(*RC, MVT::v2i64) ||
|
|
|
|
TRI->isTypeLegalForClass(*RC, MVT::v2f64))
|
2013-08-27 18:04:21 +08:00
|
|
|
Opc = Mips::LD_D;
|
2015-10-26 20:38:43 +08:00
|
|
|
else if (Mips::HI32RegClass.hasSubClassEq(RC))
|
|
|
|
Opc = Mips::LW;
|
|
|
|
else if (Mips::HI64RegClass.hasSubClassEq(RC))
|
|
|
|
Opc = Mips::LD;
|
|
|
|
else if (Mips::LO32RegClass.hasSubClassEq(RC))
|
|
|
|
Opc = Mips::LW;
|
|
|
|
else if (Mips::LO64RegClass.hasSubClassEq(RC))
|
|
|
|
Opc = Mips::LD;
|
2017-10-03 21:45:49 +08:00
|
|
|
else if (Mips::DSPRRegClass.hasSubClassEq(RC))
|
|
|
|
Opc = Mips::LWDSP;
|
2012-08-01 05:49:49 +08:00
|
|
|
|
|
|
|
assert(Opc && "Register class not handled!");
|
2015-10-26 20:38:43 +08:00
|
|
|
|
|
|
|
if (!ReqIndirectLoad)
|
|
|
|
BuildMI(MBB, I, DL, get(Opc), DestReg)
|
|
|
|
.addFrameIndex(FI)
|
|
|
|
.addImm(Offset)
|
|
|
|
.addMemOperand(MMO);
|
|
|
|
else {
|
|
|
|
// Load HI/LO through K0. Notably the DestReg is encoded into the
|
|
|
|
// instruction itself.
|
|
|
|
unsigned Reg = Mips::K0;
|
|
|
|
unsigned LdOp = Mips::MTLO;
|
|
|
|
if (DestReg == Mips::HI0)
|
|
|
|
LdOp = Mips::MTHI;
|
|
|
|
|
|
|
|
if (Subtarget.getABI().ArePtrs64bit()) {
|
|
|
|
Reg = Mips::K0_64;
|
|
|
|
if (DestReg == Mips::HI0_64)
|
|
|
|
LdOp = Mips::MTHI64;
|
|
|
|
else
|
|
|
|
LdOp = Mips::MTLO64;
|
|
|
|
}
|
|
|
|
|
|
|
|
BuildMI(MBB, I, DL, get(Opc), Reg)
|
|
|
|
.addFrameIndex(FI)
|
|
|
|
.addImm(Offset)
|
|
|
|
.addMemOperand(MMO);
|
|
|
|
BuildMI(MBB, I, DL, get(LdOp)).addReg(Reg);
|
|
|
|
}
|
2012-08-01 05:49:49 +08:00
|
|
|
}
|
|
|
|
|
2016-06-30 08:01:54 +08:00
|
|
|
bool MipsSEInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
|
|
|
|
MachineBasicBlock &MBB = *MI.getParent();
|
2014-07-19 07:25:00 +08:00
|
|
|
bool isMicroMips = Subtarget.inMicroMipsMode();
|
2014-04-03 20:47:34 +08:00
|
|
|
unsigned Opc;
|
2012-08-01 05:49:49 +08:00
|
|
|
|
2016-06-30 08:01:54 +08:00
|
|
|
switch (MI.getDesc().getOpcode()) {
|
2012-08-01 05:49:49 +08:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
case Mips::RetRA:
|
[mips][mips64r6] Use JALR for returns instead of JR (which is not available on MIPS32r6/MIPS64r6)
Summary:
RET, and RET_MM have been replaced by a pseudo named PseudoReturn.
In addition a version with a 64-bit GPR named PseudoReturn64 has been
added.
Instruction selection for a return matches RetRA, which is expanded post
register allocation to PseudoReturn/PseudoReturn64. During MipsAsmPrinter,
this PseudoReturn/PseudoReturn64 are emitted as:
- (JALR64 $zero, $rs) on MIPS64r6
- (JALR $zero, $rs) on MIPS32r6
- (JR_MM $rs) on microMIPS
- (JR $rs) otherwise
On MIPS32r6/MIPS64r6, 'jr $rs' is an alias for 'jalr $zero, $rs'. To aid
development and review (specifically, to ensure all cases of jr are
updated), these aliases are temporarily named 'r6.jr' instead of 'jr'.
A follow up patch will change them back to the correct mnemonic.
Added (JALR $zero, $rs) to MipsNaClELFStreamer's definition of an indirect
jump, and removed it from its definition of a call.
Note: I haven't accounted for MIPS64 in MipsNaClELFStreamer since it's
doesn't appear to account for any MIPS64-specifics.
The return instruction created as part of eh_return expansion is now expanded
using expandRetRA() so we use the right return instruction on MIPS32r6/MIPS64r6
('jalr $zero, $rs').
Also, fixed a misuse of isABI_N64() to detect 64-bit wide registers in
expandEhReturn().
Reviewers: jkolek, vmedic, mseaborn, zoran.jovanovic, dsanders
Reviewed By: dsanders
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D4268
llvm-svn: 212604
2014-07-09 18:16:07 +08:00
|
|
|
expandRetRA(MBB, MI);
|
2012-08-01 05:49:49 +08:00
|
|
|
break;
|
2015-10-26 20:38:43 +08:00
|
|
|
case Mips::ERet:
|
|
|
|
expandERet(MBB, MI);
|
|
|
|
break;
|
2013-10-08 02:49:46 +08:00
|
|
|
case Mips::PseudoMFHI:
|
2014-04-03 20:47:34 +08:00
|
|
|
Opc = isMicroMips ? Mips::MFHI16_MM : Mips::MFHI;
|
|
|
|
expandPseudoMFHiLo(MBB, MI, Opc);
|
2013-10-08 02:49:46 +08:00
|
|
|
break;
|
|
|
|
case Mips::PseudoMFLO:
|
2014-04-03 20:47:34 +08:00
|
|
|
Opc = isMicroMips ? Mips::MFLO16_MM : Mips::MFLO;
|
|
|
|
expandPseudoMFHiLo(MBB, MI, Opc);
|
2013-10-08 02:49:46 +08:00
|
|
|
break;
|
|
|
|
case Mips::PseudoMFHI64:
|
|
|
|
expandPseudoMFHiLo(MBB, MI, Mips::MFHI64);
|
|
|
|
break;
|
|
|
|
case Mips::PseudoMFLO64:
|
|
|
|
expandPseudoMFHiLo(MBB, MI, Mips::MFLO64);
|
|
|
|
break;
|
2013-10-15 09:48:30 +08:00
|
|
|
case Mips::PseudoMTLOHI:
|
|
|
|
expandPseudoMTLoHi(MBB, MI, Mips::MTLO, Mips::MTHI, false);
|
|
|
|
break;
|
|
|
|
case Mips::PseudoMTLOHI64:
|
|
|
|
expandPseudoMTLoHi(MBB, MI, Mips::MTLO64, Mips::MTHI64, false);
|
|
|
|
break;
|
|
|
|
case Mips::PseudoMTLOHI_DSP:
|
|
|
|
expandPseudoMTLoHi(MBB, MI, Mips::MTLO_DSP, Mips::MTHI_DSP, true);
|
|
|
|
break;
|
2013-05-17 03:48:37 +08:00
|
|
|
case Mips::PseudoCVT_S_W:
|
2013-06-08 08:14:54 +08:00
|
|
|
expandCvtFPInt(MBB, MI, Mips::CVT_S_W, Mips::MTC1, false);
|
2013-05-17 03:48:37 +08:00
|
|
|
break;
|
|
|
|
case Mips::PseudoCVT_D32_W:
|
[mips] Define certain instructions in microMIPS32r3
Instructions affected:
mthc1, mfhc1, add.d, sub.d, mul.d, div.d,
mov.d, neg.d, cvt.w.d, cvt.d.s, cvt.d.w, cvt.s.d
These instructions are now defined for
microMIPS32r3 + microMIPS32r6 in MicroMipsInstrFPU.td
since they shared their encoding with those already defined
in microMIPS32r6InstrInfo.td and have been therefore
removed from the latter file.
Some instructions present in MicroMipsInstrFPU.td which
did not have both AFGR64 and FGR64 variants defined have
been altered to do so.
Differential revision: https://reviews.llvm.org/D42738
llvm-svn: 324584
2018-02-08 17:25:17 +08:00
|
|
|
Opc = isMicroMips ? Mips::CVT_D32_W_MM : Mips::CVT_D32_W;
|
|
|
|
expandCvtFPInt(MBB, MI, Opc, Mips::MTC1, false);
|
2013-05-17 03:48:37 +08:00
|
|
|
break;
|
|
|
|
case Mips::PseudoCVT_S_L:
|
2013-06-08 08:14:54 +08:00
|
|
|
expandCvtFPInt(MBB, MI, Mips::CVT_S_L, Mips::DMTC1, true);
|
2013-05-17 03:48:37 +08:00
|
|
|
break;
|
|
|
|
case Mips::PseudoCVT_D64_W:
|
[mips] Define certain instructions in microMIPS32r3
Instructions affected:
mthc1, mfhc1, add.d, sub.d, mul.d, div.d,
mov.d, neg.d, cvt.w.d, cvt.d.s, cvt.d.w, cvt.s.d
These instructions are now defined for
microMIPS32r3 + microMIPS32r6 in MicroMipsInstrFPU.td
since they shared their encoding with those already defined
in microMIPS32r6InstrInfo.td and have been therefore
removed from the latter file.
Some instructions present in MicroMipsInstrFPU.td which
did not have both AFGR64 and FGR64 variants defined have
been altered to do so.
Differential revision: https://reviews.llvm.org/D42738
llvm-svn: 324584
2018-02-08 17:25:17 +08:00
|
|
|
Opc = isMicroMips ? Mips::CVT_D64_W_MM : Mips::CVT_D64_W;
|
|
|
|
expandCvtFPInt(MBB, MI, Opc, Mips::MTC1, true);
|
2013-05-17 03:48:37 +08:00
|
|
|
break;
|
|
|
|
case Mips::PseudoCVT_D64_L:
|
2013-06-08 08:14:54 +08:00
|
|
|
expandCvtFPInt(MBB, MI, Mips::CVT_D64_L, Mips::DMTC1, true);
|
2013-05-17 03:48:37 +08:00
|
|
|
break;
|
2012-08-01 05:49:49 +08:00
|
|
|
case Mips::BuildPairF64:
|
[mips] Define certain instructions in microMIPS32r3
Instructions affected:
mthc1, mfhc1, add.d, sub.d, mul.d, div.d,
mov.d, neg.d, cvt.w.d, cvt.d.s, cvt.d.w, cvt.s.d
These instructions are now defined for
microMIPS32r3 + microMIPS32r6 in MicroMipsInstrFPU.td
since they shared their encoding with those already defined
in microMIPS32r6InstrInfo.td and have been therefore
removed from the latter file.
Some instructions present in MicroMipsInstrFPU.td which
did not have both AFGR64 and FGR64 variants defined have
been altered to do so.
Differential revision: https://reviews.llvm.org/D42738
llvm-svn: 324584
2018-02-08 17:25:17 +08:00
|
|
|
expandBuildPairF64(MBB, MI, isMicroMips, false);
|
2013-08-21 07:47:25 +08:00
|
|
|
break;
|
|
|
|
case Mips::BuildPairF64_64:
|
[mips] Define certain instructions in microMIPS32r3
Instructions affected:
mthc1, mfhc1, add.d, sub.d, mul.d, div.d,
mov.d, neg.d, cvt.w.d, cvt.d.s, cvt.d.w, cvt.s.d
These instructions are now defined for
microMIPS32r3 + microMIPS32r6 in MicroMipsInstrFPU.td
since they shared their encoding with those already defined
in microMIPS32r6InstrInfo.td and have been therefore
removed from the latter file.
Some instructions present in MicroMipsInstrFPU.td which
did not have both AFGR64 and FGR64 variants defined have
been altered to do so.
Differential revision: https://reviews.llvm.org/D42738
llvm-svn: 324584
2018-02-08 17:25:17 +08:00
|
|
|
expandBuildPairF64(MBB, MI, isMicroMips, true);
|
2012-08-01 05:49:49 +08:00
|
|
|
break;
|
|
|
|
case Mips::ExtractElementF64:
|
[mips] Define certain instructions in microMIPS32r3
Instructions affected:
mthc1, mfhc1, add.d, sub.d, mul.d, div.d,
mov.d, neg.d, cvt.w.d, cvt.d.s, cvt.d.w, cvt.s.d
These instructions are now defined for
microMIPS32r3 + microMIPS32r6 in MicroMipsInstrFPU.td
since they shared their encoding with those already defined
in microMIPS32r6InstrInfo.td and have been therefore
removed from the latter file.
Some instructions present in MicroMipsInstrFPU.td which
did not have both AFGR64 and FGR64 variants defined have
been altered to do so.
Differential revision: https://reviews.llvm.org/D42738
llvm-svn: 324584
2018-02-08 17:25:17 +08:00
|
|
|
expandExtractElementF64(MBB, MI, isMicroMips, false);
|
2013-08-21 07:47:25 +08:00
|
|
|
break;
|
|
|
|
case Mips::ExtractElementF64_64:
|
[mips] Define certain instructions in microMIPS32r3
Instructions affected:
mthc1, mfhc1, add.d, sub.d, mul.d, div.d,
mov.d, neg.d, cvt.w.d, cvt.d.s, cvt.d.w, cvt.s.d
These instructions are now defined for
microMIPS32r3 + microMIPS32r6 in MicroMipsInstrFPU.td
since they shared their encoding with those already defined
in microMIPS32r6InstrInfo.td and have been therefore
removed from the latter file.
Some instructions present in MicroMipsInstrFPU.td which
did not have both AFGR64 and FGR64 variants defined have
been altered to do so.
Differential revision: https://reviews.llvm.org/D42738
llvm-svn: 324584
2018-02-08 17:25:17 +08:00
|
|
|
expandExtractElementF64(MBB, MI, isMicroMips, true);
|
2012-08-01 05:49:49 +08:00
|
|
|
break;
|
2013-01-30 08:26:49 +08:00
|
|
|
case Mips::MIPSeh_return32:
|
|
|
|
case Mips::MIPSeh_return64:
|
2013-05-14 01:43:19 +08:00
|
|
|
expandEhReturn(MBB, MI);
|
2013-01-30 08:26:49 +08:00
|
|
|
break;
|
2012-08-01 05:49:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
MBB.erase(MI);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-05-14 01:43:19 +08:00
|
|
|
/// getOppositeBranchOpc - Return the inverse of the specified
|
2012-08-01 05:49:49 +08:00
|
|
|
/// opcode, e.g. turning BEQ to BNE.
|
2013-05-14 01:43:19 +08:00
|
|
|
unsigned MipsSEInstrInfo::getOppositeBranchOpc(unsigned Opc) const {
|
2012-08-01 05:49:49 +08:00
|
|
|
switch (Opc) {
|
|
|
|
default: llvm_unreachable("Illegal opcode!");
|
|
|
|
case Mips::BEQ: return Mips::BNE;
|
2016-07-22 15:18:33 +08:00
|
|
|
case Mips::BEQ_MM: return Mips::BNE_MM;
|
2012-08-01 05:49:49 +08:00
|
|
|
case Mips::BNE: return Mips::BEQ;
|
2016-07-22 15:18:33 +08:00
|
|
|
case Mips::BNE_MM: return Mips::BEQ_MM;
|
2012-08-01 05:49:49 +08:00
|
|
|
case Mips::BGTZ: return Mips::BLEZ;
|
|
|
|
case Mips::BGEZ: return Mips::BLTZ;
|
|
|
|
case Mips::BLTZ: return Mips::BGEZ;
|
|
|
|
case Mips::BLEZ: return Mips::BGTZ;
|
2018-05-16 18:03:05 +08:00
|
|
|
case Mips::BGTZ_MM: return Mips::BLEZ_MM;
|
|
|
|
case Mips::BGEZ_MM: return Mips::BLTZ_MM;
|
|
|
|
case Mips::BLTZ_MM: return Mips::BGEZ_MM;
|
|
|
|
case Mips::BLEZ_MM: return Mips::BGTZ_MM;
|
2012-08-01 05:49:49 +08:00
|
|
|
case Mips::BEQ64: return Mips::BNE64;
|
|
|
|
case Mips::BNE64: return Mips::BEQ64;
|
|
|
|
case Mips::BGTZ64: return Mips::BLEZ64;
|
|
|
|
case Mips::BGEZ64: return Mips::BLTZ64;
|
|
|
|
case Mips::BLTZ64: return Mips::BGEZ64;
|
|
|
|
case Mips::BLEZ64: return Mips::BGTZ64;
|
|
|
|
case Mips::BC1T: return Mips::BC1F;
|
|
|
|
case Mips::BC1F: return Mips::BC1T;
|
2018-05-16 18:03:05 +08:00
|
|
|
case Mips::BC1T_MM: return Mips::BC1F_MM;
|
|
|
|
case Mips::BC1F_MM: return Mips::BC1T_MM;
|
|
|
|
case Mips::BEQZ16_MM: return Mips::BNEZ16_MM;
|
|
|
|
case Mips::BNEZ16_MM: return Mips::BEQZ16_MM;
|
|
|
|
case Mips::BEQZC_MM: return Mips::BNEZC_MM;
|
|
|
|
case Mips::BNEZC_MM: return Mips::BEQZC_MM;
|
2016-03-15 00:24:05 +08:00
|
|
|
case Mips::BEQZC: return Mips::BNEZC;
|
|
|
|
case Mips::BNEZC: return Mips::BEQZC;
|
2018-05-16 18:03:05 +08:00
|
|
|
case Mips::BLEZC: return Mips::BGTZC;
|
2016-03-15 00:24:05 +08:00
|
|
|
case Mips::BGEZC: return Mips::BLTZC;
|
2018-05-16 18:03:05 +08:00
|
|
|
case Mips::BGEC: return Mips::BLTC;
|
|
|
|
case Mips::BGTZC: return Mips::BLEZC;
|
2016-03-15 00:24:05 +08:00
|
|
|
case Mips::BLTZC: return Mips::BGEZC;
|
2018-05-16 18:03:05 +08:00
|
|
|
case Mips::BLTC: return Mips::BGEC;
|
|
|
|
case Mips::BGEUC: return Mips::BLTUC;
|
|
|
|
case Mips::BLTUC: return Mips::BGEUC;
|
|
|
|
case Mips::BEQC: return Mips::BNEC;
|
|
|
|
case Mips::BNEC: return Mips::BEQC;
|
|
|
|
case Mips::BC1EQZ: return Mips::BC1NEZ;
|
|
|
|
case Mips::BC1NEZ: return Mips::BC1EQZ;
|
2018-04-27 23:49:49 +08:00
|
|
|
case Mips::BEQZC_MMR6: return Mips::BNEZC_MMR6;
|
|
|
|
case Mips::BNEZC_MMR6: return Mips::BEQZC_MMR6;
|
2018-05-16 18:03:05 +08:00
|
|
|
case Mips::BLEZC_MMR6: return Mips::BGTZC_MMR6;
|
2018-04-27 23:49:49 +08:00
|
|
|
case Mips::BGEZC_MMR6: return Mips::BLTZC_MMR6;
|
2018-05-16 18:03:05 +08:00
|
|
|
case Mips::BGEC_MMR6: return Mips::BLTC_MMR6;
|
|
|
|
case Mips::BGTZC_MMR6: return Mips::BLEZC_MMR6;
|
2018-04-27 23:49:49 +08:00
|
|
|
case Mips::BLTZC_MMR6: return Mips::BGEZC_MMR6;
|
2018-05-16 18:03:05 +08:00
|
|
|
case Mips::BLTC_MMR6: return Mips::BGEC_MMR6;
|
|
|
|
case Mips::BGEUC_MMR6: return Mips::BLTUC_MMR6;
|
|
|
|
case Mips::BLTUC_MMR6: return Mips::BGEUC_MMR6;
|
|
|
|
case Mips::BEQC_MMR6: return Mips::BNEC_MMR6;
|
|
|
|
case Mips::BNEC_MMR6: return Mips::BEQC_MMR6;
|
|
|
|
case Mips::BC1EQZC_MMR6: return Mips::BC1NEZC_MMR6;
|
|
|
|
case Mips::BC1NEZC_MMR6: return Mips::BC1EQZC_MMR6;
|
2016-07-26 18:25:07 +08:00
|
|
|
case Mips::BEQZC64: return Mips::BNEZC64;
|
|
|
|
case Mips::BNEZC64: return Mips::BEQZC64;
|
|
|
|
case Mips::BEQC64: return Mips::BNEC64;
|
|
|
|
case Mips::BNEC64: return Mips::BEQC64;
|
|
|
|
case Mips::BGEC64: return Mips::BLTC64;
|
|
|
|
case Mips::BGEUC64: return Mips::BLTUC64;
|
|
|
|
case Mips::BLTC64: return Mips::BGEC64;
|
|
|
|
case Mips::BLTUC64: return Mips::BGEUC64;
|
|
|
|
case Mips::BGTZC64: return Mips::BLEZC64;
|
|
|
|
case Mips::BGEZC64: return Mips::BLTZC64;
|
|
|
|
case Mips::BLTZC64: return Mips::BGEZC64;
|
|
|
|
case Mips::BLEZC64: return Mips::BGTZC64;
|
2017-08-01 21:42:45 +08:00
|
|
|
case Mips::BBIT0: return Mips::BBIT1;
|
|
|
|
case Mips::BBIT1: return Mips::BBIT0;
|
|
|
|
case Mips::BBIT032: return Mips::BBIT132;
|
|
|
|
case Mips::BBIT132: return Mips::BBIT032;
|
2018-05-16 18:03:05 +08:00
|
|
|
case Mips::BZ_B: return Mips::BNZ_B;
|
|
|
|
case Mips::BZ_H: return Mips::BNZ_H;
|
|
|
|
case Mips::BZ_W: return Mips::BNZ_W;
|
|
|
|
case Mips::BZ_D: return Mips::BNZ_D;
|
|
|
|
case Mips::BZ_V: return Mips::BNZ_V;
|
|
|
|
case Mips::BNZ_B: return Mips::BZ_B;
|
|
|
|
case Mips::BNZ_H: return Mips::BZ_H;
|
|
|
|
case Mips::BNZ_W: return Mips::BZ_W;
|
|
|
|
case Mips::BNZ_D: return Mips::BZ_D;
|
|
|
|
case Mips::BNZ_V: return Mips::BZ_V;
|
2012-08-01 05:49:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-01 07:52:55 +08:00
|
|
|
/// Adjust SP by Amount bytes.
|
|
|
|
void MipsSEInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount,
|
|
|
|
MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator I) const {
|
2015-04-17 17:50:21 +08:00
|
|
|
MipsABIInfo ABI = Subtarget.getABI();
|
2015-08-29 01:53:26 +08:00
|
|
|
DebugLoc DL;
|
2015-04-17 17:50:21 +08:00
|
|
|
unsigned ADDiu = ABI.GetPtrAddiuOp();
|
2012-08-01 07:52:55 +08:00
|
|
|
|
2015-04-02 18:14:54 +08:00
|
|
|
if (Amount == 0)
|
|
|
|
return;
|
|
|
|
|
2016-06-14 21:39:43 +08:00
|
|
|
if (isInt<16>(Amount)) {
|
|
|
|
// addi sp, sp, amount
|
2012-08-01 07:52:55 +08:00
|
|
|
BuildMI(MBB, I, DL, get(ADDiu), SP).addReg(SP).addImm(Amount);
|
2016-06-14 21:39:43 +08:00
|
|
|
} else {
|
|
|
|
// For numbers which are not 16bit integers we synthesize Amount inline
|
|
|
|
// then add or subtract it from sp.
|
|
|
|
unsigned Opc = ABI.GetPtrAdduOp();
|
|
|
|
if (Amount < 0) {
|
|
|
|
Opc = ABI.GetPtrSubuOp();
|
|
|
|
Amount = -Amount;
|
|
|
|
}
|
2014-04-25 13:30:21 +08:00
|
|
|
unsigned Reg = loadImmediate(Amount, MBB, I, DL, nullptr);
|
2016-06-14 21:39:43 +08:00
|
|
|
BuildMI(MBB, I, DL, get(Opc), SP).addReg(SP).addReg(Reg, RegState::Kill);
|
2012-08-01 07:52:55 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-23 08:21:05 +08:00
|
|
|
/// This function generates the sequence of instructions needed to get the
|
|
|
|
/// result of adding register REG and immediate IMM.
|
2016-06-12 23:39:02 +08:00
|
|
|
unsigned MipsSEInstrInfo::loadImmediate(int64_t Imm, MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator II,
|
|
|
|
const DebugLoc &DL,
|
|
|
|
unsigned *NewImm) const {
|
2012-08-23 08:21:05 +08:00
|
|
|
MipsAnalyzeImmediate AnalyzeImm;
|
2014-07-19 07:25:00 +08:00
|
|
|
const MipsSubtarget &STI = Subtarget;
|
2012-11-03 08:05:43 +08:00
|
|
|
MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo();
|
2012-08-23 08:21:05 +08:00
|
|
|
unsigned Size = STI.isABI_N64() ? 64 : 32;
|
|
|
|
unsigned LUi = STI.isABI_N64() ? Mips::LUi64 : Mips::LUi;
|
|
|
|
unsigned ZEROReg = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO;
|
2012-11-03 08:05:43 +08:00
|
|
|
const TargetRegisterClass *RC = STI.isABI_N64() ?
|
2013-08-07 07:08:38 +08:00
|
|
|
&Mips::GPR64RegClass : &Mips::GPR32RegClass;
|
2012-08-23 08:21:05 +08:00
|
|
|
bool LastInstrIsADDiu = NewImm;
|
|
|
|
|
|
|
|
const MipsAnalyzeImmediate::InstSeq &Seq =
|
|
|
|
AnalyzeImm.Analyze(Imm, Size, LastInstrIsADDiu);
|
|
|
|
MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin();
|
|
|
|
|
|
|
|
assert(Seq.size() && (!LastInstrIsADDiu || (Seq.size() > 1)));
|
|
|
|
|
|
|
|
// The first instruction can be a LUi, which is different from other
|
|
|
|
// instructions (ADDiu, ORI and SLL) in that it does not have a register
|
|
|
|
// operand.
|
2012-11-03 08:05:43 +08:00
|
|
|
unsigned Reg = RegInfo.createVirtualRegister(RC);
|
|
|
|
|
2012-08-23 08:21:05 +08:00
|
|
|
if (Inst->Opc == LUi)
|
2012-11-03 08:05:43 +08:00
|
|
|
BuildMI(MBB, II, DL, get(LUi), Reg).addImm(SignExtend64<16>(Inst->ImmOpnd));
|
2012-08-23 08:21:05 +08:00
|
|
|
else
|
2012-11-03 08:05:43 +08:00
|
|
|
BuildMI(MBB, II, DL, get(Inst->Opc), Reg).addReg(ZEROReg)
|
2012-08-23 08:21:05 +08:00
|
|
|
.addImm(SignExtend64<16>(Inst->ImmOpnd));
|
|
|
|
|
|
|
|
// Build the remaining instructions in Seq.
|
|
|
|
for (++Inst; Inst != Seq.end() - LastInstrIsADDiu; ++Inst)
|
2012-11-03 08:05:43 +08:00
|
|
|
BuildMI(MBB, II, DL, get(Inst->Opc), Reg).addReg(Reg, RegState::Kill)
|
2012-08-23 08:21:05 +08:00
|
|
|
.addImm(SignExtend64<16>(Inst->ImmOpnd));
|
|
|
|
|
|
|
|
if (LastInstrIsADDiu)
|
|
|
|
*NewImm = Inst->ImmOpnd;
|
|
|
|
|
2012-11-03 08:05:43 +08:00
|
|
|
return Reg;
|
2012-08-23 08:21:05 +08:00
|
|
|
}
|
|
|
|
|
2013-05-14 01:43:19 +08:00
|
|
|
unsigned MipsSEInstrInfo::getAnalyzableBrOpc(unsigned Opc) const {
|
2016-07-22 15:18:33 +08:00
|
|
|
return (Opc == Mips::BEQ || Opc == Mips::BEQ_MM || Opc == Mips::BNE ||
|
|
|
|
Opc == Mips::BNE_MM || Opc == Mips::BGTZ || Opc == Mips::BGEZ ||
|
|
|
|
Opc == Mips::BLTZ || Opc == Mips::BLEZ || Opc == Mips::BEQ64 ||
|
|
|
|
Opc == Mips::BNE64 || Opc == Mips::BGTZ64 || Opc == Mips::BGEZ64 ||
|
|
|
|
Opc == Mips::BLTZ64 || Opc == Mips::BLEZ64 || Opc == Mips::BC1T ||
|
|
|
|
Opc == Mips::BC1F || Opc == Mips::B || Opc == Mips::J ||
|
2017-11-10 00:02:18 +08:00
|
|
|
Opc == Mips::B_MM || Opc == Mips::BEQZC_MM ||
|
|
|
|
Opc == Mips::BNEZC_MM || Opc == Mips::BEQC || Opc == Mips::BNEC ||
|
|
|
|
Opc == Mips::BLTC || Opc == Mips::BGEC || Opc == Mips::BLTUC ||
|
|
|
|
Opc == Mips::BGEUC || Opc == Mips::BGTZC || Opc == Mips::BLEZC ||
|
|
|
|
Opc == Mips::BGEZC || Opc == Mips::BLTZC || Opc == Mips::BEQZC ||
|
|
|
|
Opc == Mips::BNEZC || Opc == Mips::BEQZC64 || Opc == Mips::BNEZC64 ||
|
|
|
|
Opc == Mips::BEQC64 || Opc == Mips::BNEC64 || Opc == Mips::BGEC64 ||
|
|
|
|
Opc == Mips::BGEUC64 || Opc == Mips::BLTC64 || Opc == Mips::BLTUC64 ||
|
|
|
|
Opc == Mips::BGTZC64 || Opc == Mips::BGEZC64 ||
|
|
|
|
Opc == Mips::BLTZC64 || Opc == Mips::BLEZC64 || Opc == Mips::BC ||
|
|
|
|
Opc == Mips::BBIT0 || Opc == Mips::BBIT1 || Opc == Mips::BBIT032 ||
|
2018-04-27 23:49:49 +08:00
|
|
|
Opc == Mips::BBIT132 || Opc == Mips::BC_MMR6 ||
|
|
|
|
Opc == Mips::BEQC_MMR6 || Opc == Mips::BNEC_MMR6 ||
|
|
|
|
Opc == Mips::BLTC_MMR6 || Opc == Mips::BGEC_MMR6 ||
|
|
|
|
Opc == Mips::BLTUC_MMR6 || Opc == Mips::BGEUC_MMR6 ||
|
|
|
|
Opc == Mips::BGTZC_MMR6 || Opc == Mips::BLEZC_MMR6 ||
|
|
|
|
Opc == Mips::BGEZC_MMR6 || Opc == Mips::BLTZC_MMR6 ||
|
|
|
|
Opc == Mips::BEQZC_MMR6 || Opc == Mips::BNEZC_MMR6) ? Opc : 0;
|
2012-08-01 05:49:49 +08:00
|
|
|
}
|
|
|
|
|
2013-05-14 01:43:19 +08:00
|
|
|
void MipsSEInstrInfo::expandRetRA(MachineBasicBlock &MBB,
|
[mips][mips64r6] Use JALR for returns instead of JR (which is not available on MIPS32r6/MIPS64r6)
Summary:
RET, and RET_MM have been replaced by a pseudo named PseudoReturn.
In addition a version with a 64-bit GPR named PseudoReturn64 has been
added.
Instruction selection for a return matches RetRA, which is expanded post
register allocation to PseudoReturn/PseudoReturn64. During MipsAsmPrinter,
this PseudoReturn/PseudoReturn64 are emitted as:
- (JALR64 $zero, $rs) on MIPS64r6
- (JALR $zero, $rs) on MIPS32r6
- (JR_MM $rs) on microMIPS
- (JR $rs) otherwise
On MIPS32r6/MIPS64r6, 'jr $rs' is an alias for 'jalr $zero, $rs'. To aid
development and review (specifically, to ensure all cases of jr are
updated), these aliases are temporarily named 'r6.jr' instead of 'jr'.
A follow up patch will change them back to the correct mnemonic.
Added (JALR $zero, $rs) to MipsNaClELFStreamer's definition of an indirect
jump, and removed it from its definition of a call.
Note: I haven't accounted for MIPS64 in MipsNaClELFStreamer since it's
doesn't appear to account for any MIPS64-specifics.
The return instruction created as part of eh_return expansion is now expanded
using expandRetRA() so we use the right return instruction on MIPS32r6/MIPS64r6
('jalr $zero, $rs').
Also, fixed a misuse of isABI_N64() to detect 64-bit wide registers in
expandEhReturn().
Reviewers: jkolek, vmedic, mseaborn, zoran.jovanovic, dsanders
Reviewed By: dsanders
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D4268
llvm-svn: 212604
2014-07-09 18:16:07 +08:00
|
|
|
MachineBasicBlock::iterator I) const {
|
2017-03-09 19:19:48 +08:00
|
|
|
|
|
|
|
MachineInstrBuilder MIB;
|
[mips][mips64r6] Use JALR for returns instead of JR (which is not available on MIPS32r6/MIPS64r6)
Summary:
RET, and RET_MM have been replaced by a pseudo named PseudoReturn.
In addition a version with a 64-bit GPR named PseudoReturn64 has been
added.
Instruction selection for a return matches RetRA, which is expanded post
register allocation to PseudoReturn/PseudoReturn64. During MipsAsmPrinter,
this PseudoReturn/PseudoReturn64 are emitted as:
- (JALR64 $zero, $rs) on MIPS64r6
- (JALR $zero, $rs) on MIPS32r6
- (JR_MM $rs) on microMIPS
- (JR $rs) otherwise
On MIPS32r6/MIPS64r6, 'jr $rs' is an alias for 'jalr $zero, $rs'. To aid
development and review (specifically, to ensure all cases of jr are
updated), these aliases are temporarily named 'r6.jr' instead of 'jr'.
A follow up patch will change them back to the correct mnemonic.
Added (JALR $zero, $rs) to MipsNaClELFStreamer's definition of an indirect
jump, and removed it from its definition of a call.
Note: I haven't accounted for MIPS64 in MipsNaClELFStreamer since it's
doesn't appear to account for any MIPS64-specifics.
The return instruction created as part of eh_return expansion is now expanded
using expandRetRA() so we use the right return instruction on MIPS32r6/MIPS64r6
('jalr $zero, $rs').
Also, fixed a misuse of isABI_N64() to detect 64-bit wide registers in
expandEhReturn().
Reviewers: jkolek, vmedic, mseaborn, zoran.jovanovic, dsanders
Reviewed By: dsanders
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D4268
llvm-svn: 212604
2014-07-09 18:16:07 +08:00
|
|
|
if (Subtarget.isGP64bit())
|
2017-03-09 19:19:48 +08:00
|
|
|
MIB = BuildMI(MBB, I, I->getDebugLoc(), get(Mips::PseudoReturn64))
|
|
|
|
.addReg(Mips::RA_64, RegState::Undef);
|
[mips][mips64r6] Use JALR for returns instead of JR (which is not available on MIPS32r6/MIPS64r6)
Summary:
RET, and RET_MM have been replaced by a pseudo named PseudoReturn.
In addition a version with a 64-bit GPR named PseudoReturn64 has been
added.
Instruction selection for a return matches RetRA, which is expanded post
register allocation to PseudoReturn/PseudoReturn64. During MipsAsmPrinter,
this PseudoReturn/PseudoReturn64 are emitted as:
- (JALR64 $zero, $rs) on MIPS64r6
- (JALR $zero, $rs) on MIPS32r6
- (JR_MM $rs) on microMIPS
- (JR $rs) otherwise
On MIPS32r6/MIPS64r6, 'jr $rs' is an alias for 'jalr $zero, $rs'. To aid
development and review (specifically, to ensure all cases of jr are
updated), these aliases are temporarily named 'r6.jr' instead of 'jr'.
A follow up patch will change them back to the correct mnemonic.
Added (JALR $zero, $rs) to MipsNaClELFStreamer's definition of an indirect
jump, and removed it from its definition of a call.
Note: I haven't accounted for MIPS64 in MipsNaClELFStreamer since it's
doesn't appear to account for any MIPS64-specifics.
The return instruction created as part of eh_return expansion is now expanded
using expandRetRA() so we use the right return instruction on MIPS32r6/MIPS64r6
('jalr $zero, $rs').
Also, fixed a misuse of isABI_N64() to detect 64-bit wide registers in
expandEhReturn().
Reviewers: jkolek, vmedic, mseaborn, zoran.jovanovic, dsanders
Reviewed By: dsanders
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D4268
llvm-svn: 212604
2014-07-09 18:16:07 +08:00
|
|
|
else
|
2017-03-09 19:19:48 +08:00
|
|
|
MIB = BuildMI(MBB, I, I->getDebugLoc(), get(Mips::PseudoReturn))
|
|
|
|
.addReg(Mips::RA, RegState::Undef);
|
|
|
|
|
|
|
|
// Retain any imp-use flags.
|
|
|
|
for (auto & MO : I->operands()) {
|
|
|
|
if (MO.isImplicit())
|
|
|
|
MIB.add(MO);
|
|
|
|
}
|
2012-08-01 05:49:49 +08:00
|
|
|
}
|
|
|
|
|
2015-10-26 20:38:43 +08:00
|
|
|
void MipsSEInstrInfo::expandERet(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator I) const {
|
|
|
|
BuildMI(MBB, I, I->getDebugLoc(), get(Mips::ERET));
|
|
|
|
}
|
|
|
|
|
2013-06-12 02:48:16 +08:00
|
|
|
std::pair<bool, bool>
|
|
|
|
MipsSEInstrInfo::compareOpndSize(unsigned Opc,
|
|
|
|
const MachineFunction &MF) const {
|
2013-06-08 08:14:54 +08:00
|
|
|
const MCInstrDesc &Desc = get(Opc);
|
|
|
|
assert(Desc.NumOperands == 2 && "Unary instruction expected.");
|
2013-06-12 02:48:16 +08:00
|
|
|
const MipsRegisterInfo *RI = &getRegisterInfo();
|
2017-04-25 02:55:33 +08:00
|
|
|
unsigned DstRegSize = RI->getRegSizeInBits(*getRegClass(Desc, 0, RI, MF));
|
|
|
|
unsigned SrcRegSize = RI->getRegSizeInBits(*getRegClass(Desc, 1, RI, MF));
|
2013-06-08 08:14:54 +08:00
|
|
|
|
|
|
|
return std::make_pair(DstRegSize > SrcRegSize, DstRegSize < SrcRegSize);
|
|
|
|
}
|
|
|
|
|
2013-10-08 02:49:46 +08:00
|
|
|
void MipsSEInstrInfo::expandPseudoMFHiLo(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator I,
|
|
|
|
unsigned NewOpc) const {
|
|
|
|
BuildMI(MBB, I, I->getDebugLoc(), get(NewOpc), I->getOperand(0).getReg());
|
|
|
|
}
|
|
|
|
|
2013-10-15 09:48:30 +08:00
|
|
|
void MipsSEInstrInfo::expandPseudoMTLoHi(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator I,
|
|
|
|
unsigned LoOpc,
|
|
|
|
unsigned HiOpc,
|
|
|
|
bool HasExplicitDef) const {
|
|
|
|
// Expand
|
|
|
|
// lo_hi pseudomtlohi $gpr0, $gpr1
|
|
|
|
// to these two instructions:
|
|
|
|
// mtlo $gpr0
|
|
|
|
// mthi $gpr1
|
|
|
|
|
|
|
|
DebugLoc DL = I->getDebugLoc();
|
|
|
|
const MachineOperand &SrcLo = I->getOperand(1), &SrcHi = I->getOperand(2);
|
|
|
|
MachineInstrBuilder LoInst = BuildMI(MBB, I, DL, get(LoOpc));
|
|
|
|
MachineInstrBuilder HiInst = BuildMI(MBB, I, DL, get(HiOpc));
|
|
|
|
|
|
|
|
// Add lo/hi registers if the mtlo/hi instructions created have explicit
|
|
|
|
// def registers.
|
|
|
|
if (HasExplicitDef) {
|
|
|
|
unsigned DstReg = I->getOperand(0).getReg();
|
|
|
|
unsigned DstLo = getRegisterInfo().getSubReg(DstReg, Mips::sub_lo);
|
|
|
|
unsigned DstHi = getRegisterInfo().getSubReg(DstReg, Mips::sub_hi);
|
|
|
|
LoInst.addReg(DstLo, RegState::Define);
|
|
|
|
HiInst.addReg(DstHi, RegState::Define);
|
|
|
|
}
|
2016-01-12 23:15:14 +08:00
|
|
|
|
|
|
|
LoInst.addReg(SrcLo.getReg(), getKillRegState(SrcLo.isKill()));
|
|
|
|
HiInst.addReg(SrcHi.getReg(), getKillRegState(SrcHi.isKill()));
|
2013-10-15 09:48:30 +08:00
|
|
|
}
|
|
|
|
|
2013-05-17 03:48:37 +08:00
|
|
|
void MipsSEInstrInfo::expandCvtFPInt(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator I,
|
|
|
|
unsigned CvtOpc, unsigned MovOpc,
|
|
|
|
bool IsI64) const {
|
|
|
|
const MCInstrDesc &CvtDesc = get(CvtOpc), &MovDesc = get(MovOpc);
|
|
|
|
const MachineOperand &Dst = I->getOperand(0), &Src = I->getOperand(1);
|
|
|
|
unsigned DstReg = Dst.getReg(), SrcReg = Src.getReg(), TmpReg = DstReg;
|
|
|
|
unsigned KillSrc = getKillRegState(Src.isKill());
|
|
|
|
DebugLoc DL = I->getDebugLoc();
|
2013-06-08 08:14:54 +08:00
|
|
|
bool DstIsLarger, SrcIsLarger;
|
|
|
|
|
2014-03-02 21:30:33 +08:00
|
|
|
std::tie(DstIsLarger, SrcIsLarger) =
|
|
|
|
compareOpndSize(CvtOpc, *MBB.getParent());
|
2013-05-17 03:48:37 +08:00
|
|
|
|
|
|
|
if (DstIsLarger)
|
2013-08-21 06:58:56 +08:00
|
|
|
TmpReg = getRegisterInfo().getSubReg(DstReg, Mips::sub_lo);
|
2013-05-17 03:48:37 +08:00
|
|
|
|
|
|
|
if (SrcIsLarger)
|
2013-08-21 06:58:56 +08:00
|
|
|
DstReg = getRegisterInfo().getSubReg(DstReg, Mips::sub_lo);
|
2013-05-17 03:48:37 +08:00
|
|
|
|
|
|
|
BuildMI(MBB, I, DL, MovDesc, TmpReg).addReg(SrcReg, KillSrc);
|
|
|
|
BuildMI(MBB, I, DL, CvtDesc, DstReg).addReg(TmpReg, RegState::Kill);
|
|
|
|
}
|
|
|
|
|
2013-05-14 01:43:19 +08:00
|
|
|
void MipsSEInstrInfo::expandExtractElementF64(MachineBasicBlock &MBB,
|
2013-08-21 07:47:25 +08:00
|
|
|
MachineBasicBlock::iterator I,
|
[mips] Define certain instructions in microMIPS32r3
Instructions affected:
mthc1, mfhc1, add.d, sub.d, mul.d, div.d,
mov.d, neg.d, cvt.w.d, cvt.d.s, cvt.d.w, cvt.s.d
These instructions are now defined for
microMIPS32r3 + microMIPS32r6 in MicroMipsInstrFPU.td
since they shared their encoding with those already defined
in microMIPS32r6InstrInfo.td and have been therefore
removed from the latter file.
Some instructions present in MicroMipsInstrFPU.td which
did not have both AFGR64 and FGR64 variants defined have
been altered to do so.
Differential revision: https://reviews.llvm.org/D42738
llvm-svn: 324584
2018-02-08 17:25:17 +08:00
|
|
|
bool isMicroMips,
|
2013-08-21 07:47:25 +08:00
|
|
|
bool FP64) const {
|
2012-08-01 05:49:49 +08:00
|
|
|
unsigned DstReg = I->getOperand(0).getReg();
|
|
|
|
unsigned SrcReg = I->getOperand(1).getReg();
|
|
|
|
unsigned N = I->getOperand(2).getImm();
|
|
|
|
DebugLoc dl = I->getDebugLoc();
|
|
|
|
|
|
|
|
assert(N < 2 && "Invalid immediate");
|
2013-08-21 06:58:56 +08:00
|
|
|
unsigned SubIdx = N ? Mips::sub_hi : Mips::sub_lo;
|
2012-08-01 05:49:49 +08:00
|
|
|
unsigned SubReg = getRegisterInfo().getSubReg(SrcReg, SubIdx);
|
|
|
|
|
2014-07-14 21:08:14 +08:00
|
|
|
// FPXX on MIPS-II or MIPS32r1 should have been handled with a spill/reload
|
|
|
|
// in MipsSEFrameLowering.cpp.
|
|
|
|
assert(!(Subtarget.isABI_FPXX() && !Subtarget.hasMips32r2()));
|
|
|
|
|
|
|
|
// FP64A (FP64 with nooddspreg) should have been handled with a spill/reload
|
|
|
|
// in MipsSEFrameLowering.cpp.
|
|
|
|
assert(!(Subtarget.isFP64bit() && !Subtarget.useOddSPReg()));
|
|
|
|
|
|
|
|
if (SubIdx == Mips::sub_hi && Subtarget.hasMTHC1()) {
|
2014-07-14 20:41:31 +08:00
|
|
|
// FIXME: Strictly speaking MFHC1 only reads the top 32-bits however, we
|
|
|
|
// claim to read the whole 64-bits as part of a white lie used to
|
2014-03-10 23:01:57 +08:00
|
|
|
// temporarily work around a widespread bug in the -mfp64 support.
|
|
|
|
// The problem is that none of the 32-bit fpu ops mention the fact
|
|
|
|
// that they clobber the upper 32-bits of the 64-bit FPR. Fixing that
|
|
|
|
// requires a major overhaul of the FPU implementation which can't
|
|
|
|
// be done right now due to time constraints.
|
2014-03-12 21:35:43 +08:00
|
|
|
// MFHC1 is one of two instructions that are affected since they are
|
|
|
|
// the only instructions that don't read the lower 32-bits.
|
|
|
|
// We therefore pretend that it reads the bottom 32-bits to
|
|
|
|
// artificially create a dependency and prevent the scheduler
|
|
|
|
// changing the behaviour of the code.
|
[mips] Define certain instructions in microMIPS32r3
Instructions affected:
mthc1, mfhc1, add.d, sub.d, mul.d, div.d,
mov.d, neg.d, cvt.w.d, cvt.d.s, cvt.d.w, cvt.s.d
These instructions are now defined for
microMIPS32r3 + microMIPS32r6 in MicroMipsInstrFPU.td
since they shared their encoding with those already defined
in microMIPS32r6InstrInfo.td and have been therefore
removed from the latter file.
Some instructions present in MicroMipsInstrFPU.td which
did not have both AFGR64 and FGR64 variants defined have
been altered to do so.
Differential revision: https://reviews.llvm.org/D42738
llvm-svn: 324584
2018-02-08 17:25:17 +08:00
|
|
|
BuildMI(MBB, I, dl,
|
|
|
|
get(isMicroMips ? (FP64 ? Mips::MFHC1_D64_MM : Mips::MFHC1_D32_MM)
|
|
|
|
: (FP64 ? Mips::MFHC1_D64 : Mips::MFHC1_D32)),
|
|
|
|
DstReg)
|
2014-07-14 20:41:31 +08:00
|
|
|
.addReg(SrcReg);
|
2014-03-10 23:01:57 +08:00
|
|
|
} else
|
2013-08-21 07:47:25 +08:00
|
|
|
BuildMI(MBB, I, dl, get(Mips::MFC1), DstReg).addReg(SubReg);
|
2012-08-01 05:49:49 +08:00
|
|
|
}
|
|
|
|
|
2013-05-14 01:43:19 +08:00
|
|
|
void MipsSEInstrInfo::expandBuildPairF64(MachineBasicBlock &MBB,
|
2013-08-21 07:47:25 +08:00
|
|
|
MachineBasicBlock::iterator I,
|
[mips] Define certain instructions in microMIPS32r3
Instructions affected:
mthc1, mfhc1, add.d, sub.d, mul.d, div.d,
mov.d, neg.d, cvt.w.d, cvt.d.s, cvt.d.w, cvt.s.d
These instructions are now defined for
microMIPS32r3 + microMIPS32r6 in MicroMipsInstrFPU.td
since they shared their encoding with those already defined
in microMIPS32r6InstrInfo.td and have been therefore
removed from the latter file.
Some instructions present in MicroMipsInstrFPU.td which
did not have both AFGR64 and FGR64 variants defined have
been altered to do so.
Differential revision: https://reviews.llvm.org/D42738
llvm-svn: 324584
2018-02-08 17:25:17 +08:00
|
|
|
bool isMicroMips, bool FP64) const {
|
2012-08-01 05:49:49 +08:00
|
|
|
unsigned DstReg = I->getOperand(0).getReg();
|
|
|
|
unsigned LoReg = I->getOperand(1).getReg(), HiReg = I->getOperand(2).getReg();
|
|
|
|
const MCInstrDesc& Mtc1Tdd = get(Mips::MTC1);
|
|
|
|
DebugLoc dl = I->getDebugLoc();
|
|
|
|
const TargetRegisterInfo &TRI = getRegisterInfo();
|
|
|
|
|
2014-06-12 19:55:58 +08:00
|
|
|
// When mthc1 is available, use:
|
2013-11-18 21:12:43 +08:00
|
|
|
// mtc1 Lo, $fp
|
|
|
|
// mthc1 Hi, $fp
|
2014-06-12 19:55:58 +08:00
|
|
|
//
|
2014-07-14 17:40:29 +08:00
|
|
|
// Otherwise, for O32 FPXX ABI:
|
2014-06-12 19:55:58 +08:00
|
|
|
// spill + reload via ldc1
|
2014-07-14 17:40:29 +08:00
|
|
|
// This case is handled by the frame lowering code.
|
2014-06-12 19:55:58 +08:00
|
|
|
//
|
|
|
|
// Otherwise, for FP32:
|
|
|
|
// mtc1 Lo, $fp
|
|
|
|
// mtc1 Hi, $fp + 1
|
2014-07-14 17:40:29 +08:00
|
|
|
//
|
|
|
|
// The case where dmtc1 is available doesn't need to be handled here
|
|
|
|
// because it never creates a BuildPairF64 node.
|
2013-11-18 21:12:43 +08:00
|
|
|
|
2014-07-14 21:08:14 +08:00
|
|
|
// FPXX on MIPS-II or MIPS32r1 should have been handled with a spill/reload
|
|
|
|
// in MipsSEFrameLowering.cpp.
|
|
|
|
assert(!(Subtarget.isABI_FPXX() && !Subtarget.hasMips32r2()));
|
|
|
|
|
|
|
|
// FP64A (FP64 with nooddspreg) should have been handled with a spill/reload
|
|
|
|
// in MipsSEFrameLowering.cpp.
|
|
|
|
assert(!(Subtarget.isFP64bit() && !Subtarget.useOddSPReg()));
|
|
|
|
|
2013-08-21 06:58:56 +08:00
|
|
|
BuildMI(MBB, I, dl, Mtc1Tdd, TRI.getSubReg(DstReg, Mips::sub_lo))
|
2012-08-01 05:49:49 +08:00
|
|
|
.addReg(LoReg);
|
2013-08-21 07:47:25 +08:00
|
|
|
|
2014-07-14 21:08:14 +08:00
|
|
|
if (Subtarget.hasMTHC1()) {
|
2014-06-12 19:55:58 +08:00
|
|
|
// FIXME: The .addReg(DstReg) is a white lie used to temporarily work
|
|
|
|
// around a widespread bug in the -mfp64 support.
|
2014-03-12 21:35:43 +08:00
|
|
|
// The problem is that none of the 32-bit fpu ops mention the fact
|
|
|
|
// that they clobber the upper 32-bits of the 64-bit FPR. Fixing that
|
|
|
|
// requires a major overhaul of the FPU implementation which can't
|
|
|
|
// be done right now due to time constraints.
|
|
|
|
// MTHC1 is one of two instructions that are affected since they are
|
|
|
|
// the only instructions that don't read the lower 32-bits.
|
|
|
|
// We therefore pretend that it reads the bottom 32-bits to
|
|
|
|
// artificially create a dependency and prevent the scheduler
|
|
|
|
// changing the behaviour of the code.
|
[mips] Define certain instructions in microMIPS32r3
Instructions affected:
mthc1, mfhc1, add.d, sub.d, mul.d, div.d,
mov.d, neg.d, cvt.w.d, cvt.d.s, cvt.d.w, cvt.s.d
These instructions are now defined for
microMIPS32r3 + microMIPS32r6 in MicroMipsInstrFPU.td
since they shared their encoding with those already defined
in microMIPS32r6InstrInfo.td and have been therefore
removed from the latter file.
Some instructions present in MicroMipsInstrFPU.td which
did not have both AFGR64 and FGR64 variants defined have
been altered to do so.
Differential revision: https://reviews.llvm.org/D42738
llvm-svn: 324584
2018-02-08 17:25:17 +08:00
|
|
|
BuildMI(MBB, I, dl,
|
|
|
|
get(isMicroMips ? (FP64 ? Mips::MTHC1_D64_MM : Mips::MTHC1_D32_MM)
|
|
|
|
: (FP64 ? Mips::MTHC1_D64 : Mips::MTHC1_D32)),
|
|
|
|
DstReg)
|
2014-06-12 19:55:58 +08:00
|
|
|
.addReg(DstReg)
|
|
|
|
.addReg(HiReg);
|
2014-07-14 21:08:14 +08:00
|
|
|
} else if (Subtarget.isABI_FPXX())
|
2014-07-14 17:40:29 +08:00
|
|
|
llvm_unreachable("BuildPairF64 not expanded in frame lowering code!");
|
|
|
|
else
|
2013-08-21 07:47:25 +08:00
|
|
|
BuildMI(MBB, I, dl, Mtc1Tdd, TRI.getSubReg(DstReg, Mips::sub_hi))
|
|
|
|
.addReg(HiReg);
|
2012-08-01 05:49:49 +08:00
|
|
|
}
|
2012-08-03 02:21:47 +08:00
|
|
|
|
2013-05-14 01:43:19 +08:00
|
|
|
void MipsSEInstrInfo::expandEhReturn(MachineBasicBlock &MBB,
|
2013-01-30 08:26:49 +08:00
|
|
|
MachineBasicBlock::iterator I) const {
|
|
|
|
// This pseudo instruction is generated as part of the lowering of
|
|
|
|
// ISD::EH_RETURN. We convert it to a stack increment by OffsetReg, and
|
|
|
|
// indirect jump to TargetReg
|
2015-04-17 17:50:21 +08:00
|
|
|
MipsABIInfo ABI = Subtarget.getABI();
|
|
|
|
unsigned ADDU = ABI.GetPtrAdduOp();
|
2014-07-19 07:25:00 +08:00
|
|
|
unsigned SP = Subtarget.isGP64bit() ? Mips::SP_64 : Mips::SP;
|
|
|
|
unsigned RA = Subtarget.isGP64bit() ? Mips::RA_64 : Mips::RA;
|
|
|
|
unsigned T9 = Subtarget.isGP64bit() ? Mips::T9_64 : Mips::T9;
|
|
|
|
unsigned ZERO = Subtarget.isGP64bit() ? Mips::ZERO_64 : Mips::ZERO;
|
2013-01-30 08:26:49 +08:00
|
|
|
unsigned OffsetReg = I->getOperand(0).getReg();
|
|
|
|
unsigned TargetReg = I->getOperand(1).getReg();
|
|
|
|
|
2013-07-23 02:52:22 +08:00
|
|
|
// addu $ra, $v0, $zero
|
2013-01-30 08:26:49 +08:00
|
|
|
// addu $sp, $sp, $v1
|
[mips][mips64r6] Use JALR for returns instead of JR (which is not available on MIPS32r6/MIPS64r6)
Summary:
RET, and RET_MM have been replaced by a pseudo named PseudoReturn.
In addition a version with a 64-bit GPR named PseudoReturn64 has been
added.
Instruction selection for a return matches RetRA, which is expanded post
register allocation to PseudoReturn/PseudoReturn64. During MipsAsmPrinter,
this PseudoReturn/PseudoReturn64 are emitted as:
- (JALR64 $zero, $rs) on MIPS64r6
- (JALR $zero, $rs) on MIPS32r6
- (JR_MM $rs) on microMIPS
- (JR $rs) otherwise
On MIPS32r6/MIPS64r6, 'jr $rs' is an alias for 'jalr $zero, $rs'. To aid
development and review (specifically, to ensure all cases of jr are
updated), these aliases are temporarily named 'r6.jr' instead of 'jr'.
A follow up patch will change them back to the correct mnemonic.
Added (JALR $zero, $rs) to MipsNaClELFStreamer's definition of an indirect
jump, and removed it from its definition of a call.
Note: I haven't accounted for MIPS64 in MipsNaClELFStreamer since it's
doesn't appear to account for any MIPS64-specifics.
The return instruction created as part of eh_return expansion is now expanded
using expandRetRA() so we use the right return instruction on MIPS32r6/MIPS64r6
('jalr $zero, $rs').
Also, fixed a misuse of isABI_N64() to detect 64-bit wide registers in
expandEhReturn().
Reviewers: jkolek, vmedic, mseaborn, zoran.jovanovic, dsanders
Reviewed By: dsanders
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D4268
llvm-svn: 212604
2014-07-09 18:16:07 +08:00
|
|
|
// jr $ra (via RetRA)
|
2014-07-19 07:25:00 +08:00
|
|
|
const TargetMachine &TM = MBB.getParent()->getTarget();
|
2016-06-28 22:33:28 +08:00
|
|
|
if (TM.isPositionIndependent())
|
2015-01-09 02:18:50 +08:00
|
|
|
BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), T9)
|
2014-07-19 07:25:00 +08:00
|
|
|
.addReg(TargetReg)
|
|
|
|
.addReg(ZERO);
|
2015-01-09 02:18:50 +08:00
|
|
|
BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), RA)
|
2014-07-19 07:25:00 +08:00
|
|
|
.addReg(TargetReg)
|
|
|
|
.addReg(ZERO);
|
2015-01-09 02:18:50 +08:00
|
|
|
BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), SP).addReg(SP).addReg(OffsetReg);
|
[mips][mips64r6] Use JALR for returns instead of JR (which is not available on MIPS32r6/MIPS64r6)
Summary:
RET, and RET_MM have been replaced by a pseudo named PseudoReturn.
In addition a version with a 64-bit GPR named PseudoReturn64 has been
added.
Instruction selection for a return matches RetRA, which is expanded post
register allocation to PseudoReturn/PseudoReturn64. During MipsAsmPrinter,
this PseudoReturn/PseudoReturn64 are emitted as:
- (JALR64 $zero, $rs) on MIPS64r6
- (JALR $zero, $rs) on MIPS32r6
- (JR_MM $rs) on microMIPS
- (JR $rs) otherwise
On MIPS32r6/MIPS64r6, 'jr $rs' is an alias for 'jalr $zero, $rs'. To aid
development and review (specifically, to ensure all cases of jr are
updated), these aliases are temporarily named 'r6.jr' instead of 'jr'.
A follow up patch will change them back to the correct mnemonic.
Added (JALR $zero, $rs) to MipsNaClELFStreamer's definition of an indirect
jump, and removed it from its definition of a call.
Note: I haven't accounted for MIPS64 in MipsNaClELFStreamer since it's
doesn't appear to account for any MIPS64-specifics.
The return instruction created as part of eh_return expansion is now expanded
using expandRetRA() so we use the right return instruction on MIPS32r6/MIPS64r6
('jalr $zero, $rs').
Also, fixed a misuse of isABI_N64() to detect 64-bit wide registers in
expandEhReturn().
Reviewers: jkolek, vmedic, mseaborn, zoran.jovanovic, dsanders
Reviewed By: dsanders
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D4268
llvm-svn: 212604
2014-07-09 18:16:07 +08:00
|
|
|
expandRetRA(MBB, I);
|
2013-01-30 08:26:49 +08:00
|
|
|
}
|
|
|
|
|
2014-07-19 07:25:00 +08:00
|
|
|
const MipsInstrInfo *llvm::createMipsSEInstrInfo(const MipsSubtarget &STI) {
|
|
|
|
return new MipsSEInstrInfo(STI);
|
2012-08-03 02:21:47 +08:00
|
|
|
}
|