diff options
Diffstat (limited to 'lib/Target/Mips/MipsInstrInfo.cpp')
-rw-r--r-- | lib/Target/Mips/MipsInstrInfo.cpp | 160 |
1 files changed, 146 insertions, 14 deletions
diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index a3a18bf..458e4f7 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "MipsAnalyzeImmediate.h" #include "MipsInstrInfo.h" #include "MipsTargetMachine.h" #include "MipsMachineFunction.h" @@ -29,6 +30,7 @@ using namespace llvm; MipsInstrInfo::MipsInstrInfo(MipsTargetMachine &tm) : MipsGenInstrInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP), TM(tm), IsN64(TM.getSubtarget<MipsSubtarget>().isABI_N64()), + InMips16Mode(TM.getSubtarget<MipsSubtarget>().inMips16Mode()), RI(*TM.getSubtargetImpl(), *this), UncondBrOpc(TM.getRelocationModel() == Reloc::PIC_ ? Mips::B : Mips::J) {} @@ -106,8 +108,13 @@ copyPhysReg(MachineBasicBlock &MBB, unsigned Opc = 0, ZeroReg = 0; if (Mips::CPURegsRegClass.contains(DestReg)) { // Copy to CPU Reg. - if (Mips::CPURegsRegClass.contains(SrcReg)) - Opc = Mips::ADDu, ZeroReg = Mips::ZERO; + if (Mips::CPURegsRegClass.contains(SrcReg)) { + if (InMips16Mode) + Opc=Mips::Mov32R16; + else { + Opc = Mips::ADDu, ZeroReg = Mips::ZERO; + } + } else if (Mips::CCRRegClass.contains(SrcReg)) Opc = Mips::CFC1; else if (Mips::FGR32RegClass.contains(SrcReg)) @@ -189,15 +196,15 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned Opc = 0; - if (RC == Mips::CPURegsRegisterClass) + if (Mips::CPURegsRegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::SW_P8 : Mips::SW; - else if (RC == Mips::CPU64RegsRegisterClass) + else if (Mips::CPU64RegsRegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::SD_P8 : Mips::SD; - else if (RC == Mips::FGR32RegisterClass) + else if (Mips::FGR32RegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::SWC1_P8 : Mips::SWC1; - else if (RC == Mips::AFGR64RegisterClass) + else if (Mips::AFGR64RegClass.hasSubClassEq(RC)) Opc = Mips::SDC1; - else if (RC == Mips::FGR64RegisterClass) + else if (Mips::FGR64RegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::SDC164_P8 : Mips::SDC164; assert(Opc && "Register class not handled!"); @@ -216,15 +223,15 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOLoad); unsigned Opc = 0; - if (RC == Mips::CPURegsRegisterClass) + if (Mips::CPURegsRegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::LW_P8 : Mips::LW; - else if (RC == Mips::CPU64RegsRegisterClass) + else if (Mips::CPU64RegsRegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::LD_P8 : Mips::LD; - else if (RC == Mips::FGR32RegisterClass) + else if (Mips::FGR32RegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::LWC1_P8 : Mips::LWC1; - else if (RC == Mips::AFGR64RegisterClass) + else if (Mips::AFGR64RegClass.hasSubClassEq(RC)) Opc = Mips::LDC1; - else if (RC == Mips::FGR64RegisterClass) + else if (Mips::FGR64RegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::LDC164_P8 : Mips::LDC164; assert(Opc && "Register class not handled!"); @@ -232,6 +239,76 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, .addMemOperand(MMO); } +void MipsInstrInfo::ExpandRetRA(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned Opc) const { + BuildMI(MBB, I, I->getDebugLoc(), TM.getInstrInfo()->get(Opc)) + .addReg(Mips::RA); +} + +void MipsInstrInfo::ExpandRetRA16(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned Opc) const { + BuildMI(MBB, I, I->getDebugLoc(), TM.getInstrInfo()->get(Opc)); +} + +void MipsInstrInfo::ExpandExtractElementF64(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + const TargetInstrInfo *TII = TM.getInstrInfo(); + unsigned DstReg = I->getOperand(0).getReg(); + unsigned SrcReg = I->getOperand(1).getReg(); + unsigned N = I->getOperand(2).getImm(); + const MCInstrDesc& Mfc1Tdd = TII->get(Mips::MFC1); + DebugLoc dl = I->getDebugLoc(); + + assert(N < 2 && "Invalid immediate"); + unsigned SubIdx = N ? Mips::sub_fpodd : Mips::sub_fpeven; + unsigned SubReg = TM.getRegisterInfo()->getSubReg(SrcReg, SubIdx); + + BuildMI(MBB, I, dl, Mfc1Tdd, DstReg).addReg(SubReg); +} + +void MipsInstrInfo::ExpandBuildPairF64(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + const TargetInstrInfo *TII = TM.getInstrInfo(); + unsigned DstReg = I->getOperand(0).getReg(); + unsigned LoReg = I->getOperand(1).getReg(), HiReg = I->getOperand(2).getReg(); + const MCInstrDesc& Mtc1Tdd = TII->get(Mips::MTC1); + DebugLoc dl = I->getDebugLoc(); + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + + // mtc1 Lo, $fp + // mtc1 Hi, $fp + 1 + BuildMI(MBB, I, dl, Mtc1Tdd, TRI->getSubReg(DstReg, Mips::sub_fpeven)) + .addReg(LoReg); + BuildMI(MBB, I, dl, Mtc1Tdd, TRI->getSubReg(DstReg, Mips::sub_fpodd)) + .addReg(HiReg); +} + +bool MipsInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const { + MachineBasicBlock &MBB = *MI->getParent(); + + switch(MI->getDesc().getOpcode()) { + default: + return false; + case Mips::RetRA: + ExpandRetRA(MBB, MI, Mips::RET); + break; + case Mips::RetRA16: + ExpandRetRA16(MBB, MI, Mips::JrRa16); + break; + case Mips::BuildPairF64: + ExpandBuildPairF64(MBB, MI); + break; + case Mips::ExtractElementF64: + ExpandExtractElementF64(MBB, MI); + break; + } + + MBB.erase(MI); + return true; +} + MachineInstr* MipsInstrInfo::emitFrameIndexDebugValue(MachineFunction &MF, int FrameIx, uint64_t Offset, const MDNode *MDPtr, @@ -278,9 +355,9 @@ unsigned Mips::GetOppositeBranchOpc(unsigned Opc) } } -static void AnalyzeCondBr(const MachineInstr* Inst, unsigned Opc, +static void AnalyzeCondBr(const MachineInstr *Inst, unsigned Opc, MachineBasicBlock *&BB, - SmallVectorImpl<MachineOperand>& Cond) { + SmallVectorImpl<MachineOperand> &Cond) { assert(GetAnalyzableBrOpc(Opc) && "Not an analyzable branch"); int NumOp = Inst->getNumExplicitOperands(); @@ -454,3 +531,58 @@ ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const return false; } +/// Return the number of bytes of code the specified instruction may be. +unsigned MipsInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { + switch (MI->getOpcode()) { + default: + return MI->getDesc().getSize(); + case TargetOpcode::INLINEASM: { // Inline Asm: Variable size. + const MachineFunction *MF = MI->getParent()->getParent(); + const char *AsmStr = MI->getOperand(0).getSymbolName(); + return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo()); + } + } +} + +unsigned +llvm::Mips::loadImmediate(int64_t Imm, bool IsN64, const TargetInstrInfo &TII, + MachineBasicBlock& MBB, + MachineBasicBlock::iterator II, DebugLoc DL, + bool LastInstrIsADDiu, + MipsAnalyzeImmediate::Inst *LastInst) { + MipsAnalyzeImmediate AnalyzeImm; + unsigned Size = IsN64 ? 64 : 32; + unsigned LUi = IsN64 ? Mips::LUi64 : Mips::LUi; + unsigned ZEROReg = IsN64 ? Mips::ZERO_64 : Mips::ZERO; + unsigned ATReg = IsN64 ? Mips::AT_64 : Mips::AT; + + const MipsAnalyzeImmediate::InstSeq &Seq = + AnalyzeImm.Analyze(Imm, Size, LastInstrIsADDiu); + MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin(); + + if (LastInst && (Seq.size() == 1)) { + *LastInst = *Inst; + return 0; + } + + // 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. + if (Inst->Opc == LUi) + BuildMI(MBB, II, DL, TII.get(LUi), ATReg) + .addImm(SignExtend64<16>(Inst->ImmOpnd)); + else + BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ZEROReg) + .addImm(SignExtend64<16>(Inst->ImmOpnd)); + + // Build the remaining instructions in Seq. Skip the last instruction if + // LastInst is not 0. + for (++Inst; Inst != Seq.end() - !!LastInst; ++Inst) + BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ATReg) + .addImm(SignExtend64<16>(Inst->ImmOpnd)); + + if (LastInst) + *LastInst = *Inst; + + return Seq.size() - !!LastInst; +} |