179220eaeSEugene Zelenko //===- Mips16InstrInfo.cpp - Mips16 Instruction Information ---------------===//
2b7fa3c9dSAkira Hatanaka //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b7fa3c9dSAkira Hatanaka //
7b7fa3c9dSAkira Hatanaka //===----------------------------------------------------------------------===//
8b7fa3c9dSAkira Hatanaka //
9b7fa3c9dSAkira Hatanaka // This file contains the Mips16 implementation of the TargetInstrInfo class.
10b7fa3c9dSAkira Hatanaka //
11b7fa3c9dSAkira Hatanaka //===----------------------------------------------------------------------===//
1279220eaeSEugene Zelenko
13b7fa3c9dSAkira Hatanaka #include "Mips16InstrInfo.h"
1479220eaeSEugene Zelenko #include "llvm/ADT/BitVector.h"
1579220eaeSEugene Zelenko #include "llvm/CodeGen/MachineBasicBlock.h"
1679220eaeSEugene Zelenko #include "llvm/CodeGen/MachineFrameInfo.h"
1779220eaeSEugene Zelenko #include "llvm/CodeGen/MachineFunction.h"
1879220eaeSEugene Zelenko #include "llvm/CodeGen/MachineInstr.h"
19b7fa3c9dSAkira Hatanaka #include "llvm/CodeGen/MachineInstrBuilder.h"
2079220eaeSEugene Zelenko #include "llvm/CodeGen/MachineMemOperand.h"
2179220eaeSEugene Zelenko #include "llvm/CodeGen/MachineOperand.h"
2266165c8fSReed Kotler #include "llvm/CodeGen/RegisterScavenging.h"
23b3bde2eaSDavid Blaikie #include "llvm/CodeGen/TargetRegisterInfo.h"
2479220eaeSEugene Zelenko #include "llvm/IR/DebugLoc.h"
255c8ae095SReed Kotler #include "llvm/MC/MCAsmInfo.h"
26cb37409bSReed Kotler #include "llvm/Support/Debug.h"
27b7fa3c9dSAkira Hatanaka #include "llvm/Support/ErrorHandling.h"
2879220eaeSEugene Zelenko #include "llvm/Support/MathExtras.h"
29799003bfSBenjamin Kramer #include "llvm/Support/raw_ostream.h"
3079220eaeSEugene Zelenko #include <cassert>
31435f62a8SNAKAMURA Takumi #include <cctype>
3279220eaeSEugene Zelenko #include <cstdint>
3379220eaeSEugene Zelenko #include <cstdlib>
3479220eaeSEugene Zelenko #include <cstring>
3579220eaeSEugene Zelenko #include <iterator>
3679220eaeSEugene Zelenko #include <vector>
37b7fa3c9dSAkira Hatanaka
38b7fa3c9dSAkira Hatanaka using namespace llvm;
39b7fa3c9dSAkira Hatanaka
40e96dd897SChandler Carruth #define DEBUG_TYPE "mips16-instrinfo"
41d019dbf7SReed Kotler
Mips16InstrInfo(const MipsSubtarget & STI)42675cb4daSEric Christopher Mips16InstrInfo::Mips16InstrInfo(const MipsSubtarget &STI)
4379220eaeSEugene Zelenko : MipsInstrInfo(STI, Mips::Bimm16) {}
44cb37e13fSAkira Hatanaka
getRegisterInfo() const45cb37e13fSAkira Hatanaka const MipsRegisterInfo &Mips16InstrInfo::getRegisterInfo() const {
46cb37e13fSAkira Hatanaka return RI;
47cb37e13fSAkira Hatanaka }
48b7fa3c9dSAkira Hatanaka
49b7fa3c9dSAkira Hatanaka /// isLoadFromStackSlot - If the specified machine instruction is a direct
50b7fa3c9dSAkira Hatanaka /// load from a stack slot, return the virtual or physical register number of
51b7fa3c9dSAkira Hatanaka /// the destination along with the FrameIndex of the loaded stack slot. If
52b7fa3c9dSAkira Hatanaka /// not, return 0. This predicate must return 0 if the instruction has
53b7fa3c9dSAkira Hatanaka /// any side effects other than loading from the stack slot.
isLoadFromStackSlot(const MachineInstr & MI,int & FrameIndex) const549cfc75c2SDuncan P. N. Exon Smith unsigned Mips16InstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
5566b7069cSEric Christopher int &FrameIndex) const {
56b7fa3c9dSAkira Hatanaka return 0;
57b7fa3c9dSAkira Hatanaka }
58b7fa3c9dSAkira Hatanaka
59b7fa3c9dSAkira Hatanaka /// isStoreToStackSlot - If the specified machine instruction is a direct
60b7fa3c9dSAkira Hatanaka /// store to a stack slot, return the virtual or physical register number of
61b7fa3c9dSAkira Hatanaka /// the source reg along with the FrameIndex of the loaded stack slot. If
62b7fa3c9dSAkira Hatanaka /// not, return 0. This predicate must return 0 if the instruction has
63b7fa3c9dSAkira Hatanaka /// any side effects other than storing to the stack slot.
isStoreToStackSlot(const MachineInstr & MI,int & FrameIndex) const649cfc75c2SDuncan P. N. Exon Smith unsigned Mips16InstrInfo::isStoreToStackSlot(const MachineInstr &MI,
6566b7069cSEric Christopher int &FrameIndex) const {
66b7fa3c9dSAkira Hatanaka return 0;
67b7fa3c9dSAkira Hatanaka }
68b7fa3c9dSAkira Hatanaka
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,const DebugLoc & DL,MCRegister DestReg,MCRegister SrcReg,bool KillSrc) const69b7fa3c9dSAkira Hatanaka void Mips16InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
70bdc4956bSBenjamin Kramer MachineBasicBlock::iterator I,
71e6c9a9afSMatt Arsenault const DebugLoc &DL, MCRegister DestReg,
72e6c9a9afSMatt Arsenault MCRegister SrcReg, bool KillSrc) const {
73cf11c59eSReed Kotler unsigned Opc = 0;
74b7fa3c9dSAkira Hatanaka
75cf11c59eSReed Kotler if (Mips::CPU16RegsRegClass.contains(DestReg) &&
7613e6ccf3SAkira Hatanaka Mips::GPR32RegClass.contains(SrcReg))
77cf11c59eSReed Kotler Opc = Mips::MoveR3216;
7813e6ccf3SAkira Hatanaka else if (Mips::GPR32RegClass.contains(DestReg) &&
79cf11c59eSReed Kotler Mips::CPU16RegsRegClass.contains(SrcReg))
800fbaec22SAkira Hatanaka Opc = Mips::Move32R16;
818002a3f6SAkira Hatanaka else if ((SrcReg == Mips::HI0) &&
82cf11c59eSReed Kotler (Mips::CPU16RegsRegClass.contains(DestReg)))
83cf11c59eSReed Kotler Opc = Mips::Mfhi16, SrcReg = 0;
848002a3f6SAkira Hatanaka else if ((SrcReg == Mips::LO0) &&
85cf11c59eSReed Kotler (Mips::CPU16RegsRegClass.contains(DestReg)))
86cf11c59eSReed Kotler Opc = Mips::Mflo16, SrcReg = 0;
87cf11c59eSReed Kotler
88b7fa3c9dSAkira Hatanaka assert(Opc && "Cannot copy registers");
89b7fa3c9dSAkira Hatanaka
90b7fa3c9dSAkira Hatanaka MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opc));
91b7fa3c9dSAkira Hatanaka
92b7fa3c9dSAkira Hatanaka if (DestReg)
93b7fa3c9dSAkira Hatanaka MIB.addReg(DestReg, RegState::Define);
94b7fa3c9dSAkira Hatanaka
95b7fa3c9dSAkira Hatanaka if (SrcReg)
96b7fa3c9dSAkira Hatanaka MIB.addReg(SrcReg, getKillRegState(KillSrc));
97b7fa3c9dSAkira Hatanaka }
98b7fa3c9dSAkira Hatanaka
998d2ccd1aSDjordje Todorovic Optional<DestSourcePair>
isCopyInstrImpl(const MachineInstr & MI) const1008d2ccd1aSDjordje Todorovic Mips16InstrInfo::isCopyInstrImpl(const MachineInstr &MI) const {
1018d2ccd1aSDjordje Todorovic if (MI.isMoveReg())
1028d2ccd1aSDjordje Todorovic return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
1038d2ccd1aSDjordje Todorovic return None;
104c051000bSPetar Jovanovic }
105c051000bSPetar Jovanovic
storeRegToStack(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,Register SrcReg,bool isKill,int FI,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,int64_t Offset) const10666b7069cSEric Christopher void Mips16InstrInfo::storeRegToStack(MachineBasicBlock &MBB,
10766b7069cSEric Christopher MachineBasicBlock::iterator I,
1085c8ba508SSimon Moll Register SrcReg, bool isKill, int FI,
10966b7069cSEric Christopher const TargetRegisterClass *RC,
11066b7069cSEric Christopher const TargetRegisterInfo *TRI,
111465faccaSAkira Hatanaka int64_t Offset) const {
112210ebe93SReed Kotler DebugLoc DL;
113210ebe93SReed Kotler if (I != MBB.end()) DL = I->getDebugLoc();
114210ebe93SReed Kotler MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOStore);
115210ebe93SReed Kotler unsigned Opc = 0;
116210ebe93SReed Kotler if (Mips::CPU16RegsRegClass.hasSubClassEq(RC))
117210ebe93SReed Kotler Opc = Mips::SwRxSpImmX16;
118210ebe93SReed Kotler assert(Opc && "Register class not handled!");
11930cedf65SReed Kotler BuildMI(MBB, I, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill)).
12030cedf65SReed Kotler addFrameIndex(FI).addImm(Offset)
12130cedf65SReed Kotler .addMemOperand(MMO);
122b7fa3c9dSAkira Hatanaka }
123b7fa3c9dSAkira Hatanaka
loadRegFromStack(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,Register DestReg,int FI,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,int64_t Offset) const12466b7069cSEric Christopher void Mips16InstrInfo::loadRegFromStack(MachineBasicBlock &MBB,
12566b7069cSEric Christopher MachineBasicBlock::iterator I,
1265c8ba508SSimon Moll Register DestReg, int FI,
12766b7069cSEric Christopher const TargetRegisterClass *RC,
12866b7069cSEric Christopher const TargetRegisterInfo *TRI,
12966b7069cSEric Christopher int64_t Offset) const {
130210ebe93SReed Kotler DebugLoc DL;
131210ebe93SReed Kotler if (I != MBB.end()) DL = I->getDebugLoc();
132210ebe93SReed Kotler MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOLoad);
133210ebe93SReed Kotler unsigned Opc = 0;
134210ebe93SReed Kotler
135210ebe93SReed Kotler if (Mips::CPU16RegsRegClass.hasSubClassEq(RC))
136210ebe93SReed Kotler Opc = Mips::LwRxSpImmX16;
137210ebe93SReed Kotler assert(Opc && "Register class not handled!");
138465faccaSAkira Hatanaka BuildMI(MBB, I, DL, get(Opc), DestReg).addFrameIndex(FI).addImm(Offset)
139210ebe93SReed Kotler .addMemOperand(MMO);
140b7fa3c9dSAkira Hatanaka }
141b7fa3c9dSAkira Hatanaka
expandPostRAPseudo(MachineInstr & MI) const1429cfc75c2SDuncan P. N. Exon Smith bool Mips16InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
1439cfc75c2SDuncan P. N. Exon Smith MachineBasicBlock &MBB = *MI.getParent();
1449cfc75c2SDuncan P. N. Exon Smith switch (MI.getDesc().getOpcode()) {
145b7fa3c9dSAkira Hatanaka default:
146b7fa3c9dSAkira Hatanaka return false;
147b7fa3c9dSAkira Hatanaka case Mips::RetRA16:
148a8117537SReed Kotler ExpandRetRA16(MBB, MI, Mips::JrcRa16);
149b7fa3c9dSAkira Hatanaka break;
150b7fa3c9dSAkira Hatanaka }
151b7fa3c9dSAkira Hatanaka
1529cfc75c2SDuncan P. N. Exon Smith MBB.erase(MI.getIterator());
153b7fa3c9dSAkira Hatanaka return true;
154b7fa3c9dSAkira Hatanaka }
155b7fa3c9dSAkira Hatanaka
156b7fa3c9dSAkira Hatanaka /// GetOppositeBranchOpc - Return the inverse of the specified
157b7fa3c9dSAkira Hatanaka /// opcode, e.g. turning BEQ to BNE.
getOppositeBranchOpc(unsigned Opc) const158067d8152SAkira Hatanaka unsigned Mips16InstrInfo::getOppositeBranchOpc(unsigned Opc) const {
1596743924aSReed Kotler switch (Opc) {
1606743924aSReed Kotler case Mips::BeqzRxImmX16: return Mips::BnezRxImmX16;
1616743924aSReed Kotler case Mips::BnezRxImmX16: return Mips::BeqzRxImmX16;
16209e59155SReed Kotler case Mips::BeqzRxImm16: return Mips::BnezRxImm16;
16309e59155SReed Kotler case Mips::BnezRxImm16: return Mips::BeqzRxImm16;
1646743924aSReed Kotler case Mips::BteqzT8CmpX16: return Mips::BtnezT8CmpX16;
1656743924aSReed Kotler case Mips::BteqzT8SltX16: return Mips::BtnezT8SltX16;
1666743924aSReed Kotler case Mips::BteqzT8SltiX16: return Mips::BtnezT8SltiX16;
16709e59155SReed Kotler case Mips::Btnez16: return Mips::Bteqz16;
1686743924aSReed Kotler case Mips::BtnezX16: return Mips::BteqzX16;
1696743924aSReed Kotler case Mips::BtnezT8CmpiX16: return Mips::BteqzT8CmpiX16;
1706743924aSReed Kotler case Mips::BtnezT8SltuX16: return Mips::BteqzT8SltuX16;
1716743924aSReed Kotler case Mips::BtnezT8SltiuX16: return Mips::BteqzT8SltiuX16;
17209e59155SReed Kotler case Mips::Bteqz16: return Mips::Btnez16;
1736743924aSReed Kotler case Mips::BteqzX16: return Mips::BtnezX16;
1746743924aSReed Kotler case Mips::BteqzT8CmpiX16: return Mips::BtnezT8CmpiX16;
1756743924aSReed Kotler case Mips::BteqzT8SltuX16: return Mips::BtnezT8SltuX16;
1766743924aSReed Kotler case Mips::BteqzT8SltiuX16: return Mips::BtnezT8SltiuX16;
1776743924aSReed Kotler case Mips::BtnezT8CmpX16: return Mips::BteqzT8CmpX16;
1786743924aSReed Kotler case Mips::BtnezT8SltX16: return Mips::BteqzT8SltX16;
1796743924aSReed Kotler case Mips::BtnezT8SltiX16: return Mips::BteqzT8SltiX16;
1806743924aSReed Kotler }
181d3c02f17SCraig Topper llvm_unreachable("Illegal opcode!");
182b7fa3c9dSAkira Hatanaka }
183b7fa3c9dSAkira Hatanaka
addSaveRestoreRegs(MachineInstrBuilder & MIB,ArrayRef<CalleeSavedInfo> CSI,unsigned Flags=0)1845c29d63aSReed Kotler static void addSaveRestoreRegs(MachineInstrBuilder &MIB,
185e4230a9fSBenjamin Kramer ArrayRef<CalleeSavedInfo> CSI,
18666b7069cSEric Christopher unsigned Flags = 0) {
1875c29d63aSReed Kotler for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
1885c29d63aSReed Kotler // Add the callee-saved register as live-in. Do not add if the register is
1895c29d63aSReed Kotler // RA and return address is taken, because it has already been added in
19094ed30a4SDaniel Sanders // method MipsTargetLowering::lowerRETURNADDR.
1915c29d63aSReed Kotler // It's killed at the spill, unless the register is RA and return address
1925c29d63aSReed Kotler // is taken.
193*d6b07348SJim Lin Register Reg = CSI[e-i-1].getReg();
1945c29d63aSReed Kotler switch (Reg) {
1955c29d63aSReed Kotler case Mips::RA:
1965c29d63aSReed Kotler case Mips::S0:
1975c29d63aSReed Kotler case Mips::S1:
1985c29d63aSReed Kotler MIB.addReg(Reg, Flags);
1995c29d63aSReed Kotler break;
2005c29d63aSReed Kotler case Mips::S2:
2015c29d63aSReed Kotler break;
2025c29d63aSReed Kotler default:
2035c29d63aSReed Kotler llvm_unreachable("unexpected mips16 callee saved register");
2045c29d63aSReed Kotler
2055c29d63aSReed Kotler }
2065c29d63aSReed Kotler }
2075c29d63aSReed Kotler }
20879220eaeSEugene Zelenko
209d019dbf7SReed Kotler // Adjust SP by FrameSize bytes. Save RA, S0, S1
makeFrame(unsigned SP,int64_t FrameSize,MachineBasicBlock & MBB,MachineBasicBlock::iterator I) const2107ab15fafSJack Carter void Mips16InstrInfo::makeFrame(unsigned SP, int64_t FrameSize,
2117ab15fafSJack Carter MachineBasicBlock &MBB,
212d019dbf7SReed Kotler MachineBasicBlock::iterator I) const {
213057c5a6bSOleg Ranevskyy DebugLoc DL;
2145c29d63aSReed Kotler MachineFunction &MF = *MBB.getParent();
215941a705bSMatthias Braun MachineFrameInfo &MFI = MF.getFrameInfo();
2165c29d63aSReed Kotler const BitVector Reserved = RI.getReservedRegs(MF);
2170ff40017SReed Kotler bool SaveS2 = Reserved[Mips::S2];
2180ff40017SReed Kotler MachineInstrBuilder MIB;
2195bde5c35SReed Kotler unsigned Opc = ((FrameSize <= 128) && !SaveS2)? Mips::Save16:Mips::SaveX16;
2205c29d63aSReed Kotler MIB = BuildMI(MBB, I, DL, get(Opc));
221941a705bSMatthias Braun const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
2225c29d63aSReed Kotler addSaveRestoreRegs(MIB, CSI);
2235c29d63aSReed Kotler if (SaveS2)
2245c29d63aSReed Kotler MIB.addReg(Mips::S2);
225d019dbf7SReed Kotler if (isUInt<11>(FrameSize))
2265c29d63aSReed Kotler MIB.addImm(FrameSize);
227d019dbf7SReed Kotler else {
2287ab15fafSJack Carter int Base = 2040; // should create template function like isUInt that
2297ab15fafSJack Carter // returns largest possible n bit unsigned integer
230d019dbf7SReed Kotler int64_t Remainder = FrameSize - Base;
2315c29d63aSReed Kotler MIB.addImm(Base);
232d019dbf7SReed Kotler if (isInt<16>(-Remainder))
233188dad0eSReed Kotler BuildAddiuSpImm(MBB, I, -Remainder);
234d019dbf7SReed Kotler else
235d019dbf7SReed Kotler adjustStackPtrBig(SP, -Remainder, MBB, I, Mips::V0, Mips::V1);
236d019dbf7SReed Kotler }
237d019dbf7SReed Kotler }
238d019dbf7SReed Kotler
239d019dbf7SReed Kotler // Adjust SP by FrameSize bytes. Restore RA, S0, S1
restoreFrame(unsigned SP,int64_t FrameSize,MachineBasicBlock & MBB,MachineBasicBlock::iterator I) const2407ab15fafSJack Carter void Mips16InstrInfo::restoreFrame(unsigned SP, int64_t FrameSize,
2417ab15fafSJack Carter MachineBasicBlock &MBB,
242d019dbf7SReed Kotler MachineBasicBlock::iterator I) const {
243d019dbf7SReed Kotler DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
2445c29d63aSReed Kotler MachineFunction *MF = MBB.getParent();
245941a705bSMatthias Braun MachineFrameInfo &MFI = MF->getFrameInfo();
2465c29d63aSReed Kotler const BitVector Reserved = RI.getReservedRegs(*MF);
2470ff40017SReed Kotler bool SaveS2 = Reserved[Mips::S2];
2480ff40017SReed Kotler MachineInstrBuilder MIB;
2495bde5c35SReed Kotler unsigned Opc = ((FrameSize <= 128) && !SaveS2)?
2505bde5c35SReed Kotler Mips::Restore16:Mips::RestoreX16;
2515c29d63aSReed Kotler
2525c29d63aSReed Kotler if (!isUInt<11>(FrameSize)) {
2535c29d63aSReed Kotler unsigned Base = 2040;
254d019dbf7SReed Kotler int64_t Remainder = FrameSize - Base;
2555c29d63aSReed Kotler FrameSize = Base; // should create template function like isUInt that
2565c29d63aSReed Kotler // returns largest possible n bit unsigned integer
2575c29d63aSReed Kotler
258d019dbf7SReed Kotler if (isInt<16>(Remainder))
259188dad0eSReed Kotler BuildAddiuSpImm(MBB, I, Remainder);
260d019dbf7SReed Kotler else
261d019dbf7SReed Kotler adjustStackPtrBig(SP, Remainder, MBB, I, Mips::A0, Mips::A1);
262d019dbf7SReed Kotler }
2635c29d63aSReed Kotler MIB = BuildMI(MBB, I, DL, get(Opc));
264941a705bSMatthias Braun const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
2655c29d63aSReed Kotler addSaveRestoreRegs(MIB, CSI, RegState::Define);
2660ff40017SReed Kotler if (SaveS2)
2670ff40017SReed Kotler MIB.addReg(Mips::S2, RegState::Define);
2685c29d63aSReed Kotler MIB.addImm(FrameSize);
269d019dbf7SReed Kotler }
270d019dbf7SReed Kotler
271d019dbf7SReed Kotler // Adjust SP by Amount bytes where bytes can be up to 32bit number.
2727ab15fafSJack Carter // This can only be called at times that we know that there is at least one free
2737ab15fafSJack Carter // register.
274d019dbf7SReed Kotler // This is clearly safe at prologue and epilogue.
adjustStackPtrBig(unsigned SP,int64_t Amount,MachineBasicBlock & MBB,MachineBasicBlock::iterator I,unsigned Reg1,unsigned Reg2) const2757ab15fafSJack Carter void Mips16InstrInfo::adjustStackPtrBig(unsigned SP, int64_t Amount,
2767ab15fafSJack Carter MachineBasicBlock &MBB,
277d019dbf7SReed Kotler MachineBasicBlock::iterator I,
278d019dbf7SReed Kotler unsigned Reg1, unsigned Reg2) const {
279057c5a6bSOleg Ranevskyy DebugLoc DL;
280d019dbf7SReed Kotler //
281d019dbf7SReed Kotler // li reg1, constant
282d019dbf7SReed Kotler // move reg2, sp
283d019dbf7SReed Kotler // add reg1, reg1, reg2
284d019dbf7SReed Kotler // move sp, reg1
285d019dbf7SReed Kotler //
286d019dbf7SReed Kotler //
287d019dbf7SReed Kotler MachineInstrBuilder MIB1 = BuildMI(MBB, I, DL, get(Mips::LwConstant32), Reg1);
288a787aa2bSReed Kotler MIB1.addImm(Amount).addImm(-1);
289d019dbf7SReed Kotler MachineInstrBuilder MIB2 = BuildMI(MBB, I, DL, get(Mips::MoveR3216), Reg2);
290d019dbf7SReed Kotler MIB2.addReg(Mips::SP, RegState::Kill);
291d019dbf7SReed Kotler MachineInstrBuilder MIB3 = BuildMI(MBB, I, DL, get(Mips::AdduRxRyRz16), Reg1);
292d019dbf7SReed Kotler MIB3.addReg(Reg1);
293d019dbf7SReed Kotler MIB3.addReg(Reg2, RegState::Kill);
2947ab15fafSJack Carter MachineInstrBuilder MIB4 = BuildMI(MBB, I, DL, get(Mips::Move32R16),
2957ab15fafSJack Carter Mips::SP);
296d019dbf7SReed Kotler MIB4.addReg(Reg1, RegState::Kill);
297d019dbf7SReed Kotler }
298d019dbf7SReed Kotler
adjustStackPtrBigUnrestricted(unsigned SP,int64_t Amount,MachineBasicBlock & MBB,MachineBasicBlock::iterator I) const29966b7069cSEric Christopher void Mips16InstrInfo::adjustStackPtrBigUnrestricted(
30066b7069cSEric Christopher unsigned SP, int64_t Amount, MachineBasicBlock &MBB,
301d019dbf7SReed Kotler MachineBasicBlock::iterator I) const {
302d3c02f17SCraig Topper llvm_unreachable("adjust stack pointer amount exceeded");
303d019dbf7SReed Kotler }
304d019dbf7SReed Kotler
30527a7229cSReed Kotler /// Adjust SP by Amount bytes.
adjustStackPtr(unsigned SP,int64_t Amount,MachineBasicBlock & MBB,MachineBasicBlock::iterator I) const30627a7229cSReed Kotler void Mips16InstrInfo::adjustStackPtr(unsigned SP, int64_t Amount,
30727a7229cSReed Kotler MachineBasicBlock &MBB,
30827a7229cSReed Kotler MachineBasicBlock::iterator I) const {
309b3698a53SVasileios Kalintiris if (Amount == 0)
310b3698a53SVasileios Kalintiris return;
311b3698a53SVasileios Kalintiris
312d019dbf7SReed Kotler if (isInt<16>(Amount)) // need to change to addiu sp, ....and isInt<16>
313188dad0eSReed Kotler BuildAddiuSpImm(MBB, I, Amount);
31427a7229cSReed Kotler else
315d019dbf7SReed Kotler adjustStackPtrBigUnrestricted(SP, Amount, MBB, I);
316d019dbf7SReed Kotler }
317d019dbf7SReed Kotler
318d019dbf7SReed Kotler /// This function generates the sequence of instructions needed to get the
319d019dbf7SReed Kotler /// result of adding register REG and immediate IMM.
loadImmediate(unsigned FrameReg,int64_t Imm,MachineBasicBlock & MBB,MachineBasicBlock::iterator II,const DebugLoc & DL,unsigned & NewImm) const32066b7069cSEric Christopher unsigned Mips16InstrInfo::loadImmediate(unsigned FrameReg, int64_t Imm,
32166b7069cSEric Christopher MachineBasicBlock &MBB,
32266b7069cSEric Christopher MachineBasicBlock::iterator II,
323bdc4956bSBenjamin Kramer const DebugLoc &DL,
324bdc4956bSBenjamin Kramer unsigned &NewImm) const {
32566165c8fSReed Kotler //
32666165c8fSReed Kotler // given original instruction is:
32766165c8fSReed Kotler // Instr rx, T[offset] where offset is too big.
32866165c8fSReed Kotler //
32966165c8fSReed Kotler // lo = offset & 0xFFFF
33066165c8fSReed Kotler // hi = ((offset >> 16) + (lo >> 15)) & 0xFFFF;
33166165c8fSReed Kotler //
33266165c8fSReed Kotler // let T = temporary register
33366165c8fSReed Kotler // li T, hi
33466165c8fSReed Kotler // shl T, 16
33566165c8fSReed Kotler // add T, Rx, T
33666165c8fSReed Kotler //
33766165c8fSReed Kotler RegScavenger rs;
33866165c8fSReed Kotler int32_t lo = Imm & 0xFFFF;
33966165c8fSReed Kotler NewImm = lo;
34030cedf65SReed Kotler int Reg =0;
34130cedf65SReed Kotler int SpReg = 0;
34230cedf65SReed Kotler
3437dc03f06SMatthias Braun rs.enterBasicBlock(MBB);
34466165c8fSReed Kotler rs.forward(II);
34566165c8fSReed Kotler //
34630cedf65SReed Kotler // We need to know which registers can be used, in the case where there
34730cedf65SReed Kotler // are not enough free registers. We exclude all registers that
34830cedf65SReed Kotler // are used in the instruction that we are helping.
34930cedf65SReed Kotler // // Consider all allocatable registers in the register class initially
35030cedf65SReed Kotler BitVector Candidates =
35130cedf65SReed Kotler RI.getAllocatableSet
35230cedf65SReed Kotler (*II->getParent()->getParent(), &Mips::CPU16RegsRegClass);
35330cedf65SReed Kotler // Exclude all the registers being used by the instruction.
35430cedf65SReed Kotler for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) {
35530cedf65SReed Kotler MachineOperand &MO = II->getOperand(i);
35630cedf65SReed Kotler if (MO.isReg() && MO.getReg() != 0 && !MO.isDef() &&
3572bea69bfSDaniel Sanders !Register::isVirtualRegister(MO.getReg()))
35830cedf65SReed Kotler Candidates.reset(MO.getReg());
35930cedf65SReed Kotler }
36066b7069cSEric Christopher
36130cedf65SReed Kotler // If the same register was used and defined in an instruction, then
36230cedf65SReed Kotler // it will not be in the list of candidates.
36330cedf65SReed Kotler //
36430cedf65SReed Kotler // we need to analyze the instruction that we are helping.
36530cedf65SReed Kotler // we need to know if it defines register x but register x is not
36630cedf65SReed Kotler // present as an operand of the instruction. this tells
36730cedf65SReed Kotler // whether the register is live before the instruction. if it's not
36830cedf65SReed Kotler // then we don't need to save it in case there are no free registers.
36930cedf65SReed Kotler int DefReg = 0;
37030cedf65SReed Kotler for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) {
37130cedf65SReed Kotler MachineOperand &MO = II->getOperand(i);
37230cedf65SReed Kotler if (MO.isReg() && MO.isDef()) {
37330cedf65SReed Kotler DefReg = MO.getReg();
37430cedf65SReed Kotler break;
37530cedf65SReed Kotler }
37630cedf65SReed Kotler }
37730cedf65SReed Kotler
37866b7069cSEric Christopher BitVector Available = rs.getRegsAvailable(&Mips::CPU16RegsRegClass);
37930cedf65SReed Kotler Available &= Candidates;
38030cedf65SReed Kotler //
38166165c8fSReed Kotler // we use T0 for the first register, if we need to save something away.
38266165c8fSReed Kotler // we use T1 for the second register, if we need to save something away.
38366165c8fSReed Kotler //
38466165c8fSReed Kotler unsigned FirstRegSaved =0, SecondRegSaved=0;
38566165c8fSReed Kotler unsigned FirstRegSavedTo = 0, SecondRegSavedTo = 0;
386d019dbf7SReed Kotler
38730cedf65SReed Kotler Reg = Available.find_first();
38830cedf65SReed Kotler
38930cedf65SReed Kotler if (Reg == -1) {
39030cedf65SReed Kotler Reg = Candidates.find_first();
39130cedf65SReed Kotler Candidates.reset(Reg);
39230cedf65SReed Kotler if (DefReg != Reg) {
39330cedf65SReed Kotler FirstRegSaved = Reg;
39466165c8fSReed Kotler FirstRegSavedTo = Mips::T0;
39566165c8fSReed Kotler copyPhysReg(MBB, II, DL, FirstRegSavedTo, FirstRegSaved, true);
39666165c8fSReed Kotler }
39730cedf65SReed Kotler }
39866165c8fSReed Kotler else
39930cedf65SReed Kotler Available.reset(Reg);
400a787aa2bSReed Kotler BuildMI(MBB, II, DL, get(Mips::LwConstant32), Reg).addImm(Imm).addImm(-1);
40130cedf65SReed Kotler NewImm = 0;
40266165c8fSReed Kotler if (FrameReg == Mips::SP) {
40330cedf65SReed Kotler SpReg = Available.find_first();
40430cedf65SReed Kotler if (SpReg == -1) {
40530cedf65SReed Kotler SpReg = Candidates.find_first();
40630cedf65SReed Kotler // Candidates.reset(SpReg); // not really needed
40730cedf65SReed Kotler if (DefReg!= SpReg) {
40830cedf65SReed Kotler SecondRegSaved = SpReg;
40966165c8fSReed Kotler SecondRegSavedTo = Mips::T1;
41066165c8fSReed Kotler }
41130cedf65SReed Kotler if (SecondRegSaved)
41266165c8fSReed Kotler copyPhysReg(MBB, II, DL, SecondRegSavedTo, SecondRegSaved, true);
41366165c8fSReed Kotler }
41466165c8fSReed Kotler else
41530cedf65SReed Kotler Available.reset(SpReg);
41666165c8fSReed Kotler copyPhysReg(MBB, II, DL, SpReg, Mips::SP, false);
4170bd82a96SSimon Atanasyan BuildMI(MBB, II, DL, get(Mips::AdduRxRyRz16), Reg)
4180bd82a96SSimon Atanasyan .addReg(SpReg, RegState::Kill)
41966165c8fSReed Kotler .addReg(Reg);
42066165c8fSReed Kotler }
42166165c8fSReed Kotler else
42266165c8fSReed Kotler BuildMI(MBB, II, DL, get(Mips:: AdduRxRyRz16), Reg).addReg(FrameReg)
42366165c8fSReed Kotler .addReg(Reg, RegState::Kill);
42466165c8fSReed Kotler if (FirstRegSaved || SecondRegSaved) {
425b6d0bd48SBenjamin Kramer II = std::next(II);
42666165c8fSReed Kotler if (FirstRegSaved)
42766165c8fSReed Kotler copyPhysReg(MBB, II, DL, FirstRegSaved, FirstRegSavedTo, true);
42866165c8fSReed Kotler if (SecondRegSaved)
42966165c8fSReed Kotler copyPhysReg(MBB, II, DL, SecondRegSaved, SecondRegSavedTo, true);
43066165c8fSReed Kotler }
43166165c8fSReed Kotler return Reg;
43227a7229cSReed Kotler }
43327a7229cSReed Kotler
getAnalyzableBrOpc(unsigned Opc) const434067d8152SAkira Hatanaka unsigned Mips16InstrInfo::getAnalyzableBrOpc(unsigned Opc) const {
4356743924aSReed Kotler return (Opc == Mips::BeqzRxImmX16 || Opc == Mips::BimmX16 ||
436f0e6968eSReed Kotler Opc == Mips::Bimm16 ||
43709e59155SReed Kotler Opc == Mips::Bteqz16 || Opc == Mips::Btnez16 ||
43809e59155SReed Kotler Opc == Mips::BeqzRxImm16 || Opc == Mips::BnezRxImm16 ||
4396743924aSReed Kotler Opc == Mips::BnezRxImmX16 || Opc == Mips::BteqzX16 ||
4406743924aSReed Kotler Opc == Mips::BteqzT8CmpX16 || Opc == Mips::BteqzT8CmpiX16 ||
4416743924aSReed Kotler Opc == Mips::BteqzT8SltX16 || Opc == Mips::BteqzT8SltuX16 ||
4426743924aSReed Kotler Opc == Mips::BteqzT8SltiX16 || Opc == Mips::BteqzT8SltiuX16 ||
4436743924aSReed Kotler Opc == Mips::BtnezX16 || Opc == Mips::BtnezT8CmpX16 ||
4446743924aSReed Kotler Opc == Mips::BtnezT8CmpiX16 || Opc == Mips::BtnezT8SltX16 ||
4456743924aSReed Kotler Opc == Mips::BtnezT8SltuX16 || Opc == Mips::BtnezT8SltiX16 ||
4466743924aSReed Kotler Opc == Mips::BtnezT8SltiuX16 ) ? Opc : 0;
447b7fa3c9dSAkira Hatanaka }
448b7fa3c9dSAkira Hatanaka
ExpandRetRA16(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,unsigned Opc) const449b7fa3c9dSAkira Hatanaka void Mips16InstrInfo::ExpandRetRA16(MachineBasicBlock &MBB,
450b7fa3c9dSAkira Hatanaka MachineBasicBlock::iterator I,
451b7fa3c9dSAkira Hatanaka unsigned Opc) const {
452b7fa3c9dSAkira Hatanaka BuildMI(MBB, I, I->getDebugLoc(), get(Opc));
453b7fa3c9dSAkira Hatanaka }
454fab89294SAkira Hatanaka
AddiuSpImm(int64_t Imm) const4558cf5103bSReed Kotler const MCInstrDesc &Mips16InstrInfo::AddiuSpImm(int64_t Imm) const {
456f662cff6SReed Kotler if (validSpImm8(Imm))
4578cf5103bSReed Kotler return get(Mips::AddiuSpImm16);
458f662cff6SReed Kotler else
4598cf5103bSReed Kotler return get(Mips::AddiuSpImmX16);
460f662cff6SReed Kotler }
461f662cff6SReed Kotler
BuildAddiuSpImm(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,int64_t Imm) const462188dad0eSReed Kotler void Mips16InstrInfo::BuildAddiuSpImm
463188dad0eSReed Kotler (MachineBasicBlock &MBB, MachineBasicBlock::iterator I, int64_t Imm) const {
464057c5a6bSOleg Ranevskyy DebugLoc DL;
465188dad0eSReed Kotler BuildMI(MBB, I, DL, AddiuSpImm(Imm)).addImm(Imm);
466188dad0eSReed Kotler }
467188dad0eSReed Kotler
createMips16InstrInfo(const MipsSubtarget & STI)468675cb4daSEric Christopher const MipsInstrInfo *llvm::createMips16InstrInfo(const MipsSubtarget &STI) {
469675cb4daSEric Christopher return new Mips16InstrInfo(STI);
470fab89294SAkira Hatanaka }
47130cedf65SReed Kotler
validImmediate(unsigned Opcode,unsigned Reg,int64_t Amount)47230cedf65SReed Kotler bool Mips16InstrInfo::validImmediate(unsigned Opcode, unsigned Reg,
47330cedf65SReed Kotler int64_t Amount) {
47430cedf65SReed Kotler switch (Opcode) {
47530cedf65SReed Kotler case Mips::LbRxRyOffMemX16:
47630cedf65SReed Kotler case Mips::LbuRxRyOffMemX16:
47730cedf65SReed Kotler case Mips::LhRxRyOffMemX16:
47830cedf65SReed Kotler case Mips::LhuRxRyOffMemX16:
47930cedf65SReed Kotler case Mips::SbRxRyOffMemX16:
48030cedf65SReed Kotler case Mips::ShRxRyOffMemX16:
48130cedf65SReed Kotler case Mips::LwRxRyOffMemX16:
48230cedf65SReed Kotler case Mips::SwRxRyOffMemX16:
48330cedf65SReed Kotler case Mips::SwRxSpImmX16:
48430cedf65SReed Kotler case Mips::LwRxSpImmX16:
48530cedf65SReed Kotler return isInt<16>(Amount);
48630cedf65SReed Kotler case Mips::AddiuRxRyOffMemX16:
48730cedf65SReed Kotler if ((Reg == Mips::PC) || (Reg == Mips::SP))
48830cedf65SReed Kotler return isInt<16>(Amount);
48930cedf65SReed Kotler return isInt<15>(Amount);
49030cedf65SReed Kotler }
49130cedf65SReed Kotler llvm_unreachable("unexpected Opcode in validImmediate");
49230cedf65SReed Kotler }
493