1*9880d681SAndroid Build Coastguard Worker //===-- MipsISelLowering.cpp - Mips DAG Lowering Implementation -----------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file defines the interfaces that Mips uses to lower LLVM code into a
11*9880d681SAndroid Build Coastguard Worker // selection DAG.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker #include "MipsISelLowering.h"
15*9880d681SAndroid Build Coastguard Worker #include "InstPrinter/MipsInstPrinter.h"
16*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/MipsBaseInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "MipsCCState.h"
18*9880d681SAndroid Build Coastguard Worker #include "MipsMachineFunction.h"
19*9880d681SAndroid Build Coastguard Worker #include "MipsSubtarget.h"
20*9880d681SAndroid Build Coastguard Worker #include "MipsTargetMachine.h"
21*9880d681SAndroid Build Coastguard Worker #include "MipsTargetObjectFile.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringSwitch.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/CallingConvLower.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunction.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineJumpTableInfo.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/FunctionLoweringInfo.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/SelectionDAGISel.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/ValueTypes.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/CallingConv.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DerivedTypes.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/GlobalVariable.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
38*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
39*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
40*9880d681SAndroid Build Coastguard Worker #include <cctype>
41*9880d681SAndroid Build Coastguard Worker
42*9880d681SAndroid Build Coastguard Worker using namespace llvm;
43*9880d681SAndroid Build Coastguard Worker
44*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "mips-lower"
45*9880d681SAndroid Build Coastguard Worker
46*9880d681SAndroid Build Coastguard Worker STATISTIC(NumTailCalls, "Number of tail calls");
47*9880d681SAndroid Build Coastguard Worker
48*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
49*9880d681SAndroid Build Coastguard Worker LargeGOT("mxgot", cl::Hidden,
50*9880d681SAndroid Build Coastguard Worker cl::desc("MIPS: Enable GOT larger than 64k."), cl::init(false));
51*9880d681SAndroid Build Coastguard Worker
52*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
53*9880d681SAndroid Build Coastguard Worker NoZeroDivCheck("mno-check-zero-division", cl::Hidden,
54*9880d681SAndroid Build Coastguard Worker cl::desc("MIPS: Don't trap on integer division by zero."),
55*9880d681SAndroid Build Coastguard Worker cl::init(false));
56*9880d681SAndroid Build Coastguard Worker
57*9880d681SAndroid Build Coastguard Worker static const MCPhysReg Mips64DPRegs[8] = {
58*9880d681SAndroid Build Coastguard Worker Mips::D12_64, Mips::D13_64, Mips::D14_64, Mips::D15_64,
59*9880d681SAndroid Build Coastguard Worker Mips::D16_64, Mips::D17_64, Mips::D18_64, Mips::D19_64
60*9880d681SAndroid Build Coastguard Worker };
61*9880d681SAndroid Build Coastguard Worker
62*9880d681SAndroid Build Coastguard Worker // If I is a shifted mask, set the size (Size) and the first bit of the
63*9880d681SAndroid Build Coastguard Worker // mask (Pos), and return true.
64*9880d681SAndroid Build Coastguard Worker // For example, if I is 0x003ff800, (Pos, Size) = (11, 11).
isShiftedMask(uint64_t I,uint64_t & Pos,uint64_t & Size)65*9880d681SAndroid Build Coastguard Worker static bool isShiftedMask(uint64_t I, uint64_t &Pos, uint64_t &Size) {
66*9880d681SAndroid Build Coastguard Worker if (!isShiftedMask_64(I))
67*9880d681SAndroid Build Coastguard Worker return false;
68*9880d681SAndroid Build Coastguard Worker
69*9880d681SAndroid Build Coastguard Worker Size = countPopulation(I);
70*9880d681SAndroid Build Coastguard Worker Pos = countTrailingZeros(I);
71*9880d681SAndroid Build Coastguard Worker return true;
72*9880d681SAndroid Build Coastguard Worker }
73*9880d681SAndroid Build Coastguard Worker
getGlobalReg(SelectionDAG & DAG,EVT Ty) const74*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::getGlobalReg(SelectionDAG &DAG, EVT Ty) const {
75*9880d681SAndroid Build Coastguard Worker MipsFunctionInfo *FI = DAG.getMachineFunction().getInfo<MipsFunctionInfo>();
76*9880d681SAndroid Build Coastguard Worker return DAG.getRegister(FI->getGlobalBaseReg(), Ty);
77*9880d681SAndroid Build Coastguard Worker }
78*9880d681SAndroid Build Coastguard Worker
getTargetNode(GlobalAddressSDNode * N,EVT Ty,SelectionDAG & DAG,unsigned Flag) const79*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::getTargetNode(GlobalAddressSDNode *N, EVT Ty,
80*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG,
81*9880d681SAndroid Build Coastguard Worker unsigned Flag) const {
82*9880d681SAndroid Build Coastguard Worker return DAG.getTargetGlobalAddress(N->getGlobal(), SDLoc(N), Ty, 0, Flag);
83*9880d681SAndroid Build Coastguard Worker }
84*9880d681SAndroid Build Coastguard Worker
getTargetNode(ExternalSymbolSDNode * N,EVT Ty,SelectionDAG & DAG,unsigned Flag) const85*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::getTargetNode(ExternalSymbolSDNode *N, EVT Ty,
86*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG,
87*9880d681SAndroid Build Coastguard Worker unsigned Flag) const {
88*9880d681SAndroid Build Coastguard Worker return DAG.getTargetExternalSymbol(N->getSymbol(), Ty, Flag);
89*9880d681SAndroid Build Coastguard Worker }
90*9880d681SAndroid Build Coastguard Worker
getTargetNode(BlockAddressSDNode * N,EVT Ty,SelectionDAG & DAG,unsigned Flag) const91*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::getTargetNode(BlockAddressSDNode *N, EVT Ty,
92*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG,
93*9880d681SAndroid Build Coastguard Worker unsigned Flag) const {
94*9880d681SAndroid Build Coastguard Worker return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, 0, Flag);
95*9880d681SAndroid Build Coastguard Worker }
96*9880d681SAndroid Build Coastguard Worker
getTargetNode(JumpTableSDNode * N,EVT Ty,SelectionDAG & DAG,unsigned Flag) const97*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::getTargetNode(JumpTableSDNode *N, EVT Ty,
98*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG,
99*9880d681SAndroid Build Coastguard Worker unsigned Flag) const {
100*9880d681SAndroid Build Coastguard Worker return DAG.getTargetJumpTable(N->getIndex(), Ty, Flag);
101*9880d681SAndroid Build Coastguard Worker }
102*9880d681SAndroid Build Coastguard Worker
getTargetNode(ConstantPoolSDNode * N,EVT Ty,SelectionDAG & DAG,unsigned Flag) const103*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::getTargetNode(ConstantPoolSDNode *N, EVT Ty,
104*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG,
105*9880d681SAndroid Build Coastguard Worker unsigned Flag) const {
106*9880d681SAndroid Build Coastguard Worker return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlignment(),
107*9880d681SAndroid Build Coastguard Worker N->getOffset(), Flag);
108*9880d681SAndroid Build Coastguard Worker }
109*9880d681SAndroid Build Coastguard Worker
getTargetNodeName(unsigned Opcode) const110*9880d681SAndroid Build Coastguard Worker const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
111*9880d681SAndroid Build Coastguard Worker switch ((MipsISD::NodeType)Opcode) {
112*9880d681SAndroid Build Coastguard Worker case MipsISD::FIRST_NUMBER: break;
113*9880d681SAndroid Build Coastguard Worker case MipsISD::JmpLink: return "MipsISD::JmpLink";
114*9880d681SAndroid Build Coastguard Worker case MipsISD::TailCall: return "MipsISD::TailCall";
115*9880d681SAndroid Build Coastguard Worker case MipsISD::Hi: return "MipsISD::Hi";
116*9880d681SAndroid Build Coastguard Worker case MipsISD::Lo: return "MipsISD::Lo";
117*9880d681SAndroid Build Coastguard Worker case MipsISD::GPRel: return "MipsISD::GPRel";
118*9880d681SAndroid Build Coastguard Worker case MipsISD::ThreadPointer: return "MipsISD::ThreadPointer";
119*9880d681SAndroid Build Coastguard Worker case MipsISD::Ret: return "MipsISD::Ret";
120*9880d681SAndroid Build Coastguard Worker case MipsISD::ERet: return "MipsISD::ERet";
121*9880d681SAndroid Build Coastguard Worker case MipsISD::EH_RETURN: return "MipsISD::EH_RETURN";
122*9880d681SAndroid Build Coastguard Worker case MipsISD::FPBrcond: return "MipsISD::FPBrcond";
123*9880d681SAndroid Build Coastguard Worker case MipsISD::FPCmp: return "MipsISD::FPCmp";
124*9880d681SAndroid Build Coastguard Worker case MipsISD::CMovFP_T: return "MipsISD::CMovFP_T";
125*9880d681SAndroid Build Coastguard Worker case MipsISD::CMovFP_F: return "MipsISD::CMovFP_F";
126*9880d681SAndroid Build Coastguard Worker case MipsISD::TruncIntFP: return "MipsISD::TruncIntFP";
127*9880d681SAndroid Build Coastguard Worker case MipsISD::MFHI: return "MipsISD::MFHI";
128*9880d681SAndroid Build Coastguard Worker case MipsISD::MFLO: return "MipsISD::MFLO";
129*9880d681SAndroid Build Coastguard Worker case MipsISD::MTLOHI: return "MipsISD::MTLOHI";
130*9880d681SAndroid Build Coastguard Worker case MipsISD::Mult: return "MipsISD::Mult";
131*9880d681SAndroid Build Coastguard Worker case MipsISD::Multu: return "MipsISD::Multu";
132*9880d681SAndroid Build Coastguard Worker case MipsISD::MAdd: return "MipsISD::MAdd";
133*9880d681SAndroid Build Coastguard Worker case MipsISD::MAddu: return "MipsISD::MAddu";
134*9880d681SAndroid Build Coastguard Worker case MipsISD::MSub: return "MipsISD::MSub";
135*9880d681SAndroid Build Coastguard Worker case MipsISD::MSubu: return "MipsISD::MSubu";
136*9880d681SAndroid Build Coastguard Worker case MipsISD::DivRem: return "MipsISD::DivRem";
137*9880d681SAndroid Build Coastguard Worker case MipsISD::DivRemU: return "MipsISD::DivRemU";
138*9880d681SAndroid Build Coastguard Worker case MipsISD::DivRem16: return "MipsISD::DivRem16";
139*9880d681SAndroid Build Coastguard Worker case MipsISD::DivRemU16: return "MipsISD::DivRemU16";
140*9880d681SAndroid Build Coastguard Worker case MipsISD::BuildPairF64: return "MipsISD::BuildPairF64";
141*9880d681SAndroid Build Coastguard Worker case MipsISD::ExtractElementF64: return "MipsISD::ExtractElementF64";
142*9880d681SAndroid Build Coastguard Worker case MipsISD::Wrapper: return "MipsISD::Wrapper";
143*9880d681SAndroid Build Coastguard Worker case MipsISD::DynAlloc: return "MipsISD::DynAlloc";
144*9880d681SAndroid Build Coastguard Worker case MipsISD::Sync: return "MipsISD::Sync";
145*9880d681SAndroid Build Coastguard Worker case MipsISD::Ext: return "MipsISD::Ext";
146*9880d681SAndroid Build Coastguard Worker case MipsISD::Ins: return "MipsISD::Ins";
147*9880d681SAndroid Build Coastguard Worker case MipsISD::LWL: return "MipsISD::LWL";
148*9880d681SAndroid Build Coastguard Worker case MipsISD::LWR: return "MipsISD::LWR";
149*9880d681SAndroid Build Coastguard Worker case MipsISD::SWL: return "MipsISD::SWL";
150*9880d681SAndroid Build Coastguard Worker case MipsISD::SWR: return "MipsISD::SWR";
151*9880d681SAndroid Build Coastguard Worker case MipsISD::LDL: return "MipsISD::LDL";
152*9880d681SAndroid Build Coastguard Worker case MipsISD::LDR: return "MipsISD::LDR";
153*9880d681SAndroid Build Coastguard Worker case MipsISD::SDL: return "MipsISD::SDL";
154*9880d681SAndroid Build Coastguard Worker case MipsISD::SDR: return "MipsISD::SDR";
155*9880d681SAndroid Build Coastguard Worker case MipsISD::EXTP: return "MipsISD::EXTP";
156*9880d681SAndroid Build Coastguard Worker case MipsISD::EXTPDP: return "MipsISD::EXTPDP";
157*9880d681SAndroid Build Coastguard Worker case MipsISD::EXTR_S_H: return "MipsISD::EXTR_S_H";
158*9880d681SAndroid Build Coastguard Worker case MipsISD::EXTR_W: return "MipsISD::EXTR_W";
159*9880d681SAndroid Build Coastguard Worker case MipsISD::EXTR_R_W: return "MipsISD::EXTR_R_W";
160*9880d681SAndroid Build Coastguard Worker case MipsISD::EXTR_RS_W: return "MipsISD::EXTR_RS_W";
161*9880d681SAndroid Build Coastguard Worker case MipsISD::SHILO: return "MipsISD::SHILO";
162*9880d681SAndroid Build Coastguard Worker case MipsISD::MTHLIP: return "MipsISD::MTHLIP";
163*9880d681SAndroid Build Coastguard Worker case MipsISD::MULSAQ_S_W_PH: return "MipsISD::MULSAQ_S_W_PH";
164*9880d681SAndroid Build Coastguard Worker case MipsISD::MAQ_S_W_PHL: return "MipsISD::MAQ_S_W_PHL";
165*9880d681SAndroid Build Coastguard Worker case MipsISD::MAQ_S_W_PHR: return "MipsISD::MAQ_S_W_PHR";
166*9880d681SAndroid Build Coastguard Worker case MipsISD::MAQ_SA_W_PHL: return "MipsISD::MAQ_SA_W_PHL";
167*9880d681SAndroid Build Coastguard Worker case MipsISD::MAQ_SA_W_PHR: return "MipsISD::MAQ_SA_W_PHR";
168*9880d681SAndroid Build Coastguard Worker case MipsISD::DPAU_H_QBL: return "MipsISD::DPAU_H_QBL";
169*9880d681SAndroid Build Coastguard Worker case MipsISD::DPAU_H_QBR: return "MipsISD::DPAU_H_QBR";
170*9880d681SAndroid Build Coastguard Worker case MipsISD::DPSU_H_QBL: return "MipsISD::DPSU_H_QBL";
171*9880d681SAndroid Build Coastguard Worker case MipsISD::DPSU_H_QBR: return "MipsISD::DPSU_H_QBR";
172*9880d681SAndroid Build Coastguard Worker case MipsISD::DPAQ_S_W_PH: return "MipsISD::DPAQ_S_W_PH";
173*9880d681SAndroid Build Coastguard Worker case MipsISD::DPSQ_S_W_PH: return "MipsISD::DPSQ_S_W_PH";
174*9880d681SAndroid Build Coastguard Worker case MipsISD::DPAQ_SA_L_W: return "MipsISD::DPAQ_SA_L_W";
175*9880d681SAndroid Build Coastguard Worker case MipsISD::DPSQ_SA_L_W: return "MipsISD::DPSQ_SA_L_W";
176*9880d681SAndroid Build Coastguard Worker case MipsISD::DPA_W_PH: return "MipsISD::DPA_W_PH";
177*9880d681SAndroid Build Coastguard Worker case MipsISD::DPS_W_PH: return "MipsISD::DPS_W_PH";
178*9880d681SAndroid Build Coastguard Worker case MipsISD::DPAQX_S_W_PH: return "MipsISD::DPAQX_S_W_PH";
179*9880d681SAndroid Build Coastguard Worker case MipsISD::DPAQX_SA_W_PH: return "MipsISD::DPAQX_SA_W_PH";
180*9880d681SAndroid Build Coastguard Worker case MipsISD::DPAX_W_PH: return "MipsISD::DPAX_W_PH";
181*9880d681SAndroid Build Coastguard Worker case MipsISD::DPSX_W_PH: return "MipsISD::DPSX_W_PH";
182*9880d681SAndroid Build Coastguard Worker case MipsISD::DPSQX_S_W_PH: return "MipsISD::DPSQX_S_W_PH";
183*9880d681SAndroid Build Coastguard Worker case MipsISD::DPSQX_SA_W_PH: return "MipsISD::DPSQX_SA_W_PH";
184*9880d681SAndroid Build Coastguard Worker case MipsISD::MULSA_W_PH: return "MipsISD::MULSA_W_PH";
185*9880d681SAndroid Build Coastguard Worker case MipsISD::MULT: return "MipsISD::MULT";
186*9880d681SAndroid Build Coastguard Worker case MipsISD::MULTU: return "MipsISD::MULTU";
187*9880d681SAndroid Build Coastguard Worker case MipsISD::MADD_DSP: return "MipsISD::MADD_DSP";
188*9880d681SAndroid Build Coastguard Worker case MipsISD::MADDU_DSP: return "MipsISD::MADDU_DSP";
189*9880d681SAndroid Build Coastguard Worker case MipsISD::MSUB_DSP: return "MipsISD::MSUB_DSP";
190*9880d681SAndroid Build Coastguard Worker case MipsISD::MSUBU_DSP: return "MipsISD::MSUBU_DSP";
191*9880d681SAndroid Build Coastguard Worker case MipsISD::SHLL_DSP: return "MipsISD::SHLL_DSP";
192*9880d681SAndroid Build Coastguard Worker case MipsISD::SHRA_DSP: return "MipsISD::SHRA_DSP";
193*9880d681SAndroid Build Coastguard Worker case MipsISD::SHRL_DSP: return "MipsISD::SHRL_DSP";
194*9880d681SAndroid Build Coastguard Worker case MipsISD::SETCC_DSP: return "MipsISD::SETCC_DSP";
195*9880d681SAndroid Build Coastguard Worker case MipsISD::SELECT_CC_DSP: return "MipsISD::SELECT_CC_DSP";
196*9880d681SAndroid Build Coastguard Worker case MipsISD::VALL_ZERO: return "MipsISD::VALL_ZERO";
197*9880d681SAndroid Build Coastguard Worker case MipsISD::VANY_ZERO: return "MipsISD::VANY_ZERO";
198*9880d681SAndroid Build Coastguard Worker case MipsISD::VALL_NONZERO: return "MipsISD::VALL_NONZERO";
199*9880d681SAndroid Build Coastguard Worker case MipsISD::VANY_NONZERO: return "MipsISD::VANY_NONZERO";
200*9880d681SAndroid Build Coastguard Worker case MipsISD::VCEQ: return "MipsISD::VCEQ";
201*9880d681SAndroid Build Coastguard Worker case MipsISD::VCLE_S: return "MipsISD::VCLE_S";
202*9880d681SAndroid Build Coastguard Worker case MipsISD::VCLE_U: return "MipsISD::VCLE_U";
203*9880d681SAndroid Build Coastguard Worker case MipsISD::VCLT_S: return "MipsISD::VCLT_S";
204*9880d681SAndroid Build Coastguard Worker case MipsISD::VCLT_U: return "MipsISD::VCLT_U";
205*9880d681SAndroid Build Coastguard Worker case MipsISD::VSMAX: return "MipsISD::VSMAX";
206*9880d681SAndroid Build Coastguard Worker case MipsISD::VSMIN: return "MipsISD::VSMIN";
207*9880d681SAndroid Build Coastguard Worker case MipsISD::VUMAX: return "MipsISD::VUMAX";
208*9880d681SAndroid Build Coastguard Worker case MipsISD::VUMIN: return "MipsISD::VUMIN";
209*9880d681SAndroid Build Coastguard Worker case MipsISD::VEXTRACT_SEXT_ELT: return "MipsISD::VEXTRACT_SEXT_ELT";
210*9880d681SAndroid Build Coastguard Worker case MipsISD::VEXTRACT_ZEXT_ELT: return "MipsISD::VEXTRACT_ZEXT_ELT";
211*9880d681SAndroid Build Coastguard Worker case MipsISD::VNOR: return "MipsISD::VNOR";
212*9880d681SAndroid Build Coastguard Worker case MipsISD::VSHF: return "MipsISD::VSHF";
213*9880d681SAndroid Build Coastguard Worker case MipsISD::SHF: return "MipsISD::SHF";
214*9880d681SAndroid Build Coastguard Worker case MipsISD::ILVEV: return "MipsISD::ILVEV";
215*9880d681SAndroid Build Coastguard Worker case MipsISD::ILVOD: return "MipsISD::ILVOD";
216*9880d681SAndroid Build Coastguard Worker case MipsISD::ILVL: return "MipsISD::ILVL";
217*9880d681SAndroid Build Coastguard Worker case MipsISD::ILVR: return "MipsISD::ILVR";
218*9880d681SAndroid Build Coastguard Worker case MipsISD::PCKEV: return "MipsISD::PCKEV";
219*9880d681SAndroid Build Coastguard Worker case MipsISD::PCKOD: return "MipsISD::PCKOD";
220*9880d681SAndroid Build Coastguard Worker case MipsISD::INSVE: return "MipsISD::INSVE";
221*9880d681SAndroid Build Coastguard Worker }
222*9880d681SAndroid Build Coastguard Worker return nullptr;
223*9880d681SAndroid Build Coastguard Worker }
224*9880d681SAndroid Build Coastguard Worker
MipsTargetLowering(const MipsTargetMachine & TM,const MipsSubtarget & STI)225*9880d681SAndroid Build Coastguard Worker MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
226*9880d681SAndroid Build Coastguard Worker const MipsSubtarget &STI)
227*9880d681SAndroid Build Coastguard Worker : TargetLowering(TM), Subtarget(STI), ABI(TM.getABI()) {
228*9880d681SAndroid Build Coastguard Worker // Mips does not have i1 type, so use i32 for
229*9880d681SAndroid Build Coastguard Worker // setcc operations results (slt, sgt, ...).
230*9880d681SAndroid Build Coastguard Worker setBooleanContents(ZeroOrOneBooleanContent);
231*9880d681SAndroid Build Coastguard Worker setBooleanVectorContents(ZeroOrNegativeOneBooleanContent);
232*9880d681SAndroid Build Coastguard Worker // The cmp.cond.fmt instruction in MIPS32r6/MIPS64r6 uses 0 and -1 like MSA
233*9880d681SAndroid Build Coastguard Worker // does. Integer booleans still use 0 and 1.
234*9880d681SAndroid Build Coastguard Worker if (Subtarget.hasMips32r6())
235*9880d681SAndroid Build Coastguard Worker setBooleanContents(ZeroOrOneBooleanContent,
236*9880d681SAndroid Build Coastguard Worker ZeroOrNegativeOneBooleanContent);
237*9880d681SAndroid Build Coastguard Worker
238*9880d681SAndroid Build Coastguard Worker // Load extented operations for i1 types must be promoted
239*9880d681SAndroid Build Coastguard Worker for (MVT VT : MVT::integer_valuetypes()) {
240*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote);
241*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote);
242*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote);
243*9880d681SAndroid Build Coastguard Worker }
244*9880d681SAndroid Build Coastguard Worker
245*9880d681SAndroid Build Coastguard Worker // MIPS doesn't have extending float->double load/store. Set LoadExtAction
246*9880d681SAndroid Build Coastguard Worker // for f32, f16
247*9880d681SAndroid Build Coastguard Worker for (MVT VT : MVT::fp_valuetypes()) {
248*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand);
249*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, VT, MVT::f16, Expand);
250*9880d681SAndroid Build Coastguard Worker }
251*9880d681SAndroid Build Coastguard Worker
252*9880d681SAndroid Build Coastguard Worker // Set LoadExtAction for f16 vectors to Expand
253*9880d681SAndroid Build Coastguard Worker for (MVT VT : MVT::fp_vector_valuetypes()) {
254*9880d681SAndroid Build Coastguard Worker MVT F16VT = MVT::getVectorVT(MVT::f16, VT.getVectorNumElements());
255*9880d681SAndroid Build Coastguard Worker if (F16VT.isValid())
256*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, VT, F16VT, Expand);
257*9880d681SAndroid Build Coastguard Worker }
258*9880d681SAndroid Build Coastguard Worker
259*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::f32, MVT::f16, Expand);
260*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::f64, MVT::f16, Expand);
261*9880d681SAndroid Build Coastguard Worker
262*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::f64, MVT::f32, Expand);
263*9880d681SAndroid Build Coastguard Worker
264*9880d681SAndroid Build Coastguard Worker // Used by legalize types to correctly generate the setcc result.
265*9880d681SAndroid Build Coastguard Worker // Without this, every float setcc comes with a AND/OR with the result,
266*9880d681SAndroid Build Coastguard Worker // we don't want this, since the fpcmp result goes to a flag register,
267*9880d681SAndroid Build Coastguard Worker // which is used implicitly by brcond and select operations.
268*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::SETCC, MVT::i1, MVT::i32);
269*9880d681SAndroid Build Coastguard Worker
270*9880d681SAndroid Build Coastguard Worker // Mips Custom Operations
271*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::BR_JT, MVT::Other, Custom);
272*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
273*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::BlockAddress, MVT::i32, Custom);
274*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
275*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::JumpTable, MVT::i32, Custom);
276*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
277*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT, MVT::f32, Custom);
278*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT, MVT::f64, Custom);
279*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT, MVT::i32, Custom);
280*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SETCC, MVT::f32, Custom);
281*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SETCC, MVT::f64, Custom);
282*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::BRCOND, MVT::Other, Custom);
283*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FCOPYSIGN, MVT::f32, Custom);
284*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom);
285*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
286*9880d681SAndroid Build Coastguard Worker
287*9880d681SAndroid Build Coastguard Worker if (Subtarget.isGP64bit()) {
288*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::GlobalAddress, MVT::i64, Custom);
289*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::BlockAddress, MVT::i64, Custom);
290*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom);
291*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::JumpTable, MVT::i64, Custom);
292*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ConstantPool, MVT::i64, Custom);
293*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT, MVT::i64, Custom);
294*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::LOAD, MVT::i64, Custom);
295*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::STORE, MVT::i64, Custom);
296*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
297*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SHL_PARTS, MVT::i64, Custom);
298*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SRA_PARTS, MVT::i64, Custom);
299*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SRL_PARTS, MVT::i64, Custom);
300*9880d681SAndroid Build Coastguard Worker }
301*9880d681SAndroid Build Coastguard Worker
302*9880d681SAndroid Build Coastguard Worker if (!Subtarget.isGP64bit()) {
303*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom);
304*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom);
305*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom);
306*9880d681SAndroid Build Coastguard Worker }
307*9880d681SAndroid Build Coastguard Worker
308*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ADD, MVT::i32, Custom);
309*9880d681SAndroid Build Coastguard Worker if (Subtarget.isGP64bit())
310*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ADD, MVT::i64, Custom);
311*9880d681SAndroid Build Coastguard Worker
312*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SDIV, MVT::i32, Expand);
313*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SREM, MVT::i32, Expand);
314*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UDIV, MVT::i32, Expand);
315*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UREM, MVT::i32, Expand);
316*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SDIV, MVT::i64, Expand);
317*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SREM, MVT::i64, Expand);
318*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UDIV, MVT::i64, Expand);
319*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UREM, MVT::i64, Expand);
320*9880d681SAndroid Build Coastguard Worker
321*9880d681SAndroid Build Coastguard Worker // Operations not directly supported by Mips.
322*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::BR_CC, MVT::f32, Expand);
323*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::BR_CC, MVT::f64, Expand);
324*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::BR_CC, MVT::i32, Expand);
325*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::BR_CC, MVT::i64, Expand);
326*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT_CC, MVT::i32, Expand);
327*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT_CC, MVT::i64, Expand);
328*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT_CC, MVT::f32, Expand);
329*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT_CC, MVT::f64, Expand);
330*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand);
331*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand);
332*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand);
333*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand);
334*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
335*9880d681SAndroid Build Coastguard Worker if (Subtarget.hasCnMips()) {
336*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CTPOP, MVT::i32, Legal);
337*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CTPOP, MVT::i64, Legal);
338*9880d681SAndroid Build Coastguard Worker } else {
339*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CTPOP, MVT::i32, Expand);
340*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CTPOP, MVT::i64, Expand);
341*9880d681SAndroid Build Coastguard Worker }
342*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CTTZ, MVT::i32, Expand);
343*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CTTZ, MVT::i64, Expand);
344*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ROTL, MVT::i32, Expand);
345*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ROTL, MVT::i64, Expand);
346*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
347*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand);
348*9880d681SAndroid Build Coastguard Worker
349*9880d681SAndroid Build Coastguard Worker if (!Subtarget.hasMips32r2())
350*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ROTR, MVT::i32, Expand);
351*9880d681SAndroid Build Coastguard Worker
352*9880d681SAndroid Build Coastguard Worker if (!Subtarget.hasMips64r2())
353*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ROTR, MVT::i64, Expand);
354*9880d681SAndroid Build Coastguard Worker
355*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FSIN, MVT::f32, Expand);
356*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FSIN, MVT::f64, Expand);
357*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FCOS, MVT::f32, Expand);
358*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FCOS, MVT::f64, Expand);
359*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FSINCOS, MVT::f32, Expand);
360*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FSINCOS, MVT::f64, Expand);
361*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FPOWI, MVT::f32, Expand);
362*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FPOW, MVT::f32, Expand);
363*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FPOW, MVT::f64, Expand);
364*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FLOG, MVT::f32, Expand);
365*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FLOG2, MVT::f32, Expand);
366*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FLOG10, MVT::f32, Expand);
367*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FEXP, MVT::f32, Expand);
368*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FMA, MVT::f32, Expand);
369*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FMA, MVT::f64, Expand);
370*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FREM, MVT::f32, Expand);
371*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FREM, MVT::f64, Expand);
372*9880d681SAndroid Build Coastguard Worker
373*9880d681SAndroid Build Coastguard Worker // Lower f16 conversion operations into library calls
374*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FP16_TO_FP, MVT::f32, Expand);
375*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FP_TO_FP16, MVT::f32, Expand);
376*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FP16_TO_FP, MVT::f64, Expand);
377*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FP_TO_FP16, MVT::f64, Expand);
378*9880d681SAndroid Build Coastguard Worker
379*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::EH_RETURN, MVT::Other, Custom);
380*9880d681SAndroid Build Coastguard Worker
381*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::VASTART, MVT::Other, Custom);
382*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::VAARG, MVT::Other, Custom);
383*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::VACOPY, MVT::Other, Expand);
384*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::VAEND, MVT::Other, Expand);
385*9880d681SAndroid Build Coastguard Worker
386*9880d681SAndroid Build Coastguard Worker // Use the default for now
387*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
388*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
389*9880d681SAndroid Build Coastguard Worker
390*9880d681SAndroid Build Coastguard Worker if (!Subtarget.isGP64bit()) {
391*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Expand);
392*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Expand);
393*9880d681SAndroid Build Coastguard Worker }
394*9880d681SAndroid Build Coastguard Worker
395*9880d681SAndroid Build Coastguard Worker
396*9880d681SAndroid Build Coastguard Worker if (!Subtarget.hasMips32r2()) {
397*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand);
398*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand);
399*9880d681SAndroid Build Coastguard Worker }
400*9880d681SAndroid Build Coastguard Worker
401*9880d681SAndroid Build Coastguard Worker // MIPS16 lacks MIPS32's clz and clo instructions.
402*9880d681SAndroid Build Coastguard Worker if (!Subtarget.hasMips32() || Subtarget.inMips16Mode())
403*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CTLZ, MVT::i32, Expand);
404*9880d681SAndroid Build Coastguard Worker if (!Subtarget.hasMips64())
405*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CTLZ, MVT::i64, Expand);
406*9880d681SAndroid Build Coastguard Worker
407*9880d681SAndroid Build Coastguard Worker if (!Subtarget.hasMips32r2())
408*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::BSWAP, MVT::i32, Expand);
409*9880d681SAndroid Build Coastguard Worker if (!Subtarget.hasMips64r2())
410*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::BSWAP, MVT::i64, Expand);
411*9880d681SAndroid Build Coastguard Worker
412*9880d681SAndroid Build Coastguard Worker if (Subtarget.isGP64bit()) {
413*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::SEXTLOAD, MVT::i64, MVT::i32, Custom);
414*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::ZEXTLOAD, MVT::i64, MVT::i32, Custom);
415*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, MVT::i64, MVT::i32, Custom);
416*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::i64, MVT::i32, Custom);
417*9880d681SAndroid Build Coastguard Worker }
418*9880d681SAndroid Build Coastguard Worker
419*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::TRAP, MVT::Other, Legal);
420*9880d681SAndroid Build Coastguard Worker
421*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::SDIVREM);
422*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::UDIVREM);
423*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::SELECT);
424*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::AND);
425*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::OR);
426*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::ADD);
427*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::AssertZext);
428*9880d681SAndroid Build Coastguard Worker
429*9880d681SAndroid Build Coastguard Worker setMinFunctionAlignment(Subtarget.isGP64bit() ? 3 : 2);
430*9880d681SAndroid Build Coastguard Worker
431*9880d681SAndroid Build Coastguard Worker // The arguments on the stack are defined in terms of 4-byte slots on O32
432*9880d681SAndroid Build Coastguard Worker // and 8-byte slots on N32/N64.
433*9880d681SAndroid Build Coastguard Worker setMinStackArgumentAlignment((ABI.IsN32() || ABI.IsN64()) ? 8 : 4);
434*9880d681SAndroid Build Coastguard Worker
435*9880d681SAndroid Build Coastguard Worker setStackPointerRegisterToSaveRestore(ABI.IsN64() ? Mips::SP_64 : Mips::SP);
436*9880d681SAndroid Build Coastguard Worker
437*9880d681SAndroid Build Coastguard Worker MaxStoresPerMemcpy = 16;
438*9880d681SAndroid Build Coastguard Worker
439*9880d681SAndroid Build Coastguard Worker isMicroMips = Subtarget.inMicroMipsMode();
440*9880d681SAndroid Build Coastguard Worker }
441*9880d681SAndroid Build Coastguard Worker
create(const MipsTargetMachine & TM,const MipsSubtarget & STI)442*9880d681SAndroid Build Coastguard Worker const MipsTargetLowering *MipsTargetLowering::create(const MipsTargetMachine &TM,
443*9880d681SAndroid Build Coastguard Worker const MipsSubtarget &STI) {
444*9880d681SAndroid Build Coastguard Worker if (STI.inMips16Mode())
445*9880d681SAndroid Build Coastguard Worker return llvm::createMips16TargetLowering(TM, STI);
446*9880d681SAndroid Build Coastguard Worker
447*9880d681SAndroid Build Coastguard Worker return llvm::createMipsSETargetLowering(TM, STI);
448*9880d681SAndroid Build Coastguard Worker }
449*9880d681SAndroid Build Coastguard Worker
450*9880d681SAndroid Build Coastguard Worker // Create a fast isel object.
451*9880d681SAndroid Build Coastguard Worker FastISel *
createFastISel(FunctionLoweringInfo & funcInfo,const TargetLibraryInfo * libInfo) const452*9880d681SAndroid Build Coastguard Worker MipsTargetLowering::createFastISel(FunctionLoweringInfo &funcInfo,
453*9880d681SAndroid Build Coastguard Worker const TargetLibraryInfo *libInfo) const {
454*9880d681SAndroid Build Coastguard Worker if (!funcInfo.MF->getTarget().Options.EnableFastISel)
455*9880d681SAndroid Build Coastguard Worker return TargetLowering::createFastISel(funcInfo, libInfo);
456*9880d681SAndroid Build Coastguard Worker return Mips::createFastISel(funcInfo, libInfo);
457*9880d681SAndroid Build Coastguard Worker }
458*9880d681SAndroid Build Coastguard Worker
getSetCCResultType(const DataLayout &,LLVMContext &,EVT VT) const459*9880d681SAndroid Build Coastguard Worker EVT MipsTargetLowering::getSetCCResultType(const DataLayout &, LLVMContext &,
460*9880d681SAndroid Build Coastguard Worker EVT VT) const {
461*9880d681SAndroid Build Coastguard Worker if (!VT.isVector())
462*9880d681SAndroid Build Coastguard Worker return MVT::i32;
463*9880d681SAndroid Build Coastguard Worker return VT.changeVectorElementTypeToInteger();
464*9880d681SAndroid Build Coastguard Worker }
465*9880d681SAndroid Build Coastguard Worker
performDivRemCombine(SDNode * N,SelectionDAG & DAG,TargetLowering::DAGCombinerInfo & DCI,const MipsSubtarget & Subtarget)466*9880d681SAndroid Build Coastguard Worker static SDValue performDivRemCombine(SDNode *N, SelectionDAG &DAG,
467*9880d681SAndroid Build Coastguard Worker TargetLowering::DAGCombinerInfo &DCI,
468*9880d681SAndroid Build Coastguard Worker const MipsSubtarget &Subtarget) {
469*9880d681SAndroid Build Coastguard Worker if (DCI.isBeforeLegalizeOps())
470*9880d681SAndroid Build Coastguard Worker return SDValue();
471*9880d681SAndroid Build Coastguard Worker
472*9880d681SAndroid Build Coastguard Worker EVT Ty = N->getValueType(0);
473*9880d681SAndroid Build Coastguard Worker unsigned LO = (Ty == MVT::i32) ? Mips::LO0 : Mips::LO0_64;
474*9880d681SAndroid Build Coastguard Worker unsigned HI = (Ty == MVT::i32) ? Mips::HI0 : Mips::HI0_64;
475*9880d681SAndroid Build Coastguard Worker unsigned Opc = N->getOpcode() == ISD::SDIVREM ? MipsISD::DivRem16 :
476*9880d681SAndroid Build Coastguard Worker MipsISD::DivRemU16;
477*9880d681SAndroid Build Coastguard Worker SDLoc DL(N);
478*9880d681SAndroid Build Coastguard Worker
479*9880d681SAndroid Build Coastguard Worker SDValue DivRem = DAG.getNode(Opc, DL, MVT::Glue,
480*9880d681SAndroid Build Coastguard Worker N->getOperand(0), N->getOperand(1));
481*9880d681SAndroid Build Coastguard Worker SDValue InChain = DAG.getEntryNode();
482*9880d681SAndroid Build Coastguard Worker SDValue InGlue = DivRem;
483*9880d681SAndroid Build Coastguard Worker
484*9880d681SAndroid Build Coastguard Worker // insert MFLO
485*9880d681SAndroid Build Coastguard Worker if (N->hasAnyUseOfValue(0)) {
486*9880d681SAndroid Build Coastguard Worker SDValue CopyFromLo = DAG.getCopyFromReg(InChain, DL, LO, Ty,
487*9880d681SAndroid Build Coastguard Worker InGlue);
488*9880d681SAndroid Build Coastguard Worker DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), CopyFromLo);
489*9880d681SAndroid Build Coastguard Worker InChain = CopyFromLo.getValue(1);
490*9880d681SAndroid Build Coastguard Worker InGlue = CopyFromLo.getValue(2);
491*9880d681SAndroid Build Coastguard Worker }
492*9880d681SAndroid Build Coastguard Worker
493*9880d681SAndroid Build Coastguard Worker // insert MFHI
494*9880d681SAndroid Build Coastguard Worker if (N->hasAnyUseOfValue(1)) {
495*9880d681SAndroid Build Coastguard Worker SDValue CopyFromHi = DAG.getCopyFromReg(InChain, DL,
496*9880d681SAndroid Build Coastguard Worker HI, Ty, InGlue);
497*9880d681SAndroid Build Coastguard Worker DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), CopyFromHi);
498*9880d681SAndroid Build Coastguard Worker }
499*9880d681SAndroid Build Coastguard Worker
500*9880d681SAndroid Build Coastguard Worker return SDValue();
501*9880d681SAndroid Build Coastguard Worker }
502*9880d681SAndroid Build Coastguard Worker
condCodeToFCC(ISD::CondCode CC)503*9880d681SAndroid Build Coastguard Worker static Mips::CondCode condCodeToFCC(ISD::CondCode CC) {
504*9880d681SAndroid Build Coastguard Worker switch (CC) {
505*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Unknown fp condition code!");
506*9880d681SAndroid Build Coastguard Worker case ISD::SETEQ:
507*9880d681SAndroid Build Coastguard Worker case ISD::SETOEQ: return Mips::FCOND_OEQ;
508*9880d681SAndroid Build Coastguard Worker case ISD::SETUNE: return Mips::FCOND_UNE;
509*9880d681SAndroid Build Coastguard Worker case ISD::SETLT:
510*9880d681SAndroid Build Coastguard Worker case ISD::SETOLT: return Mips::FCOND_OLT;
511*9880d681SAndroid Build Coastguard Worker case ISD::SETGT:
512*9880d681SAndroid Build Coastguard Worker case ISD::SETOGT: return Mips::FCOND_OGT;
513*9880d681SAndroid Build Coastguard Worker case ISD::SETLE:
514*9880d681SAndroid Build Coastguard Worker case ISD::SETOLE: return Mips::FCOND_OLE;
515*9880d681SAndroid Build Coastguard Worker case ISD::SETGE:
516*9880d681SAndroid Build Coastguard Worker case ISD::SETOGE: return Mips::FCOND_OGE;
517*9880d681SAndroid Build Coastguard Worker case ISD::SETULT: return Mips::FCOND_ULT;
518*9880d681SAndroid Build Coastguard Worker case ISD::SETULE: return Mips::FCOND_ULE;
519*9880d681SAndroid Build Coastguard Worker case ISD::SETUGT: return Mips::FCOND_UGT;
520*9880d681SAndroid Build Coastguard Worker case ISD::SETUGE: return Mips::FCOND_UGE;
521*9880d681SAndroid Build Coastguard Worker case ISD::SETUO: return Mips::FCOND_UN;
522*9880d681SAndroid Build Coastguard Worker case ISD::SETO: return Mips::FCOND_OR;
523*9880d681SAndroid Build Coastguard Worker case ISD::SETNE:
524*9880d681SAndroid Build Coastguard Worker case ISD::SETONE: return Mips::FCOND_ONE;
525*9880d681SAndroid Build Coastguard Worker case ISD::SETUEQ: return Mips::FCOND_UEQ;
526*9880d681SAndroid Build Coastguard Worker }
527*9880d681SAndroid Build Coastguard Worker }
528*9880d681SAndroid Build Coastguard Worker
529*9880d681SAndroid Build Coastguard Worker
530*9880d681SAndroid Build Coastguard Worker /// This function returns true if the floating point conditional branches and
531*9880d681SAndroid Build Coastguard Worker /// conditional moves which use condition code CC should be inverted.
invertFPCondCodeUser(Mips::CondCode CC)532*9880d681SAndroid Build Coastguard Worker static bool invertFPCondCodeUser(Mips::CondCode CC) {
533*9880d681SAndroid Build Coastguard Worker if (CC >= Mips::FCOND_F && CC <= Mips::FCOND_NGT)
534*9880d681SAndroid Build Coastguard Worker return false;
535*9880d681SAndroid Build Coastguard Worker
536*9880d681SAndroid Build Coastguard Worker assert((CC >= Mips::FCOND_T && CC <= Mips::FCOND_GT) &&
537*9880d681SAndroid Build Coastguard Worker "Illegal Condition Code");
538*9880d681SAndroid Build Coastguard Worker
539*9880d681SAndroid Build Coastguard Worker return true;
540*9880d681SAndroid Build Coastguard Worker }
541*9880d681SAndroid Build Coastguard Worker
542*9880d681SAndroid Build Coastguard Worker // Creates and returns an FPCmp node from a setcc node.
543*9880d681SAndroid Build Coastguard Worker // Returns Op if setcc is not a floating point comparison.
createFPCmp(SelectionDAG & DAG,const SDValue & Op)544*9880d681SAndroid Build Coastguard Worker static SDValue createFPCmp(SelectionDAG &DAG, const SDValue &Op) {
545*9880d681SAndroid Build Coastguard Worker // must be a SETCC node
546*9880d681SAndroid Build Coastguard Worker if (Op.getOpcode() != ISD::SETCC)
547*9880d681SAndroid Build Coastguard Worker return Op;
548*9880d681SAndroid Build Coastguard Worker
549*9880d681SAndroid Build Coastguard Worker SDValue LHS = Op.getOperand(0);
550*9880d681SAndroid Build Coastguard Worker
551*9880d681SAndroid Build Coastguard Worker if (!LHS.getValueType().isFloatingPoint())
552*9880d681SAndroid Build Coastguard Worker return Op;
553*9880d681SAndroid Build Coastguard Worker
554*9880d681SAndroid Build Coastguard Worker SDValue RHS = Op.getOperand(1);
555*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
556*9880d681SAndroid Build Coastguard Worker
557*9880d681SAndroid Build Coastguard Worker // Assume the 3rd operand is a CondCodeSDNode. Add code to check the type of
558*9880d681SAndroid Build Coastguard Worker // node if necessary.
559*9880d681SAndroid Build Coastguard Worker ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
560*9880d681SAndroid Build Coastguard Worker
561*9880d681SAndroid Build Coastguard Worker return DAG.getNode(MipsISD::FPCmp, DL, MVT::Glue, LHS, RHS,
562*9880d681SAndroid Build Coastguard Worker DAG.getConstant(condCodeToFCC(CC), DL, MVT::i32));
563*9880d681SAndroid Build Coastguard Worker }
564*9880d681SAndroid Build Coastguard Worker
565*9880d681SAndroid Build Coastguard Worker // Creates and returns a CMovFPT/F node.
createCMovFP(SelectionDAG & DAG,SDValue Cond,SDValue True,SDValue False,const SDLoc & DL)566*9880d681SAndroid Build Coastguard Worker static SDValue createCMovFP(SelectionDAG &DAG, SDValue Cond, SDValue True,
567*9880d681SAndroid Build Coastguard Worker SDValue False, const SDLoc &DL) {
568*9880d681SAndroid Build Coastguard Worker ConstantSDNode *CC = cast<ConstantSDNode>(Cond.getOperand(2));
569*9880d681SAndroid Build Coastguard Worker bool invert = invertFPCondCodeUser((Mips::CondCode)CC->getSExtValue());
570*9880d681SAndroid Build Coastguard Worker SDValue FCC0 = DAG.getRegister(Mips::FCC0, MVT::i32);
571*9880d681SAndroid Build Coastguard Worker
572*9880d681SAndroid Build Coastguard Worker return DAG.getNode((invert ? MipsISD::CMovFP_F : MipsISD::CMovFP_T), DL,
573*9880d681SAndroid Build Coastguard Worker True.getValueType(), True, FCC0, False, Cond);
574*9880d681SAndroid Build Coastguard Worker }
575*9880d681SAndroid Build Coastguard Worker
performSELECTCombine(SDNode * N,SelectionDAG & DAG,TargetLowering::DAGCombinerInfo & DCI,const MipsSubtarget & Subtarget)576*9880d681SAndroid Build Coastguard Worker static SDValue performSELECTCombine(SDNode *N, SelectionDAG &DAG,
577*9880d681SAndroid Build Coastguard Worker TargetLowering::DAGCombinerInfo &DCI,
578*9880d681SAndroid Build Coastguard Worker const MipsSubtarget &Subtarget) {
579*9880d681SAndroid Build Coastguard Worker if (DCI.isBeforeLegalizeOps())
580*9880d681SAndroid Build Coastguard Worker return SDValue();
581*9880d681SAndroid Build Coastguard Worker
582*9880d681SAndroid Build Coastguard Worker SDValue SetCC = N->getOperand(0);
583*9880d681SAndroid Build Coastguard Worker
584*9880d681SAndroid Build Coastguard Worker if ((SetCC.getOpcode() != ISD::SETCC) ||
585*9880d681SAndroid Build Coastguard Worker !SetCC.getOperand(0).getValueType().isInteger())
586*9880d681SAndroid Build Coastguard Worker return SDValue();
587*9880d681SAndroid Build Coastguard Worker
588*9880d681SAndroid Build Coastguard Worker SDValue False = N->getOperand(2);
589*9880d681SAndroid Build Coastguard Worker EVT FalseTy = False.getValueType();
590*9880d681SAndroid Build Coastguard Worker
591*9880d681SAndroid Build Coastguard Worker if (!FalseTy.isInteger())
592*9880d681SAndroid Build Coastguard Worker return SDValue();
593*9880d681SAndroid Build Coastguard Worker
594*9880d681SAndroid Build Coastguard Worker ConstantSDNode *FalseC = dyn_cast<ConstantSDNode>(False);
595*9880d681SAndroid Build Coastguard Worker
596*9880d681SAndroid Build Coastguard Worker // If the RHS (False) is 0, we swap the order of the operands
597*9880d681SAndroid Build Coastguard Worker // of ISD::SELECT (obviously also inverting the condition) so that we can
598*9880d681SAndroid Build Coastguard Worker // take advantage of conditional moves using the $0 register.
599*9880d681SAndroid Build Coastguard Worker // Example:
600*9880d681SAndroid Build Coastguard Worker // return (a != 0) ? x : 0;
601*9880d681SAndroid Build Coastguard Worker // load $reg, x
602*9880d681SAndroid Build Coastguard Worker // movz $reg, $0, a
603*9880d681SAndroid Build Coastguard Worker if (!FalseC)
604*9880d681SAndroid Build Coastguard Worker return SDValue();
605*9880d681SAndroid Build Coastguard Worker
606*9880d681SAndroid Build Coastguard Worker const SDLoc DL(N);
607*9880d681SAndroid Build Coastguard Worker
608*9880d681SAndroid Build Coastguard Worker if (!FalseC->getZExtValue()) {
609*9880d681SAndroid Build Coastguard Worker ISD::CondCode CC = cast<CondCodeSDNode>(SetCC.getOperand(2))->get();
610*9880d681SAndroid Build Coastguard Worker SDValue True = N->getOperand(1);
611*9880d681SAndroid Build Coastguard Worker
612*9880d681SAndroid Build Coastguard Worker SetCC = DAG.getSetCC(DL, SetCC.getValueType(), SetCC.getOperand(0),
613*9880d681SAndroid Build Coastguard Worker SetCC.getOperand(1), ISD::getSetCCInverse(CC, true));
614*9880d681SAndroid Build Coastguard Worker
615*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::SELECT, DL, FalseTy, SetCC, False, True);
616*9880d681SAndroid Build Coastguard Worker }
617*9880d681SAndroid Build Coastguard Worker
618*9880d681SAndroid Build Coastguard Worker // If both operands are integer constants there's a possibility that we
619*9880d681SAndroid Build Coastguard Worker // can do some interesting optimizations.
620*9880d681SAndroid Build Coastguard Worker SDValue True = N->getOperand(1);
621*9880d681SAndroid Build Coastguard Worker ConstantSDNode *TrueC = dyn_cast<ConstantSDNode>(True);
622*9880d681SAndroid Build Coastguard Worker
623*9880d681SAndroid Build Coastguard Worker if (!TrueC || !True.getValueType().isInteger())
624*9880d681SAndroid Build Coastguard Worker return SDValue();
625*9880d681SAndroid Build Coastguard Worker
626*9880d681SAndroid Build Coastguard Worker // We'll also ignore MVT::i64 operands as this optimizations proves
627*9880d681SAndroid Build Coastguard Worker // to be ineffective because of the required sign extensions as the result
628*9880d681SAndroid Build Coastguard Worker // of a SETCC operator is always MVT::i32 for non-vector types.
629*9880d681SAndroid Build Coastguard Worker if (True.getValueType() == MVT::i64)
630*9880d681SAndroid Build Coastguard Worker return SDValue();
631*9880d681SAndroid Build Coastguard Worker
632*9880d681SAndroid Build Coastguard Worker int64_t Diff = TrueC->getSExtValue() - FalseC->getSExtValue();
633*9880d681SAndroid Build Coastguard Worker
634*9880d681SAndroid Build Coastguard Worker // 1) (a < x) ? y : y-1
635*9880d681SAndroid Build Coastguard Worker // slti $reg1, a, x
636*9880d681SAndroid Build Coastguard Worker // addiu $reg2, $reg1, y-1
637*9880d681SAndroid Build Coastguard Worker if (Diff == 1)
638*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::ADD, DL, SetCC.getValueType(), SetCC, False);
639*9880d681SAndroid Build Coastguard Worker
640*9880d681SAndroid Build Coastguard Worker // 2) (a < x) ? y-1 : y
641*9880d681SAndroid Build Coastguard Worker // slti $reg1, a, x
642*9880d681SAndroid Build Coastguard Worker // xor $reg1, $reg1, 1
643*9880d681SAndroid Build Coastguard Worker // addiu $reg2, $reg1, y-1
644*9880d681SAndroid Build Coastguard Worker if (Diff == -1) {
645*9880d681SAndroid Build Coastguard Worker ISD::CondCode CC = cast<CondCodeSDNode>(SetCC.getOperand(2))->get();
646*9880d681SAndroid Build Coastguard Worker SetCC = DAG.getSetCC(DL, SetCC.getValueType(), SetCC.getOperand(0),
647*9880d681SAndroid Build Coastguard Worker SetCC.getOperand(1), ISD::getSetCCInverse(CC, true));
648*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::ADD, DL, SetCC.getValueType(), SetCC, True);
649*9880d681SAndroid Build Coastguard Worker }
650*9880d681SAndroid Build Coastguard Worker
651*9880d681SAndroid Build Coastguard Worker // Couldn't optimize.
652*9880d681SAndroid Build Coastguard Worker return SDValue();
653*9880d681SAndroid Build Coastguard Worker }
654*9880d681SAndroid Build Coastguard Worker
performCMovFPCombine(SDNode * N,SelectionDAG & DAG,TargetLowering::DAGCombinerInfo & DCI,const MipsSubtarget & Subtarget)655*9880d681SAndroid Build Coastguard Worker static SDValue performCMovFPCombine(SDNode *N, SelectionDAG &DAG,
656*9880d681SAndroid Build Coastguard Worker TargetLowering::DAGCombinerInfo &DCI,
657*9880d681SAndroid Build Coastguard Worker const MipsSubtarget &Subtarget) {
658*9880d681SAndroid Build Coastguard Worker if (DCI.isBeforeLegalizeOps())
659*9880d681SAndroid Build Coastguard Worker return SDValue();
660*9880d681SAndroid Build Coastguard Worker
661*9880d681SAndroid Build Coastguard Worker SDValue ValueIfTrue = N->getOperand(0), ValueIfFalse = N->getOperand(2);
662*9880d681SAndroid Build Coastguard Worker
663*9880d681SAndroid Build Coastguard Worker ConstantSDNode *FalseC = dyn_cast<ConstantSDNode>(ValueIfFalse);
664*9880d681SAndroid Build Coastguard Worker if (!FalseC || FalseC->getZExtValue())
665*9880d681SAndroid Build Coastguard Worker return SDValue();
666*9880d681SAndroid Build Coastguard Worker
667*9880d681SAndroid Build Coastguard Worker // Since RHS (False) is 0, we swap the order of the True/False operands
668*9880d681SAndroid Build Coastguard Worker // (obviously also inverting the condition) so that we can
669*9880d681SAndroid Build Coastguard Worker // take advantage of conditional moves using the $0 register.
670*9880d681SAndroid Build Coastguard Worker // Example:
671*9880d681SAndroid Build Coastguard Worker // return (a != 0) ? x : 0;
672*9880d681SAndroid Build Coastguard Worker // load $reg, x
673*9880d681SAndroid Build Coastguard Worker // movz $reg, $0, a
674*9880d681SAndroid Build Coastguard Worker unsigned Opc = (N->getOpcode() == MipsISD::CMovFP_T) ? MipsISD::CMovFP_F :
675*9880d681SAndroid Build Coastguard Worker MipsISD::CMovFP_T;
676*9880d681SAndroid Build Coastguard Worker
677*9880d681SAndroid Build Coastguard Worker SDValue FCC = N->getOperand(1), Glue = N->getOperand(3);
678*9880d681SAndroid Build Coastguard Worker return DAG.getNode(Opc, SDLoc(N), ValueIfFalse.getValueType(),
679*9880d681SAndroid Build Coastguard Worker ValueIfFalse, FCC, ValueIfTrue, Glue);
680*9880d681SAndroid Build Coastguard Worker }
681*9880d681SAndroid Build Coastguard Worker
performANDCombine(SDNode * N,SelectionDAG & DAG,TargetLowering::DAGCombinerInfo & DCI,const MipsSubtarget & Subtarget)682*9880d681SAndroid Build Coastguard Worker static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG,
683*9880d681SAndroid Build Coastguard Worker TargetLowering::DAGCombinerInfo &DCI,
684*9880d681SAndroid Build Coastguard Worker const MipsSubtarget &Subtarget) {
685*9880d681SAndroid Build Coastguard Worker // Pattern match EXT.
686*9880d681SAndroid Build Coastguard Worker // $dst = and ((sra or srl) $src , pos), (2**size - 1)
687*9880d681SAndroid Build Coastguard Worker // => ext $dst, $src, size, pos
688*9880d681SAndroid Build Coastguard Worker if (DCI.isBeforeLegalizeOps() || !Subtarget.hasExtractInsert())
689*9880d681SAndroid Build Coastguard Worker return SDValue();
690*9880d681SAndroid Build Coastguard Worker
691*9880d681SAndroid Build Coastguard Worker SDValue ShiftRight = N->getOperand(0), Mask = N->getOperand(1);
692*9880d681SAndroid Build Coastguard Worker unsigned ShiftRightOpc = ShiftRight.getOpcode();
693*9880d681SAndroid Build Coastguard Worker
694*9880d681SAndroid Build Coastguard Worker // Op's first operand must be a shift right.
695*9880d681SAndroid Build Coastguard Worker if (ShiftRightOpc != ISD::SRA && ShiftRightOpc != ISD::SRL)
696*9880d681SAndroid Build Coastguard Worker return SDValue();
697*9880d681SAndroid Build Coastguard Worker
698*9880d681SAndroid Build Coastguard Worker // The second operand of the shift must be an immediate.
699*9880d681SAndroid Build Coastguard Worker ConstantSDNode *CN;
700*9880d681SAndroid Build Coastguard Worker if (!(CN = dyn_cast<ConstantSDNode>(ShiftRight.getOperand(1))))
701*9880d681SAndroid Build Coastguard Worker return SDValue();
702*9880d681SAndroid Build Coastguard Worker
703*9880d681SAndroid Build Coastguard Worker uint64_t Pos = CN->getZExtValue();
704*9880d681SAndroid Build Coastguard Worker uint64_t SMPos, SMSize;
705*9880d681SAndroid Build Coastguard Worker
706*9880d681SAndroid Build Coastguard Worker // Op's second operand must be a shifted mask.
707*9880d681SAndroid Build Coastguard Worker if (!(CN = dyn_cast<ConstantSDNode>(Mask)) ||
708*9880d681SAndroid Build Coastguard Worker !isShiftedMask(CN->getZExtValue(), SMPos, SMSize))
709*9880d681SAndroid Build Coastguard Worker return SDValue();
710*9880d681SAndroid Build Coastguard Worker
711*9880d681SAndroid Build Coastguard Worker // Return if the shifted mask does not start at bit 0 or the sum of its size
712*9880d681SAndroid Build Coastguard Worker // and Pos exceeds the word's size.
713*9880d681SAndroid Build Coastguard Worker EVT ValTy = N->getValueType(0);
714*9880d681SAndroid Build Coastguard Worker if (SMPos != 0 || Pos + SMSize > ValTy.getSizeInBits())
715*9880d681SAndroid Build Coastguard Worker return SDValue();
716*9880d681SAndroid Build Coastguard Worker
717*9880d681SAndroid Build Coastguard Worker SDLoc DL(N);
718*9880d681SAndroid Build Coastguard Worker return DAG.getNode(MipsISD::Ext, DL, ValTy,
719*9880d681SAndroid Build Coastguard Worker ShiftRight.getOperand(0),
720*9880d681SAndroid Build Coastguard Worker DAG.getConstant(Pos, DL, MVT::i32),
721*9880d681SAndroid Build Coastguard Worker DAG.getConstant(SMSize, DL, MVT::i32));
722*9880d681SAndroid Build Coastguard Worker }
723*9880d681SAndroid Build Coastguard Worker
performORCombine(SDNode * N,SelectionDAG & DAG,TargetLowering::DAGCombinerInfo & DCI,const MipsSubtarget & Subtarget)724*9880d681SAndroid Build Coastguard Worker static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
725*9880d681SAndroid Build Coastguard Worker TargetLowering::DAGCombinerInfo &DCI,
726*9880d681SAndroid Build Coastguard Worker const MipsSubtarget &Subtarget) {
727*9880d681SAndroid Build Coastguard Worker // Pattern match INS.
728*9880d681SAndroid Build Coastguard Worker // $dst = or (and $src1 , mask0), (and (shl $src, pos), mask1),
729*9880d681SAndroid Build Coastguard Worker // where mask1 = (2**size - 1) << pos, mask0 = ~mask1
730*9880d681SAndroid Build Coastguard Worker // => ins $dst, $src, size, pos, $src1
731*9880d681SAndroid Build Coastguard Worker if (DCI.isBeforeLegalizeOps() || !Subtarget.hasExtractInsert())
732*9880d681SAndroid Build Coastguard Worker return SDValue();
733*9880d681SAndroid Build Coastguard Worker
734*9880d681SAndroid Build Coastguard Worker SDValue And0 = N->getOperand(0), And1 = N->getOperand(1);
735*9880d681SAndroid Build Coastguard Worker uint64_t SMPos0, SMSize0, SMPos1, SMSize1;
736*9880d681SAndroid Build Coastguard Worker ConstantSDNode *CN;
737*9880d681SAndroid Build Coastguard Worker
738*9880d681SAndroid Build Coastguard Worker // See if Op's first operand matches (and $src1 , mask0).
739*9880d681SAndroid Build Coastguard Worker if (And0.getOpcode() != ISD::AND)
740*9880d681SAndroid Build Coastguard Worker return SDValue();
741*9880d681SAndroid Build Coastguard Worker
742*9880d681SAndroid Build Coastguard Worker if (!(CN = dyn_cast<ConstantSDNode>(And0.getOperand(1))) ||
743*9880d681SAndroid Build Coastguard Worker !isShiftedMask(~CN->getSExtValue(), SMPos0, SMSize0))
744*9880d681SAndroid Build Coastguard Worker return SDValue();
745*9880d681SAndroid Build Coastguard Worker
746*9880d681SAndroid Build Coastguard Worker // See if Op's second operand matches (and (shl $src, pos), mask1).
747*9880d681SAndroid Build Coastguard Worker if (And1.getOpcode() != ISD::AND)
748*9880d681SAndroid Build Coastguard Worker return SDValue();
749*9880d681SAndroid Build Coastguard Worker
750*9880d681SAndroid Build Coastguard Worker if (!(CN = dyn_cast<ConstantSDNode>(And1.getOperand(1))) ||
751*9880d681SAndroid Build Coastguard Worker !isShiftedMask(CN->getZExtValue(), SMPos1, SMSize1))
752*9880d681SAndroid Build Coastguard Worker return SDValue();
753*9880d681SAndroid Build Coastguard Worker
754*9880d681SAndroid Build Coastguard Worker // The shift masks must have the same position and size.
755*9880d681SAndroid Build Coastguard Worker if (SMPos0 != SMPos1 || SMSize0 != SMSize1)
756*9880d681SAndroid Build Coastguard Worker return SDValue();
757*9880d681SAndroid Build Coastguard Worker
758*9880d681SAndroid Build Coastguard Worker SDValue Shl = And1.getOperand(0);
759*9880d681SAndroid Build Coastguard Worker if (Shl.getOpcode() != ISD::SHL)
760*9880d681SAndroid Build Coastguard Worker return SDValue();
761*9880d681SAndroid Build Coastguard Worker
762*9880d681SAndroid Build Coastguard Worker if (!(CN = dyn_cast<ConstantSDNode>(Shl.getOperand(1))))
763*9880d681SAndroid Build Coastguard Worker return SDValue();
764*9880d681SAndroid Build Coastguard Worker
765*9880d681SAndroid Build Coastguard Worker unsigned Shamt = CN->getZExtValue();
766*9880d681SAndroid Build Coastguard Worker
767*9880d681SAndroid Build Coastguard Worker // Return if the shift amount and the first bit position of mask are not the
768*9880d681SAndroid Build Coastguard Worker // same.
769*9880d681SAndroid Build Coastguard Worker EVT ValTy = N->getValueType(0);
770*9880d681SAndroid Build Coastguard Worker if ((Shamt != SMPos0) || (SMPos0 + SMSize0 > ValTy.getSizeInBits()))
771*9880d681SAndroid Build Coastguard Worker return SDValue();
772*9880d681SAndroid Build Coastguard Worker
773*9880d681SAndroid Build Coastguard Worker SDLoc DL(N);
774*9880d681SAndroid Build Coastguard Worker return DAG.getNode(MipsISD::Ins, DL, ValTy, Shl.getOperand(0),
775*9880d681SAndroid Build Coastguard Worker DAG.getConstant(SMPos0, DL, MVT::i32),
776*9880d681SAndroid Build Coastguard Worker DAG.getConstant(SMSize0, DL, MVT::i32),
777*9880d681SAndroid Build Coastguard Worker And0.getOperand(0));
778*9880d681SAndroid Build Coastguard Worker }
779*9880d681SAndroid Build Coastguard Worker
performADDCombine(SDNode * N,SelectionDAG & DAG,TargetLowering::DAGCombinerInfo & DCI,const MipsSubtarget & Subtarget)780*9880d681SAndroid Build Coastguard Worker static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG,
781*9880d681SAndroid Build Coastguard Worker TargetLowering::DAGCombinerInfo &DCI,
782*9880d681SAndroid Build Coastguard Worker const MipsSubtarget &Subtarget) {
783*9880d681SAndroid Build Coastguard Worker // (add v0, (add v1, abs_lo(tjt))) => (add (add v0, v1), abs_lo(tjt))
784*9880d681SAndroid Build Coastguard Worker
785*9880d681SAndroid Build Coastguard Worker if (DCI.isBeforeLegalizeOps())
786*9880d681SAndroid Build Coastguard Worker return SDValue();
787*9880d681SAndroid Build Coastguard Worker
788*9880d681SAndroid Build Coastguard Worker SDValue Add = N->getOperand(1);
789*9880d681SAndroid Build Coastguard Worker
790*9880d681SAndroid Build Coastguard Worker if (Add.getOpcode() != ISD::ADD)
791*9880d681SAndroid Build Coastguard Worker return SDValue();
792*9880d681SAndroid Build Coastguard Worker
793*9880d681SAndroid Build Coastguard Worker SDValue Lo = Add.getOperand(1);
794*9880d681SAndroid Build Coastguard Worker
795*9880d681SAndroid Build Coastguard Worker if ((Lo.getOpcode() != MipsISD::Lo) ||
796*9880d681SAndroid Build Coastguard Worker (Lo.getOperand(0).getOpcode() != ISD::TargetJumpTable))
797*9880d681SAndroid Build Coastguard Worker return SDValue();
798*9880d681SAndroid Build Coastguard Worker
799*9880d681SAndroid Build Coastguard Worker EVT ValTy = N->getValueType(0);
800*9880d681SAndroid Build Coastguard Worker SDLoc DL(N);
801*9880d681SAndroid Build Coastguard Worker
802*9880d681SAndroid Build Coastguard Worker SDValue Add1 = DAG.getNode(ISD::ADD, DL, ValTy, N->getOperand(0),
803*9880d681SAndroid Build Coastguard Worker Add.getOperand(0));
804*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::ADD, DL, ValTy, Add1, Lo);
805*9880d681SAndroid Build Coastguard Worker }
806*9880d681SAndroid Build Coastguard Worker
performAssertZextCombine(SDNode * N,SelectionDAG & DAG,TargetLowering::DAGCombinerInfo & DCI,const MipsSubtarget & Subtarget)807*9880d681SAndroid Build Coastguard Worker static SDValue performAssertZextCombine(SDNode *N, SelectionDAG &DAG,
808*9880d681SAndroid Build Coastguard Worker TargetLowering::DAGCombinerInfo &DCI,
809*9880d681SAndroid Build Coastguard Worker const MipsSubtarget &Subtarget) {
810*9880d681SAndroid Build Coastguard Worker SDValue N0 = N->getOperand(0);
811*9880d681SAndroid Build Coastguard Worker EVT NarrowerVT = cast<VTSDNode>(N->getOperand(1))->getVT();
812*9880d681SAndroid Build Coastguard Worker
813*9880d681SAndroid Build Coastguard Worker if (N0.getOpcode() != ISD::TRUNCATE)
814*9880d681SAndroid Build Coastguard Worker return SDValue();
815*9880d681SAndroid Build Coastguard Worker
816*9880d681SAndroid Build Coastguard Worker if (N0.getOperand(0).getOpcode() != ISD::AssertZext)
817*9880d681SAndroid Build Coastguard Worker return SDValue();
818*9880d681SAndroid Build Coastguard Worker
819*9880d681SAndroid Build Coastguard Worker // fold (AssertZext (trunc (AssertZext x))) -> (trunc (AssertZext x))
820*9880d681SAndroid Build Coastguard Worker // if the type of the extension of the innermost AssertZext node is
821*9880d681SAndroid Build Coastguard Worker // smaller from that of the outermost node, eg:
822*9880d681SAndroid Build Coastguard Worker // (AssertZext:i32 (trunc:i32 (AssertZext:i64 X, i32)), i8)
823*9880d681SAndroid Build Coastguard Worker // -> (trunc:i32 (AssertZext X, i8))
824*9880d681SAndroid Build Coastguard Worker SDValue WiderAssertZext = N0.getOperand(0);
825*9880d681SAndroid Build Coastguard Worker EVT WiderVT = cast<VTSDNode>(WiderAssertZext->getOperand(1))->getVT();
826*9880d681SAndroid Build Coastguard Worker
827*9880d681SAndroid Build Coastguard Worker if (NarrowerVT.bitsLT(WiderVT)) {
828*9880d681SAndroid Build Coastguard Worker SDValue NewAssertZext = DAG.getNode(
829*9880d681SAndroid Build Coastguard Worker ISD::AssertZext, SDLoc(N), WiderAssertZext.getValueType(),
830*9880d681SAndroid Build Coastguard Worker WiderAssertZext.getOperand(0), DAG.getValueType(NarrowerVT));
831*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::TRUNCATE, SDLoc(N), N->getValueType(0),
832*9880d681SAndroid Build Coastguard Worker NewAssertZext);
833*9880d681SAndroid Build Coastguard Worker }
834*9880d681SAndroid Build Coastguard Worker
835*9880d681SAndroid Build Coastguard Worker return SDValue();
836*9880d681SAndroid Build Coastguard Worker }
837*9880d681SAndroid Build Coastguard Worker
PerformDAGCombine(SDNode * N,DAGCombinerInfo & DCI) const838*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
839*9880d681SAndroid Build Coastguard Worker const {
840*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG = DCI.DAG;
841*9880d681SAndroid Build Coastguard Worker unsigned Opc = N->getOpcode();
842*9880d681SAndroid Build Coastguard Worker
843*9880d681SAndroid Build Coastguard Worker switch (Opc) {
844*9880d681SAndroid Build Coastguard Worker default: break;
845*9880d681SAndroid Build Coastguard Worker case ISD::SDIVREM:
846*9880d681SAndroid Build Coastguard Worker case ISD::UDIVREM:
847*9880d681SAndroid Build Coastguard Worker return performDivRemCombine(N, DAG, DCI, Subtarget);
848*9880d681SAndroid Build Coastguard Worker case ISD::SELECT:
849*9880d681SAndroid Build Coastguard Worker return performSELECTCombine(N, DAG, DCI, Subtarget);
850*9880d681SAndroid Build Coastguard Worker case MipsISD::CMovFP_F:
851*9880d681SAndroid Build Coastguard Worker case MipsISD::CMovFP_T:
852*9880d681SAndroid Build Coastguard Worker return performCMovFPCombine(N, DAG, DCI, Subtarget);
853*9880d681SAndroid Build Coastguard Worker case ISD::AND:
854*9880d681SAndroid Build Coastguard Worker return performANDCombine(N, DAG, DCI, Subtarget);
855*9880d681SAndroid Build Coastguard Worker case ISD::OR:
856*9880d681SAndroid Build Coastguard Worker return performORCombine(N, DAG, DCI, Subtarget);
857*9880d681SAndroid Build Coastguard Worker case ISD::ADD:
858*9880d681SAndroid Build Coastguard Worker return performADDCombine(N, DAG, DCI, Subtarget);
859*9880d681SAndroid Build Coastguard Worker case ISD::AssertZext:
860*9880d681SAndroid Build Coastguard Worker return performAssertZextCombine(N, DAG, DCI, Subtarget);
861*9880d681SAndroid Build Coastguard Worker }
862*9880d681SAndroid Build Coastguard Worker
863*9880d681SAndroid Build Coastguard Worker return SDValue();
864*9880d681SAndroid Build Coastguard Worker }
865*9880d681SAndroid Build Coastguard Worker
isCheapToSpeculateCttz() const866*9880d681SAndroid Build Coastguard Worker bool MipsTargetLowering::isCheapToSpeculateCttz() const {
867*9880d681SAndroid Build Coastguard Worker return Subtarget.hasMips32();
868*9880d681SAndroid Build Coastguard Worker }
869*9880d681SAndroid Build Coastguard Worker
isCheapToSpeculateCtlz() const870*9880d681SAndroid Build Coastguard Worker bool MipsTargetLowering::isCheapToSpeculateCtlz() const {
871*9880d681SAndroid Build Coastguard Worker return Subtarget.hasMips32();
872*9880d681SAndroid Build Coastguard Worker }
873*9880d681SAndroid Build Coastguard Worker
874*9880d681SAndroid Build Coastguard Worker void
LowerOperationWrapper(SDNode * N,SmallVectorImpl<SDValue> & Results,SelectionDAG & DAG) const875*9880d681SAndroid Build Coastguard Worker MipsTargetLowering::LowerOperationWrapper(SDNode *N,
876*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<SDValue> &Results,
877*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
878*9880d681SAndroid Build Coastguard Worker SDValue Res = LowerOperation(SDValue(N, 0), DAG);
879*9880d681SAndroid Build Coastguard Worker
880*9880d681SAndroid Build Coastguard Worker for (unsigned I = 0, E = Res->getNumValues(); I != E; ++I)
881*9880d681SAndroid Build Coastguard Worker Results.push_back(Res.getValue(I));
882*9880d681SAndroid Build Coastguard Worker }
883*9880d681SAndroid Build Coastguard Worker
884*9880d681SAndroid Build Coastguard Worker void
ReplaceNodeResults(SDNode * N,SmallVectorImpl<SDValue> & Results,SelectionDAG & DAG) const885*9880d681SAndroid Build Coastguard Worker MipsTargetLowering::ReplaceNodeResults(SDNode *N,
886*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<SDValue> &Results,
887*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
888*9880d681SAndroid Build Coastguard Worker return LowerOperationWrapper(N, Results, DAG);
889*9880d681SAndroid Build Coastguard Worker }
890*9880d681SAndroid Build Coastguard Worker
891*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::
LowerOperation(SDValue Op,SelectionDAG & DAG) const892*9880d681SAndroid Build Coastguard Worker LowerOperation(SDValue Op, SelectionDAG &DAG) const
893*9880d681SAndroid Build Coastguard Worker {
894*9880d681SAndroid Build Coastguard Worker switch (Op.getOpcode())
895*9880d681SAndroid Build Coastguard Worker {
896*9880d681SAndroid Build Coastguard Worker case ISD::BR_JT: return lowerBR_JT(Op, DAG);
897*9880d681SAndroid Build Coastguard Worker case ISD::BRCOND: return lowerBRCOND(Op, DAG);
898*9880d681SAndroid Build Coastguard Worker case ISD::ConstantPool: return lowerConstantPool(Op, DAG);
899*9880d681SAndroid Build Coastguard Worker case ISD::GlobalAddress: return lowerGlobalAddress(Op, DAG);
900*9880d681SAndroid Build Coastguard Worker case ISD::BlockAddress: return lowerBlockAddress(Op, DAG);
901*9880d681SAndroid Build Coastguard Worker case ISD::GlobalTLSAddress: return lowerGlobalTLSAddress(Op, DAG);
902*9880d681SAndroid Build Coastguard Worker case ISD::JumpTable: return lowerJumpTable(Op, DAG);
903*9880d681SAndroid Build Coastguard Worker case ISD::SELECT: return lowerSELECT(Op, DAG);
904*9880d681SAndroid Build Coastguard Worker case ISD::SETCC: return lowerSETCC(Op, DAG);
905*9880d681SAndroid Build Coastguard Worker case ISD::VASTART: return lowerVASTART(Op, DAG);
906*9880d681SAndroid Build Coastguard Worker case ISD::VAARG: return lowerVAARG(Op, DAG);
907*9880d681SAndroid Build Coastguard Worker case ISD::FCOPYSIGN: return lowerFCOPYSIGN(Op, DAG);
908*9880d681SAndroid Build Coastguard Worker case ISD::FRAMEADDR: return lowerFRAMEADDR(Op, DAG);
909*9880d681SAndroid Build Coastguard Worker case ISD::RETURNADDR: return lowerRETURNADDR(Op, DAG);
910*9880d681SAndroid Build Coastguard Worker case ISD::EH_RETURN: return lowerEH_RETURN(Op, DAG);
911*9880d681SAndroid Build Coastguard Worker case ISD::ATOMIC_FENCE: return lowerATOMIC_FENCE(Op, DAG);
912*9880d681SAndroid Build Coastguard Worker case ISD::SHL_PARTS: return lowerShiftLeftParts(Op, DAG);
913*9880d681SAndroid Build Coastguard Worker case ISD::SRA_PARTS: return lowerShiftRightParts(Op, DAG, true);
914*9880d681SAndroid Build Coastguard Worker case ISD::SRL_PARTS: return lowerShiftRightParts(Op, DAG, false);
915*9880d681SAndroid Build Coastguard Worker case ISD::LOAD: return lowerLOAD(Op, DAG);
916*9880d681SAndroid Build Coastguard Worker case ISD::STORE: return lowerSTORE(Op, DAG);
917*9880d681SAndroid Build Coastguard Worker case ISD::ADD: return lowerADD(Op, DAG);
918*9880d681SAndroid Build Coastguard Worker case ISD::FP_TO_SINT: return lowerFP_TO_SINT(Op, DAG);
919*9880d681SAndroid Build Coastguard Worker }
920*9880d681SAndroid Build Coastguard Worker return SDValue();
921*9880d681SAndroid Build Coastguard Worker }
922*9880d681SAndroid Build Coastguard Worker
923*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
924*9880d681SAndroid Build Coastguard Worker // Lower helper functions
925*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
926*9880d681SAndroid Build Coastguard Worker
927*9880d681SAndroid Build Coastguard Worker // addLiveIn - This helper function adds the specified physical register to the
928*9880d681SAndroid Build Coastguard Worker // MachineFunction as a live in value. It also creates a corresponding
929*9880d681SAndroid Build Coastguard Worker // virtual register for it.
930*9880d681SAndroid Build Coastguard Worker static unsigned
addLiveIn(MachineFunction & MF,unsigned PReg,const TargetRegisterClass * RC)931*9880d681SAndroid Build Coastguard Worker addLiveIn(MachineFunction &MF, unsigned PReg, const TargetRegisterClass *RC)
932*9880d681SAndroid Build Coastguard Worker {
933*9880d681SAndroid Build Coastguard Worker unsigned VReg = MF.getRegInfo().createVirtualRegister(RC);
934*9880d681SAndroid Build Coastguard Worker MF.getRegInfo().addLiveIn(PReg, VReg);
935*9880d681SAndroid Build Coastguard Worker return VReg;
936*9880d681SAndroid Build Coastguard Worker }
937*9880d681SAndroid Build Coastguard Worker
insertDivByZeroTrap(MachineInstr & MI,MachineBasicBlock & MBB,const TargetInstrInfo & TII,bool Is64Bit,bool IsMicroMips)938*9880d681SAndroid Build Coastguard Worker static MachineBasicBlock *insertDivByZeroTrap(MachineInstr &MI,
939*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB,
940*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo &TII,
941*9880d681SAndroid Build Coastguard Worker bool Is64Bit, bool IsMicroMips) {
942*9880d681SAndroid Build Coastguard Worker if (NoZeroDivCheck)
943*9880d681SAndroid Build Coastguard Worker return &MBB;
944*9880d681SAndroid Build Coastguard Worker
945*9880d681SAndroid Build Coastguard Worker // Insert instruction "teq $divisor_reg, $zero, 7".
946*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator I(MI);
947*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder MIB;
948*9880d681SAndroid Build Coastguard Worker MachineOperand &Divisor = MI.getOperand(2);
949*9880d681SAndroid Build Coastguard Worker MIB = BuildMI(MBB, std::next(I), MI.getDebugLoc(),
950*9880d681SAndroid Build Coastguard Worker TII.get(IsMicroMips ? Mips::TEQ_MM : Mips::TEQ))
951*9880d681SAndroid Build Coastguard Worker .addReg(Divisor.getReg(), getKillRegState(Divisor.isKill()))
952*9880d681SAndroid Build Coastguard Worker .addReg(Mips::ZERO)
953*9880d681SAndroid Build Coastguard Worker .addImm(7);
954*9880d681SAndroid Build Coastguard Worker
955*9880d681SAndroid Build Coastguard Worker // Use the 32-bit sub-register if this is a 64-bit division.
956*9880d681SAndroid Build Coastguard Worker if (Is64Bit)
957*9880d681SAndroid Build Coastguard Worker MIB->getOperand(0).setSubReg(Mips::sub_32);
958*9880d681SAndroid Build Coastguard Worker
959*9880d681SAndroid Build Coastguard Worker // Clear Divisor's kill flag.
960*9880d681SAndroid Build Coastguard Worker Divisor.setIsKill(false);
961*9880d681SAndroid Build Coastguard Worker
962*9880d681SAndroid Build Coastguard Worker // We would normally delete the original instruction here but in this case
963*9880d681SAndroid Build Coastguard Worker // we only needed to inject an additional instruction rather than replace it.
964*9880d681SAndroid Build Coastguard Worker
965*9880d681SAndroid Build Coastguard Worker return &MBB;
966*9880d681SAndroid Build Coastguard Worker }
967*9880d681SAndroid Build Coastguard Worker
968*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr & MI,MachineBasicBlock * BB) const969*9880d681SAndroid Build Coastguard Worker MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
970*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *BB) const {
971*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
972*9880d681SAndroid Build Coastguard Worker default:
973*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unexpected instr type to insert");
974*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_ADD_I8:
975*9880d681SAndroid Build Coastguard Worker return emitAtomicBinaryPartword(MI, BB, 1, Mips::ADDu);
976*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_ADD_I16:
977*9880d681SAndroid Build Coastguard Worker return emitAtomicBinaryPartword(MI, BB, 2, Mips::ADDu);
978*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_ADD_I32:
979*9880d681SAndroid Build Coastguard Worker return emitAtomicBinary(MI, BB, 4, Mips::ADDu);
980*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_ADD_I64:
981*9880d681SAndroid Build Coastguard Worker return emitAtomicBinary(MI, BB, 8, Mips::DADDu);
982*9880d681SAndroid Build Coastguard Worker
983*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_AND_I8:
984*9880d681SAndroid Build Coastguard Worker return emitAtomicBinaryPartword(MI, BB, 1, Mips::AND);
985*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_AND_I16:
986*9880d681SAndroid Build Coastguard Worker return emitAtomicBinaryPartword(MI, BB, 2, Mips::AND);
987*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_AND_I32:
988*9880d681SAndroid Build Coastguard Worker return emitAtomicBinary(MI, BB, 4, Mips::AND);
989*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_AND_I64:
990*9880d681SAndroid Build Coastguard Worker return emitAtomicBinary(MI, BB, 8, Mips::AND64);
991*9880d681SAndroid Build Coastguard Worker
992*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_OR_I8:
993*9880d681SAndroid Build Coastguard Worker return emitAtomicBinaryPartword(MI, BB, 1, Mips::OR);
994*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_OR_I16:
995*9880d681SAndroid Build Coastguard Worker return emitAtomicBinaryPartword(MI, BB, 2, Mips::OR);
996*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_OR_I32:
997*9880d681SAndroid Build Coastguard Worker return emitAtomicBinary(MI, BB, 4, Mips::OR);
998*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_OR_I64:
999*9880d681SAndroid Build Coastguard Worker return emitAtomicBinary(MI, BB, 8, Mips::OR64);
1000*9880d681SAndroid Build Coastguard Worker
1001*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_XOR_I8:
1002*9880d681SAndroid Build Coastguard Worker return emitAtomicBinaryPartword(MI, BB, 1, Mips::XOR);
1003*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_XOR_I16:
1004*9880d681SAndroid Build Coastguard Worker return emitAtomicBinaryPartword(MI, BB, 2, Mips::XOR);
1005*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_XOR_I32:
1006*9880d681SAndroid Build Coastguard Worker return emitAtomicBinary(MI, BB, 4, Mips::XOR);
1007*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_XOR_I64:
1008*9880d681SAndroid Build Coastguard Worker return emitAtomicBinary(MI, BB, 8, Mips::XOR64);
1009*9880d681SAndroid Build Coastguard Worker
1010*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_NAND_I8:
1011*9880d681SAndroid Build Coastguard Worker return emitAtomicBinaryPartword(MI, BB, 1, 0, true);
1012*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_NAND_I16:
1013*9880d681SAndroid Build Coastguard Worker return emitAtomicBinaryPartword(MI, BB, 2, 0, true);
1014*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_NAND_I32:
1015*9880d681SAndroid Build Coastguard Worker return emitAtomicBinary(MI, BB, 4, 0, true);
1016*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_NAND_I64:
1017*9880d681SAndroid Build Coastguard Worker return emitAtomicBinary(MI, BB, 8, 0, true);
1018*9880d681SAndroid Build Coastguard Worker
1019*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_SUB_I8:
1020*9880d681SAndroid Build Coastguard Worker return emitAtomicBinaryPartword(MI, BB, 1, Mips::SUBu);
1021*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_SUB_I16:
1022*9880d681SAndroid Build Coastguard Worker return emitAtomicBinaryPartword(MI, BB, 2, Mips::SUBu);
1023*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_SUB_I32:
1024*9880d681SAndroid Build Coastguard Worker return emitAtomicBinary(MI, BB, 4, Mips::SUBu);
1025*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_LOAD_SUB_I64:
1026*9880d681SAndroid Build Coastguard Worker return emitAtomicBinary(MI, BB, 8, Mips::DSUBu);
1027*9880d681SAndroid Build Coastguard Worker
1028*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_SWAP_I8:
1029*9880d681SAndroid Build Coastguard Worker return emitAtomicBinaryPartword(MI, BB, 1, 0);
1030*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_SWAP_I16:
1031*9880d681SAndroid Build Coastguard Worker return emitAtomicBinaryPartword(MI, BB, 2, 0);
1032*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_SWAP_I32:
1033*9880d681SAndroid Build Coastguard Worker return emitAtomicBinary(MI, BB, 4, 0);
1034*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_SWAP_I64:
1035*9880d681SAndroid Build Coastguard Worker return emitAtomicBinary(MI, BB, 8, 0);
1036*9880d681SAndroid Build Coastguard Worker
1037*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_CMP_SWAP_I8:
1038*9880d681SAndroid Build Coastguard Worker return emitAtomicCmpSwapPartword(MI, BB, 1);
1039*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_CMP_SWAP_I16:
1040*9880d681SAndroid Build Coastguard Worker return emitAtomicCmpSwapPartword(MI, BB, 2);
1041*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_CMP_SWAP_I32:
1042*9880d681SAndroid Build Coastguard Worker return emitAtomicCmpSwap(MI, BB, 4);
1043*9880d681SAndroid Build Coastguard Worker case Mips::ATOMIC_CMP_SWAP_I64:
1044*9880d681SAndroid Build Coastguard Worker return emitAtomicCmpSwap(MI, BB, 8);
1045*9880d681SAndroid Build Coastguard Worker case Mips::PseudoSDIV:
1046*9880d681SAndroid Build Coastguard Worker case Mips::PseudoUDIV:
1047*9880d681SAndroid Build Coastguard Worker case Mips::DIV:
1048*9880d681SAndroid Build Coastguard Worker case Mips::DIVU:
1049*9880d681SAndroid Build Coastguard Worker case Mips::MOD:
1050*9880d681SAndroid Build Coastguard Worker case Mips::MODU:
1051*9880d681SAndroid Build Coastguard Worker return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), false,
1052*9880d681SAndroid Build Coastguard Worker false);
1053*9880d681SAndroid Build Coastguard Worker case Mips::SDIV_MM_Pseudo:
1054*9880d681SAndroid Build Coastguard Worker case Mips::UDIV_MM_Pseudo:
1055*9880d681SAndroid Build Coastguard Worker case Mips::SDIV_MM:
1056*9880d681SAndroid Build Coastguard Worker case Mips::UDIV_MM:
1057*9880d681SAndroid Build Coastguard Worker case Mips::DIV_MMR6:
1058*9880d681SAndroid Build Coastguard Worker case Mips::DIVU_MMR6:
1059*9880d681SAndroid Build Coastguard Worker case Mips::MOD_MMR6:
1060*9880d681SAndroid Build Coastguard Worker case Mips::MODU_MMR6:
1061*9880d681SAndroid Build Coastguard Worker return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), false, true);
1062*9880d681SAndroid Build Coastguard Worker case Mips::PseudoDSDIV:
1063*9880d681SAndroid Build Coastguard Worker case Mips::PseudoDUDIV:
1064*9880d681SAndroid Build Coastguard Worker case Mips::DDIV:
1065*9880d681SAndroid Build Coastguard Worker case Mips::DDIVU:
1066*9880d681SAndroid Build Coastguard Worker case Mips::DMOD:
1067*9880d681SAndroid Build Coastguard Worker case Mips::DMODU:
1068*9880d681SAndroid Build Coastguard Worker return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), true, false);
1069*9880d681SAndroid Build Coastguard Worker case Mips::DDIV_MM64R6:
1070*9880d681SAndroid Build Coastguard Worker case Mips::DDIVU_MM64R6:
1071*9880d681SAndroid Build Coastguard Worker case Mips::DMOD_MM64R6:
1072*9880d681SAndroid Build Coastguard Worker case Mips::DMODU_MM64R6:
1073*9880d681SAndroid Build Coastguard Worker return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), true, true);
1074*9880d681SAndroid Build Coastguard Worker case Mips::SEL_D:
1075*9880d681SAndroid Build Coastguard Worker case Mips::SEL_D_MMR6:
1076*9880d681SAndroid Build Coastguard Worker return emitSEL_D(MI, BB);
1077*9880d681SAndroid Build Coastguard Worker
1078*9880d681SAndroid Build Coastguard Worker case Mips::PseudoSELECT_I:
1079*9880d681SAndroid Build Coastguard Worker case Mips::PseudoSELECT_I64:
1080*9880d681SAndroid Build Coastguard Worker case Mips::PseudoSELECT_S:
1081*9880d681SAndroid Build Coastguard Worker case Mips::PseudoSELECT_D32:
1082*9880d681SAndroid Build Coastguard Worker case Mips::PseudoSELECT_D64:
1083*9880d681SAndroid Build Coastguard Worker return emitPseudoSELECT(MI, BB, false, Mips::BNE);
1084*9880d681SAndroid Build Coastguard Worker case Mips::PseudoSELECTFP_F_I:
1085*9880d681SAndroid Build Coastguard Worker case Mips::PseudoSELECTFP_F_I64:
1086*9880d681SAndroid Build Coastguard Worker case Mips::PseudoSELECTFP_F_S:
1087*9880d681SAndroid Build Coastguard Worker case Mips::PseudoSELECTFP_F_D32:
1088*9880d681SAndroid Build Coastguard Worker case Mips::PseudoSELECTFP_F_D64:
1089*9880d681SAndroid Build Coastguard Worker return emitPseudoSELECT(MI, BB, true, Mips::BC1F);
1090*9880d681SAndroid Build Coastguard Worker case Mips::PseudoSELECTFP_T_I:
1091*9880d681SAndroid Build Coastguard Worker case Mips::PseudoSELECTFP_T_I64:
1092*9880d681SAndroid Build Coastguard Worker case Mips::PseudoSELECTFP_T_S:
1093*9880d681SAndroid Build Coastguard Worker case Mips::PseudoSELECTFP_T_D32:
1094*9880d681SAndroid Build Coastguard Worker case Mips::PseudoSELECTFP_T_D64:
1095*9880d681SAndroid Build Coastguard Worker return emitPseudoSELECT(MI, BB, true, Mips::BC1T);
1096*9880d681SAndroid Build Coastguard Worker }
1097*9880d681SAndroid Build Coastguard Worker }
1098*9880d681SAndroid Build Coastguard Worker
1099*9880d681SAndroid Build Coastguard Worker // This function also handles Mips::ATOMIC_SWAP_I32 (when BinOpcode == 0), and
1100*9880d681SAndroid Build Coastguard Worker // Mips::ATOMIC_LOAD_NAND_I32 (when Nand == true)
emitAtomicBinary(MachineInstr & MI,MachineBasicBlock * BB,unsigned Size,unsigned BinOpcode,bool Nand) const1101*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MipsTargetLowering::emitAtomicBinary(MachineInstr &MI,
1102*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *BB,
1103*9880d681SAndroid Build Coastguard Worker unsigned Size,
1104*9880d681SAndroid Build Coastguard Worker unsigned BinOpcode,
1105*9880d681SAndroid Build Coastguard Worker bool Nand) const {
1106*9880d681SAndroid Build Coastguard Worker assert((Size == 4 || Size == 8) && "Unsupported size for EmitAtomicBinary.");
1107*9880d681SAndroid Build Coastguard Worker
1108*9880d681SAndroid Build Coastguard Worker MachineFunction *MF = BB->getParent();
1109*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo &RegInfo = MF->getRegInfo();
1110*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8));
1111*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo *TII = Subtarget.getInstrInfo();
1112*9880d681SAndroid Build Coastguard Worker const bool ArePtrs64bit = ABI.ArePtrs64bit();
1113*9880d681SAndroid Build Coastguard Worker DebugLoc DL = MI.getDebugLoc();
1114*9880d681SAndroid Build Coastguard Worker unsigned LL, SC, AND, NOR, ZERO, BEQ;
1115*9880d681SAndroid Build Coastguard Worker
1116*9880d681SAndroid Build Coastguard Worker if (Size == 4) {
1117*9880d681SAndroid Build Coastguard Worker if (isMicroMips) {
1118*9880d681SAndroid Build Coastguard Worker LL = Mips::LL_MM;
1119*9880d681SAndroid Build Coastguard Worker SC = Mips::SC_MM;
1120*9880d681SAndroid Build Coastguard Worker } else {
1121*9880d681SAndroid Build Coastguard Worker LL = Subtarget.hasMips32r6()
1122*9880d681SAndroid Build Coastguard Worker ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6)
1123*9880d681SAndroid Build Coastguard Worker : (ArePtrs64bit ? Mips::LL64 : Mips::LL);
1124*9880d681SAndroid Build Coastguard Worker SC = Subtarget.hasMips32r6()
1125*9880d681SAndroid Build Coastguard Worker ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6)
1126*9880d681SAndroid Build Coastguard Worker : (ArePtrs64bit ? Mips::SC64 : Mips::SC);
1127*9880d681SAndroid Build Coastguard Worker }
1128*9880d681SAndroid Build Coastguard Worker
1129*9880d681SAndroid Build Coastguard Worker AND = Mips::AND;
1130*9880d681SAndroid Build Coastguard Worker NOR = Mips::NOR;
1131*9880d681SAndroid Build Coastguard Worker ZERO = Mips::ZERO;
1132*9880d681SAndroid Build Coastguard Worker BEQ = Mips::BEQ;
1133*9880d681SAndroid Build Coastguard Worker } else {
1134*9880d681SAndroid Build Coastguard Worker LL = Subtarget.hasMips64r6() ? Mips::LLD_R6 : Mips::LLD;
1135*9880d681SAndroid Build Coastguard Worker SC = Subtarget.hasMips64r6() ? Mips::SCD_R6 : Mips::SCD;
1136*9880d681SAndroid Build Coastguard Worker AND = Mips::AND64;
1137*9880d681SAndroid Build Coastguard Worker NOR = Mips::NOR64;
1138*9880d681SAndroid Build Coastguard Worker ZERO = Mips::ZERO_64;
1139*9880d681SAndroid Build Coastguard Worker BEQ = Mips::BEQ64;
1140*9880d681SAndroid Build Coastguard Worker }
1141*9880d681SAndroid Build Coastguard Worker
1142*9880d681SAndroid Build Coastguard Worker unsigned OldVal = MI.getOperand(0).getReg();
1143*9880d681SAndroid Build Coastguard Worker unsigned Ptr = MI.getOperand(1).getReg();
1144*9880d681SAndroid Build Coastguard Worker unsigned Incr = MI.getOperand(2).getReg();
1145*9880d681SAndroid Build Coastguard Worker
1146*9880d681SAndroid Build Coastguard Worker unsigned StoreVal = RegInfo.createVirtualRegister(RC);
1147*9880d681SAndroid Build Coastguard Worker unsigned AndRes = RegInfo.createVirtualRegister(RC);
1148*9880d681SAndroid Build Coastguard Worker unsigned Success = RegInfo.createVirtualRegister(RC);
1149*9880d681SAndroid Build Coastguard Worker
1150*9880d681SAndroid Build Coastguard Worker // insert new blocks after the current block
1151*9880d681SAndroid Build Coastguard Worker const BasicBlock *LLVM_BB = BB->getBasicBlock();
1152*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB);
1153*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB);
1154*9880d681SAndroid Build Coastguard Worker MachineFunction::iterator It = ++BB->getIterator();
1155*9880d681SAndroid Build Coastguard Worker MF->insert(It, loopMBB);
1156*9880d681SAndroid Build Coastguard Worker MF->insert(It, exitMBB);
1157*9880d681SAndroid Build Coastguard Worker
1158*9880d681SAndroid Build Coastguard Worker // Transfer the remainder of BB and its successor edges to exitMBB.
1159*9880d681SAndroid Build Coastguard Worker exitMBB->splice(exitMBB->begin(), BB,
1160*9880d681SAndroid Build Coastguard Worker std::next(MachineBasicBlock::iterator(MI)), BB->end());
1161*9880d681SAndroid Build Coastguard Worker exitMBB->transferSuccessorsAndUpdatePHIs(BB);
1162*9880d681SAndroid Build Coastguard Worker
1163*9880d681SAndroid Build Coastguard Worker // thisMBB:
1164*9880d681SAndroid Build Coastguard Worker // ...
1165*9880d681SAndroid Build Coastguard Worker // fallthrough --> loopMBB
1166*9880d681SAndroid Build Coastguard Worker BB->addSuccessor(loopMBB);
1167*9880d681SAndroid Build Coastguard Worker loopMBB->addSuccessor(loopMBB);
1168*9880d681SAndroid Build Coastguard Worker loopMBB->addSuccessor(exitMBB);
1169*9880d681SAndroid Build Coastguard Worker
1170*9880d681SAndroid Build Coastguard Worker // loopMBB:
1171*9880d681SAndroid Build Coastguard Worker // ll oldval, 0(ptr)
1172*9880d681SAndroid Build Coastguard Worker // <binop> storeval, oldval, incr
1173*9880d681SAndroid Build Coastguard Worker // sc success, storeval, 0(ptr)
1174*9880d681SAndroid Build Coastguard Worker // beq success, $0, loopMBB
1175*9880d681SAndroid Build Coastguard Worker BB = loopMBB;
1176*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(LL), OldVal).addReg(Ptr).addImm(0);
1177*9880d681SAndroid Build Coastguard Worker if (Nand) {
1178*9880d681SAndroid Build Coastguard Worker // and andres, oldval, incr
1179*9880d681SAndroid Build Coastguard Worker // nor storeval, $0, andres
1180*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(AND), AndRes).addReg(OldVal).addReg(Incr);
1181*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(NOR), StoreVal).addReg(ZERO).addReg(AndRes);
1182*9880d681SAndroid Build Coastguard Worker } else if (BinOpcode) {
1183*9880d681SAndroid Build Coastguard Worker // <binop> storeval, oldval, incr
1184*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(BinOpcode), StoreVal).addReg(OldVal).addReg(Incr);
1185*9880d681SAndroid Build Coastguard Worker } else {
1186*9880d681SAndroid Build Coastguard Worker StoreVal = Incr;
1187*9880d681SAndroid Build Coastguard Worker }
1188*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(SC), Success).addReg(StoreVal).addReg(Ptr).addImm(0);
1189*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(BEQ)).addReg(Success).addReg(ZERO).addMBB(loopMBB);
1190*9880d681SAndroid Build Coastguard Worker
1191*9880d681SAndroid Build Coastguard Worker MI.eraseFromParent(); // The instruction is gone now.
1192*9880d681SAndroid Build Coastguard Worker
1193*9880d681SAndroid Build Coastguard Worker return exitMBB;
1194*9880d681SAndroid Build Coastguard Worker }
1195*9880d681SAndroid Build Coastguard Worker
emitSignExtendToI32InReg(MachineInstr & MI,MachineBasicBlock * BB,unsigned Size,unsigned DstReg,unsigned SrcReg) const1196*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MipsTargetLowering::emitSignExtendToI32InReg(
1197*9880d681SAndroid Build Coastguard Worker MachineInstr &MI, MachineBasicBlock *BB, unsigned Size, unsigned DstReg,
1198*9880d681SAndroid Build Coastguard Worker unsigned SrcReg) const {
1199*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo *TII = Subtarget.getInstrInfo();
1200*9880d681SAndroid Build Coastguard Worker const DebugLoc &DL = MI.getDebugLoc();
1201*9880d681SAndroid Build Coastguard Worker
1202*9880d681SAndroid Build Coastguard Worker if (Subtarget.hasMips32r2() && Size == 1) {
1203*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::SEB), DstReg).addReg(SrcReg);
1204*9880d681SAndroid Build Coastguard Worker return BB;
1205*9880d681SAndroid Build Coastguard Worker }
1206*9880d681SAndroid Build Coastguard Worker
1207*9880d681SAndroid Build Coastguard Worker if (Subtarget.hasMips32r2() && Size == 2) {
1208*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::SEH), DstReg).addReg(SrcReg);
1209*9880d681SAndroid Build Coastguard Worker return BB;
1210*9880d681SAndroid Build Coastguard Worker }
1211*9880d681SAndroid Build Coastguard Worker
1212*9880d681SAndroid Build Coastguard Worker MachineFunction *MF = BB->getParent();
1213*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo &RegInfo = MF->getRegInfo();
1214*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = getRegClassFor(MVT::i32);
1215*9880d681SAndroid Build Coastguard Worker unsigned ScrReg = RegInfo.createVirtualRegister(RC);
1216*9880d681SAndroid Build Coastguard Worker
1217*9880d681SAndroid Build Coastguard Worker assert(Size < 32);
1218*9880d681SAndroid Build Coastguard Worker int64_t ShiftImm = 32 - (Size * 8);
1219*9880d681SAndroid Build Coastguard Worker
1220*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::SLL), ScrReg).addReg(SrcReg).addImm(ShiftImm);
1221*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::SRA), DstReg).addReg(ScrReg).addImm(ShiftImm);
1222*9880d681SAndroid Build Coastguard Worker
1223*9880d681SAndroid Build Coastguard Worker return BB;
1224*9880d681SAndroid Build Coastguard Worker }
1225*9880d681SAndroid Build Coastguard Worker
emitAtomicBinaryPartword(MachineInstr & MI,MachineBasicBlock * BB,unsigned Size,unsigned BinOpcode,bool Nand) const1226*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword(
1227*9880d681SAndroid Build Coastguard Worker MachineInstr &MI, MachineBasicBlock *BB, unsigned Size, unsigned BinOpcode,
1228*9880d681SAndroid Build Coastguard Worker bool Nand) const {
1229*9880d681SAndroid Build Coastguard Worker assert((Size == 1 || Size == 2) &&
1230*9880d681SAndroid Build Coastguard Worker "Unsupported size for EmitAtomicBinaryPartial.");
1231*9880d681SAndroid Build Coastguard Worker
1232*9880d681SAndroid Build Coastguard Worker MachineFunction *MF = BB->getParent();
1233*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo &RegInfo = MF->getRegInfo();
1234*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = getRegClassFor(MVT::i32);
1235*9880d681SAndroid Build Coastguard Worker const bool ArePtrs64bit = ABI.ArePtrs64bit();
1236*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RCp =
1237*9880d681SAndroid Build Coastguard Worker getRegClassFor(ArePtrs64bit ? MVT::i64 : MVT::i32);
1238*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo *TII = Subtarget.getInstrInfo();
1239*9880d681SAndroid Build Coastguard Worker DebugLoc DL = MI.getDebugLoc();
1240*9880d681SAndroid Build Coastguard Worker
1241*9880d681SAndroid Build Coastguard Worker unsigned Dest = MI.getOperand(0).getReg();
1242*9880d681SAndroid Build Coastguard Worker unsigned Ptr = MI.getOperand(1).getReg();
1243*9880d681SAndroid Build Coastguard Worker unsigned Incr = MI.getOperand(2).getReg();
1244*9880d681SAndroid Build Coastguard Worker
1245*9880d681SAndroid Build Coastguard Worker unsigned AlignedAddr = RegInfo.createVirtualRegister(RCp);
1246*9880d681SAndroid Build Coastguard Worker unsigned ShiftAmt = RegInfo.createVirtualRegister(RC);
1247*9880d681SAndroid Build Coastguard Worker unsigned Mask = RegInfo.createVirtualRegister(RC);
1248*9880d681SAndroid Build Coastguard Worker unsigned Mask2 = RegInfo.createVirtualRegister(RC);
1249*9880d681SAndroid Build Coastguard Worker unsigned NewVal = RegInfo.createVirtualRegister(RC);
1250*9880d681SAndroid Build Coastguard Worker unsigned OldVal = RegInfo.createVirtualRegister(RC);
1251*9880d681SAndroid Build Coastguard Worker unsigned Incr2 = RegInfo.createVirtualRegister(RC);
1252*9880d681SAndroid Build Coastguard Worker unsigned MaskLSB2 = RegInfo.createVirtualRegister(RCp);
1253*9880d681SAndroid Build Coastguard Worker unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC);
1254*9880d681SAndroid Build Coastguard Worker unsigned MaskUpper = RegInfo.createVirtualRegister(RC);
1255*9880d681SAndroid Build Coastguard Worker unsigned AndRes = RegInfo.createVirtualRegister(RC);
1256*9880d681SAndroid Build Coastguard Worker unsigned BinOpRes = RegInfo.createVirtualRegister(RC);
1257*9880d681SAndroid Build Coastguard Worker unsigned MaskedOldVal0 = RegInfo.createVirtualRegister(RC);
1258*9880d681SAndroid Build Coastguard Worker unsigned StoreVal = RegInfo.createVirtualRegister(RC);
1259*9880d681SAndroid Build Coastguard Worker unsigned MaskedOldVal1 = RegInfo.createVirtualRegister(RC);
1260*9880d681SAndroid Build Coastguard Worker unsigned SrlRes = RegInfo.createVirtualRegister(RC);
1261*9880d681SAndroid Build Coastguard Worker unsigned Success = RegInfo.createVirtualRegister(RC);
1262*9880d681SAndroid Build Coastguard Worker
1263*9880d681SAndroid Build Coastguard Worker unsigned LL, SC;
1264*9880d681SAndroid Build Coastguard Worker if (isMicroMips) {
1265*9880d681SAndroid Build Coastguard Worker LL = Mips::LL_MM;
1266*9880d681SAndroid Build Coastguard Worker SC = Mips::SC_MM;
1267*9880d681SAndroid Build Coastguard Worker } else {
1268*9880d681SAndroid Build Coastguard Worker LL = Subtarget.hasMips32r6() ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6)
1269*9880d681SAndroid Build Coastguard Worker : (ArePtrs64bit ? Mips::LL64 : Mips::LL);
1270*9880d681SAndroid Build Coastguard Worker SC = Subtarget.hasMips32r6() ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6)
1271*9880d681SAndroid Build Coastguard Worker : (ArePtrs64bit ? Mips::SC64 : Mips::SC);
1272*9880d681SAndroid Build Coastguard Worker }
1273*9880d681SAndroid Build Coastguard Worker
1274*9880d681SAndroid Build Coastguard Worker // insert new blocks after the current block
1275*9880d681SAndroid Build Coastguard Worker const BasicBlock *LLVM_BB = BB->getBasicBlock();
1276*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB);
1277*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB);
1278*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB);
1279*9880d681SAndroid Build Coastguard Worker MachineFunction::iterator It = ++BB->getIterator();
1280*9880d681SAndroid Build Coastguard Worker MF->insert(It, loopMBB);
1281*9880d681SAndroid Build Coastguard Worker MF->insert(It, sinkMBB);
1282*9880d681SAndroid Build Coastguard Worker MF->insert(It, exitMBB);
1283*9880d681SAndroid Build Coastguard Worker
1284*9880d681SAndroid Build Coastguard Worker // Transfer the remainder of BB and its successor edges to exitMBB.
1285*9880d681SAndroid Build Coastguard Worker exitMBB->splice(exitMBB->begin(), BB,
1286*9880d681SAndroid Build Coastguard Worker std::next(MachineBasicBlock::iterator(MI)), BB->end());
1287*9880d681SAndroid Build Coastguard Worker exitMBB->transferSuccessorsAndUpdatePHIs(BB);
1288*9880d681SAndroid Build Coastguard Worker
1289*9880d681SAndroid Build Coastguard Worker BB->addSuccessor(loopMBB);
1290*9880d681SAndroid Build Coastguard Worker loopMBB->addSuccessor(loopMBB);
1291*9880d681SAndroid Build Coastguard Worker loopMBB->addSuccessor(sinkMBB);
1292*9880d681SAndroid Build Coastguard Worker sinkMBB->addSuccessor(exitMBB);
1293*9880d681SAndroid Build Coastguard Worker
1294*9880d681SAndroid Build Coastguard Worker // thisMBB:
1295*9880d681SAndroid Build Coastguard Worker // addiu masklsb2,$0,-4 # 0xfffffffc
1296*9880d681SAndroid Build Coastguard Worker // and alignedaddr,ptr,masklsb2
1297*9880d681SAndroid Build Coastguard Worker // andi ptrlsb2,ptr,3
1298*9880d681SAndroid Build Coastguard Worker // sll shiftamt,ptrlsb2,3
1299*9880d681SAndroid Build Coastguard Worker // ori maskupper,$0,255 # 0xff
1300*9880d681SAndroid Build Coastguard Worker // sll mask,maskupper,shiftamt
1301*9880d681SAndroid Build Coastguard Worker // nor mask2,$0,mask
1302*9880d681SAndroid Build Coastguard Worker // sll incr2,incr,shiftamt
1303*9880d681SAndroid Build Coastguard Worker
1304*9880d681SAndroid Build Coastguard Worker int64_t MaskImm = (Size == 1) ? 255 : 65535;
1305*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(ABI.GetPtrAddiuOp()), MaskLSB2)
1306*9880d681SAndroid Build Coastguard Worker .addReg(ABI.GetNullPtr()).addImm(-4);
1307*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(ABI.GetPtrAndOp()), AlignedAddr)
1308*9880d681SAndroid Build Coastguard Worker .addReg(Ptr).addReg(MaskLSB2);
1309*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::ANDi), PtrLSB2)
1310*9880d681SAndroid Build Coastguard Worker .addReg(Ptr, 0, ArePtrs64bit ? Mips::sub_32 : 0).addImm(3);
1311*9880d681SAndroid Build Coastguard Worker if (Subtarget.isLittle()) {
1312*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::SLL), ShiftAmt).addReg(PtrLSB2).addImm(3);
1313*9880d681SAndroid Build Coastguard Worker } else {
1314*9880d681SAndroid Build Coastguard Worker unsigned Off = RegInfo.createVirtualRegister(RC);
1315*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::XORi), Off)
1316*9880d681SAndroid Build Coastguard Worker .addReg(PtrLSB2).addImm((Size == 1) ? 3 : 2);
1317*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::SLL), ShiftAmt).addReg(Off).addImm(3);
1318*9880d681SAndroid Build Coastguard Worker }
1319*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::ORi), MaskUpper)
1320*9880d681SAndroid Build Coastguard Worker .addReg(Mips::ZERO).addImm(MaskImm);
1321*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::SLLV), Mask)
1322*9880d681SAndroid Build Coastguard Worker .addReg(MaskUpper).addReg(ShiftAmt);
1323*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::NOR), Mask2).addReg(Mips::ZERO).addReg(Mask);
1324*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::SLLV), Incr2).addReg(Incr).addReg(ShiftAmt);
1325*9880d681SAndroid Build Coastguard Worker
1326*9880d681SAndroid Build Coastguard Worker // atomic.load.binop
1327*9880d681SAndroid Build Coastguard Worker // loopMBB:
1328*9880d681SAndroid Build Coastguard Worker // ll oldval,0(alignedaddr)
1329*9880d681SAndroid Build Coastguard Worker // binop binopres,oldval,incr2
1330*9880d681SAndroid Build Coastguard Worker // and newval,binopres,mask
1331*9880d681SAndroid Build Coastguard Worker // and maskedoldval0,oldval,mask2
1332*9880d681SAndroid Build Coastguard Worker // or storeval,maskedoldval0,newval
1333*9880d681SAndroid Build Coastguard Worker // sc success,storeval,0(alignedaddr)
1334*9880d681SAndroid Build Coastguard Worker // beq success,$0,loopMBB
1335*9880d681SAndroid Build Coastguard Worker
1336*9880d681SAndroid Build Coastguard Worker // atomic.swap
1337*9880d681SAndroid Build Coastguard Worker // loopMBB:
1338*9880d681SAndroid Build Coastguard Worker // ll oldval,0(alignedaddr)
1339*9880d681SAndroid Build Coastguard Worker // and newval,incr2,mask
1340*9880d681SAndroid Build Coastguard Worker // and maskedoldval0,oldval,mask2
1341*9880d681SAndroid Build Coastguard Worker // or storeval,maskedoldval0,newval
1342*9880d681SAndroid Build Coastguard Worker // sc success,storeval,0(alignedaddr)
1343*9880d681SAndroid Build Coastguard Worker // beq success,$0,loopMBB
1344*9880d681SAndroid Build Coastguard Worker
1345*9880d681SAndroid Build Coastguard Worker BB = loopMBB;
1346*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(LL), OldVal).addReg(AlignedAddr).addImm(0);
1347*9880d681SAndroid Build Coastguard Worker if (Nand) {
1348*9880d681SAndroid Build Coastguard Worker // and andres, oldval, incr2
1349*9880d681SAndroid Build Coastguard Worker // nor binopres, $0, andres
1350*9880d681SAndroid Build Coastguard Worker // and newval, binopres, mask
1351*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::AND), AndRes).addReg(OldVal).addReg(Incr2);
1352*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::NOR), BinOpRes)
1353*9880d681SAndroid Build Coastguard Worker .addReg(Mips::ZERO).addReg(AndRes);
1354*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::AND), NewVal).addReg(BinOpRes).addReg(Mask);
1355*9880d681SAndroid Build Coastguard Worker } else if (BinOpcode) {
1356*9880d681SAndroid Build Coastguard Worker // <binop> binopres, oldval, incr2
1357*9880d681SAndroid Build Coastguard Worker // and newval, binopres, mask
1358*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(BinOpcode), BinOpRes).addReg(OldVal).addReg(Incr2);
1359*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::AND), NewVal).addReg(BinOpRes).addReg(Mask);
1360*9880d681SAndroid Build Coastguard Worker } else { // atomic.swap
1361*9880d681SAndroid Build Coastguard Worker // and newval, incr2, mask
1362*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::AND), NewVal).addReg(Incr2).addReg(Mask);
1363*9880d681SAndroid Build Coastguard Worker }
1364*9880d681SAndroid Build Coastguard Worker
1365*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::AND), MaskedOldVal0)
1366*9880d681SAndroid Build Coastguard Worker .addReg(OldVal).addReg(Mask2);
1367*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::OR), StoreVal)
1368*9880d681SAndroid Build Coastguard Worker .addReg(MaskedOldVal0).addReg(NewVal);
1369*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(SC), Success)
1370*9880d681SAndroid Build Coastguard Worker .addReg(StoreVal).addReg(AlignedAddr).addImm(0);
1371*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::BEQ))
1372*9880d681SAndroid Build Coastguard Worker .addReg(Success).addReg(Mips::ZERO).addMBB(loopMBB);
1373*9880d681SAndroid Build Coastguard Worker
1374*9880d681SAndroid Build Coastguard Worker // sinkMBB:
1375*9880d681SAndroid Build Coastguard Worker // and maskedoldval1,oldval,mask
1376*9880d681SAndroid Build Coastguard Worker // srl srlres,maskedoldval1,shiftamt
1377*9880d681SAndroid Build Coastguard Worker // sign_extend dest,srlres
1378*9880d681SAndroid Build Coastguard Worker BB = sinkMBB;
1379*9880d681SAndroid Build Coastguard Worker
1380*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::AND), MaskedOldVal1)
1381*9880d681SAndroid Build Coastguard Worker .addReg(OldVal).addReg(Mask);
1382*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::SRLV), SrlRes)
1383*9880d681SAndroid Build Coastguard Worker .addReg(MaskedOldVal1).addReg(ShiftAmt);
1384*9880d681SAndroid Build Coastguard Worker BB = emitSignExtendToI32InReg(MI, BB, Size, Dest, SrlRes);
1385*9880d681SAndroid Build Coastguard Worker
1386*9880d681SAndroid Build Coastguard Worker MI.eraseFromParent(); // The instruction is gone now.
1387*9880d681SAndroid Build Coastguard Worker
1388*9880d681SAndroid Build Coastguard Worker return exitMBB;
1389*9880d681SAndroid Build Coastguard Worker }
1390*9880d681SAndroid Build Coastguard Worker
emitAtomicCmpSwap(MachineInstr & MI,MachineBasicBlock * BB,unsigned Size) const1391*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MipsTargetLowering::emitAtomicCmpSwap(MachineInstr &MI,
1392*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *BB,
1393*9880d681SAndroid Build Coastguard Worker unsigned Size) const {
1394*9880d681SAndroid Build Coastguard Worker assert((Size == 4 || Size == 8) && "Unsupported size for EmitAtomicCmpSwap.");
1395*9880d681SAndroid Build Coastguard Worker
1396*9880d681SAndroid Build Coastguard Worker MachineFunction *MF = BB->getParent();
1397*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo &RegInfo = MF->getRegInfo();
1398*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8));
1399*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo *TII = Subtarget.getInstrInfo();
1400*9880d681SAndroid Build Coastguard Worker const bool ArePtrs64bit = ABI.ArePtrs64bit();
1401*9880d681SAndroid Build Coastguard Worker DebugLoc DL = MI.getDebugLoc();
1402*9880d681SAndroid Build Coastguard Worker unsigned LL, SC, ZERO, BNE, BEQ;
1403*9880d681SAndroid Build Coastguard Worker
1404*9880d681SAndroid Build Coastguard Worker if (Size == 4) {
1405*9880d681SAndroid Build Coastguard Worker if (isMicroMips) {
1406*9880d681SAndroid Build Coastguard Worker LL = Mips::LL_MM;
1407*9880d681SAndroid Build Coastguard Worker SC = Mips::SC_MM;
1408*9880d681SAndroid Build Coastguard Worker } else {
1409*9880d681SAndroid Build Coastguard Worker LL = Subtarget.hasMips32r6()
1410*9880d681SAndroid Build Coastguard Worker ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6)
1411*9880d681SAndroid Build Coastguard Worker : (ArePtrs64bit ? Mips::LL64 : Mips::LL);
1412*9880d681SAndroid Build Coastguard Worker SC = Subtarget.hasMips32r6()
1413*9880d681SAndroid Build Coastguard Worker ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6)
1414*9880d681SAndroid Build Coastguard Worker : (ArePtrs64bit ? Mips::SC64 : Mips::SC);
1415*9880d681SAndroid Build Coastguard Worker }
1416*9880d681SAndroid Build Coastguard Worker
1417*9880d681SAndroid Build Coastguard Worker ZERO = Mips::ZERO;
1418*9880d681SAndroid Build Coastguard Worker BNE = Mips::BNE;
1419*9880d681SAndroid Build Coastguard Worker BEQ = Mips::BEQ;
1420*9880d681SAndroid Build Coastguard Worker } else {
1421*9880d681SAndroid Build Coastguard Worker LL = Subtarget.hasMips64r6() ? Mips::LLD_R6 : Mips::LLD;
1422*9880d681SAndroid Build Coastguard Worker SC = Subtarget.hasMips64r6() ? Mips::SCD_R6 : Mips::SCD;
1423*9880d681SAndroid Build Coastguard Worker ZERO = Mips::ZERO_64;
1424*9880d681SAndroid Build Coastguard Worker BNE = Mips::BNE64;
1425*9880d681SAndroid Build Coastguard Worker BEQ = Mips::BEQ64;
1426*9880d681SAndroid Build Coastguard Worker }
1427*9880d681SAndroid Build Coastguard Worker
1428*9880d681SAndroid Build Coastguard Worker unsigned Dest = MI.getOperand(0).getReg();
1429*9880d681SAndroid Build Coastguard Worker unsigned Ptr = MI.getOperand(1).getReg();
1430*9880d681SAndroid Build Coastguard Worker unsigned OldVal = MI.getOperand(2).getReg();
1431*9880d681SAndroid Build Coastguard Worker unsigned NewVal = MI.getOperand(3).getReg();
1432*9880d681SAndroid Build Coastguard Worker
1433*9880d681SAndroid Build Coastguard Worker unsigned Success = RegInfo.createVirtualRegister(RC);
1434*9880d681SAndroid Build Coastguard Worker
1435*9880d681SAndroid Build Coastguard Worker // insert new blocks after the current block
1436*9880d681SAndroid Build Coastguard Worker const BasicBlock *LLVM_BB = BB->getBasicBlock();
1437*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB);
1438*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB);
1439*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB);
1440*9880d681SAndroid Build Coastguard Worker MachineFunction::iterator It = ++BB->getIterator();
1441*9880d681SAndroid Build Coastguard Worker MF->insert(It, loop1MBB);
1442*9880d681SAndroid Build Coastguard Worker MF->insert(It, loop2MBB);
1443*9880d681SAndroid Build Coastguard Worker MF->insert(It, exitMBB);
1444*9880d681SAndroid Build Coastguard Worker
1445*9880d681SAndroid Build Coastguard Worker // Transfer the remainder of BB and its successor edges to exitMBB.
1446*9880d681SAndroid Build Coastguard Worker exitMBB->splice(exitMBB->begin(), BB,
1447*9880d681SAndroid Build Coastguard Worker std::next(MachineBasicBlock::iterator(MI)), BB->end());
1448*9880d681SAndroid Build Coastguard Worker exitMBB->transferSuccessorsAndUpdatePHIs(BB);
1449*9880d681SAndroid Build Coastguard Worker
1450*9880d681SAndroid Build Coastguard Worker // thisMBB:
1451*9880d681SAndroid Build Coastguard Worker // ...
1452*9880d681SAndroid Build Coastguard Worker // fallthrough --> loop1MBB
1453*9880d681SAndroid Build Coastguard Worker BB->addSuccessor(loop1MBB);
1454*9880d681SAndroid Build Coastguard Worker loop1MBB->addSuccessor(exitMBB);
1455*9880d681SAndroid Build Coastguard Worker loop1MBB->addSuccessor(loop2MBB);
1456*9880d681SAndroid Build Coastguard Worker loop2MBB->addSuccessor(loop1MBB);
1457*9880d681SAndroid Build Coastguard Worker loop2MBB->addSuccessor(exitMBB);
1458*9880d681SAndroid Build Coastguard Worker
1459*9880d681SAndroid Build Coastguard Worker // loop1MBB:
1460*9880d681SAndroid Build Coastguard Worker // ll dest, 0(ptr)
1461*9880d681SAndroid Build Coastguard Worker // bne dest, oldval, exitMBB
1462*9880d681SAndroid Build Coastguard Worker BB = loop1MBB;
1463*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(LL), Dest).addReg(Ptr).addImm(0);
1464*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(BNE))
1465*9880d681SAndroid Build Coastguard Worker .addReg(Dest).addReg(OldVal).addMBB(exitMBB);
1466*9880d681SAndroid Build Coastguard Worker
1467*9880d681SAndroid Build Coastguard Worker // loop2MBB:
1468*9880d681SAndroid Build Coastguard Worker // sc success, newval, 0(ptr)
1469*9880d681SAndroid Build Coastguard Worker // beq success, $0, loop1MBB
1470*9880d681SAndroid Build Coastguard Worker BB = loop2MBB;
1471*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(SC), Success)
1472*9880d681SAndroid Build Coastguard Worker .addReg(NewVal).addReg(Ptr).addImm(0);
1473*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(BEQ))
1474*9880d681SAndroid Build Coastguard Worker .addReg(Success).addReg(ZERO).addMBB(loop1MBB);
1475*9880d681SAndroid Build Coastguard Worker
1476*9880d681SAndroid Build Coastguard Worker MI.eraseFromParent(); // The instruction is gone now.
1477*9880d681SAndroid Build Coastguard Worker
1478*9880d681SAndroid Build Coastguard Worker return exitMBB;
1479*9880d681SAndroid Build Coastguard Worker }
1480*9880d681SAndroid Build Coastguard Worker
emitAtomicCmpSwapPartword(MachineInstr & MI,MachineBasicBlock * BB,unsigned Size) const1481*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MipsTargetLowering::emitAtomicCmpSwapPartword(
1482*9880d681SAndroid Build Coastguard Worker MachineInstr &MI, MachineBasicBlock *BB, unsigned Size) const {
1483*9880d681SAndroid Build Coastguard Worker assert((Size == 1 || Size == 2) &&
1484*9880d681SAndroid Build Coastguard Worker "Unsupported size for EmitAtomicCmpSwapPartial.");
1485*9880d681SAndroid Build Coastguard Worker
1486*9880d681SAndroid Build Coastguard Worker MachineFunction *MF = BB->getParent();
1487*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo &RegInfo = MF->getRegInfo();
1488*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = getRegClassFor(MVT::i32);
1489*9880d681SAndroid Build Coastguard Worker const bool ArePtrs64bit = ABI.ArePtrs64bit();
1490*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RCp =
1491*9880d681SAndroid Build Coastguard Worker getRegClassFor(ArePtrs64bit ? MVT::i64 : MVT::i32);
1492*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo *TII = Subtarget.getInstrInfo();
1493*9880d681SAndroid Build Coastguard Worker DebugLoc DL = MI.getDebugLoc();
1494*9880d681SAndroid Build Coastguard Worker
1495*9880d681SAndroid Build Coastguard Worker unsigned Dest = MI.getOperand(0).getReg();
1496*9880d681SAndroid Build Coastguard Worker unsigned Ptr = MI.getOperand(1).getReg();
1497*9880d681SAndroid Build Coastguard Worker unsigned CmpVal = MI.getOperand(2).getReg();
1498*9880d681SAndroid Build Coastguard Worker unsigned NewVal = MI.getOperand(3).getReg();
1499*9880d681SAndroid Build Coastguard Worker
1500*9880d681SAndroid Build Coastguard Worker unsigned AlignedAddr = RegInfo.createVirtualRegister(RCp);
1501*9880d681SAndroid Build Coastguard Worker unsigned ShiftAmt = RegInfo.createVirtualRegister(RC);
1502*9880d681SAndroid Build Coastguard Worker unsigned Mask = RegInfo.createVirtualRegister(RC);
1503*9880d681SAndroid Build Coastguard Worker unsigned Mask2 = RegInfo.createVirtualRegister(RC);
1504*9880d681SAndroid Build Coastguard Worker unsigned ShiftedCmpVal = RegInfo.createVirtualRegister(RC);
1505*9880d681SAndroid Build Coastguard Worker unsigned OldVal = RegInfo.createVirtualRegister(RC);
1506*9880d681SAndroid Build Coastguard Worker unsigned MaskedOldVal0 = RegInfo.createVirtualRegister(RC);
1507*9880d681SAndroid Build Coastguard Worker unsigned ShiftedNewVal = RegInfo.createVirtualRegister(RC);
1508*9880d681SAndroid Build Coastguard Worker unsigned MaskLSB2 = RegInfo.createVirtualRegister(RCp);
1509*9880d681SAndroid Build Coastguard Worker unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC);
1510*9880d681SAndroid Build Coastguard Worker unsigned MaskUpper = RegInfo.createVirtualRegister(RC);
1511*9880d681SAndroid Build Coastguard Worker unsigned MaskedCmpVal = RegInfo.createVirtualRegister(RC);
1512*9880d681SAndroid Build Coastguard Worker unsigned MaskedNewVal = RegInfo.createVirtualRegister(RC);
1513*9880d681SAndroid Build Coastguard Worker unsigned MaskedOldVal1 = RegInfo.createVirtualRegister(RC);
1514*9880d681SAndroid Build Coastguard Worker unsigned StoreVal = RegInfo.createVirtualRegister(RC);
1515*9880d681SAndroid Build Coastguard Worker unsigned SrlRes = RegInfo.createVirtualRegister(RC);
1516*9880d681SAndroid Build Coastguard Worker unsigned Success = RegInfo.createVirtualRegister(RC);
1517*9880d681SAndroid Build Coastguard Worker unsigned LL, SC;
1518*9880d681SAndroid Build Coastguard Worker
1519*9880d681SAndroid Build Coastguard Worker if (isMicroMips) {
1520*9880d681SAndroid Build Coastguard Worker LL = Mips::LL_MM;
1521*9880d681SAndroid Build Coastguard Worker SC = Mips::SC_MM;
1522*9880d681SAndroid Build Coastguard Worker } else {
1523*9880d681SAndroid Build Coastguard Worker LL = Subtarget.hasMips32r6() ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6)
1524*9880d681SAndroid Build Coastguard Worker : (ArePtrs64bit ? Mips::LL64 : Mips::LL);
1525*9880d681SAndroid Build Coastguard Worker SC = Subtarget.hasMips32r6() ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6)
1526*9880d681SAndroid Build Coastguard Worker : (ArePtrs64bit ? Mips::SC64 : Mips::SC);
1527*9880d681SAndroid Build Coastguard Worker }
1528*9880d681SAndroid Build Coastguard Worker
1529*9880d681SAndroid Build Coastguard Worker // insert new blocks after the current block
1530*9880d681SAndroid Build Coastguard Worker const BasicBlock *LLVM_BB = BB->getBasicBlock();
1531*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB);
1532*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB);
1533*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB);
1534*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB);
1535*9880d681SAndroid Build Coastguard Worker MachineFunction::iterator It = ++BB->getIterator();
1536*9880d681SAndroid Build Coastguard Worker MF->insert(It, loop1MBB);
1537*9880d681SAndroid Build Coastguard Worker MF->insert(It, loop2MBB);
1538*9880d681SAndroid Build Coastguard Worker MF->insert(It, sinkMBB);
1539*9880d681SAndroid Build Coastguard Worker MF->insert(It, exitMBB);
1540*9880d681SAndroid Build Coastguard Worker
1541*9880d681SAndroid Build Coastguard Worker // Transfer the remainder of BB and its successor edges to exitMBB.
1542*9880d681SAndroid Build Coastguard Worker exitMBB->splice(exitMBB->begin(), BB,
1543*9880d681SAndroid Build Coastguard Worker std::next(MachineBasicBlock::iterator(MI)), BB->end());
1544*9880d681SAndroid Build Coastguard Worker exitMBB->transferSuccessorsAndUpdatePHIs(BB);
1545*9880d681SAndroid Build Coastguard Worker
1546*9880d681SAndroid Build Coastguard Worker BB->addSuccessor(loop1MBB);
1547*9880d681SAndroid Build Coastguard Worker loop1MBB->addSuccessor(sinkMBB);
1548*9880d681SAndroid Build Coastguard Worker loop1MBB->addSuccessor(loop2MBB);
1549*9880d681SAndroid Build Coastguard Worker loop2MBB->addSuccessor(loop1MBB);
1550*9880d681SAndroid Build Coastguard Worker loop2MBB->addSuccessor(sinkMBB);
1551*9880d681SAndroid Build Coastguard Worker sinkMBB->addSuccessor(exitMBB);
1552*9880d681SAndroid Build Coastguard Worker
1553*9880d681SAndroid Build Coastguard Worker // FIXME: computation of newval2 can be moved to loop2MBB.
1554*9880d681SAndroid Build Coastguard Worker // thisMBB:
1555*9880d681SAndroid Build Coastguard Worker // addiu masklsb2,$0,-4 # 0xfffffffc
1556*9880d681SAndroid Build Coastguard Worker // and alignedaddr,ptr,masklsb2
1557*9880d681SAndroid Build Coastguard Worker // andi ptrlsb2,ptr,3
1558*9880d681SAndroid Build Coastguard Worker // xori ptrlsb2,ptrlsb2,3 # Only for BE
1559*9880d681SAndroid Build Coastguard Worker // sll shiftamt,ptrlsb2,3
1560*9880d681SAndroid Build Coastguard Worker // ori maskupper,$0,255 # 0xff
1561*9880d681SAndroid Build Coastguard Worker // sll mask,maskupper,shiftamt
1562*9880d681SAndroid Build Coastguard Worker // nor mask2,$0,mask
1563*9880d681SAndroid Build Coastguard Worker // andi maskedcmpval,cmpval,255
1564*9880d681SAndroid Build Coastguard Worker // sll shiftedcmpval,maskedcmpval,shiftamt
1565*9880d681SAndroid Build Coastguard Worker // andi maskednewval,newval,255
1566*9880d681SAndroid Build Coastguard Worker // sll shiftednewval,maskednewval,shiftamt
1567*9880d681SAndroid Build Coastguard Worker int64_t MaskImm = (Size == 1) ? 255 : 65535;
1568*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(ArePtrs64bit ? Mips::DADDiu : Mips::ADDiu), MaskLSB2)
1569*9880d681SAndroid Build Coastguard Worker .addReg(ABI.GetNullPtr()).addImm(-4);
1570*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(ArePtrs64bit ? Mips::AND64 : Mips::AND), AlignedAddr)
1571*9880d681SAndroid Build Coastguard Worker .addReg(Ptr).addReg(MaskLSB2);
1572*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::ANDi), PtrLSB2)
1573*9880d681SAndroid Build Coastguard Worker .addReg(Ptr, 0, ArePtrs64bit ? Mips::sub_32 : 0).addImm(3);
1574*9880d681SAndroid Build Coastguard Worker if (Subtarget.isLittle()) {
1575*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::SLL), ShiftAmt).addReg(PtrLSB2).addImm(3);
1576*9880d681SAndroid Build Coastguard Worker } else {
1577*9880d681SAndroid Build Coastguard Worker unsigned Off = RegInfo.createVirtualRegister(RC);
1578*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::XORi), Off)
1579*9880d681SAndroid Build Coastguard Worker .addReg(PtrLSB2).addImm((Size == 1) ? 3 : 2);
1580*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::SLL), ShiftAmt).addReg(Off).addImm(3);
1581*9880d681SAndroid Build Coastguard Worker }
1582*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::ORi), MaskUpper)
1583*9880d681SAndroid Build Coastguard Worker .addReg(Mips::ZERO).addImm(MaskImm);
1584*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::SLLV), Mask)
1585*9880d681SAndroid Build Coastguard Worker .addReg(MaskUpper).addReg(ShiftAmt);
1586*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::NOR), Mask2).addReg(Mips::ZERO).addReg(Mask);
1587*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::ANDi), MaskedCmpVal)
1588*9880d681SAndroid Build Coastguard Worker .addReg(CmpVal).addImm(MaskImm);
1589*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::SLLV), ShiftedCmpVal)
1590*9880d681SAndroid Build Coastguard Worker .addReg(MaskedCmpVal).addReg(ShiftAmt);
1591*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::ANDi), MaskedNewVal)
1592*9880d681SAndroid Build Coastguard Worker .addReg(NewVal).addImm(MaskImm);
1593*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::SLLV), ShiftedNewVal)
1594*9880d681SAndroid Build Coastguard Worker .addReg(MaskedNewVal).addReg(ShiftAmt);
1595*9880d681SAndroid Build Coastguard Worker
1596*9880d681SAndroid Build Coastguard Worker // loop1MBB:
1597*9880d681SAndroid Build Coastguard Worker // ll oldval,0(alginedaddr)
1598*9880d681SAndroid Build Coastguard Worker // and maskedoldval0,oldval,mask
1599*9880d681SAndroid Build Coastguard Worker // bne maskedoldval0,shiftedcmpval,sinkMBB
1600*9880d681SAndroid Build Coastguard Worker BB = loop1MBB;
1601*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(LL), OldVal).addReg(AlignedAddr).addImm(0);
1602*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::AND), MaskedOldVal0)
1603*9880d681SAndroid Build Coastguard Worker .addReg(OldVal).addReg(Mask);
1604*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::BNE))
1605*9880d681SAndroid Build Coastguard Worker .addReg(MaskedOldVal0).addReg(ShiftedCmpVal).addMBB(sinkMBB);
1606*9880d681SAndroid Build Coastguard Worker
1607*9880d681SAndroid Build Coastguard Worker // loop2MBB:
1608*9880d681SAndroid Build Coastguard Worker // and maskedoldval1,oldval,mask2
1609*9880d681SAndroid Build Coastguard Worker // or storeval,maskedoldval1,shiftednewval
1610*9880d681SAndroid Build Coastguard Worker // sc success,storeval,0(alignedaddr)
1611*9880d681SAndroid Build Coastguard Worker // beq success,$0,loop1MBB
1612*9880d681SAndroid Build Coastguard Worker BB = loop2MBB;
1613*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::AND), MaskedOldVal1)
1614*9880d681SAndroid Build Coastguard Worker .addReg(OldVal).addReg(Mask2);
1615*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::OR), StoreVal)
1616*9880d681SAndroid Build Coastguard Worker .addReg(MaskedOldVal1).addReg(ShiftedNewVal);
1617*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(SC), Success)
1618*9880d681SAndroid Build Coastguard Worker .addReg(StoreVal).addReg(AlignedAddr).addImm(0);
1619*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::BEQ))
1620*9880d681SAndroid Build Coastguard Worker .addReg(Success).addReg(Mips::ZERO).addMBB(loop1MBB);
1621*9880d681SAndroid Build Coastguard Worker
1622*9880d681SAndroid Build Coastguard Worker // sinkMBB:
1623*9880d681SAndroid Build Coastguard Worker // srl srlres,maskedoldval0,shiftamt
1624*9880d681SAndroid Build Coastguard Worker // sign_extend dest,srlres
1625*9880d681SAndroid Build Coastguard Worker BB = sinkMBB;
1626*9880d681SAndroid Build Coastguard Worker
1627*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Mips::SRLV), SrlRes)
1628*9880d681SAndroid Build Coastguard Worker .addReg(MaskedOldVal0).addReg(ShiftAmt);
1629*9880d681SAndroid Build Coastguard Worker BB = emitSignExtendToI32InReg(MI, BB, Size, Dest, SrlRes);
1630*9880d681SAndroid Build Coastguard Worker
1631*9880d681SAndroid Build Coastguard Worker MI.eraseFromParent(); // The instruction is gone now.
1632*9880d681SAndroid Build Coastguard Worker
1633*9880d681SAndroid Build Coastguard Worker return exitMBB;
1634*9880d681SAndroid Build Coastguard Worker }
1635*9880d681SAndroid Build Coastguard Worker
emitSEL_D(MachineInstr & MI,MachineBasicBlock * BB) const1636*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MipsTargetLowering::emitSEL_D(MachineInstr &MI,
1637*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *BB) const {
1638*9880d681SAndroid Build Coastguard Worker MachineFunction *MF = BB->getParent();
1639*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
1640*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo *TII = Subtarget.getInstrInfo();
1641*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo &RegInfo = MF->getRegInfo();
1642*9880d681SAndroid Build Coastguard Worker DebugLoc DL = MI.getDebugLoc();
1643*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator II(MI);
1644*9880d681SAndroid Build Coastguard Worker
1645*9880d681SAndroid Build Coastguard Worker unsigned Fc = MI.getOperand(1).getReg();
1646*9880d681SAndroid Build Coastguard Worker const auto &FGR64RegClass = TRI->getRegClass(Mips::FGR64RegClassID);
1647*9880d681SAndroid Build Coastguard Worker
1648*9880d681SAndroid Build Coastguard Worker unsigned Fc2 = RegInfo.createVirtualRegister(FGR64RegClass);
1649*9880d681SAndroid Build Coastguard Worker
1650*9880d681SAndroid Build Coastguard Worker BuildMI(*BB, II, DL, TII->get(Mips::SUBREG_TO_REG), Fc2)
1651*9880d681SAndroid Build Coastguard Worker .addImm(0)
1652*9880d681SAndroid Build Coastguard Worker .addReg(Fc)
1653*9880d681SAndroid Build Coastguard Worker .addImm(Mips::sub_lo);
1654*9880d681SAndroid Build Coastguard Worker
1655*9880d681SAndroid Build Coastguard Worker // We don't erase the original instruction, we just replace the condition
1656*9880d681SAndroid Build Coastguard Worker // register with the 64-bit super-register.
1657*9880d681SAndroid Build Coastguard Worker MI.getOperand(1).setReg(Fc2);
1658*9880d681SAndroid Build Coastguard Worker
1659*9880d681SAndroid Build Coastguard Worker return BB;
1660*9880d681SAndroid Build Coastguard Worker }
1661*9880d681SAndroid Build Coastguard Worker
1662*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1663*9880d681SAndroid Build Coastguard Worker // Misc Lower Operation implementation
1664*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
lowerBR_JT(SDValue Op,SelectionDAG & DAG) const1665*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::lowerBR_JT(SDValue Op, SelectionDAG &DAG) const {
1666*9880d681SAndroid Build Coastguard Worker SDValue Chain = Op.getOperand(0);
1667*9880d681SAndroid Build Coastguard Worker SDValue Table = Op.getOperand(1);
1668*9880d681SAndroid Build Coastguard Worker SDValue Index = Op.getOperand(2);
1669*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
1670*9880d681SAndroid Build Coastguard Worker auto &TD = DAG.getDataLayout();
1671*9880d681SAndroid Build Coastguard Worker EVT PTy = getPointerTy(TD);
1672*9880d681SAndroid Build Coastguard Worker unsigned EntrySize =
1673*9880d681SAndroid Build Coastguard Worker DAG.getMachineFunction().getJumpTableInfo()->getEntrySize(TD);
1674*9880d681SAndroid Build Coastguard Worker
1675*9880d681SAndroid Build Coastguard Worker Index = DAG.getNode(ISD::MUL, DL, PTy, Index,
1676*9880d681SAndroid Build Coastguard Worker DAG.getConstant(EntrySize, DL, PTy));
1677*9880d681SAndroid Build Coastguard Worker SDValue Addr = DAG.getNode(ISD::ADD, DL, PTy, Index, Table);
1678*9880d681SAndroid Build Coastguard Worker
1679*9880d681SAndroid Build Coastguard Worker EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), EntrySize * 8);
1680*9880d681SAndroid Build Coastguard Worker Addr =
1681*9880d681SAndroid Build Coastguard Worker DAG.getExtLoad(ISD::SEXTLOAD, DL, PTy, Chain, Addr,
1682*9880d681SAndroid Build Coastguard Worker MachinePointerInfo::getJumpTable(DAG.getMachineFunction()),
1683*9880d681SAndroid Build Coastguard Worker MemVT, false, false, false, 0);
1684*9880d681SAndroid Build Coastguard Worker Chain = Addr.getValue(1);
1685*9880d681SAndroid Build Coastguard Worker
1686*9880d681SAndroid Build Coastguard Worker if (isPositionIndependent() || ABI.IsN64()) {
1687*9880d681SAndroid Build Coastguard Worker // For PIC, the sequence is:
1688*9880d681SAndroid Build Coastguard Worker // BRIND(load(Jumptable + index) + RelocBase)
1689*9880d681SAndroid Build Coastguard Worker // RelocBase can be JumpTable, GOT or some sort of global base.
1690*9880d681SAndroid Build Coastguard Worker Addr = DAG.getNode(ISD::ADD, DL, PTy, Addr,
1691*9880d681SAndroid Build Coastguard Worker getPICJumpTableRelocBase(Table, DAG));
1692*9880d681SAndroid Build Coastguard Worker }
1693*9880d681SAndroid Build Coastguard Worker
1694*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::BRIND, DL, MVT::Other, Chain, Addr);
1695*9880d681SAndroid Build Coastguard Worker }
1696*9880d681SAndroid Build Coastguard Worker
lowerBRCOND(SDValue Op,SelectionDAG & DAG) const1697*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::lowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
1698*9880d681SAndroid Build Coastguard Worker // The first operand is the chain, the second is the condition, the third is
1699*9880d681SAndroid Build Coastguard Worker // the block to branch to if the condition is true.
1700*9880d681SAndroid Build Coastguard Worker SDValue Chain = Op.getOperand(0);
1701*9880d681SAndroid Build Coastguard Worker SDValue Dest = Op.getOperand(2);
1702*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
1703*9880d681SAndroid Build Coastguard Worker
1704*9880d681SAndroid Build Coastguard Worker assert(!Subtarget.hasMips32r6() && !Subtarget.hasMips64r6());
1705*9880d681SAndroid Build Coastguard Worker SDValue CondRes = createFPCmp(DAG, Op.getOperand(1));
1706*9880d681SAndroid Build Coastguard Worker
1707*9880d681SAndroid Build Coastguard Worker // Return if flag is not set by a floating point comparison.
1708*9880d681SAndroid Build Coastguard Worker if (CondRes.getOpcode() != MipsISD::FPCmp)
1709*9880d681SAndroid Build Coastguard Worker return Op;
1710*9880d681SAndroid Build Coastguard Worker
1711*9880d681SAndroid Build Coastguard Worker SDValue CCNode = CondRes.getOperand(2);
1712*9880d681SAndroid Build Coastguard Worker Mips::CondCode CC =
1713*9880d681SAndroid Build Coastguard Worker (Mips::CondCode)cast<ConstantSDNode>(CCNode)->getZExtValue();
1714*9880d681SAndroid Build Coastguard Worker unsigned Opc = invertFPCondCodeUser(CC) ? Mips::BRANCH_F : Mips::BRANCH_T;
1715*9880d681SAndroid Build Coastguard Worker SDValue BrCode = DAG.getConstant(Opc, DL, MVT::i32);
1716*9880d681SAndroid Build Coastguard Worker SDValue FCC0 = DAG.getRegister(Mips::FCC0, MVT::i32);
1717*9880d681SAndroid Build Coastguard Worker return DAG.getNode(MipsISD::FPBrcond, DL, Op.getValueType(), Chain, BrCode,
1718*9880d681SAndroid Build Coastguard Worker FCC0, Dest, CondRes);
1719*9880d681SAndroid Build Coastguard Worker }
1720*9880d681SAndroid Build Coastguard Worker
1721*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::
lowerSELECT(SDValue Op,SelectionDAG & DAG) const1722*9880d681SAndroid Build Coastguard Worker lowerSELECT(SDValue Op, SelectionDAG &DAG) const
1723*9880d681SAndroid Build Coastguard Worker {
1724*9880d681SAndroid Build Coastguard Worker assert(!Subtarget.hasMips32r6() && !Subtarget.hasMips64r6());
1725*9880d681SAndroid Build Coastguard Worker SDValue Cond = createFPCmp(DAG, Op.getOperand(0));
1726*9880d681SAndroid Build Coastguard Worker
1727*9880d681SAndroid Build Coastguard Worker // Return if flag is not set by a floating point comparison.
1728*9880d681SAndroid Build Coastguard Worker if (Cond.getOpcode() != MipsISD::FPCmp)
1729*9880d681SAndroid Build Coastguard Worker return Op;
1730*9880d681SAndroid Build Coastguard Worker
1731*9880d681SAndroid Build Coastguard Worker return createCMovFP(DAG, Cond, Op.getOperand(1), Op.getOperand(2),
1732*9880d681SAndroid Build Coastguard Worker SDLoc(Op));
1733*9880d681SAndroid Build Coastguard Worker }
1734*9880d681SAndroid Build Coastguard Worker
lowerSETCC(SDValue Op,SelectionDAG & DAG) const1735*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::lowerSETCC(SDValue Op, SelectionDAG &DAG) const {
1736*9880d681SAndroid Build Coastguard Worker assert(!Subtarget.hasMips32r6() && !Subtarget.hasMips64r6());
1737*9880d681SAndroid Build Coastguard Worker SDValue Cond = createFPCmp(DAG, Op);
1738*9880d681SAndroid Build Coastguard Worker
1739*9880d681SAndroid Build Coastguard Worker assert(Cond.getOpcode() == MipsISD::FPCmp &&
1740*9880d681SAndroid Build Coastguard Worker "Floating point operand expected.");
1741*9880d681SAndroid Build Coastguard Worker
1742*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
1743*9880d681SAndroid Build Coastguard Worker SDValue True = DAG.getConstant(1, DL, MVT::i32);
1744*9880d681SAndroid Build Coastguard Worker SDValue False = DAG.getConstant(0, DL, MVT::i32);
1745*9880d681SAndroid Build Coastguard Worker
1746*9880d681SAndroid Build Coastguard Worker return createCMovFP(DAG, Cond, True, False, DL);
1747*9880d681SAndroid Build Coastguard Worker }
1748*9880d681SAndroid Build Coastguard Worker
lowerGlobalAddress(SDValue Op,SelectionDAG & DAG) const1749*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op,
1750*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
1751*9880d681SAndroid Build Coastguard Worker EVT Ty = Op.getValueType();
1752*9880d681SAndroid Build Coastguard Worker GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
1753*9880d681SAndroid Build Coastguard Worker const GlobalValue *GV = N->getGlobal();
1754*9880d681SAndroid Build Coastguard Worker
1755*9880d681SAndroid Build Coastguard Worker if (!isPositionIndependent() && !ABI.IsN64()) {
1756*9880d681SAndroid Build Coastguard Worker const MipsTargetObjectFile *TLOF =
1757*9880d681SAndroid Build Coastguard Worker static_cast<const MipsTargetObjectFile *>(
1758*9880d681SAndroid Build Coastguard Worker getTargetMachine().getObjFileLowering());
1759*9880d681SAndroid Build Coastguard Worker if (TLOF->IsGlobalInSmallSection(GV, getTargetMachine()))
1760*9880d681SAndroid Build Coastguard Worker // %gp_rel relocation
1761*9880d681SAndroid Build Coastguard Worker return getAddrGPRel(N, SDLoc(N), Ty, DAG);
1762*9880d681SAndroid Build Coastguard Worker
1763*9880d681SAndroid Build Coastguard Worker // %hi/%lo relocation
1764*9880d681SAndroid Build Coastguard Worker return getAddrNonPIC(N, SDLoc(N), Ty, DAG);
1765*9880d681SAndroid Build Coastguard Worker }
1766*9880d681SAndroid Build Coastguard Worker
1767*9880d681SAndroid Build Coastguard Worker // Every other architecture would use shouldAssumeDSOLocal in here, but
1768*9880d681SAndroid Build Coastguard Worker // mips is special.
1769*9880d681SAndroid Build Coastguard Worker // * In PIC code mips requires got loads even for local statics!
1770*9880d681SAndroid Build Coastguard Worker // * To save on got entries, for local statics the got entry contains the
1771*9880d681SAndroid Build Coastguard Worker // page and an additional add instruction takes care of the low bits.
1772*9880d681SAndroid Build Coastguard Worker // * It is legal to access a hidden symbol with a non hidden undefined,
1773*9880d681SAndroid Build Coastguard Worker // so one cannot guarantee that all access to a hidden symbol will know
1774*9880d681SAndroid Build Coastguard Worker // it is hidden.
1775*9880d681SAndroid Build Coastguard Worker // * Mips linkers don't support creating a page and a full got entry for
1776*9880d681SAndroid Build Coastguard Worker // the same symbol.
1777*9880d681SAndroid Build Coastguard Worker // * Given all that, we have to use a full got entry for hidden symbols :-(
1778*9880d681SAndroid Build Coastguard Worker if (GV->hasLocalLinkage())
1779*9880d681SAndroid Build Coastguard Worker return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64());
1780*9880d681SAndroid Build Coastguard Worker
1781*9880d681SAndroid Build Coastguard Worker if (LargeGOT)
1782*9880d681SAndroid Build Coastguard Worker return getAddrGlobalLargeGOT(
1783*9880d681SAndroid Build Coastguard Worker N, SDLoc(N), Ty, DAG, MipsII::MO_GOT_HI16, MipsII::MO_GOT_LO16,
1784*9880d681SAndroid Build Coastguard Worker DAG.getEntryNode(),
1785*9880d681SAndroid Build Coastguard Worker MachinePointerInfo::getGOT(DAG.getMachineFunction()));
1786*9880d681SAndroid Build Coastguard Worker
1787*9880d681SAndroid Build Coastguard Worker return getAddrGlobal(
1788*9880d681SAndroid Build Coastguard Worker N, SDLoc(N), Ty, DAG,
1789*9880d681SAndroid Build Coastguard Worker (ABI.IsN32() || ABI.IsN64()) ? MipsII::MO_GOT_DISP : MipsII::MO_GOT,
1790*9880d681SAndroid Build Coastguard Worker DAG.getEntryNode(), MachinePointerInfo::getGOT(DAG.getMachineFunction()));
1791*9880d681SAndroid Build Coastguard Worker }
1792*9880d681SAndroid Build Coastguard Worker
lowerBlockAddress(SDValue Op,SelectionDAG & DAG) const1793*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::lowerBlockAddress(SDValue Op,
1794*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
1795*9880d681SAndroid Build Coastguard Worker BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op);
1796*9880d681SAndroid Build Coastguard Worker EVT Ty = Op.getValueType();
1797*9880d681SAndroid Build Coastguard Worker
1798*9880d681SAndroid Build Coastguard Worker if (!isPositionIndependent() && !ABI.IsN64())
1799*9880d681SAndroid Build Coastguard Worker return getAddrNonPIC(N, SDLoc(N), Ty, DAG);
1800*9880d681SAndroid Build Coastguard Worker
1801*9880d681SAndroid Build Coastguard Worker return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64());
1802*9880d681SAndroid Build Coastguard Worker }
1803*9880d681SAndroid Build Coastguard Worker
1804*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::
lowerGlobalTLSAddress(SDValue Op,SelectionDAG & DAG) const1805*9880d681SAndroid Build Coastguard Worker lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const
1806*9880d681SAndroid Build Coastguard Worker {
1807*9880d681SAndroid Build Coastguard Worker // If the relocation model is PIC, use the General Dynamic TLS Model or
1808*9880d681SAndroid Build Coastguard Worker // Local Dynamic TLS model, otherwise use the Initial Exec or
1809*9880d681SAndroid Build Coastguard Worker // Local Exec TLS Model.
1810*9880d681SAndroid Build Coastguard Worker
1811*9880d681SAndroid Build Coastguard Worker GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
1812*9880d681SAndroid Build Coastguard Worker if (DAG.getTarget().Options.EmulatedTLS)
1813*9880d681SAndroid Build Coastguard Worker return LowerToTLSEmulatedModel(GA, DAG);
1814*9880d681SAndroid Build Coastguard Worker
1815*9880d681SAndroid Build Coastguard Worker SDLoc DL(GA);
1816*9880d681SAndroid Build Coastguard Worker const GlobalValue *GV = GA->getGlobal();
1817*9880d681SAndroid Build Coastguard Worker EVT PtrVT = getPointerTy(DAG.getDataLayout());
1818*9880d681SAndroid Build Coastguard Worker
1819*9880d681SAndroid Build Coastguard Worker TLSModel::Model model = getTargetMachine().getTLSModel(GV);
1820*9880d681SAndroid Build Coastguard Worker
1821*9880d681SAndroid Build Coastguard Worker if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) {
1822*9880d681SAndroid Build Coastguard Worker // General Dynamic and Local Dynamic TLS Model.
1823*9880d681SAndroid Build Coastguard Worker unsigned Flag = (model == TLSModel::LocalDynamic) ? MipsII::MO_TLSLDM
1824*9880d681SAndroid Build Coastguard Worker : MipsII::MO_TLSGD;
1825*9880d681SAndroid Build Coastguard Worker
1826*9880d681SAndroid Build Coastguard Worker SDValue TGA = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, Flag);
1827*9880d681SAndroid Build Coastguard Worker SDValue Argument = DAG.getNode(MipsISD::Wrapper, DL, PtrVT,
1828*9880d681SAndroid Build Coastguard Worker getGlobalReg(DAG, PtrVT), TGA);
1829*9880d681SAndroid Build Coastguard Worker unsigned PtrSize = PtrVT.getSizeInBits();
1830*9880d681SAndroid Build Coastguard Worker IntegerType *PtrTy = Type::getIntNTy(*DAG.getContext(), PtrSize);
1831*9880d681SAndroid Build Coastguard Worker
1832*9880d681SAndroid Build Coastguard Worker SDValue TlsGetAddr = DAG.getExternalSymbol("__tls_get_addr", PtrVT);
1833*9880d681SAndroid Build Coastguard Worker
1834*9880d681SAndroid Build Coastguard Worker ArgListTy Args;
1835*9880d681SAndroid Build Coastguard Worker ArgListEntry Entry;
1836*9880d681SAndroid Build Coastguard Worker Entry.Node = Argument;
1837*9880d681SAndroid Build Coastguard Worker Entry.Ty = PtrTy;
1838*9880d681SAndroid Build Coastguard Worker Args.push_back(Entry);
1839*9880d681SAndroid Build Coastguard Worker
1840*9880d681SAndroid Build Coastguard Worker TargetLowering::CallLoweringInfo CLI(DAG);
1841*9880d681SAndroid Build Coastguard Worker CLI.setDebugLoc(DL).setChain(DAG.getEntryNode())
1842*9880d681SAndroid Build Coastguard Worker .setCallee(CallingConv::C, PtrTy, TlsGetAddr, std::move(Args));
1843*9880d681SAndroid Build Coastguard Worker std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
1844*9880d681SAndroid Build Coastguard Worker
1845*9880d681SAndroid Build Coastguard Worker SDValue Ret = CallResult.first;
1846*9880d681SAndroid Build Coastguard Worker
1847*9880d681SAndroid Build Coastguard Worker if (model != TLSModel::LocalDynamic)
1848*9880d681SAndroid Build Coastguard Worker return Ret;
1849*9880d681SAndroid Build Coastguard Worker
1850*9880d681SAndroid Build Coastguard Worker SDValue TGAHi = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0,
1851*9880d681SAndroid Build Coastguard Worker MipsII::MO_DTPREL_HI);
1852*9880d681SAndroid Build Coastguard Worker SDValue Hi = DAG.getNode(MipsISD::Hi, DL, PtrVT, TGAHi);
1853*9880d681SAndroid Build Coastguard Worker SDValue TGALo = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0,
1854*9880d681SAndroid Build Coastguard Worker MipsII::MO_DTPREL_LO);
1855*9880d681SAndroid Build Coastguard Worker SDValue Lo = DAG.getNode(MipsISD::Lo, DL, PtrVT, TGALo);
1856*9880d681SAndroid Build Coastguard Worker SDValue Add = DAG.getNode(ISD::ADD, DL, PtrVT, Hi, Ret);
1857*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::ADD, DL, PtrVT, Add, Lo);
1858*9880d681SAndroid Build Coastguard Worker }
1859*9880d681SAndroid Build Coastguard Worker
1860*9880d681SAndroid Build Coastguard Worker SDValue Offset;
1861*9880d681SAndroid Build Coastguard Worker if (model == TLSModel::InitialExec) {
1862*9880d681SAndroid Build Coastguard Worker // Initial Exec TLS Model
1863*9880d681SAndroid Build Coastguard Worker SDValue TGA = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0,
1864*9880d681SAndroid Build Coastguard Worker MipsII::MO_GOTTPREL);
1865*9880d681SAndroid Build Coastguard Worker TGA = DAG.getNode(MipsISD::Wrapper, DL, PtrVT, getGlobalReg(DAG, PtrVT),
1866*9880d681SAndroid Build Coastguard Worker TGA);
1867*9880d681SAndroid Build Coastguard Worker Offset = DAG.getLoad(PtrVT, DL,
1868*9880d681SAndroid Build Coastguard Worker DAG.getEntryNode(), TGA, MachinePointerInfo(),
1869*9880d681SAndroid Build Coastguard Worker false, false, false, 0);
1870*9880d681SAndroid Build Coastguard Worker } else {
1871*9880d681SAndroid Build Coastguard Worker // Local Exec TLS Model
1872*9880d681SAndroid Build Coastguard Worker assert(model == TLSModel::LocalExec);
1873*9880d681SAndroid Build Coastguard Worker SDValue TGAHi = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0,
1874*9880d681SAndroid Build Coastguard Worker MipsII::MO_TPREL_HI);
1875*9880d681SAndroid Build Coastguard Worker SDValue TGALo = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0,
1876*9880d681SAndroid Build Coastguard Worker MipsII::MO_TPREL_LO);
1877*9880d681SAndroid Build Coastguard Worker SDValue Hi = DAG.getNode(MipsISD::Hi, DL, PtrVT, TGAHi);
1878*9880d681SAndroid Build Coastguard Worker SDValue Lo = DAG.getNode(MipsISD::Lo, DL, PtrVT, TGALo);
1879*9880d681SAndroid Build Coastguard Worker Offset = DAG.getNode(ISD::ADD, DL, PtrVT, Hi, Lo);
1880*9880d681SAndroid Build Coastguard Worker }
1881*9880d681SAndroid Build Coastguard Worker
1882*9880d681SAndroid Build Coastguard Worker SDValue ThreadPointer = DAG.getNode(MipsISD::ThreadPointer, DL, PtrVT);
1883*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::ADD, DL, PtrVT, ThreadPointer, Offset);
1884*9880d681SAndroid Build Coastguard Worker }
1885*9880d681SAndroid Build Coastguard Worker
1886*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::
lowerJumpTable(SDValue Op,SelectionDAG & DAG) const1887*9880d681SAndroid Build Coastguard Worker lowerJumpTable(SDValue Op, SelectionDAG &DAG) const
1888*9880d681SAndroid Build Coastguard Worker {
1889*9880d681SAndroid Build Coastguard Worker JumpTableSDNode *N = cast<JumpTableSDNode>(Op);
1890*9880d681SAndroid Build Coastguard Worker EVT Ty = Op.getValueType();
1891*9880d681SAndroid Build Coastguard Worker
1892*9880d681SAndroid Build Coastguard Worker if (!isPositionIndependent() && !ABI.IsN64())
1893*9880d681SAndroid Build Coastguard Worker return getAddrNonPIC(N, SDLoc(N), Ty, DAG);
1894*9880d681SAndroid Build Coastguard Worker
1895*9880d681SAndroid Build Coastguard Worker return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64());
1896*9880d681SAndroid Build Coastguard Worker }
1897*9880d681SAndroid Build Coastguard Worker
1898*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::
lowerConstantPool(SDValue Op,SelectionDAG & DAG) const1899*9880d681SAndroid Build Coastguard Worker lowerConstantPool(SDValue Op, SelectionDAG &DAG) const
1900*9880d681SAndroid Build Coastguard Worker {
1901*9880d681SAndroid Build Coastguard Worker ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);
1902*9880d681SAndroid Build Coastguard Worker EVT Ty = Op.getValueType();
1903*9880d681SAndroid Build Coastguard Worker
1904*9880d681SAndroid Build Coastguard Worker if (!isPositionIndependent() && !ABI.IsN64()) {
1905*9880d681SAndroid Build Coastguard Worker const MipsTargetObjectFile *TLOF =
1906*9880d681SAndroid Build Coastguard Worker static_cast<const MipsTargetObjectFile *>(
1907*9880d681SAndroid Build Coastguard Worker getTargetMachine().getObjFileLowering());
1908*9880d681SAndroid Build Coastguard Worker
1909*9880d681SAndroid Build Coastguard Worker if (TLOF->IsConstantInSmallSection(DAG.getDataLayout(), N->getConstVal(),
1910*9880d681SAndroid Build Coastguard Worker getTargetMachine()))
1911*9880d681SAndroid Build Coastguard Worker // %gp_rel relocation
1912*9880d681SAndroid Build Coastguard Worker return getAddrGPRel(N, SDLoc(N), Ty, DAG);
1913*9880d681SAndroid Build Coastguard Worker
1914*9880d681SAndroid Build Coastguard Worker return getAddrNonPIC(N, SDLoc(N), Ty, DAG);
1915*9880d681SAndroid Build Coastguard Worker }
1916*9880d681SAndroid Build Coastguard Worker
1917*9880d681SAndroid Build Coastguard Worker return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64());
1918*9880d681SAndroid Build Coastguard Worker }
1919*9880d681SAndroid Build Coastguard Worker
lowerVASTART(SDValue Op,SelectionDAG & DAG) const1920*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const {
1921*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = DAG.getMachineFunction();
1922*9880d681SAndroid Build Coastguard Worker MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();
1923*9880d681SAndroid Build Coastguard Worker
1924*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
1925*9880d681SAndroid Build Coastguard Worker SDValue FI = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(),
1926*9880d681SAndroid Build Coastguard Worker getPointerTy(MF.getDataLayout()));
1927*9880d681SAndroid Build Coastguard Worker
1928*9880d681SAndroid Build Coastguard Worker // vastart just stores the address of the VarArgsFrameIndex slot into the
1929*9880d681SAndroid Build Coastguard Worker // memory location argument.
1930*9880d681SAndroid Build Coastguard Worker const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
1931*9880d681SAndroid Build Coastguard Worker return DAG.getStore(Op.getOperand(0), DL, FI, Op.getOperand(1),
1932*9880d681SAndroid Build Coastguard Worker MachinePointerInfo(SV), false, false, 0);
1933*9880d681SAndroid Build Coastguard Worker }
1934*9880d681SAndroid Build Coastguard Worker
lowerVAARG(SDValue Op,SelectionDAG & DAG) const1935*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const {
1936*9880d681SAndroid Build Coastguard Worker SDNode *Node = Op.getNode();
1937*9880d681SAndroid Build Coastguard Worker EVT VT = Node->getValueType(0);
1938*9880d681SAndroid Build Coastguard Worker SDValue Chain = Node->getOperand(0);
1939*9880d681SAndroid Build Coastguard Worker SDValue VAListPtr = Node->getOperand(1);
1940*9880d681SAndroid Build Coastguard Worker unsigned Align = Node->getConstantOperandVal(3);
1941*9880d681SAndroid Build Coastguard Worker const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
1942*9880d681SAndroid Build Coastguard Worker SDLoc DL(Node);
1943*9880d681SAndroid Build Coastguard Worker unsigned ArgSlotSizeInBytes = (ABI.IsN32() || ABI.IsN64()) ? 8 : 4;
1944*9880d681SAndroid Build Coastguard Worker
1945*9880d681SAndroid Build Coastguard Worker SDValue VAListLoad =
1946*9880d681SAndroid Build Coastguard Worker DAG.getLoad(getPointerTy(DAG.getDataLayout()), DL, Chain, VAListPtr,
1947*9880d681SAndroid Build Coastguard Worker MachinePointerInfo(SV), false, false, false, 0);
1948*9880d681SAndroid Build Coastguard Worker SDValue VAList = VAListLoad;
1949*9880d681SAndroid Build Coastguard Worker
1950*9880d681SAndroid Build Coastguard Worker // Re-align the pointer if necessary.
1951*9880d681SAndroid Build Coastguard Worker // It should only ever be necessary for 64-bit types on O32 since the minimum
1952*9880d681SAndroid Build Coastguard Worker // argument alignment is the same as the maximum type alignment for N32/N64.
1953*9880d681SAndroid Build Coastguard Worker //
1954*9880d681SAndroid Build Coastguard Worker // FIXME: We currently align too often. The code generator doesn't notice
1955*9880d681SAndroid Build Coastguard Worker // when the pointer is still aligned from the last va_arg (or pair of
1956*9880d681SAndroid Build Coastguard Worker // va_args for the i64 on O32 case).
1957*9880d681SAndroid Build Coastguard Worker if (Align > getMinStackArgumentAlignment()) {
1958*9880d681SAndroid Build Coastguard Worker assert(((Align & (Align-1)) == 0) && "Expected Align to be a power of 2");
1959*9880d681SAndroid Build Coastguard Worker
1960*9880d681SAndroid Build Coastguard Worker VAList = DAG.getNode(ISD::ADD, DL, VAList.getValueType(), VAList,
1961*9880d681SAndroid Build Coastguard Worker DAG.getConstant(Align - 1, DL, VAList.getValueType()));
1962*9880d681SAndroid Build Coastguard Worker
1963*9880d681SAndroid Build Coastguard Worker VAList = DAG.getNode(ISD::AND, DL, VAList.getValueType(), VAList,
1964*9880d681SAndroid Build Coastguard Worker DAG.getConstant(-(int64_t)Align, DL,
1965*9880d681SAndroid Build Coastguard Worker VAList.getValueType()));
1966*9880d681SAndroid Build Coastguard Worker }
1967*9880d681SAndroid Build Coastguard Worker
1968*9880d681SAndroid Build Coastguard Worker // Increment the pointer, VAList, to the next vaarg.
1969*9880d681SAndroid Build Coastguard Worker auto &TD = DAG.getDataLayout();
1970*9880d681SAndroid Build Coastguard Worker unsigned ArgSizeInBytes =
1971*9880d681SAndroid Build Coastguard Worker TD.getTypeAllocSize(VT.getTypeForEVT(*DAG.getContext()));
1972*9880d681SAndroid Build Coastguard Worker SDValue Tmp3 =
1973*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::ADD, DL, VAList.getValueType(), VAList,
1974*9880d681SAndroid Build Coastguard Worker DAG.getConstant(alignTo(ArgSizeInBytes, ArgSlotSizeInBytes),
1975*9880d681SAndroid Build Coastguard Worker DL, VAList.getValueType()));
1976*9880d681SAndroid Build Coastguard Worker // Store the incremented VAList to the legalized pointer
1977*9880d681SAndroid Build Coastguard Worker Chain = DAG.getStore(VAListLoad.getValue(1), DL, Tmp3, VAListPtr,
1978*9880d681SAndroid Build Coastguard Worker MachinePointerInfo(SV), false, false, 0);
1979*9880d681SAndroid Build Coastguard Worker
1980*9880d681SAndroid Build Coastguard Worker // In big-endian mode we must adjust the pointer when the load size is smaller
1981*9880d681SAndroid Build Coastguard Worker // than the argument slot size. We must also reduce the known alignment to
1982*9880d681SAndroid Build Coastguard Worker // match. For example in the N64 ABI, we must add 4 bytes to the offset to get
1983*9880d681SAndroid Build Coastguard Worker // the correct half of the slot, and reduce the alignment from 8 (slot
1984*9880d681SAndroid Build Coastguard Worker // alignment) down to 4 (type alignment).
1985*9880d681SAndroid Build Coastguard Worker if (!Subtarget.isLittle() && ArgSizeInBytes < ArgSlotSizeInBytes) {
1986*9880d681SAndroid Build Coastguard Worker unsigned Adjustment = ArgSlotSizeInBytes - ArgSizeInBytes;
1987*9880d681SAndroid Build Coastguard Worker VAList = DAG.getNode(ISD::ADD, DL, VAListPtr.getValueType(), VAList,
1988*9880d681SAndroid Build Coastguard Worker DAG.getIntPtrConstant(Adjustment, DL));
1989*9880d681SAndroid Build Coastguard Worker }
1990*9880d681SAndroid Build Coastguard Worker // Load the actual argument out of the pointer VAList
1991*9880d681SAndroid Build Coastguard Worker return DAG.getLoad(VT, DL, Chain, VAList, MachinePointerInfo(), false, false,
1992*9880d681SAndroid Build Coastguard Worker false, 0);
1993*9880d681SAndroid Build Coastguard Worker }
1994*9880d681SAndroid Build Coastguard Worker
lowerFCOPYSIGN32(SDValue Op,SelectionDAG & DAG,bool HasExtractInsert)1995*9880d681SAndroid Build Coastguard Worker static SDValue lowerFCOPYSIGN32(SDValue Op, SelectionDAG &DAG,
1996*9880d681SAndroid Build Coastguard Worker bool HasExtractInsert) {
1997*9880d681SAndroid Build Coastguard Worker EVT TyX = Op.getOperand(0).getValueType();
1998*9880d681SAndroid Build Coastguard Worker EVT TyY = Op.getOperand(1).getValueType();
1999*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
2000*9880d681SAndroid Build Coastguard Worker SDValue Const1 = DAG.getConstant(1, DL, MVT::i32);
2001*9880d681SAndroid Build Coastguard Worker SDValue Const31 = DAG.getConstant(31, DL, MVT::i32);
2002*9880d681SAndroid Build Coastguard Worker SDValue Res;
2003*9880d681SAndroid Build Coastguard Worker
2004*9880d681SAndroid Build Coastguard Worker // If operand is of type f64, extract the upper 32-bit. Otherwise, bitcast it
2005*9880d681SAndroid Build Coastguard Worker // to i32.
2006*9880d681SAndroid Build Coastguard Worker SDValue X = (TyX == MVT::f32) ?
2007*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::BITCAST, DL, MVT::i32, Op.getOperand(0)) :
2008*9880d681SAndroid Build Coastguard Worker DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(0),
2009*9880d681SAndroid Build Coastguard Worker Const1);
2010*9880d681SAndroid Build Coastguard Worker SDValue Y = (TyY == MVT::f32) ?
2011*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::BITCAST, DL, MVT::i32, Op.getOperand(1)) :
2012*9880d681SAndroid Build Coastguard Worker DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(1),
2013*9880d681SAndroid Build Coastguard Worker Const1);
2014*9880d681SAndroid Build Coastguard Worker
2015*9880d681SAndroid Build Coastguard Worker if (HasExtractInsert) {
2016*9880d681SAndroid Build Coastguard Worker // ext E, Y, 31, 1 ; extract bit31 of Y
2017*9880d681SAndroid Build Coastguard Worker // ins X, E, 31, 1 ; insert extracted bit at bit31 of X
2018*9880d681SAndroid Build Coastguard Worker SDValue E = DAG.getNode(MipsISD::Ext, DL, MVT::i32, Y, Const31, Const1);
2019*9880d681SAndroid Build Coastguard Worker Res = DAG.getNode(MipsISD::Ins, DL, MVT::i32, E, Const31, Const1, X);
2020*9880d681SAndroid Build Coastguard Worker } else {
2021*9880d681SAndroid Build Coastguard Worker // sll SllX, X, 1
2022*9880d681SAndroid Build Coastguard Worker // srl SrlX, SllX, 1
2023*9880d681SAndroid Build Coastguard Worker // srl SrlY, Y, 31
2024*9880d681SAndroid Build Coastguard Worker // sll SllY, SrlX, 31
2025*9880d681SAndroid Build Coastguard Worker // or Or, SrlX, SllY
2026*9880d681SAndroid Build Coastguard Worker SDValue SllX = DAG.getNode(ISD::SHL, DL, MVT::i32, X, Const1);
2027*9880d681SAndroid Build Coastguard Worker SDValue SrlX = DAG.getNode(ISD::SRL, DL, MVT::i32, SllX, Const1);
2028*9880d681SAndroid Build Coastguard Worker SDValue SrlY = DAG.getNode(ISD::SRL, DL, MVT::i32, Y, Const31);
2029*9880d681SAndroid Build Coastguard Worker SDValue SllY = DAG.getNode(ISD::SHL, DL, MVT::i32, SrlY, Const31);
2030*9880d681SAndroid Build Coastguard Worker Res = DAG.getNode(ISD::OR, DL, MVT::i32, SrlX, SllY);
2031*9880d681SAndroid Build Coastguard Worker }
2032*9880d681SAndroid Build Coastguard Worker
2033*9880d681SAndroid Build Coastguard Worker if (TyX == MVT::f32)
2034*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::BITCAST, DL, Op.getOperand(0).getValueType(), Res);
2035*9880d681SAndroid Build Coastguard Worker
2036*9880d681SAndroid Build Coastguard Worker SDValue LowX = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32,
2037*9880d681SAndroid Build Coastguard Worker Op.getOperand(0),
2038*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0, DL, MVT::i32));
2039*9880d681SAndroid Build Coastguard Worker return DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, LowX, Res);
2040*9880d681SAndroid Build Coastguard Worker }
2041*9880d681SAndroid Build Coastguard Worker
lowerFCOPYSIGN64(SDValue Op,SelectionDAG & DAG,bool HasExtractInsert)2042*9880d681SAndroid Build Coastguard Worker static SDValue lowerFCOPYSIGN64(SDValue Op, SelectionDAG &DAG,
2043*9880d681SAndroid Build Coastguard Worker bool HasExtractInsert) {
2044*9880d681SAndroid Build Coastguard Worker unsigned WidthX = Op.getOperand(0).getValueSizeInBits();
2045*9880d681SAndroid Build Coastguard Worker unsigned WidthY = Op.getOperand(1).getValueSizeInBits();
2046*9880d681SAndroid Build Coastguard Worker EVT TyX = MVT::getIntegerVT(WidthX), TyY = MVT::getIntegerVT(WidthY);
2047*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
2048*9880d681SAndroid Build Coastguard Worker SDValue Const1 = DAG.getConstant(1, DL, MVT::i32);
2049*9880d681SAndroid Build Coastguard Worker
2050*9880d681SAndroid Build Coastguard Worker // Bitcast to integer nodes.
2051*9880d681SAndroid Build Coastguard Worker SDValue X = DAG.getNode(ISD::BITCAST, DL, TyX, Op.getOperand(0));
2052*9880d681SAndroid Build Coastguard Worker SDValue Y = DAG.getNode(ISD::BITCAST, DL, TyY, Op.getOperand(1));
2053*9880d681SAndroid Build Coastguard Worker
2054*9880d681SAndroid Build Coastguard Worker if (HasExtractInsert) {
2055*9880d681SAndroid Build Coastguard Worker // ext E, Y, width(Y) - 1, 1 ; extract bit width(Y)-1 of Y
2056*9880d681SAndroid Build Coastguard Worker // ins X, E, width(X) - 1, 1 ; insert extracted bit at bit width(X)-1 of X
2057*9880d681SAndroid Build Coastguard Worker SDValue E = DAG.getNode(MipsISD::Ext, DL, TyY, Y,
2058*9880d681SAndroid Build Coastguard Worker DAG.getConstant(WidthY - 1, DL, MVT::i32), Const1);
2059*9880d681SAndroid Build Coastguard Worker
2060*9880d681SAndroid Build Coastguard Worker if (WidthX > WidthY)
2061*9880d681SAndroid Build Coastguard Worker E = DAG.getNode(ISD::ZERO_EXTEND, DL, TyX, E);
2062*9880d681SAndroid Build Coastguard Worker else if (WidthY > WidthX)
2063*9880d681SAndroid Build Coastguard Worker E = DAG.getNode(ISD::TRUNCATE, DL, TyX, E);
2064*9880d681SAndroid Build Coastguard Worker
2065*9880d681SAndroid Build Coastguard Worker SDValue I = DAG.getNode(MipsISD::Ins, DL, TyX, E,
2066*9880d681SAndroid Build Coastguard Worker DAG.getConstant(WidthX - 1, DL, MVT::i32), Const1,
2067*9880d681SAndroid Build Coastguard Worker X);
2068*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::BITCAST, DL, Op.getOperand(0).getValueType(), I);
2069*9880d681SAndroid Build Coastguard Worker }
2070*9880d681SAndroid Build Coastguard Worker
2071*9880d681SAndroid Build Coastguard Worker // (d)sll SllX, X, 1
2072*9880d681SAndroid Build Coastguard Worker // (d)srl SrlX, SllX, 1
2073*9880d681SAndroid Build Coastguard Worker // (d)srl SrlY, Y, width(Y)-1
2074*9880d681SAndroid Build Coastguard Worker // (d)sll SllY, SrlX, width(Y)-1
2075*9880d681SAndroid Build Coastguard Worker // or Or, SrlX, SllY
2076*9880d681SAndroid Build Coastguard Worker SDValue SllX = DAG.getNode(ISD::SHL, DL, TyX, X, Const1);
2077*9880d681SAndroid Build Coastguard Worker SDValue SrlX = DAG.getNode(ISD::SRL, DL, TyX, SllX, Const1);
2078*9880d681SAndroid Build Coastguard Worker SDValue SrlY = DAG.getNode(ISD::SRL, DL, TyY, Y,
2079*9880d681SAndroid Build Coastguard Worker DAG.getConstant(WidthY - 1, DL, MVT::i32));
2080*9880d681SAndroid Build Coastguard Worker
2081*9880d681SAndroid Build Coastguard Worker if (WidthX > WidthY)
2082*9880d681SAndroid Build Coastguard Worker SrlY = DAG.getNode(ISD::ZERO_EXTEND, DL, TyX, SrlY);
2083*9880d681SAndroid Build Coastguard Worker else if (WidthY > WidthX)
2084*9880d681SAndroid Build Coastguard Worker SrlY = DAG.getNode(ISD::TRUNCATE, DL, TyX, SrlY);
2085*9880d681SAndroid Build Coastguard Worker
2086*9880d681SAndroid Build Coastguard Worker SDValue SllY = DAG.getNode(ISD::SHL, DL, TyX, SrlY,
2087*9880d681SAndroid Build Coastguard Worker DAG.getConstant(WidthX - 1, DL, MVT::i32));
2088*9880d681SAndroid Build Coastguard Worker SDValue Or = DAG.getNode(ISD::OR, DL, TyX, SrlX, SllY);
2089*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::BITCAST, DL, Op.getOperand(0).getValueType(), Or);
2090*9880d681SAndroid Build Coastguard Worker }
2091*9880d681SAndroid Build Coastguard Worker
2092*9880d681SAndroid Build Coastguard Worker SDValue
lowerFCOPYSIGN(SDValue Op,SelectionDAG & DAG) const2093*9880d681SAndroid Build Coastguard Worker MipsTargetLowering::lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
2094*9880d681SAndroid Build Coastguard Worker if (Subtarget.isGP64bit())
2095*9880d681SAndroid Build Coastguard Worker return lowerFCOPYSIGN64(Op, DAG, Subtarget.hasExtractInsert());
2096*9880d681SAndroid Build Coastguard Worker
2097*9880d681SAndroid Build Coastguard Worker return lowerFCOPYSIGN32(Op, DAG, Subtarget.hasExtractInsert());
2098*9880d681SAndroid Build Coastguard Worker }
2099*9880d681SAndroid Build Coastguard Worker
2100*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::
lowerFRAMEADDR(SDValue Op,SelectionDAG & DAG) const2101*9880d681SAndroid Build Coastguard Worker lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
2102*9880d681SAndroid Build Coastguard Worker // check the depth
2103*9880d681SAndroid Build Coastguard Worker assert((cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0) &&
2104*9880d681SAndroid Build Coastguard Worker "Frame address can only be determined for current frame.");
2105*9880d681SAndroid Build Coastguard Worker
2106*9880d681SAndroid Build Coastguard Worker MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
2107*9880d681SAndroid Build Coastguard Worker MFI->setFrameAddressIsTaken(true);
2108*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
2109*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
2110*9880d681SAndroid Build Coastguard Worker SDValue FrameAddr = DAG.getCopyFromReg(
2111*9880d681SAndroid Build Coastguard Worker DAG.getEntryNode(), DL, ABI.IsN64() ? Mips::FP_64 : Mips::FP, VT);
2112*9880d681SAndroid Build Coastguard Worker return FrameAddr;
2113*9880d681SAndroid Build Coastguard Worker }
2114*9880d681SAndroid Build Coastguard Worker
lowerRETURNADDR(SDValue Op,SelectionDAG & DAG) const2115*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::lowerRETURNADDR(SDValue Op,
2116*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
2117*9880d681SAndroid Build Coastguard Worker if (verifyReturnAddressArgumentIsConstant(Op, DAG))
2118*9880d681SAndroid Build Coastguard Worker return SDValue();
2119*9880d681SAndroid Build Coastguard Worker
2120*9880d681SAndroid Build Coastguard Worker // check the depth
2121*9880d681SAndroid Build Coastguard Worker assert((cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0) &&
2122*9880d681SAndroid Build Coastguard Worker "Return address can be determined only for current frame.");
2123*9880d681SAndroid Build Coastguard Worker
2124*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = DAG.getMachineFunction();
2125*9880d681SAndroid Build Coastguard Worker MachineFrameInfo *MFI = MF.getFrameInfo();
2126*9880d681SAndroid Build Coastguard Worker MVT VT = Op.getSimpleValueType();
2127*9880d681SAndroid Build Coastguard Worker unsigned RA = ABI.IsN64() ? Mips::RA_64 : Mips::RA;
2128*9880d681SAndroid Build Coastguard Worker MFI->setReturnAddressIsTaken(true);
2129*9880d681SAndroid Build Coastguard Worker
2130*9880d681SAndroid Build Coastguard Worker // Return RA, which contains the return address. Mark it an implicit live-in.
2131*9880d681SAndroid Build Coastguard Worker unsigned Reg = MF.addLiveIn(RA, getRegClassFor(VT));
2132*9880d681SAndroid Build Coastguard Worker return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), Reg, VT);
2133*9880d681SAndroid Build Coastguard Worker }
2134*9880d681SAndroid Build Coastguard Worker
2135*9880d681SAndroid Build Coastguard Worker // An EH_RETURN is the result of lowering llvm.eh.return which in turn is
2136*9880d681SAndroid Build Coastguard Worker // generated from __builtin_eh_return (offset, handler)
2137*9880d681SAndroid Build Coastguard Worker // The effect of this is to adjust the stack pointer by "offset"
2138*9880d681SAndroid Build Coastguard Worker // and then branch to "handler".
lowerEH_RETURN(SDValue Op,SelectionDAG & DAG) const2139*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::lowerEH_RETURN(SDValue Op, SelectionDAG &DAG)
2140*9880d681SAndroid Build Coastguard Worker const {
2141*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = DAG.getMachineFunction();
2142*9880d681SAndroid Build Coastguard Worker MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
2143*9880d681SAndroid Build Coastguard Worker
2144*9880d681SAndroid Build Coastguard Worker MipsFI->setCallsEhReturn();
2145*9880d681SAndroid Build Coastguard Worker SDValue Chain = Op.getOperand(0);
2146*9880d681SAndroid Build Coastguard Worker SDValue Offset = Op.getOperand(1);
2147*9880d681SAndroid Build Coastguard Worker SDValue Handler = Op.getOperand(2);
2148*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
2149*9880d681SAndroid Build Coastguard Worker EVT Ty = ABI.IsN64() ? MVT::i64 : MVT::i32;
2150*9880d681SAndroid Build Coastguard Worker
2151*9880d681SAndroid Build Coastguard Worker // Store stack offset in V1, store jump target in V0. Glue CopyToReg and
2152*9880d681SAndroid Build Coastguard Worker // EH_RETURN nodes, so that instructions are emitted back-to-back.
2153*9880d681SAndroid Build Coastguard Worker unsigned OffsetReg = ABI.IsN64() ? Mips::V1_64 : Mips::V1;
2154*9880d681SAndroid Build Coastguard Worker unsigned AddrReg = ABI.IsN64() ? Mips::V0_64 : Mips::V0;
2155*9880d681SAndroid Build Coastguard Worker Chain = DAG.getCopyToReg(Chain, DL, OffsetReg, Offset, SDValue());
2156*9880d681SAndroid Build Coastguard Worker Chain = DAG.getCopyToReg(Chain, DL, AddrReg, Handler, Chain.getValue(1));
2157*9880d681SAndroid Build Coastguard Worker return DAG.getNode(MipsISD::EH_RETURN, DL, MVT::Other, Chain,
2158*9880d681SAndroid Build Coastguard Worker DAG.getRegister(OffsetReg, Ty),
2159*9880d681SAndroid Build Coastguard Worker DAG.getRegister(AddrReg, getPointerTy(MF.getDataLayout())),
2160*9880d681SAndroid Build Coastguard Worker Chain.getValue(1));
2161*9880d681SAndroid Build Coastguard Worker }
2162*9880d681SAndroid Build Coastguard Worker
lowerATOMIC_FENCE(SDValue Op,SelectionDAG & DAG) const2163*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::lowerATOMIC_FENCE(SDValue Op,
2164*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
2165*9880d681SAndroid Build Coastguard Worker // FIXME: Need pseudo-fence for 'singlethread' fences
2166*9880d681SAndroid Build Coastguard Worker // FIXME: Set SType for weaker fences where supported/appropriate.
2167*9880d681SAndroid Build Coastguard Worker unsigned SType = 0;
2168*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
2169*9880d681SAndroid Build Coastguard Worker return DAG.getNode(MipsISD::Sync, DL, MVT::Other, Op.getOperand(0),
2170*9880d681SAndroid Build Coastguard Worker DAG.getConstant(SType, DL, MVT::i32));
2171*9880d681SAndroid Build Coastguard Worker }
2172*9880d681SAndroid Build Coastguard Worker
lowerShiftLeftParts(SDValue Op,SelectionDAG & DAG) const2173*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::lowerShiftLeftParts(SDValue Op,
2174*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
2175*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
2176*9880d681SAndroid Build Coastguard Worker MVT VT = Subtarget.isGP64bit() ? MVT::i64 : MVT::i32;
2177*9880d681SAndroid Build Coastguard Worker
2178*9880d681SAndroid Build Coastguard Worker SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1);
2179*9880d681SAndroid Build Coastguard Worker SDValue Shamt = Op.getOperand(2);
2180*9880d681SAndroid Build Coastguard Worker // if shamt < (VT.bits):
2181*9880d681SAndroid Build Coastguard Worker // lo = (shl lo, shamt)
2182*9880d681SAndroid Build Coastguard Worker // hi = (or (shl hi, shamt) (srl (srl lo, 1), ~shamt))
2183*9880d681SAndroid Build Coastguard Worker // else:
2184*9880d681SAndroid Build Coastguard Worker // lo = 0
2185*9880d681SAndroid Build Coastguard Worker // hi = (shl lo, shamt[4:0])
2186*9880d681SAndroid Build Coastguard Worker SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt,
2187*9880d681SAndroid Build Coastguard Worker DAG.getConstant(-1, DL, MVT::i32));
2188*9880d681SAndroid Build Coastguard Worker SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo,
2189*9880d681SAndroid Build Coastguard Worker DAG.getConstant(1, DL, VT));
2190*9880d681SAndroid Build Coastguard Worker SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, Not);
2191*9880d681SAndroid Build Coastguard Worker SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, Hi, Shamt);
2192*9880d681SAndroid Build Coastguard Worker SDValue Or = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo);
2193*9880d681SAndroid Build Coastguard Worker SDValue ShiftLeftLo = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt);
2194*9880d681SAndroid Build Coastguard Worker SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt,
2195*9880d681SAndroid Build Coastguard Worker DAG.getConstant(VT.getSizeInBits(), DL, MVT::i32));
2196*9880d681SAndroid Build Coastguard Worker Lo = DAG.getNode(ISD::SELECT, DL, VT, Cond,
2197*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0, DL, VT), ShiftLeftLo);
2198*9880d681SAndroid Build Coastguard Worker Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond, ShiftLeftLo, Or);
2199*9880d681SAndroid Build Coastguard Worker
2200*9880d681SAndroid Build Coastguard Worker SDValue Ops[2] = {Lo, Hi};
2201*9880d681SAndroid Build Coastguard Worker return DAG.getMergeValues(Ops, DL);
2202*9880d681SAndroid Build Coastguard Worker }
2203*9880d681SAndroid Build Coastguard Worker
lowerShiftRightParts(SDValue Op,SelectionDAG & DAG,bool IsSRA) const2204*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG,
2205*9880d681SAndroid Build Coastguard Worker bool IsSRA) const {
2206*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
2207*9880d681SAndroid Build Coastguard Worker SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1);
2208*9880d681SAndroid Build Coastguard Worker SDValue Shamt = Op.getOperand(2);
2209*9880d681SAndroid Build Coastguard Worker MVT VT = Subtarget.isGP64bit() ? MVT::i64 : MVT::i32;
2210*9880d681SAndroid Build Coastguard Worker
2211*9880d681SAndroid Build Coastguard Worker // if shamt < (VT.bits):
2212*9880d681SAndroid Build Coastguard Worker // lo = (or (shl (shl hi, 1), ~shamt) (srl lo, shamt))
2213*9880d681SAndroid Build Coastguard Worker // if isSRA:
2214*9880d681SAndroid Build Coastguard Worker // hi = (sra hi, shamt)
2215*9880d681SAndroid Build Coastguard Worker // else:
2216*9880d681SAndroid Build Coastguard Worker // hi = (srl hi, shamt)
2217*9880d681SAndroid Build Coastguard Worker // else:
2218*9880d681SAndroid Build Coastguard Worker // if isSRA:
2219*9880d681SAndroid Build Coastguard Worker // lo = (sra hi, shamt[4:0])
2220*9880d681SAndroid Build Coastguard Worker // hi = (sra hi, 31)
2221*9880d681SAndroid Build Coastguard Worker // else:
2222*9880d681SAndroid Build Coastguard Worker // lo = (srl hi, shamt[4:0])
2223*9880d681SAndroid Build Coastguard Worker // hi = 0
2224*9880d681SAndroid Build Coastguard Worker SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt,
2225*9880d681SAndroid Build Coastguard Worker DAG.getConstant(-1, DL, MVT::i32));
2226*9880d681SAndroid Build Coastguard Worker SDValue ShiftLeft1Hi = DAG.getNode(ISD::SHL, DL, VT, Hi,
2227*9880d681SAndroid Build Coastguard Worker DAG.getConstant(1, DL, VT));
2228*9880d681SAndroid Build Coastguard Worker SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, ShiftLeft1Hi, Not);
2229*9880d681SAndroid Build Coastguard Worker SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, Lo, Shamt);
2230*9880d681SAndroid Build Coastguard Worker SDValue Or = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo);
2231*9880d681SAndroid Build Coastguard Worker SDValue ShiftRightHi = DAG.getNode(IsSRA ? ISD::SRA : ISD::SRL,
2232*9880d681SAndroid Build Coastguard Worker DL, VT, Hi, Shamt);
2233*9880d681SAndroid Build Coastguard Worker SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt,
2234*9880d681SAndroid Build Coastguard Worker DAG.getConstant(VT.getSizeInBits(), DL, MVT::i32));
2235*9880d681SAndroid Build Coastguard Worker SDValue Ext = DAG.getNode(ISD::SRA, DL, VT, Hi,
2236*9880d681SAndroid Build Coastguard Worker DAG.getConstant(VT.getSizeInBits() - 1, DL, VT));
2237*9880d681SAndroid Build Coastguard Worker Lo = DAG.getNode(ISD::SELECT, DL, VT, Cond, ShiftRightHi, Or);
2238*9880d681SAndroid Build Coastguard Worker Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond,
2239*9880d681SAndroid Build Coastguard Worker IsSRA ? Ext : DAG.getConstant(0, DL, VT), ShiftRightHi);
2240*9880d681SAndroid Build Coastguard Worker
2241*9880d681SAndroid Build Coastguard Worker SDValue Ops[2] = {Lo, Hi};
2242*9880d681SAndroid Build Coastguard Worker return DAG.getMergeValues(Ops, DL);
2243*9880d681SAndroid Build Coastguard Worker }
2244*9880d681SAndroid Build Coastguard Worker
createLoadLR(unsigned Opc,SelectionDAG & DAG,LoadSDNode * LD,SDValue Chain,SDValue Src,unsigned Offset)2245*9880d681SAndroid Build Coastguard Worker static SDValue createLoadLR(unsigned Opc, SelectionDAG &DAG, LoadSDNode *LD,
2246*9880d681SAndroid Build Coastguard Worker SDValue Chain, SDValue Src, unsigned Offset) {
2247*9880d681SAndroid Build Coastguard Worker SDValue Ptr = LD->getBasePtr();
2248*9880d681SAndroid Build Coastguard Worker EVT VT = LD->getValueType(0), MemVT = LD->getMemoryVT();
2249*9880d681SAndroid Build Coastguard Worker EVT BasePtrVT = Ptr.getValueType();
2250*9880d681SAndroid Build Coastguard Worker SDLoc DL(LD);
2251*9880d681SAndroid Build Coastguard Worker SDVTList VTList = DAG.getVTList(VT, MVT::Other);
2252*9880d681SAndroid Build Coastguard Worker
2253*9880d681SAndroid Build Coastguard Worker if (Offset)
2254*9880d681SAndroid Build Coastguard Worker Ptr = DAG.getNode(ISD::ADD, DL, BasePtrVT, Ptr,
2255*9880d681SAndroid Build Coastguard Worker DAG.getConstant(Offset, DL, BasePtrVT));
2256*9880d681SAndroid Build Coastguard Worker
2257*9880d681SAndroid Build Coastguard Worker SDValue Ops[] = { Chain, Ptr, Src };
2258*9880d681SAndroid Build Coastguard Worker return DAG.getMemIntrinsicNode(Opc, DL, VTList, Ops, MemVT,
2259*9880d681SAndroid Build Coastguard Worker LD->getMemOperand());
2260*9880d681SAndroid Build Coastguard Worker }
2261*9880d681SAndroid Build Coastguard Worker
2262*9880d681SAndroid Build Coastguard Worker // Expand an unaligned 32 or 64-bit integer load node.
lowerLOAD(SDValue Op,SelectionDAG & DAG) const2263*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const {
2264*9880d681SAndroid Build Coastguard Worker LoadSDNode *LD = cast<LoadSDNode>(Op);
2265*9880d681SAndroid Build Coastguard Worker EVT MemVT = LD->getMemoryVT();
2266*9880d681SAndroid Build Coastguard Worker
2267*9880d681SAndroid Build Coastguard Worker if (Subtarget.systemSupportsUnalignedAccess())
2268*9880d681SAndroid Build Coastguard Worker return Op;
2269*9880d681SAndroid Build Coastguard Worker
2270*9880d681SAndroid Build Coastguard Worker // Return if load is aligned or if MemVT is neither i32 nor i64.
2271*9880d681SAndroid Build Coastguard Worker if ((LD->getAlignment() >= MemVT.getSizeInBits() / 8) ||
2272*9880d681SAndroid Build Coastguard Worker ((MemVT != MVT::i32) && (MemVT != MVT::i64)))
2273*9880d681SAndroid Build Coastguard Worker return SDValue();
2274*9880d681SAndroid Build Coastguard Worker
2275*9880d681SAndroid Build Coastguard Worker bool IsLittle = Subtarget.isLittle();
2276*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
2277*9880d681SAndroid Build Coastguard Worker ISD::LoadExtType ExtType = LD->getExtensionType();
2278*9880d681SAndroid Build Coastguard Worker SDValue Chain = LD->getChain(), Undef = DAG.getUNDEF(VT);
2279*9880d681SAndroid Build Coastguard Worker
2280*9880d681SAndroid Build Coastguard Worker assert((VT == MVT::i32) || (VT == MVT::i64));
2281*9880d681SAndroid Build Coastguard Worker
2282*9880d681SAndroid Build Coastguard Worker // Expand
2283*9880d681SAndroid Build Coastguard Worker // (set dst, (i64 (load baseptr)))
2284*9880d681SAndroid Build Coastguard Worker // to
2285*9880d681SAndroid Build Coastguard Worker // (set tmp, (ldl (add baseptr, 7), undef))
2286*9880d681SAndroid Build Coastguard Worker // (set dst, (ldr baseptr, tmp))
2287*9880d681SAndroid Build Coastguard Worker if ((VT == MVT::i64) && (ExtType == ISD::NON_EXTLOAD)) {
2288*9880d681SAndroid Build Coastguard Worker SDValue LDL = createLoadLR(MipsISD::LDL, DAG, LD, Chain, Undef,
2289*9880d681SAndroid Build Coastguard Worker IsLittle ? 7 : 0);
2290*9880d681SAndroid Build Coastguard Worker return createLoadLR(MipsISD::LDR, DAG, LD, LDL.getValue(1), LDL,
2291*9880d681SAndroid Build Coastguard Worker IsLittle ? 0 : 7);
2292*9880d681SAndroid Build Coastguard Worker }
2293*9880d681SAndroid Build Coastguard Worker
2294*9880d681SAndroid Build Coastguard Worker SDValue LWL = createLoadLR(MipsISD::LWL, DAG, LD, Chain, Undef,
2295*9880d681SAndroid Build Coastguard Worker IsLittle ? 3 : 0);
2296*9880d681SAndroid Build Coastguard Worker SDValue LWR = createLoadLR(MipsISD::LWR, DAG, LD, LWL.getValue(1), LWL,
2297*9880d681SAndroid Build Coastguard Worker IsLittle ? 0 : 3);
2298*9880d681SAndroid Build Coastguard Worker
2299*9880d681SAndroid Build Coastguard Worker // Expand
2300*9880d681SAndroid Build Coastguard Worker // (set dst, (i32 (load baseptr))) or
2301*9880d681SAndroid Build Coastguard Worker // (set dst, (i64 (sextload baseptr))) or
2302*9880d681SAndroid Build Coastguard Worker // (set dst, (i64 (extload baseptr)))
2303*9880d681SAndroid Build Coastguard Worker // to
2304*9880d681SAndroid Build Coastguard Worker // (set tmp, (lwl (add baseptr, 3), undef))
2305*9880d681SAndroid Build Coastguard Worker // (set dst, (lwr baseptr, tmp))
2306*9880d681SAndroid Build Coastguard Worker if ((VT == MVT::i32) || (ExtType == ISD::SEXTLOAD) ||
2307*9880d681SAndroid Build Coastguard Worker (ExtType == ISD::EXTLOAD))
2308*9880d681SAndroid Build Coastguard Worker return LWR;
2309*9880d681SAndroid Build Coastguard Worker
2310*9880d681SAndroid Build Coastguard Worker assert((VT == MVT::i64) && (ExtType == ISD::ZEXTLOAD));
2311*9880d681SAndroid Build Coastguard Worker
2312*9880d681SAndroid Build Coastguard Worker // Expand
2313*9880d681SAndroid Build Coastguard Worker // (set dst, (i64 (zextload baseptr)))
2314*9880d681SAndroid Build Coastguard Worker // to
2315*9880d681SAndroid Build Coastguard Worker // (set tmp0, (lwl (add baseptr, 3), undef))
2316*9880d681SAndroid Build Coastguard Worker // (set tmp1, (lwr baseptr, tmp0))
2317*9880d681SAndroid Build Coastguard Worker // (set tmp2, (shl tmp1, 32))
2318*9880d681SAndroid Build Coastguard Worker // (set dst, (srl tmp2, 32))
2319*9880d681SAndroid Build Coastguard Worker SDLoc DL(LD);
2320*9880d681SAndroid Build Coastguard Worker SDValue Const32 = DAG.getConstant(32, DL, MVT::i32);
2321*9880d681SAndroid Build Coastguard Worker SDValue SLL = DAG.getNode(ISD::SHL, DL, MVT::i64, LWR, Const32);
2322*9880d681SAndroid Build Coastguard Worker SDValue SRL = DAG.getNode(ISD::SRL, DL, MVT::i64, SLL, Const32);
2323*9880d681SAndroid Build Coastguard Worker SDValue Ops[] = { SRL, LWR.getValue(1) };
2324*9880d681SAndroid Build Coastguard Worker return DAG.getMergeValues(Ops, DL);
2325*9880d681SAndroid Build Coastguard Worker }
2326*9880d681SAndroid Build Coastguard Worker
createStoreLR(unsigned Opc,SelectionDAG & DAG,StoreSDNode * SD,SDValue Chain,unsigned Offset)2327*9880d681SAndroid Build Coastguard Worker static SDValue createStoreLR(unsigned Opc, SelectionDAG &DAG, StoreSDNode *SD,
2328*9880d681SAndroid Build Coastguard Worker SDValue Chain, unsigned Offset) {
2329*9880d681SAndroid Build Coastguard Worker SDValue Ptr = SD->getBasePtr(), Value = SD->getValue();
2330*9880d681SAndroid Build Coastguard Worker EVT MemVT = SD->getMemoryVT(), BasePtrVT = Ptr.getValueType();
2331*9880d681SAndroid Build Coastguard Worker SDLoc DL(SD);
2332*9880d681SAndroid Build Coastguard Worker SDVTList VTList = DAG.getVTList(MVT::Other);
2333*9880d681SAndroid Build Coastguard Worker
2334*9880d681SAndroid Build Coastguard Worker if (Offset)
2335*9880d681SAndroid Build Coastguard Worker Ptr = DAG.getNode(ISD::ADD, DL, BasePtrVT, Ptr,
2336*9880d681SAndroid Build Coastguard Worker DAG.getConstant(Offset, DL, BasePtrVT));
2337*9880d681SAndroid Build Coastguard Worker
2338*9880d681SAndroid Build Coastguard Worker SDValue Ops[] = { Chain, Value, Ptr };
2339*9880d681SAndroid Build Coastguard Worker return DAG.getMemIntrinsicNode(Opc, DL, VTList, Ops, MemVT,
2340*9880d681SAndroid Build Coastguard Worker SD->getMemOperand());
2341*9880d681SAndroid Build Coastguard Worker }
2342*9880d681SAndroid Build Coastguard Worker
2343*9880d681SAndroid Build Coastguard Worker // Expand an unaligned 32 or 64-bit integer store node.
lowerUnalignedIntStore(StoreSDNode * SD,SelectionDAG & DAG,bool IsLittle)2344*9880d681SAndroid Build Coastguard Worker static SDValue lowerUnalignedIntStore(StoreSDNode *SD, SelectionDAG &DAG,
2345*9880d681SAndroid Build Coastguard Worker bool IsLittle) {
2346*9880d681SAndroid Build Coastguard Worker SDValue Value = SD->getValue(), Chain = SD->getChain();
2347*9880d681SAndroid Build Coastguard Worker EVT VT = Value.getValueType();
2348*9880d681SAndroid Build Coastguard Worker
2349*9880d681SAndroid Build Coastguard Worker // Expand
2350*9880d681SAndroid Build Coastguard Worker // (store val, baseptr) or
2351*9880d681SAndroid Build Coastguard Worker // (truncstore val, baseptr)
2352*9880d681SAndroid Build Coastguard Worker // to
2353*9880d681SAndroid Build Coastguard Worker // (swl val, (add baseptr, 3))
2354*9880d681SAndroid Build Coastguard Worker // (swr val, baseptr)
2355*9880d681SAndroid Build Coastguard Worker if ((VT == MVT::i32) || SD->isTruncatingStore()) {
2356*9880d681SAndroid Build Coastguard Worker SDValue SWL = createStoreLR(MipsISD::SWL, DAG, SD, Chain,
2357*9880d681SAndroid Build Coastguard Worker IsLittle ? 3 : 0);
2358*9880d681SAndroid Build Coastguard Worker return createStoreLR(MipsISD::SWR, DAG, SD, SWL, IsLittle ? 0 : 3);
2359*9880d681SAndroid Build Coastguard Worker }
2360*9880d681SAndroid Build Coastguard Worker
2361*9880d681SAndroid Build Coastguard Worker assert(VT == MVT::i64);
2362*9880d681SAndroid Build Coastguard Worker
2363*9880d681SAndroid Build Coastguard Worker // Expand
2364*9880d681SAndroid Build Coastguard Worker // (store val, baseptr)
2365*9880d681SAndroid Build Coastguard Worker // to
2366*9880d681SAndroid Build Coastguard Worker // (sdl val, (add baseptr, 7))
2367*9880d681SAndroid Build Coastguard Worker // (sdr val, baseptr)
2368*9880d681SAndroid Build Coastguard Worker SDValue SDL = createStoreLR(MipsISD::SDL, DAG, SD, Chain, IsLittle ? 7 : 0);
2369*9880d681SAndroid Build Coastguard Worker return createStoreLR(MipsISD::SDR, DAG, SD, SDL, IsLittle ? 0 : 7);
2370*9880d681SAndroid Build Coastguard Worker }
2371*9880d681SAndroid Build Coastguard Worker
2372*9880d681SAndroid Build Coastguard Worker // Lower (store (fp_to_sint $fp) $ptr) to (store (TruncIntFP $fp), $ptr).
lowerFP_TO_SINT_STORE(StoreSDNode * SD,SelectionDAG & DAG)2373*9880d681SAndroid Build Coastguard Worker static SDValue lowerFP_TO_SINT_STORE(StoreSDNode *SD, SelectionDAG &DAG) {
2374*9880d681SAndroid Build Coastguard Worker SDValue Val = SD->getValue();
2375*9880d681SAndroid Build Coastguard Worker
2376*9880d681SAndroid Build Coastguard Worker if (Val.getOpcode() != ISD::FP_TO_SINT)
2377*9880d681SAndroid Build Coastguard Worker return SDValue();
2378*9880d681SAndroid Build Coastguard Worker
2379*9880d681SAndroid Build Coastguard Worker EVT FPTy = EVT::getFloatingPointVT(Val.getValueSizeInBits());
2380*9880d681SAndroid Build Coastguard Worker SDValue Tr = DAG.getNode(MipsISD::TruncIntFP, SDLoc(Val), FPTy,
2381*9880d681SAndroid Build Coastguard Worker Val.getOperand(0));
2382*9880d681SAndroid Build Coastguard Worker
2383*9880d681SAndroid Build Coastguard Worker return DAG.getStore(SD->getChain(), SDLoc(SD), Tr, SD->getBasePtr(),
2384*9880d681SAndroid Build Coastguard Worker SD->getPointerInfo(), SD->isVolatile(),
2385*9880d681SAndroid Build Coastguard Worker SD->isNonTemporal(), SD->getAlignment());
2386*9880d681SAndroid Build Coastguard Worker }
2387*9880d681SAndroid Build Coastguard Worker
lowerSTORE(SDValue Op,SelectionDAG & DAG) const2388*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const {
2389*9880d681SAndroid Build Coastguard Worker StoreSDNode *SD = cast<StoreSDNode>(Op);
2390*9880d681SAndroid Build Coastguard Worker EVT MemVT = SD->getMemoryVT();
2391*9880d681SAndroid Build Coastguard Worker
2392*9880d681SAndroid Build Coastguard Worker // Lower unaligned integer stores.
2393*9880d681SAndroid Build Coastguard Worker if (!Subtarget.systemSupportsUnalignedAccess() &&
2394*9880d681SAndroid Build Coastguard Worker (SD->getAlignment() < MemVT.getSizeInBits() / 8) &&
2395*9880d681SAndroid Build Coastguard Worker ((MemVT == MVT::i32) || (MemVT == MVT::i64)))
2396*9880d681SAndroid Build Coastguard Worker return lowerUnalignedIntStore(SD, DAG, Subtarget.isLittle());
2397*9880d681SAndroid Build Coastguard Worker
2398*9880d681SAndroid Build Coastguard Worker return lowerFP_TO_SINT_STORE(SD, DAG);
2399*9880d681SAndroid Build Coastguard Worker }
2400*9880d681SAndroid Build Coastguard Worker
lowerADD(SDValue Op,SelectionDAG & DAG) const2401*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::lowerADD(SDValue Op, SelectionDAG &DAG) const {
2402*9880d681SAndroid Build Coastguard Worker if (Op->getOperand(0).getOpcode() != ISD::FRAMEADDR
2403*9880d681SAndroid Build Coastguard Worker || cast<ConstantSDNode>
2404*9880d681SAndroid Build Coastguard Worker (Op->getOperand(0).getOperand(0))->getZExtValue() != 0
2405*9880d681SAndroid Build Coastguard Worker || Op->getOperand(1).getOpcode() != ISD::FRAME_TO_ARGS_OFFSET)
2406*9880d681SAndroid Build Coastguard Worker return SDValue();
2407*9880d681SAndroid Build Coastguard Worker
2408*9880d681SAndroid Build Coastguard Worker // The pattern
2409*9880d681SAndroid Build Coastguard Worker // (add (frameaddr 0), (frame_to_args_offset))
2410*9880d681SAndroid Build Coastguard Worker // results from lowering llvm.eh.dwarf.cfa intrinsic. Transform it to
2411*9880d681SAndroid Build Coastguard Worker // (add FrameObject, 0)
2412*9880d681SAndroid Build Coastguard Worker // where FrameObject is a fixed StackObject with offset 0 which points to
2413*9880d681SAndroid Build Coastguard Worker // the old stack pointer.
2414*9880d681SAndroid Build Coastguard Worker MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
2415*9880d681SAndroid Build Coastguard Worker EVT ValTy = Op->getValueType(0);
2416*9880d681SAndroid Build Coastguard Worker int FI = MFI->CreateFixedObject(Op.getValueSizeInBits() / 8, 0, false);
2417*9880d681SAndroid Build Coastguard Worker SDValue InArgsAddr = DAG.getFrameIndex(FI, ValTy);
2418*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
2419*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::ADD, DL, ValTy, InArgsAddr,
2420*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0, DL, ValTy));
2421*9880d681SAndroid Build Coastguard Worker }
2422*9880d681SAndroid Build Coastguard Worker
lowerFP_TO_SINT(SDValue Op,SelectionDAG & DAG) const2423*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::lowerFP_TO_SINT(SDValue Op,
2424*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
2425*9880d681SAndroid Build Coastguard Worker EVT FPTy = EVT::getFloatingPointVT(Op.getValueSizeInBits());
2426*9880d681SAndroid Build Coastguard Worker SDValue Trunc = DAG.getNode(MipsISD::TruncIntFP, SDLoc(Op), FPTy,
2427*9880d681SAndroid Build Coastguard Worker Op.getOperand(0));
2428*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::BITCAST, SDLoc(Op), Op.getValueType(), Trunc);
2429*9880d681SAndroid Build Coastguard Worker }
2430*9880d681SAndroid Build Coastguard Worker
2431*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2432*9880d681SAndroid Build Coastguard Worker // Calling Convention Implementation
2433*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2434*9880d681SAndroid Build Coastguard Worker
2435*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2436*9880d681SAndroid Build Coastguard Worker // TODO: Implement a generic logic using tblgen that can support this.
2437*9880d681SAndroid Build Coastguard Worker // Mips O32 ABI rules:
2438*9880d681SAndroid Build Coastguard Worker // ---
2439*9880d681SAndroid Build Coastguard Worker // i32 - Passed in A0, A1, A2, A3 and stack
2440*9880d681SAndroid Build Coastguard Worker // f32 - Only passed in f32 registers if no int reg has been used yet to hold
2441*9880d681SAndroid Build Coastguard Worker // an argument. Otherwise, passed in A1, A2, A3 and stack.
2442*9880d681SAndroid Build Coastguard Worker // f64 - Only passed in two aliased f32 registers if no int reg has been used
2443*9880d681SAndroid Build Coastguard Worker // yet to hold an argument. Otherwise, use A2, A3 and stack. If A1 is
2444*9880d681SAndroid Build Coastguard Worker // not used, it must be shadowed. If only A3 is available, shadow it and
2445*9880d681SAndroid Build Coastguard Worker // go to stack.
2446*9880d681SAndroid Build Coastguard Worker //
2447*9880d681SAndroid Build Coastguard Worker // For vararg functions, all arguments are passed in A0, A1, A2, A3 and stack.
2448*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2449*9880d681SAndroid Build Coastguard Worker
CC_MipsO32(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State,ArrayRef<MCPhysReg> F64Regs)2450*9880d681SAndroid Build Coastguard Worker static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT,
2451*9880d681SAndroid Build Coastguard Worker CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,
2452*9880d681SAndroid Build Coastguard Worker CCState &State, ArrayRef<MCPhysReg> F64Regs) {
2453*9880d681SAndroid Build Coastguard Worker const MipsSubtarget &Subtarget = static_cast<const MipsSubtarget &>(
2454*9880d681SAndroid Build Coastguard Worker State.getMachineFunction().getSubtarget());
2455*9880d681SAndroid Build Coastguard Worker
2456*9880d681SAndroid Build Coastguard Worker static const MCPhysReg IntRegs[] = { Mips::A0, Mips::A1, Mips::A2, Mips::A3 };
2457*9880d681SAndroid Build Coastguard Worker static const MCPhysReg F32Regs[] = { Mips::F12, Mips::F14 };
2458*9880d681SAndroid Build Coastguard Worker
2459*9880d681SAndroid Build Coastguard Worker // Do not process byval args here.
2460*9880d681SAndroid Build Coastguard Worker if (ArgFlags.isByVal())
2461*9880d681SAndroid Build Coastguard Worker return true;
2462*9880d681SAndroid Build Coastguard Worker
2463*9880d681SAndroid Build Coastguard Worker // Promote i8 and i16
2464*9880d681SAndroid Build Coastguard Worker if (ArgFlags.isInReg() && !Subtarget.isLittle()) {
2465*9880d681SAndroid Build Coastguard Worker if (LocVT == MVT::i8 || LocVT == MVT::i16 || LocVT == MVT::i32) {
2466*9880d681SAndroid Build Coastguard Worker LocVT = MVT::i32;
2467*9880d681SAndroid Build Coastguard Worker if (ArgFlags.isSExt())
2468*9880d681SAndroid Build Coastguard Worker LocInfo = CCValAssign::SExtUpper;
2469*9880d681SAndroid Build Coastguard Worker else if (ArgFlags.isZExt())
2470*9880d681SAndroid Build Coastguard Worker LocInfo = CCValAssign::ZExtUpper;
2471*9880d681SAndroid Build Coastguard Worker else
2472*9880d681SAndroid Build Coastguard Worker LocInfo = CCValAssign::AExtUpper;
2473*9880d681SAndroid Build Coastguard Worker }
2474*9880d681SAndroid Build Coastguard Worker }
2475*9880d681SAndroid Build Coastguard Worker
2476*9880d681SAndroid Build Coastguard Worker // Promote i8 and i16
2477*9880d681SAndroid Build Coastguard Worker if (LocVT == MVT::i8 || LocVT == MVT::i16) {
2478*9880d681SAndroid Build Coastguard Worker LocVT = MVT::i32;
2479*9880d681SAndroid Build Coastguard Worker if (ArgFlags.isSExt())
2480*9880d681SAndroid Build Coastguard Worker LocInfo = CCValAssign::SExt;
2481*9880d681SAndroid Build Coastguard Worker else if (ArgFlags.isZExt())
2482*9880d681SAndroid Build Coastguard Worker LocInfo = CCValAssign::ZExt;
2483*9880d681SAndroid Build Coastguard Worker else
2484*9880d681SAndroid Build Coastguard Worker LocInfo = CCValAssign::AExt;
2485*9880d681SAndroid Build Coastguard Worker }
2486*9880d681SAndroid Build Coastguard Worker
2487*9880d681SAndroid Build Coastguard Worker unsigned Reg;
2488*9880d681SAndroid Build Coastguard Worker
2489*9880d681SAndroid Build Coastguard Worker // f32 and f64 are allocated in A0, A1, A2, A3 when either of the following
2490*9880d681SAndroid Build Coastguard Worker // is true: function is vararg, argument is 3rd or higher, there is previous
2491*9880d681SAndroid Build Coastguard Worker // argument which is not f32 or f64.
2492*9880d681SAndroid Build Coastguard Worker bool AllocateFloatsInIntReg = State.isVarArg() || ValNo > 1 ||
2493*9880d681SAndroid Build Coastguard Worker State.getFirstUnallocated(F32Regs) != ValNo;
2494*9880d681SAndroid Build Coastguard Worker unsigned OrigAlign = ArgFlags.getOrigAlign();
2495*9880d681SAndroid Build Coastguard Worker bool isI64 = (ValVT == MVT::i32 && OrigAlign == 8);
2496*9880d681SAndroid Build Coastguard Worker
2497*9880d681SAndroid Build Coastguard Worker if (ValVT == MVT::i32 || (ValVT == MVT::f32 && AllocateFloatsInIntReg)) {
2498*9880d681SAndroid Build Coastguard Worker Reg = State.AllocateReg(IntRegs);
2499*9880d681SAndroid Build Coastguard Worker // If this is the first part of an i64 arg,
2500*9880d681SAndroid Build Coastguard Worker // the allocated register must be either A0 or A2.
2501*9880d681SAndroid Build Coastguard Worker if (isI64 && (Reg == Mips::A1 || Reg == Mips::A3))
2502*9880d681SAndroid Build Coastguard Worker Reg = State.AllocateReg(IntRegs);
2503*9880d681SAndroid Build Coastguard Worker LocVT = MVT::i32;
2504*9880d681SAndroid Build Coastguard Worker } else if (ValVT == MVT::f64 && AllocateFloatsInIntReg) {
2505*9880d681SAndroid Build Coastguard Worker // Allocate int register and shadow next int register. If first
2506*9880d681SAndroid Build Coastguard Worker // available register is Mips::A1 or Mips::A3, shadow it too.
2507*9880d681SAndroid Build Coastguard Worker Reg = State.AllocateReg(IntRegs);
2508*9880d681SAndroid Build Coastguard Worker if (Reg == Mips::A1 || Reg == Mips::A3)
2509*9880d681SAndroid Build Coastguard Worker Reg = State.AllocateReg(IntRegs);
2510*9880d681SAndroid Build Coastguard Worker State.AllocateReg(IntRegs);
2511*9880d681SAndroid Build Coastguard Worker LocVT = MVT::i32;
2512*9880d681SAndroid Build Coastguard Worker } else if (ValVT.isFloatingPoint() && !AllocateFloatsInIntReg) {
2513*9880d681SAndroid Build Coastguard Worker // we are guaranteed to find an available float register
2514*9880d681SAndroid Build Coastguard Worker if (ValVT == MVT::f32) {
2515*9880d681SAndroid Build Coastguard Worker Reg = State.AllocateReg(F32Regs);
2516*9880d681SAndroid Build Coastguard Worker // Shadow int register
2517*9880d681SAndroid Build Coastguard Worker State.AllocateReg(IntRegs);
2518*9880d681SAndroid Build Coastguard Worker } else {
2519*9880d681SAndroid Build Coastguard Worker Reg = State.AllocateReg(F64Regs);
2520*9880d681SAndroid Build Coastguard Worker // Shadow int registers
2521*9880d681SAndroid Build Coastguard Worker unsigned Reg2 = State.AllocateReg(IntRegs);
2522*9880d681SAndroid Build Coastguard Worker if (Reg2 == Mips::A1 || Reg2 == Mips::A3)
2523*9880d681SAndroid Build Coastguard Worker State.AllocateReg(IntRegs);
2524*9880d681SAndroid Build Coastguard Worker State.AllocateReg(IntRegs);
2525*9880d681SAndroid Build Coastguard Worker }
2526*9880d681SAndroid Build Coastguard Worker } else
2527*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Cannot handle this ValVT.");
2528*9880d681SAndroid Build Coastguard Worker
2529*9880d681SAndroid Build Coastguard Worker if (!Reg) {
2530*9880d681SAndroid Build Coastguard Worker unsigned Offset = State.AllocateStack(ValVT.getSizeInBits() >> 3,
2531*9880d681SAndroid Build Coastguard Worker OrigAlign);
2532*9880d681SAndroid Build Coastguard Worker State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
2533*9880d681SAndroid Build Coastguard Worker } else
2534*9880d681SAndroid Build Coastguard Worker State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
2535*9880d681SAndroid Build Coastguard Worker
2536*9880d681SAndroid Build Coastguard Worker return false;
2537*9880d681SAndroid Build Coastguard Worker }
2538*9880d681SAndroid Build Coastguard Worker
CC_MipsO32_FP32(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)2539*9880d681SAndroid Build Coastguard Worker static bool CC_MipsO32_FP32(unsigned ValNo, MVT ValVT,
2540*9880d681SAndroid Build Coastguard Worker MVT LocVT, CCValAssign::LocInfo LocInfo,
2541*9880d681SAndroid Build Coastguard Worker ISD::ArgFlagsTy ArgFlags, CCState &State) {
2542*9880d681SAndroid Build Coastguard Worker static const MCPhysReg F64Regs[] = { Mips::D6, Mips::D7 };
2543*9880d681SAndroid Build Coastguard Worker
2544*9880d681SAndroid Build Coastguard Worker return CC_MipsO32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State, F64Regs);
2545*9880d681SAndroid Build Coastguard Worker }
2546*9880d681SAndroid Build Coastguard Worker
CC_MipsO32_FP64(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)2547*9880d681SAndroid Build Coastguard Worker static bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT,
2548*9880d681SAndroid Build Coastguard Worker MVT LocVT, CCValAssign::LocInfo LocInfo,
2549*9880d681SAndroid Build Coastguard Worker ISD::ArgFlagsTy ArgFlags, CCState &State) {
2550*9880d681SAndroid Build Coastguard Worker static const MCPhysReg F64Regs[] = { Mips::D12_64, Mips::D14_64 };
2551*9880d681SAndroid Build Coastguard Worker
2552*9880d681SAndroid Build Coastguard Worker return CC_MipsO32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State, F64Regs);
2553*9880d681SAndroid Build Coastguard Worker }
2554*9880d681SAndroid Build Coastguard Worker
2555*9880d681SAndroid Build Coastguard Worker static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT,
2556*9880d681SAndroid Build Coastguard Worker CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,
2557*9880d681SAndroid Build Coastguard Worker CCState &State) LLVM_ATTRIBUTE_UNUSED;
2558*9880d681SAndroid Build Coastguard Worker
2559*9880d681SAndroid Build Coastguard Worker #include "MipsGenCallingConv.inc"
2560*9880d681SAndroid Build Coastguard Worker
2561*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2562*9880d681SAndroid Build Coastguard Worker // Call Calling Convention Implementation
2563*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2564*9880d681SAndroid Build Coastguard Worker
2565*9880d681SAndroid Build Coastguard Worker // Return next O32 integer argument register.
getNextIntArgReg(unsigned Reg)2566*9880d681SAndroid Build Coastguard Worker static unsigned getNextIntArgReg(unsigned Reg) {
2567*9880d681SAndroid Build Coastguard Worker assert((Reg == Mips::A0) || (Reg == Mips::A2));
2568*9880d681SAndroid Build Coastguard Worker return (Reg == Mips::A0) ? Mips::A1 : Mips::A3;
2569*9880d681SAndroid Build Coastguard Worker }
2570*9880d681SAndroid Build Coastguard Worker
passArgOnStack(SDValue StackPtr,unsigned Offset,SDValue Chain,SDValue Arg,const SDLoc & DL,bool IsTailCall,SelectionDAG & DAG) const2571*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::passArgOnStack(SDValue StackPtr, unsigned Offset,
2572*9880d681SAndroid Build Coastguard Worker SDValue Chain, SDValue Arg,
2573*9880d681SAndroid Build Coastguard Worker const SDLoc &DL, bool IsTailCall,
2574*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
2575*9880d681SAndroid Build Coastguard Worker if (!IsTailCall) {
2576*9880d681SAndroid Build Coastguard Worker SDValue PtrOff =
2577*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::ADD, DL, getPointerTy(DAG.getDataLayout()), StackPtr,
2578*9880d681SAndroid Build Coastguard Worker DAG.getIntPtrConstant(Offset, DL));
2579*9880d681SAndroid Build Coastguard Worker return DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo(), false,
2580*9880d681SAndroid Build Coastguard Worker false, 0);
2581*9880d681SAndroid Build Coastguard Worker }
2582*9880d681SAndroid Build Coastguard Worker
2583*9880d681SAndroid Build Coastguard Worker MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
2584*9880d681SAndroid Build Coastguard Worker int FI = MFI->CreateFixedObject(Arg.getValueSizeInBits() / 8, Offset, false);
2585*9880d681SAndroid Build Coastguard Worker SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
2586*9880d681SAndroid Build Coastguard Worker return DAG.getStore(Chain, DL, Arg, FIN, MachinePointerInfo(),
2587*9880d681SAndroid Build Coastguard Worker /*isVolatile=*/ true, false, 0);
2588*9880d681SAndroid Build Coastguard Worker }
2589*9880d681SAndroid Build Coastguard Worker
2590*9880d681SAndroid Build Coastguard Worker void MipsTargetLowering::
getOpndList(SmallVectorImpl<SDValue> & Ops,std::deque<std::pair<unsigned,SDValue>> & RegsToPass,bool IsPICCall,bool GlobalOrExternal,bool InternalLinkage,bool IsCallReloc,CallLoweringInfo & CLI,SDValue Callee,SDValue Chain) const2591*9880d681SAndroid Build Coastguard Worker getOpndList(SmallVectorImpl<SDValue> &Ops,
2592*9880d681SAndroid Build Coastguard Worker std::deque< std::pair<unsigned, SDValue> > &RegsToPass,
2593*9880d681SAndroid Build Coastguard Worker bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,
2594*9880d681SAndroid Build Coastguard Worker bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee,
2595*9880d681SAndroid Build Coastguard Worker SDValue Chain) const {
2596*9880d681SAndroid Build Coastguard Worker // Insert node "GP copy globalreg" before call to function.
2597*9880d681SAndroid Build Coastguard Worker //
2598*9880d681SAndroid Build Coastguard Worker // R_MIPS_CALL* operators (emitted when non-internal functions are called
2599*9880d681SAndroid Build Coastguard Worker // in PIC mode) allow symbols to be resolved via lazy binding.
2600*9880d681SAndroid Build Coastguard Worker // The lazy binding stub requires GP to point to the GOT.
2601*9880d681SAndroid Build Coastguard Worker // Note that we don't need GP to point to the GOT for indirect calls
2602*9880d681SAndroid Build Coastguard Worker // (when R_MIPS_CALL* is not used for the call) because Mips linker generates
2603*9880d681SAndroid Build Coastguard Worker // lazy binding stub for a function only when R_MIPS_CALL* are the only relocs
2604*9880d681SAndroid Build Coastguard Worker // used for the function (that is, Mips linker doesn't generate lazy binding
2605*9880d681SAndroid Build Coastguard Worker // stub for a function whose address is taken in the program).
2606*9880d681SAndroid Build Coastguard Worker if (IsPICCall && !InternalLinkage && IsCallReloc) {
2607*9880d681SAndroid Build Coastguard Worker unsigned GPReg = ABI.IsN64() ? Mips::GP_64 : Mips::GP;
2608*9880d681SAndroid Build Coastguard Worker EVT Ty = ABI.IsN64() ? MVT::i64 : MVT::i32;
2609*9880d681SAndroid Build Coastguard Worker RegsToPass.push_back(std::make_pair(GPReg, getGlobalReg(CLI.DAG, Ty)));
2610*9880d681SAndroid Build Coastguard Worker }
2611*9880d681SAndroid Build Coastguard Worker
2612*9880d681SAndroid Build Coastguard Worker // Build a sequence of copy-to-reg nodes chained together with token
2613*9880d681SAndroid Build Coastguard Worker // chain and flag operands which copy the outgoing args into registers.
2614*9880d681SAndroid Build Coastguard Worker // The InFlag in necessary since all emitted instructions must be
2615*9880d681SAndroid Build Coastguard Worker // stuck together.
2616*9880d681SAndroid Build Coastguard Worker SDValue InFlag;
2617*9880d681SAndroid Build Coastguard Worker
2618*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
2619*9880d681SAndroid Build Coastguard Worker Chain = CLI.DAG.getCopyToReg(Chain, CLI.DL, RegsToPass[i].first,
2620*9880d681SAndroid Build Coastguard Worker RegsToPass[i].second, InFlag);
2621*9880d681SAndroid Build Coastguard Worker InFlag = Chain.getValue(1);
2622*9880d681SAndroid Build Coastguard Worker }
2623*9880d681SAndroid Build Coastguard Worker
2624*9880d681SAndroid Build Coastguard Worker // Add argument registers to the end of the list so that they are
2625*9880d681SAndroid Build Coastguard Worker // known live into the call.
2626*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
2627*9880d681SAndroid Build Coastguard Worker Ops.push_back(CLI.DAG.getRegister(RegsToPass[i].first,
2628*9880d681SAndroid Build Coastguard Worker RegsToPass[i].second.getValueType()));
2629*9880d681SAndroid Build Coastguard Worker
2630*9880d681SAndroid Build Coastguard Worker // Add a register mask operand representing the call-preserved registers.
2631*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
2632*9880d681SAndroid Build Coastguard Worker const uint32_t *Mask =
2633*9880d681SAndroid Build Coastguard Worker TRI->getCallPreservedMask(CLI.DAG.getMachineFunction(), CLI.CallConv);
2634*9880d681SAndroid Build Coastguard Worker assert(Mask && "Missing call preserved mask for calling convention");
2635*9880d681SAndroid Build Coastguard Worker if (Subtarget.inMips16HardFloat()) {
2636*9880d681SAndroid Build Coastguard Worker if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(CLI.Callee)) {
2637*9880d681SAndroid Build Coastguard Worker llvm::StringRef Sym = G->getGlobal()->getName();
2638*9880d681SAndroid Build Coastguard Worker Function *F = G->getGlobal()->getParent()->getFunction(Sym);
2639*9880d681SAndroid Build Coastguard Worker if (F && F->hasFnAttribute("__Mips16RetHelper")) {
2640*9880d681SAndroid Build Coastguard Worker Mask = MipsRegisterInfo::getMips16RetHelperMask();
2641*9880d681SAndroid Build Coastguard Worker }
2642*9880d681SAndroid Build Coastguard Worker }
2643*9880d681SAndroid Build Coastguard Worker }
2644*9880d681SAndroid Build Coastguard Worker Ops.push_back(CLI.DAG.getRegisterMask(Mask));
2645*9880d681SAndroid Build Coastguard Worker
2646*9880d681SAndroid Build Coastguard Worker if (InFlag.getNode())
2647*9880d681SAndroid Build Coastguard Worker Ops.push_back(InFlag);
2648*9880d681SAndroid Build Coastguard Worker }
2649*9880d681SAndroid Build Coastguard Worker
2650*9880d681SAndroid Build Coastguard Worker /// LowerCall - functions arguments are copied from virtual regs to
2651*9880d681SAndroid Build Coastguard Worker /// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
2652*9880d681SAndroid Build Coastguard Worker SDValue
LowerCall(TargetLowering::CallLoweringInfo & CLI,SmallVectorImpl<SDValue> & InVals) const2653*9880d681SAndroid Build Coastguard Worker MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
2654*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<SDValue> &InVals) const {
2655*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG = CLI.DAG;
2656*9880d681SAndroid Build Coastguard Worker SDLoc DL = CLI.DL;
2657*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
2658*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
2659*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
2660*9880d681SAndroid Build Coastguard Worker SDValue Chain = CLI.Chain;
2661*9880d681SAndroid Build Coastguard Worker SDValue Callee = CLI.Callee;
2662*9880d681SAndroid Build Coastguard Worker bool &IsTailCall = CLI.IsTailCall;
2663*9880d681SAndroid Build Coastguard Worker CallingConv::ID CallConv = CLI.CallConv;
2664*9880d681SAndroid Build Coastguard Worker bool IsVarArg = CLI.IsVarArg;
2665*9880d681SAndroid Build Coastguard Worker
2666*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = DAG.getMachineFunction();
2667*9880d681SAndroid Build Coastguard Worker MachineFrameInfo *MFI = MF.getFrameInfo();
2668*9880d681SAndroid Build Coastguard Worker const TargetFrameLowering *TFL = Subtarget.getFrameLowering();
2669*9880d681SAndroid Build Coastguard Worker MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();
2670*9880d681SAndroid Build Coastguard Worker bool IsPIC = isPositionIndependent();
2671*9880d681SAndroid Build Coastguard Worker
2672*9880d681SAndroid Build Coastguard Worker // Analyze operands of the call, assigning locations to each operand.
2673*9880d681SAndroid Build Coastguard Worker SmallVector<CCValAssign, 16> ArgLocs;
2674*9880d681SAndroid Build Coastguard Worker MipsCCState CCInfo(
2675*9880d681SAndroid Build Coastguard Worker CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext(),
2676*9880d681SAndroid Build Coastguard Worker MipsCCState::getSpecialCallingConvForCallee(Callee.getNode(), Subtarget));
2677*9880d681SAndroid Build Coastguard Worker
2678*9880d681SAndroid Build Coastguard Worker // Allocate the reserved argument area. It seems strange to do this from the
2679*9880d681SAndroid Build Coastguard Worker // caller side but removing it breaks the frame size calculation.
2680*9880d681SAndroid Build Coastguard Worker CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1);
2681*9880d681SAndroid Build Coastguard Worker
2682*9880d681SAndroid Build Coastguard Worker CCInfo.AnalyzeCallOperands(Outs, CC_Mips, CLI.getArgs(), Callee.getNode());
2683*9880d681SAndroid Build Coastguard Worker
2684*9880d681SAndroid Build Coastguard Worker // Get a count of how many bytes are to be pushed on the stack.
2685*9880d681SAndroid Build Coastguard Worker unsigned NextStackOffset = CCInfo.getNextStackOffset();
2686*9880d681SAndroid Build Coastguard Worker
2687*9880d681SAndroid Build Coastguard Worker // Check if it's really possible to do a tail call.
2688*9880d681SAndroid Build Coastguard Worker if (IsTailCall)
2689*9880d681SAndroid Build Coastguard Worker IsTailCall = isEligibleForTailCallOptimization(
2690*9880d681SAndroid Build Coastguard Worker CCInfo, NextStackOffset, *MF.getInfo<MipsFunctionInfo>());
2691*9880d681SAndroid Build Coastguard Worker
2692*9880d681SAndroid Build Coastguard Worker if (!IsTailCall && CLI.CS && CLI.CS->isMustTailCall())
2693*9880d681SAndroid Build Coastguard Worker report_fatal_error("failed to perform tail call elimination on a call "
2694*9880d681SAndroid Build Coastguard Worker "site marked musttail");
2695*9880d681SAndroid Build Coastguard Worker
2696*9880d681SAndroid Build Coastguard Worker if (IsTailCall)
2697*9880d681SAndroid Build Coastguard Worker ++NumTailCalls;
2698*9880d681SAndroid Build Coastguard Worker
2699*9880d681SAndroid Build Coastguard Worker // Chain is the output chain of the last Load/Store or CopyToReg node.
2700*9880d681SAndroid Build Coastguard Worker // ByValChain is the output chain of the last Memcpy node created for copying
2701*9880d681SAndroid Build Coastguard Worker // byval arguments to the stack.
2702*9880d681SAndroid Build Coastguard Worker unsigned StackAlignment = TFL->getStackAlignment();
2703*9880d681SAndroid Build Coastguard Worker NextStackOffset = alignTo(NextStackOffset, StackAlignment);
2704*9880d681SAndroid Build Coastguard Worker SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, DL, true);
2705*9880d681SAndroid Build Coastguard Worker
2706*9880d681SAndroid Build Coastguard Worker if (!IsTailCall)
2707*9880d681SAndroid Build Coastguard Worker Chain = DAG.getCALLSEQ_START(Chain, NextStackOffsetVal, DL);
2708*9880d681SAndroid Build Coastguard Worker
2709*9880d681SAndroid Build Coastguard Worker SDValue StackPtr =
2710*9880d681SAndroid Build Coastguard Worker DAG.getCopyFromReg(Chain, DL, ABI.IsN64() ? Mips::SP_64 : Mips::SP,
2711*9880d681SAndroid Build Coastguard Worker getPointerTy(DAG.getDataLayout()));
2712*9880d681SAndroid Build Coastguard Worker
2713*9880d681SAndroid Build Coastguard Worker std::deque< std::pair<unsigned, SDValue> > RegsToPass;
2714*9880d681SAndroid Build Coastguard Worker SmallVector<SDValue, 8> MemOpChains;
2715*9880d681SAndroid Build Coastguard Worker
2716*9880d681SAndroid Build Coastguard Worker CCInfo.rewindByValRegsInfo();
2717*9880d681SAndroid Build Coastguard Worker
2718*9880d681SAndroid Build Coastguard Worker // Walk the register/memloc assignments, inserting copies/loads.
2719*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
2720*9880d681SAndroid Build Coastguard Worker SDValue Arg = OutVals[i];
2721*9880d681SAndroid Build Coastguard Worker CCValAssign &VA = ArgLocs[i];
2722*9880d681SAndroid Build Coastguard Worker MVT ValVT = VA.getValVT(), LocVT = VA.getLocVT();
2723*9880d681SAndroid Build Coastguard Worker ISD::ArgFlagsTy Flags = Outs[i].Flags;
2724*9880d681SAndroid Build Coastguard Worker bool UseUpperBits = false;
2725*9880d681SAndroid Build Coastguard Worker
2726*9880d681SAndroid Build Coastguard Worker // ByVal Arg.
2727*9880d681SAndroid Build Coastguard Worker if (Flags.isByVal()) {
2728*9880d681SAndroid Build Coastguard Worker unsigned FirstByValReg, LastByValReg;
2729*9880d681SAndroid Build Coastguard Worker unsigned ByValIdx = CCInfo.getInRegsParamsProcessed();
2730*9880d681SAndroid Build Coastguard Worker CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg);
2731*9880d681SAndroid Build Coastguard Worker
2732*9880d681SAndroid Build Coastguard Worker assert(Flags.getByValSize() &&
2733*9880d681SAndroid Build Coastguard Worker "ByVal args of size 0 should have been ignored by front-end.");
2734*9880d681SAndroid Build Coastguard Worker assert(ByValIdx < CCInfo.getInRegsParamsCount());
2735*9880d681SAndroid Build Coastguard Worker assert(!IsTailCall &&
2736*9880d681SAndroid Build Coastguard Worker "Do not tail-call optimize if there is a byval argument.");
2737*9880d681SAndroid Build Coastguard Worker passByValArg(Chain, DL, RegsToPass, MemOpChains, StackPtr, MFI, DAG, Arg,
2738*9880d681SAndroid Build Coastguard Worker FirstByValReg, LastByValReg, Flags, Subtarget.isLittle(),
2739*9880d681SAndroid Build Coastguard Worker VA);
2740*9880d681SAndroid Build Coastguard Worker CCInfo.nextInRegsParam();
2741*9880d681SAndroid Build Coastguard Worker continue;
2742*9880d681SAndroid Build Coastguard Worker }
2743*9880d681SAndroid Build Coastguard Worker
2744*9880d681SAndroid Build Coastguard Worker // Promote the value if needed.
2745*9880d681SAndroid Build Coastguard Worker switch (VA.getLocInfo()) {
2746*9880d681SAndroid Build Coastguard Worker default:
2747*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown loc info!");
2748*9880d681SAndroid Build Coastguard Worker case CCValAssign::Full:
2749*9880d681SAndroid Build Coastguard Worker if (VA.isRegLoc()) {
2750*9880d681SAndroid Build Coastguard Worker if ((ValVT == MVT::f32 && LocVT == MVT::i32) ||
2751*9880d681SAndroid Build Coastguard Worker (ValVT == MVT::f64 && LocVT == MVT::i64) ||
2752*9880d681SAndroid Build Coastguard Worker (ValVT == MVT::i64 && LocVT == MVT::f64))
2753*9880d681SAndroid Build Coastguard Worker Arg = DAG.getNode(ISD::BITCAST, DL, LocVT, Arg);
2754*9880d681SAndroid Build Coastguard Worker else if (ValVT == MVT::f64 && LocVT == MVT::i32) {
2755*9880d681SAndroid Build Coastguard Worker SDValue Lo = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32,
2756*9880d681SAndroid Build Coastguard Worker Arg, DAG.getConstant(0, DL, MVT::i32));
2757*9880d681SAndroid Build Coastguard Worker SDValue Hi = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32,
2758*9880d681SAndroid Build Coastguard Worker Arg, DAG.getConstant(1, DL, MVT::i32));
2759*9880d681SAndroid Build Coastguard Worker if (!Subtarget.isLittle())
2760*9880d681SAndroid Build Coastguard Worker std::swap(Lo, Hi);
2761*9880d681SAndroid Build Coastguard Worker unsigned LocRegLo = VA.getLocReg();
2762*9880d681SAndroid Build Coastguard Worker unsigned LocRegHigh = getNextIntArgReg(LocRegLo);
2763*9880d681SAndroid Build Coastguard Worker RegsToPass.push_back(std::make_pair(LocRegLo, Lo));
2764*9880d681SAndroid Build Coastguard Worker RegsToPass.push_back(std::make_pair(LocRegHigh, Hi));
2765*9880d681SAndroid Build Coastguard Worker continue;
2766*9880d681SAndroid Build Coastguard Worker }
2767*9880d681SAndroid Build Coastguard Worker }
2768*9880d681SAndroid Build Coastguard Worker break;
2769*9880d681SAndroid Build Coastguard Worker case CCValAssign::BCvt:
2770*9880d681SAndroid Build Coastguard Worker Arg = DAG.getNode(ISD::BITCAST, DL, LocVT, Arg);
2771*9880d681SAndroid Build Coastguard Worker break;
2772*9880d681SAndroid Build Coastguard Worker case CCValAssign::SExtUpper:
2773*9880d681SAndroid Build Coastguard Worker UseUpperBits = true;
2774*9880d681SAndroid Build Coastguard Worker // Fallthrough
2775*9880d681SAndroid Build Coastguard Worker case CCValAssign::SExt:
2776*9880d681SAndroid Build Coastguard Worker Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, LocVT, Arg);
2777*9880d681SAndroid Build Coastguard Worker break;
2778*9880d681SAndroid Build Coastguard Worker case CCValAssign::ZExtUpper:
2779*9880d681SAndroid Build Coastguard Worker UseUpperBits = true;
2780*9880d681SAndroid Build Coastguard Worker // Fallthrough
2781*9880d681SAndroid Build Coastguard Worker case CCValAssign::ZExt:
2782*9880d681SAndroid Build Coastguard Worker Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, LocVT, Arg);
2783*9880d681SAndroid Build Coastguard Worker break;
2784*9880d681SAndroid Build Coastguard Worker case CCValAssign::AExtUpper:
2785*9880d681SAndroid Build Coastguard Worker UseUpperBits = true;
2786*9880d681SAndroid Build Coastguard Worker // Fallthrough
2787*9880d681SAndroid Build Coastguard Worker case CCValAssign::AExt:
2788*9880d681SAndroid Build Coastguard Worker Arg = DAG.getNode(ISD::ANY_EXTEND, DL, LocVT, Arg);
2789*9880d681SAndroid Build Coastguard Worker break;
2790*9880d681SAndroid Build Coastguard Worker }
2791*9880d681SAndroid Build Coastguard Worker
2792*9880d681SAndroid Build Coastguard Worker if (UseUpperBits) {
2793*9880d681SAndroid Build Coastguard Worker unsigned ValSizeInBits = Outs[i].ArgVT.getSizeInBits();
2794*9880d681SAndroid Build Coastguard Worker unsigned LocSizeInBits = VA.getLocVT().getSizeInBits();
2795*9880d681SAndroid Build Coastguard Worker Arg = DAG.getNode(
2796*9880d681SAndroid Build Coastguard Worker ISD::SHL, DL, VA.getLocVT(), Arg,
2797*9880d681SAndroid Build Coastguard Worker DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT()));
2798*9880d681SAndroid Build Coastguard Worker }
2799*9880d681SAndroid Build Coastguard Worker
2800*9880d681SAndroid Build Coastguard Worker // Arguments that can be passed on register must be kept at
2801*9880d681SAndroid Build Coastguard Worker // RegsToPass vector
2802*9880d681SAndroid Build Coastguard Worker if (VA.isRegLoc()) {
2803*9880d681SAndroid Build Coastguard Worker RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
2804*9880d681SAndroid Build Coastguard Worker continue;
2805*9880d681SAndroid Build Coastguard Worker }
2806*9880d681SAndroid Build Coastguard Worker
2807*9880d681SAndroid Build Coastguard Worker // Register can't get to this point...
2808*9880d681SAndroid Build Coastguard Worker assert(VA.isMemLoc());
2809*9880d681SAndroid Build Coastguard Worker
2810*9880d681SAndroid Build Coastguard Worker // emit ISD::STORE whichs stores the
2811*9880d681SAndroid Build Coastguard Worker // parameter value to a stack Location
2812*9880d681SAndroid Build Coastguard Worker MemOpChains.push_back(passArgOnStack(StackPtr, VA.getLocMemOffset(),
2813*9880d681SAndroid Build Coastguard Worker Chain, Arg, DL, IsTailCall, DAG));
2814*9880d681SAndroid Build Coastguard Worker }
2815*9880d681SAndroid Build Coastguard Worker
2816*9880d681SAndroid Build Coastguard Worker // Transform all store nodes into one single node because all store
2817*9880d681SAndroid Build Coastguard Worker // nodes are independent of each other.
2818*9880d681SAndroid Build Coastguard Worker if (!MemOpChains.empty())
2819*9880d681SAndroid Build Coastguard Worker Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
2820*9880d681SAndroid Build Coastguard Worker
2821*9880d681SAndroid Build Coastguard Worker // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
2822*9880d681SAndroid Build Coastguard Worker // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
2823*9880d681SAndroid Build Coastguard Worker // node so that legalize doesn't hack it.
2824*9880d681SAndroid Build Coastguard Worker bool IsPICCall = (ABI.IsN64() || IsPIC); // true if calls are translated to
2825*9880d681SAndroid Build Coastguard Worker // jalr $25
2826*9880d681SAndroid Build Coastguard Worker bool GlobalOrExternal = false, InternalLinkage = false, IsCallReloc = false;
2827*9880d681SAndroid Build Coastguard Worker SDValue CalleeLo;
2828*9880d681SAndroid Build Coastguard Worker EVT Ty = Callee.getValueType();
2829*9880d681SAndroid Build Coastguard Worker
2830*9880d681SAndroid Build Coastguard Worker if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
2831*9880d681SAndroid Build Coastguard Worker if (IsPICCall) {
2832*9880d681SAndroid Build Coastguard Worker const GlobalValue *Val = G->getGlobal();
2833*9880d681SAndroid Build Coastguard Worker InternalLinkage = Val->hasInternalLinkage();
2834*9880d681SAndroid Build Coastguard Worker
2835*9880d681SAndroid Build Coastguard Worker if (InternalLinkage)
2836*9880d681SAndroid Build Coastguard Worker Callee = getAddrLocal(G, DL, Ty, DAG, ABI.IsN32() || ABI.IsN64());
2837*9880d681SAndroid Build Coastguard Worker else if (LargeGOT) {
2838*9880d681SAndroid Build Coastguard Worker Callee = getAddrGlobalLargeGOT(G, DL, Ty, DAG, MipsII::MO_CALL_HI16,
2839*9880d681SAndroid Build Coastguard Worker MipsII::MO_CALL_LO16, Chain,
2840*9880d681SAndroid Build Coastguard Worker FuncInfo->callPtrInfo(Val));
2841*9880d681SAndroid Build Coastguard Worker IsCallReloc = true;
2842*9880d681SAndroid Build Coastguard Worker } else {
2843*9880d681SAndroid Build Coastguard Worker Callee = getAddrGlobal(G, DL, Ty, DAG, MipsII::MO_GOT_CALL, Chain,
2844*9880d681SAndroid Build Coastguard Worker FuncInfo->callPtrInfo(Val));
2845*9880d681SAndroid Build Coastguard Worker IsCallReloc = true;
2846*9880d681SAndroid Build Coastguard Worker }
2847*9880d681SAndroid Build Coastguard Worker } else
2848*9880d681SAndroid Build Coastguard Worker Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL,
2849*9880d681SAndroid Build Coastguard Worker getPointerTy(DAG.getDataLayout()), 0,
2850*9880d681SAndroid Build Coastguard Worker MipsII::MO_NO_FLAG);
2851*9880d681SAndroid Build Coastguard Worker GlobalOrExternal = true;
2852*9880d681SAndroid Build Coastguard Worker }
2853*9880d681SAndroid Build Coastguard Worker else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
2854*9880d681SAndroid Build Coastguard Worker const char *Sym = S->getSymbol();
2855*9880d681SAndroid Build Coastguard Worker
2856*9880d681SAndroid Build Coastguard Worker if (!ABI.IsN64() && !IsPIC) // !N64 && static
2857*9880d681SAndroid Build Coastguard Worker Callee = DAG.getTargetExternalSymbol(
2858*9880d681SAndroid Build Coastguard Worker Sym, getPointerTy(DAG.getDataLayout()), MipsII::MO_NO_FLAG);
2859*9880d681SAndroid Build Coastguard Worker else if (LargeGOT) {
2860*9880d681SAndroid Build Coastguard Worker Callee = getAddrGlobalLargeGOT(S, DL, Ty, DAG, MipsII::MO_CALL_HI16,
2861*9880d681SAndroid Build Coastguard Worker MipsII::MO_CALL_LO16, Chain,
2862*9880d681SAndroid Build Coastguard Worker FuncInfo->callPtrInfo(Sym));
2863*9880d681SAndroid Build Coastguard Worker IsCallReloc = true;
2864*9880d681SAndroid Build Coastguard Worker } else { // N64 || PIC
2865*9880d681SAndroid Build Coastguard Worker Callee = getAddrGlobal(S, DL, Ty, DAG, MipsII::MO_GOT_CALL, Chain,
2866*9880d681SAndroid Build Coastguard Worker FuncInfo->callPtrInfo(Sym));
2867*9880d681SAndroid Build Coastguard Worker IsCallReloc = true;
2868*9880d681SAndroid Build Coastguard Worker }
2869*9880d681SAndroid Build Coastguard Worker
2870*9880d681SAndroid Build Coastguard Worker GlobalOrExternal = true;
2871*9880d681SAndroid Build Coastguard Worker }
2872*9880d681SAndroid Build Coastguard Worker
2873*9880d681SAndroid Build Coastguard Worker SmallVector<SDValue, 8> Ops(1, Chain);
2874*9880d681SAndroid Build Coastguard Worker SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
2875*9880d681SAndroid Build Coastguard Worker
2876*9880d681SAndroid Build Coastguard Worker getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal, InternalLinkage,
2877*9880d681SAndroid Build Coastguard Worker IsCallReloc, CLI, Callee, Chain);
2878*9880d681SAndroid Build Coastguard Worker
2879*9880d681SAndroid Build Coastguard Worker if (IsTailCall)
2880*9880d681SAndroid Build Coastguard Worker return DAG.getNode(MipsISD::TailCall, DL, MVT::Other, Ops);
2881*9880d681SAndroid Build Coastguard Worker
2882*9880d681SAndroid Build Coastguard Worker Chain = DAG.getNode(MipsISD::JmpLink, DL, NodeTys, Ops);
2883*9880d681SAndroid Build Coastguard Worker SDValue InFlag = Chain.getValue(1);
2884*9880d681SAndroid Build Coastguard Worker
2885*9880d681SAndroid Build Coastguard Worker // Create the CALLSEQ_END node.
2886*9880d681SAndroid Build Coastguard Worker Chain = DAG.getCALLSEQ_END(Chain, NextStackOffsetVal,
2887*9880d681SAndroid Build Coastguard Worker DAG.getIntPtrConstant(0, DL, true), InFlag, DL);
2888*9880d681SAndroid Build Coastguard Worker InFlag = Chain.getValue(1);
2889*9880d681SAndroid Build Coastguard Worker
2890*9880d681SAndroid Build Coastguard Worker // Handle result values, copying them out of physregs into vregs that we
2891*9880d681SAndroid Build Coastguard Worker // return.
2892*9880d681SAndroid Build Coastguard Worker return LowerCallResult(Chain, InFlag, CallConv, IsVarArg, Ins, DL, DAG,
2893*9880d681SAndroid Build Coastguard Worker InVals, CLI);
2894*9880d681SAndroid Build Coastguard Worker }
2895*9880d681SAndroid Build Coastguard Worker
2896*9880d681SAndroid Build Coastguard Worker /// LowerCallResult - Lower the result values of a call into the
2897*9880d681SAndroid Build Coastguard Worker /// appropriate copies out of appropriate physical registers.
LowerCallResult(SDValue Chain,SDValue InFlag,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::InputArg> & Ins,const SDLoc & DL,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals,TargetLowering::CallLoweringInfo & CLI) const2898*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::LowerCallResult(
2899*9880d681SAndroid Build Coastguard Worker SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool IsVarArg,
2900*9880d681SAndroid Build Coastguard Worker const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
2901*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
2902*9880d681SAndroid Build Coastguard Worker TargetLowering::CallLoweringInfo &CLI) const {
2903*9880d681SAndroid Build Coastguard Worker // Assign locations to each value returned by this call.
2904*9880d681SAndroid Build Coastguard Worker SmallVector<CCValAssign, 16> RVLocs;
2905*9880d681SAndroid Build Coastguard Worker MipsCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
2906*9880d681SAndroid Build Coastguard Worker *DAG.getContext());
2907*9880d681SAndroid Build Coastguard Worker CCInfo.AnalyzeCallResult(Ins, RetCC_Mips, CLI);
2908*9880d681SAndroid Build Coastguard Worker
2909*9880d681SAndroid Build Coastguard Worker // Copy all of the result registers out of their specified physreg.
2910*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i != RVLocs.size(); ++i) {
2911*9880d681SAndroid Build Coastguard Worker CCValAssign &VA = RVLocs[i];
2912*9880d681SAndroid Build Coastguard Worker assert(VA.isRegLoc() && "Can only return in registers!");
2913*9880d681SAndroid Build Coastguard Worker
2914*9880d681SAndroid Build Coastguard Worker SDValue Val = DAG.getCopyFromReg(Chain, DL, RVLocs[i].getLocReg(),
2915*9880d681SAndroid Build Coastguard Worker RVLocs[i].getLocVT(), InFlag);
2916*9880d681SAndroid Build Coastguard Worker Chain = Val.getValue(1);
2917*9880d681SAndroid Build Coastguard Worker InFlag = Val.getValue(2);
2918*9880d681SAndroid Build Coastguard Worker
2919*9880d681SAndroid Build Coastguard Worker if (VA.isUpperBitsInLoc()) {
2920*9880d681SAndroid Build Coastguard Worker unsigned ValSizeInBits = Ins[i].ArgVT.getSizeInBits();
2921*9880d681SAndroid Build Coastguard Worker unsigned LocSizeInBits = VA.getLocVT().getSizeInBits();
2922*9880d681SAndroid Build Coastguard Worker unsigned Shift =
2923*9880d681SAndroid Build Coastguard Worker VA.getLocInfo() == CCValAssign::ZExtUpper ? ISD::SRL : ISD::SRA;
2924*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(
2925*9880d681SAndroid Build Coastguard Worker Shift, DL, VA.getLocVT(), Val,
2926*9880d681SAndroid Build Coastguard Worker DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT()));
2927*9880d681SAndroid Build Coastguard Worker }
2928*9880d681SAndroid Build Coastguard Worker
2929*9880d681SAndroid Build Coastguard Worker switch (VA.getLocInfo()) {
2930*9880d681SAndroid Build Coastguard Worker default:
2931*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown loc info!");
2932*9880d681SAndroid Build Coastguard Worker case CCValAssign::Full:
2933*9880d681SAndroid Build Coastguard Worker break;
2934*9880d681SAndroid Build Coastguard Worker case CCValAssign::BCvt:
2935*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val);
2936*9880d681SAndroid Build Coastguard Worker break;
2937*9880d681SAndroid Build Coastguard Worker case CCValAssign::AExt:
2938*9880d681SAndroid Build Coastguard Worker case CCValAssign::AExtUpper:
2939*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
2940*9880d681SAndroid Build Coastguard Worker break;
2941*9880d681SAndroid Build Coastguard Worker case CCValAssign::ZExt:
2942*9880d681SAndroid Build Coastguard Worker case CCValAssign::ZExtUpper:
2943*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Val,
2944*9880d681SAndroid Build Coastguard Worker DAG.getValueType(VA.getValVT()));
2945*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
2946*9880d681SAndroid Build Coastguard Worker break;
2947*9880d681SAndroid Build Coastguard Worker case CCValAssign::SExt:
2948*9880d681SAndroid Build Coastguard Worker case CCValAssign::SExtUpper:
2949*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Val,
2950*9880d681SAndroid Build Coastguard Worker DAG.getValueType(VA.getValVT()));
2951*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
2952*9880d681SAndroid Build Coastguard Worker break;
2953*9880d681SAndroid Build Coastguard Worker }
2954*9880d681SAndroid Build Coastguard Worker
2955*9880d681SAndroid Build Coastguard Worker InVals.push_back(Val);
2956*9880d681SAndroid Build Coastguard Worker }
2957*9880d681SAndroid Build Coastguard Worker
2958*9880d681SAndroid Build Coastguard Worker return Chain;
2959*9880d681SAndroid Build Coastguard Worker }
2960*9880d681SAndroid Build Coastguard Worker
UnpackFromArgumentSlot(SDValue Val,const CCValAssign & VA,EVT ArgVT,const SDLoc & DL,SelectionDAG & DAG)2961*9880d681SAndroid Build Coastguard Worker static SDValue UnpackFromArgumentSlot(SDValue Val, const CCValAssign &VA,
2962*9880d681SAndroid Build Coastguard Worker EVT ArgVT, const SDLoc &DL,
2963*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) {
2964*9880d681SAndroid Build Coastguard Worker MVT LocVT = VA.getLocVT();
2965*9880d681SAndroid Build Coastguard Worker EVT ValVT = VA.getValVT();
2966*9880d681SAndroid Build Coastguard Worker
2967*9880d681SAndroid Build Coastguard Worker // Shift into the upper bits if necessary.
2968*9880d681SAndroid Build Coastguard Worker switch (VA.getLocInfo()) {
2969*9880d681SAndroid Build Coastguard Worker default:
2970*9880d681SAndroid Build Coastguard Worker break;
2971*9880d681SAndroid Build Coastguard Worker case CCValAssign::AExtUpper:
2972*9880d681SAndroid Build Coastguard Worker case CCValAssign::SExtUpper:
2973*9880d681SAndroid Build Coastguard Worker case CCValAssign::ZExtUpper: {
2974*9880d681SAndroid Build Coastguard Worker unsigned ValSizeInBits = ArgVT.getSizeInBits();
2975*9880d681SAndroid Build Coastguard Worker unsigned LocSizeInBits = VA.getLocVT().getSizeInBits();
2976*9880d681SAndroid Build Coastguard Worker unsigned Opcode =
2977*9880d681SAndroid Build Coastguard Worker VA.getLocInfo() == CCValAssign::ZExtUpper ? ISD::SRL : ISD::SRA;
2978*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(
2979*9880d681SAndroid Build Coastguard Worker Opcode, DL, VA.getLocVT(), Val,
2980*9880d681SAndroid Build Coastguard Worker DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT()));
2981*9880d681SAndroid Build Coastguard Worker break;
2982*9880d681SAndroid Build Coastguard Worker }
2983*9880d681SAndroid Build Coastguard Worker }
2984*9880d681SAndroid Build Coastguard Worker
2985*9880d681SAndroid Build Coastguard Worker // If this is an value smaller than the argument slot size (32-bit for O32,
2986*9880d681SAndroid Build Coastguard Worker // 64-bit for N32/N64), it has been promoted in some way to the argument slot
2987*9880d681SAndroid Build Coastguard Worker // size. Extract the value and insert any appropriate assertions regarding
2988*9880d681SAndroid Build Coastguard Worker // sign/zero extension.
2989*9880d681SAndroid Build Coastguard Worker switch (VA.getLocInfo()) {
2990*9880d681SAndroid Build Coastguard Worker default:
2991*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown loc info!");
2992*9880d681SAndroid Build Coastguard Worker case CCValAssign::Full:
2993*9880d681SAndroid Build Coastguard Worker break;
2994*9880d681SAndroid Build Coastguard Worker case CCValAssign::AExtUpper:
2995*9880d681SAndroid Build Coastguard Worker case CCValAssign::AExt:
2996*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val);
2997*9880d681SAndroid Build Coastguard Worker break;
2998*9880d681SAndroid Build Coastguard Worker case CCValAssign::SExtUpper:
2999*9880d681SAndroid Build Coastguard Worker case CCValAssign::SExt:
3000*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(ISD::AssertSext, DL, LocVT, Val, DAG.getValueType(ValVT));
3001*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val);
3002*9880d681SAndroid Build Coastguard Worker break;
3003*9880d681SAndroid Build Coastguard Worker case CCValAssign::ZExtUpper:
3004*9880d681SAndroid Build Coastguard Worker case CCValAssign::ZExt:
3005*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(ISD::AssertZext, DL, LocVT, Val, DAG.getValueType(ValVT));
3006*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val);
3007*9880d681SAndroid Build Coastguard Worker break;
3008*9880d681SAndroid Build Coastguard Worker case CCValAssign::BCvt:
3009*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(ISD::BITCAST, DL, ValVT, Val);
3010*9880d681SAndroid Build Coastguard Worker break;
3011*9880d681SAndroid Build Coastguard Worker }
3012*9880d681SAndroid Build Coastguard Worker
3013*9880d681SAndroid Build Coastguard Worker return Val;
3014*9880d681SAndroid Build Coastguard Worker }
3015*9880d681SAndroid Build Coastguard Worker
3016*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
3017*9880d681SAndroid Build Coastguard Worker // Formal Arguments Calling Convention Implementation
3018*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
3019*9880d681SAndroid Build Coastguard Worker /// LowerFormalArguments - transform physical registers into virtual registers
3020*9880d681SAndroid Build Coastguard Worker /// and generate load operations for arguments places on the stack.
LowerFormalArguments(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::InputArg> & Ins,const SDLoc & DL,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals) const3021*9880d681SAndroid Build Coastguard Worker SDValue MipsTargetLowering::LowerFormalArguments(
3022*9880d681SAndroid Build Coastguard Worker SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
3023*9880d681SAndroid Build Coastguard Worker const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
3024*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
3025*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = DAG.getMachineFunction();
3026*9880d681SAndroid Build Coastguard Worker MachineFrameInfo *MFI = MF.getFrameInfo();
3027*9880d681SAndroid Build Coastguard Worker MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
3028*9880d681SAndroid Build Coastguard Worker
3029*9880d681SAndroid Build Coastguard Worker MipsFI->setVarArgsFrameIndex(0);
3030*9880d681SAndroid Build Coastguard Worker
3031*9880d681SAndroid Build Coastguard Worker // Used with vargs to acumulate store chains.
3032*9880d681SAndroid Build Coastguard Worker std::vector<SDValue> OutChains;
3033*9880d681SAndroid Build Coastguard Worker
3034*9880d681SAndroid Build Coastguard Worker // Assign locations to all of the incoming arguments.
3035*9880d681SAndroid Build Coastguard Worker SmallVector<CCValAssign, 16> ArgLocs;
3036*9880d681SAndroid Build Coastguard Worker MipsCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
3037*9880d681SAndroid Build Coastguard Worker *DAG.getContext());
3038*9880d681SAndroid Build Coastguard Worker CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1);
3039*9880d681SAndroid Build Coastguard Worker const Function *Func = DAG.getMachineFunction().getFunction();
3040*9880d681SAndroid Build Coastguard Worker Function::const_arg_iterator FuncArg = Func->arg_begin();
3041*9880d681SAndroid Build Coastguard Worker
3042*9880d681SAndroid Build Coastguard Worker if (Func->hasFnAttribute("interrupt") && !Func->arg_empty())
3043*9880d681SAndroid Build Coastguard Worker report_fatal_error(
3044*9880d681SAndroid Build Coastguard Worker "Functions with the interrupt attribute cannot have arguments!");
3045*9880d681SAndroid Build Coastguard Worker
3046*9880d681SAndroid Build Coastguard Worker CCInfo.AnalyzeFormalArguments(Ins, CC_Mips_FixedArg);
3047*9880d681SAndroid Build Coastguard Worker MipsFI->setFormalArgInfo(CCInfo.getNextStackOffset(),
3048*9880d681SAndroid Build Coastguard Worker CCInfo.getInRegsParamsCount() > 0);
3049*9880d681SAndroid Build Coastguard Worker
3050*9880d681SAndroid Build Coastguard Worker unsigned CurArgIdx = 0;
3051*9880d681SAndroid Build Coastguard Worker CCInfo.rewindByValRegsInfo();
3052*9880d681SAndroid Build Coastguard Worker
3053*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
3054*9880d681SAndroid Build Coastguard Worker CCValAssign &VA = ArgLocs[i];
3055*9880d681SAndroid Build Coastguard Worker if (Ins[i].isOrigArg()) {
3056*9880d681SAndroid Build Coastguard Worker std::advance(FuncArg, Ins[i].getOrigArgIndex() - CurArgIdx);
3057*9880d681SAndroid Build Coastguard Worker CurArgIdx = Ins[i].getOrigArgIndex();
3058*9880d681SAndroid Build Coastguard Worker }
3059*9880d681SAndroid Build Coastguard Worker EVT ValVT = VA.getValVT();
3060*9880d681SAndroid Build Coastguard Worker ISD::ArgFlagsTy Flags = Ins[i].Flags;
3061*9880d681SAndroid Build Coastguard Worker bool IsRegLoc = VA.isRegLoc();
3062*9880d681SAndroid Build Coastguard Worker
3063*9880d681SAndroid Build Coastguard Worker if (Flags.isByVal()) {
3064*9880d681SAndroid Build Coastguard Worker assert(Ins[i].isOrigArg() && "Byval arguments cannot be implicit");
3065*9880d681SAndroid Build Coastguard Worker unsigned FirstByValReg, LastByValReg;
3066*9880d681SAndroid Build Coastguard Worker unsigned ByValIdx = CCInfo.getInRegsParamsProcessed();
3067*9880d681SAndroid Build Coastguard Worker CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg);
3068*9880d681SAndroid Build Coastguard Worker
3069*9880d681SAndroid Build Coastguard Worker assert(Flags.getByValSize() &&
3070*9880d681SAndroid Build Coastguard Worker "ByVal args of size 0 should have been ignored by front-end.");
3071*9880d681SAndroid Build Coastguard Worker assert(ByValIdx < CCInfo.getInRegsParamsCount());
3072*9880d681SAndroid Build Coastguard Worker copyByValRegs(Chain, DL, OutChains, DAG, Flags, InVals, &*FuncArg,
3073*9880d681SAndroid Build Coastguard Worker FirstByValReg, LastByValReg, VA, CCInfo);
3074*9880d681SAndroid Build Coastguard Worker CCInfo.nextInRegsParam();
3075*9880d681SAndroid Build Coastguard Worker continue;
3076*9880d681SAndroid Build Coastguard Worker }
3077*9880d681SAndroid Build Coastguard Worker
3078*9880d681SAndroid Build Coastguard Worker // Arguments stored on registers
3079*9880d681SAndroid Build Coastguard Worker if (IsRegLoc) {
3080*9880d681SAndroid Build Coastguard Worker MVT RegVT = VA.getLocVT();
3081*9880d681SAndroid Build Coastguard Worker unsigned ArgReg = VA.getLocReg();
3082*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = getRegClassFor(RegVT);
3083*9880d681SAndroid Build Coastguard Worker
3084*9880d681SAndroid Build Coastguard Worker // Transform the arguments stored on
3085*9880d681SAndroid Build Coastguard Worker // physical registers into virtual ones
3086*9880d681SAndroid Build Coastguard Worker unsigned Reg = addLiveIn(DAG.getMachineFunction(), ArgReg, RC);
3087*9880d681SAndroid Build Coastguard Worker SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT);
3088*9880d681SAndroid Build Coastguard Worker
3089*9880d681SAndroid Build Coastguard Worker ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG);
3090*9880d681SAndroid Build Coastguard Worker
3091*9880d681SAndroid Build Coastguard Worker // Handle floating point arguments passed in integer registers and
3092*9880d681SAndroid Build Coastguard Worker // long double arguments passed in floating point registers.
3093*9880d681SAndroid Build Coastguard Worker if ((RegVT == MVT::i32 && ValVT == MVT::f32) ||
3094*9880d681SAndroid Build Coastguard Worker (RegVT == MVT::i64 && ValVT == MVT::f64) ||
3095*9880d681SAndroid Build Coastguard Worker (RegVT == MVT::f64 && ValVT == MVT::i64))
3096*9880d681SAndroid Build Coastguard Worker ArgValue = DAG.getNode(ISD::BITCAST, DL, ValVT, ArgValue);
3097*9880d681SAndroid Build Coastguard Worker else if (ABI.IsO32() && RegVT == MVT::i32 &&
3098*9880d681SAndroid Build Coastguard Worker ValVT == MVT::f64) {
3099*9880d681SAndroid Build Coastguard Worker unsigned Reg2 = addLiveIn(DAG.getMachineFunction(),
3100*9880d681SAndroid Build Coastguard Worker getNextIntArgReg(ArgReg), RC);
3101*9880d681SAndroid Build Coastguard Worker SDValue ArgValue2 = DAG.getCopyFromReg(Chain, DL, Reg2, RegVT);
3102*9880d681SAndroid Build Coastguard Worker if (!Subtarget.isLittle())
3103*9880d681SAndroid Build Coastguard Worker std::swap(ArgValue, ArgValue2);
3104*9880d681SAndroid Build Coastguard Worker ArgValue = DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64,
3105*9880d681SAndroid Build Coastguard Worker ArgValue, ArgValue2);
3106*9880d681SAndroid Build Coastguard Worker }
3107*9880d681SAndroid Build Coastguard Worker
3108*9880d681SAndroid Build Coastguard Worker InVals.push_back(ArgValue);
3109*9880d681SAndroid Build Coastguard Worker } else { // VA.isRegLoc()
3110*9880d681SAndroid Build Coastguard Worker MVT LocVT = VA.getLocVT();
3111*9880d681SAndroid Build Coastguard Worker
3112*9880d681SAndroid Build Coastguard Worker if (ABI.IsO32()) {
3113*9880d681SAndroid Build Coastguard Worker // We ought to be able to use LocVT directly but O32 sets it to i32
3114*9880d681SAndroid Build Coastguard Worker // when allocating floating point values to integer registers.
3115*9880d681SAndroid Build Coastguard Worker // This shouldn't influence how we load the value into registers unless
3116*9880d681SAndroid Build Coastguard Worker // we are targeting softfloat.
3117*9880d681SAndroid Build Coastguard Worker if (VA.getValVT().isFloatingPoint() && !Subtarget.useSoftFloat())
3118*9880d681SAndroid Build Coastguard Worker LocVT = VA.getValVT();
3119*9880d681SAndroid Build Coastguard Worker }
3120*9880d681SAndroid Build Coastguard Worker
3121*9880d681SAndroid Build Coastguard Worker // sanity check
3122*9880d681SAndroid Build Coastguard Worker assert(VA.isMemLoc());
3123*9880d681SAndroid Build Coastguard Worker
3124*9880d681SAndroid Build Coastguard Worker // The stack pointer offset is relative to the caller stack frame.
3125*9880d681SAndroid Build Coastguard Worker int FI = MFI->CreateFixedObject(LocVT.getSizeInBits() / 8,
3126*9880d681SAndroid Build Coastguard Worker VA.getLocMemOffset(), true);
3127*9880d681SAndroid Build Coastguard Worker
3128*9880d681SAndroid Build Coastguard Worker // Create load nodes to retrieve arguments from the stack
3129*9880d681SAndroid Build Coastguard Worker SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
3130*9880d681SAndroid Build Coastguard Worker SDValue ArgValue = DAG.getLoad(
3131*9880d681SAndroid Build Coastguard Worker LocVT, DL, Chain, FIN,
3132*9880d681SAndroid Build Coastguard Worker MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI),
3133*9880d681SAndroid Build Coastguard Worker false, false, false, 0);
3134*9880d681SAndroid Build Coastguard Worker OutChains.push_back(ArgValue.getValue(1));
3135*9880d681SAndroid Build Coastguard Worker
3136*9880d681SAndroid Build Coastguard Worker ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG);
3137*9880d681SAndroid Build Coastguard Worker
3138*9880d681SAndroid Build Coastguard Worker InVals.push_back(ArgValue);
3139*9880d681SAndroid Build Coastguard Worker }
3140*9880d681SAndroid Build Coastguard Worker }
3141*9880d681SAndroid Build Coastguard Worker
3142*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
3143*9880d681SAndroid Build Coastguard Worker // The mips ABIs for returning structs by value requires that we copy
3144*9880d681SAndroid Build Coastguard Worker // the sret argument into $v0 for the return. Save the argument into
3145*9880d681SAndroid Build Coastguard Worker // a virtual register so that we can access it from the return points.
3146*9880d681SAndroid Build Coastguard Worker if (Ins[i].Flags.isSRet()) {
3147*9880d681SAndroid Build Coastguard Worker unsigned Reg = MipsFI->getSRetReturnReg();
3148*9880d681SAndroid Build Coastguard Worker if (!Reg) {
3149*9880d681SAndroid Build Coastguard Worker Reg = MF.getRegInfo().createVirtualRegister(
3150*9880d681SAndroid Build Coastguard Worker getRegClassFor(ABI.IsN64() ? MVT::i64 : MVT::i32));
3151*9880d681SAndroid Build Coastguard Worker MipsFI->setSRetReturnReg(Reg);
3152*9880d681SAndroid Build Coastguard Worker }
3153*9880d681SAndroid Build Coastguard Worker SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), DL, Reg, InVals[i]);
3154*9880d681SAndroid Build Coastguard Worker Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Copy, Chain);
3155*9880d681SAndroid Build Coastguard Worker break;
3156*9880d681SAndroid Build Coastguard Worker }
3157*9880d681SAndroid Build Coastguard Worker }
3158*9880d681SAndroid Build Coastguard Worker
3159*9880d681SAndroid Build Coastguard Worker if (IsVarArg)
3160*9880d681SAndroid Build Coastguard Worker writeVarArgRegs(OutChains, Chain, DL, DAG, CCInfo);
3161*9880d681SAndroid Build Coastguard Worker
3162*9880d681SAndroid Build Coastguard Worker // All stores are grouped in one node to allow the matching between
3163*9880d681SAndroid Build Coastguard Worker // the size of Ins and InVals. This only happens when on varg functions
3164*9880d681SAndroid Build Coastguard Worker if (!OutChains.empty()) {
3165*9880d681SAndroid Build Coastguard Worker OutChains.push_back(Chain);
3166*9880d681SAndroid Build Coastguard Worker Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
3167*9880d681SAndroid Build Coastguard Worker }
3168*9880d681SAndroid Build Coastguard Worker
3169*9880d681SAndroid Build Coastguard Worker return Chain;
3170*9880d681SAndroid Build Coastguard Worker }
3171*9880d681SAndroid Build Coastguard Worker
3172*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
3173*9880d681SAndroid Build Coastguard Worker // Return Value Calling Convention Implementation
3174*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
3175*9880d681SAndroid Build Coastguard Worker
3176*9880d681SAndroid Build Coastguard Worker bool
CanLowerReturn(CallingConv::ID CallConv,MachineFunction & MF,bool IsVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,LLVMContext & Context) const3177*9880d681SAndroid Build Coastguard Worker MipsTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
3178*9880d681SAndroid Build Coastguard Worker MachineFunction &MF, bool IsVarArg,
3179*9880d681SAndroid Build Coastguard Worker const SmallVectorImpl<ISD::OutputArg> &Outs,
3180*9880d681SAndroid Build Coastguard Worker LLVMContext &Context) const {
3181*9880d681SAndroid Build Coastguard Worker SmallVector<CCValAssign, 16> RVLocs;
3182*9880d681SAndroid Build Coastguard Worker MipsCCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
3183*9880d681SAndroid Build Coastguard Worker return CCInfo.CheckReturn(Outs, RetCC_Mips);
3184*9880d681SAndroid Build Coastguard Worker }
3185*9880d681SAndroid Build Coastguard Worker
3186*9880d681SAndroid Build Coastguard Worker bool
shouldSignExtendTypeInLibCall(EVT Type,bool IsSigned) const3187*9880d681SAndroid Build Coastguard Worker MipsTargetLowering::shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const {
3188*9880d681SAndroid Build Coastguard Worker if (Subtarget.hasMips3() && Subtarget.useSoftFloat()) {
3189*9880d681SAndroid Build Coastguard Worker if (Type == MVT::i32)
3190*9880d681SAndroid Build Coastguard Worker return true;
3191*9880d681SAndroid Build Coastguard Worker }
3192*9880d681SAndroid Build Coastguard Worker return IsSigned;
3193*9880d681SAndroid Build Coastguard Worker }
3194*9880d681SAndroid Build Coastguard Worker
3195*9880d681SAndroid Build Coastguard Worker SDValue
LowerInterruptReturn(SmallVectorImpl<SDValue> & RetOps,const SDLoc & DL,SelectionDAG & DAG) const3196*9880d681SAndroid Build Coastguard Worker MipsTargetLowering::LowerInterruptReturn(SmallVectorImpl<SDValue> &RetOps,
3197*9880d681SAndroid Build Coastguard Worker const SDLoc &DL,
3198*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
3199*9880d681SAndroid Build Coastguard Worker
3200*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = DAG.getMachineFunction();
3201*9880d681SAndroid Build Coastguard Worker MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
3202*9880d681SAndroid Build Coastguard Worker
3203*9880d681SAndroid Build Coastguard Worker MipsFI->setISR();
3204*9880d681SAndroid Build Coastguard Worker
3205*9880d681SAndroid Build Coastguard Worker return DAG.getNode(MipsISD::ERet, DL, MVT::Other, RetOps);
3206*9880d681SAndroid Build Coastguard Worker }
3207*9880d681SAndroid Build Coastguard Worker
3208*9880d681SAndroid Build Coastguard Worker SDValue
LowerReturn(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,const SmallVectorImpl<SDValue> & OutVals,const SDLoc & DL,SelectionDAG & DAG) const3209*9880d681SAndroid Build Coastguard Worker MipsTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
3210*9880d681SAndroid Build Coastguard Worker bool IsVarArg,
3211*9880d681SAndroid Build Coastguard Worker const SmallVectorImpl<ISD::OutputArg> &Outs,
3212*9880d681SAndroid Build Coastguard Worker const SmallVectorImpl<SDValue> &OutVals,
3213*9880d681SAndroid Build Coastguard Worker const SDLoc &DL, SelectionDAG &DAG) const {
3214*9880d681SAndroid Build Coastguard Worker // CCValAssign - represent the assignment of
3215*9880d681SAndroid Build Coastguard Worker // the return value to a location
3216*9880d681SAndroid Build Coastguard Worker SmallVector<CCValAssign, 16> RVLocs;
3217*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = DAG.getMachineFunction();
3218*9880d681SAndroid Build Coastguard Worker
3219*9880d681SAndroid Build Coastguard Worker // CCState - Info about the registers and stack slot.
3220*9880d681SAndroid Build Coastguard Worker MipsCCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext());
3221*9880d681SAndroid Build Coastguard Worker
3222*9880d681SAndroid Build Coastguard Worker // Analyze return values.
3223*9880d681SAndroid Build Coastguard Worker CCInfo.AnalyzeReturn(Outs, RetCC_Mips);
3224*9880d681SAndroid Build Coastguard Worker
3225*9880d681SAndroid Build Coastguard Worker SDValue Flag;
3226*9880d681SAndroid Build Coastguard Worker SmallVector<SDValue, 4> RetOps(1, Chain);
3227*9880d681SAndroid Build Coastguard Worker
3228*9880d681SAndroid Build Coastguard Worker // Copy the result values into the output registers.
3229*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i != RVLocs.size(); ++i) {
3230*9880d681SAndroid Build Coastguard Worker SDValue Val = OutVals[i];
3231*9880d681SAndroid Build Coastguard Worker CCValAssign &VA = RVLocs[i];
3232*9880d681SAndroid Build Coastguard Worker assert(VA.isRegLoc() && "Can only return in registers!");
3233*9880d681SAndroid Build Coastguard Worker bool UseUpperBits = false;
3234*9880d681SAndroid Build Coastguard Worker
3235*9880d681SAndroid Build Coastguard Worker switch (VA.getLocInfo()) {
3236*9880d681SAndroid Build Coastguard Worker default:
3237*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown loc info!");
3238*9880d681SAndroid Build Coastguard Worker case CCValAssign::Full:
3239*9880d681SAndroid Build Coastguard Worker break;
3240*9880d681SAndroid Build Coastguard Worker case CCValAssign::BCvt:
3241*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Val);
3242*9880d681SAndroid Build Coastguard Worker break;
3243*9880d681SAndroid Build Coastguard Worker case CCValAssign::AExtUpper:
3244*9880d681SAndroid Build Coastguard Worker UseUpperBits = true;
3245*9880d681SAndroid Build Coastguard Worker // Fallthrough
3246*9880d681SAndroid Build Coastguard Worker case CCValAssign::AExt:
3247*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Val);
3248*9880d681SAndroid Build Coastguard Worker break;
3249*9880d681SAndroid Build Coastguard Worker case CCValAssign::ZExtUpper:
3250*9880d681SAndroid Build Coastguard Worker UseUpperBits = true;
3251*9880d681SAndroid Build Coastguard Worker // Fallthrough
3252*9880d681SAndroid Build Coastguard Worker case CCValAssign::ZExt:
3253*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Val);
3254*9880d681SAndroid Build Coastguard Worker break;
3255*9880d681SAndroid Build Coastguard Worker case CCValAssign::SExtUpper:
3256*9880d681SAndroid Build Coastguard Worker UseUpperBits = true;
3257*9880d681SAndroid Build Coastguard Worker // Fallthrough
3258*9880d681SAndroid Build Coastguard Worker case CCValAssign::SExt:
3259*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Val);
3260*9880d681SAndroid Build Coastguard Worker break;
3261*9880d681SAndroid Build Coastguard Worker }
3262*9880d681SAndroid Build Coastguard Worker
3263*9880d681SAndroid Build Coastguard Worker if (UseUpperBits) {
3264*9880d681SAndroid Build Coastguard Worker unsigned ValSizeInBits = Outs[i].ArgVT.getSizeInBits();
3265*9880d681SAndroid Build Coastguard Worker unsigned LocSizeInBits = VA.getLocVT().getSizeInBits();
3266*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(
3267*9880d681SAndroid Build Coastguard Worker ISD::SHL, DL, VA.getLocVT(), Val,
3268*9880d681SAndroid Build Coastguard Worker DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT()));
3269*9880d681SAndroid Build Coastguard Worker }
3270*9880d681SAndroid Build Coastguard Worker
3271*9880d681SAndroid Build Coastguard Worker Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Flag);
3272*9880d681SAndroid Build Coastguard Worker
3273*9880d681SAndroid Build Coastguard Worker // Guarantee that all emitted copies are stuck together with flags.
3274*9880d681SAndroid Build Coastguard Worker Flag = Chain.getValue(1);
3275*9880d681SAndroid Build Coastguard Worker RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
3276*9880d681SAndroid Build Coastguard Worker }
3277*9880d681SAndroid Build Coastguard Worker
3278*9880d681SAndroid Build Coastguard Worker // The mips ABIs for returning structs by value requires that we copy
3279*9880d681SAndroid Build Coastguard Worker // the sret argument into $v0 for the return. We saved the argument into
3280*9880d681SAndroid Build Coastguard Worker // a virtual register in the entry block, so now we copy the value out
3281*9880d681SAndroid Build Coastguard Worker // and into $v0.
3282*9880d681SAndroid Build Coastguard Worker if (MF.getFunction()->hasStructRetAttr()) {
3283*9880d681SAndroid Build Coastguard Worker MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
3284*9880d681SAndroid Build Coastguard Worker unsigned Reg = MipsFI->getSRetReturnReg();
3285*9880d681SAndroid Build Coastguard Worker
3286*9880d681SAndroid Build Coastguard Worker if (!Reg)
3287*9880d681SAndroid Build Coastguard Worker llvm_unreachable("sret virtual register not created in the entry block");
3288*9880d681SAndroid Build Coastguard Worker SDValue Val =
3289*9880d681SAndroid Build Coastguard Worker DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy(DAG.getDataLayout()));
3290*9880d681SAndroid Build Coastguard Worker unsigned V0 = ABI.IsN64() ? Mips::V0_64 : Mips::V0;
3291*9880d681SAndroid Build Coastguard Worker
3292*9880d681SAndroid Build Coastguard Worker Chain = DAG.getCopyToReg(Chain, DL, V0, Val, Flag);
3293*9880d681SAndroid Build Coastguard Worker Flag = Chain.getValue(1);
3294*9880d681SAndroid Build Coastguard Worker RetOps.push_back(DAG.getRegister(V0, getPointerTy(DAG.getDataLayout())));
3295*9880d681SAndroid Build Coastguard Worker }
3296*9880d681SAndroid Build Coastguard Worker
3297*9880d681SAndroid Build Coastguard Worker RetOps[0] = Chain; // Update chain.
3298*9880d681SAndroid Build Coastguard Worker
3299*9880d681SAndroid Build Coastguard Worker // Add the flag if we have it.
3300*9880d681SAndroid Build Coastguard Worker if (Flag.getNode())
3301*9880d681SAndroid Build Coastguard Worker RetOps.push_back(Flag);
3302*9880d681SAndroid Build Coastguard Worker
3303*9880d681SAndroid Build Coastguard Worker // ISRs must use "eret".
3304*9880d681SAndroid Build Coastguard Worker if (DAG.getMachineFunction().getFunction()->hasFnAttribute("interrupt"))
3305*9880d681SAndroid Build Coastguard Worker return LowerInterruptReturn(RetOps, DL, DAG);
3306*9880d681SAndroid Build Coastguard Worker
3307*9880d681SAndroid Build Coastguard Worker // Standard return on Mips is a "jr $ra"
3308*9880d681SAndroid Build Coastguard Worker return DAG.getNode(MipsISD::Ret, DL, MVT::Other, RetOps);
3309*9880d681SAndroid Build Coastguard Worker }
3310*9880d681SAndroid Build Coastguard Worker
3311*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
3312*9880d681SAndroid Build Coastguard Worker // Mips Inline Assembly Support
3313*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
3314*9880d681SAndroid Build Coastguard Worker
3315*9880d681SAndroid Build Coastguard Worker /// getConstraintType - Given a constraint letter, return the type of
3316*9880d681SAndroid Build Coastguard Worker /// constraint it is for this target.
3317*9880d681SAndroid Build Coastguard Worker MipsTargetLowering::ConstraintType
getConstraintType(StringRef Constraint) const3318*9880d681SAndroid Build Coastguard Worker MipsTargetLowering::getConstraintType(StringRef Constraint) const {
3319*9880d681SAndroid Build Coastguard Worker // Mips specific constraints
3320*9880d681SAndroid Build Coastguard Worker // GCC config/mips/constraints.md
3321*9880d681SAndroid Build Coastguard Worker //
3322*9880d681SAndroid Build Coastguard Worker // 'd' : An address register. Equivalent to r
3323*9880d681SAndroid Build Coastguard Worker // unless generating MIPS16 code.
3324*9880d681SAndroid Build Coastguard Worker // 'y' : Equivalent to r; retained for
3325*9880d681SAndroid Build Coastguard Worker // backwards compatibility.
3326*9880d681SAndroid Build Coastguard Worker // 'c' : A register suitable for use in an indirect
3327*9880d681SAndroid Build Coastguard Worker // jump. This will always be $25 for -mabicalls.
3328*9880d681SAndroid Build Coastguard Worker // 'l' : The lo register. 1 word storage.
3329*9880d681SAndroid Build Coastguard Worker // 'x' : The hilo register pair. Double word storage.
3330*9880d681SAndroid Build Coastguard Worker if (Constraint.size() == 1) {
3331*9880d681SAndroid Build Coastguard Worker switch (Constraint[0]) {
3332*9880d681SAndroid Build Coastguard Worker default : break;
3333*9880d681SAndroid Build Coastguard Worker case 'd':
3334*9880d681SAndroid Build Coastguard Worker case 'y':
3335*9880d681SAndroid Build Coastguard Worker case 'f':
3336*9880d681SAndroid Build Coastguard Worker case 'c':
3337*9880d681SAndroid Build Coastguard Worker case 'l':
3338*9880d681SAndroid Build Coastguard Worker case 'x':
3339*9880d681SAndroid Build Coastguard Worker return C_RegisterClass;
3340*9880d681SAndroid Build Coastguard Worker case 'R':
3341*9880d681SAndroid Build Coastguard Worker return C_Memory;
3342*9880d681SAndroid Build Coastguard Worker }
3343*9880d681SAndroid Build Coastguard Worker }
3344*9880d681SAndroid Build Coastguard Worker
3345*9880d681SAndroid Build Coastguard Worker if (Constraint == "ZC")
3346*9880d681SAndroid Build Coastguard Worker return C_Memory;
3347*9880d681SAndroid Build Coastguard Worker
3348*9880d681SAndroid Build Coastguard Worker return TargetLowering::getConstraintType(Constraint);
3349*9880d681SAndroid Build Coastguard Worker }
3350*9880d681SAndroid Build Coastguard Worker
3351*9880d681SAndroid Build Coastguard Worker /// Examine constraint type and operand type and determine a weight value.
3352*9880d681SAndroid Build Coastguard Worker /// This object must already have been set up with the operand type
3353*9880d681SAndroid Build Coastguard Worker /// and the current alternative constraint selected.
3354*9880d681SAndroid Build Coastguard Worker TargetLowering::ConstraintWeight
getSingleConstraintMatchWeight(AsmOperandInfo & info,const char * constraint) const3355*9880d681SAndroid Build Coastguard Worker MipsTargetLowering::getSingleConstraintMatchWeight(
3356*9880d681SAndroid Build Coastguard Worker AsmOperandInfo &info, const char *constraint) const {
3357*9880d681SAndroid Build Coastguard Worker ConstraintWeight weight = CW_Invalid;
3358*9880d681SAndroid Build Coastguard Worker Value *CallOperandVal = info.CallOperandVal;
3359*9880d681SAndroid Build Coastguard Worker // If we don't have a value, we can't do a match,
3360*9880d681SAndroid Build Coastguard Worker // but allow it at the lowest weight.
3361*9880d681SAndroid Build Coastguard Worker if (!CallOperandVal)
3362*9880d681SAndroid Build Coastguard Worker return CW_Default;
3363*9880d681SAndroid Build Coastguard Worker Type *type = CallOperandVal->getType();
3364*9880d681SAndroid Build Coastguard Worker // Look at the constraint type.
3365*9880d681SAndroid Build Coastguard Worker switch (*constraint) {
3366*9880d681SAndroid Build Coastguard Worker default:
3367*9880d681SAndroid Build Coastguard Worker weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
3368*9880d681SAndroid Build Coastguard Worker break;
3369*9880d681SAndroid Build Coastguard Worker case 'd':
3370*9880d681SAndroid Build Coastguard Worker case 'y':
3371*9880d681SAndroid Build Coastguard Worker if (type->isIntegerTy())
3372*9880d681SAndroid Build Coastguard Worker weight = CW_Register;
3373*9880d681SAndroid Build Coastguard Worker break;
3374*9880d681SAndroid Build Coastguard Worker case 'f': // FPU or MSA register
3375*9880d681SAndroid Build Coastguard Worker if (Subtarget.hasMSA() && type->isVectorTy() &&
3376*9880d681SAndroid Build Coastguard Worker cast<VectorType>(type)->getBitWidth() == 128)
3377*9880d681SAndroid Build Coastguard Worker weight = CW_Register;
3378*9880d681SAndroid Build Coastguard Worker else if (type->isFloatTy())
3379*9880d681SAndroid Build Coastguard Worker weight = CW_Register;
3380*9880d681SAndroid Build Coastguard Worker break;
3381*9880d681SAndroid Build Coastguard Worker case 'c': // $25 for indirect jumps
3382*9880d681SAndroid Build Coastguard Worker case 'l': // lo register
3383*9880d681SAndroid Build Coastguard Worker case 'x': // hilo register pair
3384*9880d681SAndroid Build Coastguard Worker if (type->isIntegerTy())
3385*9880d681SAndroid Build Coastguard Worker weight = CW_SpecificReg;
3386*9880d681SAndroid Build Coastguard Worker break;
3387*9880d681SAndroid Build Coastguard Worker case 'I': // signed 16 bit immediate
3388*9880d681SAndroid Build Coastguard Worker case 'J': // integer zero
3389*9880d681SAndroid Build Coastguard Worker case 'K': // unsigned 16 bit immediate
3390*9880d681SAndroid Build Coastguard Worker case 'L': // signed 32 bit immediate where lower 16 bits are 0
3391*9880d681SAndroid Build Coastguard Worker case 'N': // immediate in the range of -65535 to -1 (inclusive)
3392*9880d681SAndroid Build Coastguard Worker case 'O': // signed 15 bit immediate (+- 16383)
3393*9880d681SAndroid Build Coastguard Worker case 'P': // immediate in the range of 65535 to 1 (inclusive)
3394*9880d681SAndroid Build Coastguard Worker if (isa<ConstantInt>(CallOperandVal))
3395*9880d681SAndroid Build Coastguard Worker weight = CW_Constant;
3396*9880d681SAndroid Build Coastguard Worker break;
3397*9880d681SAndroid Build Coastguard Worker case 'R':
3398*9880d681SAndroid Build Coastguard Worker weight = CW_Memory;
3399*9880d681SAndroid Build Coastguard Worker break;
3400*9880d681SAndroid Build Coastguard Worker }
3401*9880d681SAndroid Build Coastguard Worker return weight;
3402*9880d681SAndroid Build Coastguard Worker }
3403*9880d681SAndroid Build Coastguard Worker
3404*9880d681SAndroid Build Coastguard Worker /// This is a helper function to parse a physical register string and split it
3405*9880d681SAndroid Build Coastguard Worker /// into non-numeric and numeric parts (Prefix and Reg). The first boolean flag
3406*9880d681SAndroid Build Coastguard Worker /// that is returned indicates whether parsing was successful. The second flag
3407*9880d681SAndroid Build Coastguard Worker /// is true if the numeric part exists.
parsePhysicalReg(StringRef C,StringRef & Prefix,unsigned long long & Reg)3408*9880d681SAndroid Build Coastguard Worker static std::pair<bool, bool> parsePhysicalReg(StringRef C, StringRef &Prefix,
3409*9880d681SAndroid Build Coastguard Worker unsigned long long &Reg) {
3410*9880d681SAndroid Build Coastguard Worker if (C.front() != '{' || C.back() != '}')
3411*9880d681SAndroid Build Coastguard Worker return std::make_pair(false, false);
3412*9880d681SAndroid Build Coastguard Worker
3413*9880d681SAndroid Build Coastguard Worker // Search for the first numeric character.
3414*9880d681SAndroid Build Coastguard Worker StringRef::const_iterator I, B = C.begin() + 1, E = C.end() - 1;
3415*9880d681SAndroid Build Coastguard Worker I = std::find_if(B, E, isdigit);
3416*9880d681SAndroid Build Coastguard Worker
3417*9880d681SAndroid Build Coastguard Worker Prefix = StringRef(B, I - B);
3418*9880d681SAndroid Build Coastguard Worker
3419*9880d681SAndroid Build Coastguard Worker // The second flag is set to false if no numeric characters were found.
3420*9880d681SAndroid Build Coastguard Worker if (I == E)
3421*9880d681SAndroid Build Coastguard Worker return std::make_pair(true, false);
3422*9880d681SAndroid Build Coastguard Worker
3423*9880d681SAndroid Build Coastguard Worker // Parse the numeric characters.
3424*9880d681SAndroid Build Coastguard Worker return std::make_pair(!getAsUnsignedInteger(StringRef(I, E - I), 10, Reg),
3425*9880d681SAndroid Build Coastguard Worker true);
3426*9880d681SAndroid Build Coastguard Worker }
3427*9880d681SAndroid Build Coastguard Worker
3428*9880d681SAndroid Build Coastguard Worker std::pair<unsigned, const TargetRegisterClass *> MipsTargetLowering::
parseRegForInlineAsmConstraint(StringRef C,MVT VT) const3429*9880d681SAndroid Build Coastguard Worker parseRegForInlineAsmConstraint(StringRef C, MVT VT) const {
3430*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI =
3431*9880d681SAndroid Build Coastguard Worker Subtarget.getRegisterInfo();
3432*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC;
3433*9880d681SAndroid Build Coastguard Worker StringRef Prefix;
3434*9880d681SAndroid Build Coastguard Worker unsigned long long Reg;
3435*9880d681SAndroid Build Coastguard Worker
3436*9880d681SAndroid Build Coastguard Worker std::pair<bool, bool> R = parsePhysicalReg(C, Prefix, Reg);
3437*9880d681SAndroid Build Coastguard Worker
3438*9880d681SAndroid Build Coastguard Worker if (!R.first)
3439*9880d681SAndroid Build Coastguard Worker return std::make_pair(0U, nullptr);
3440*9880d681SAndroid Build Coastguard Worker
3441*9880d681SAndroid Build Coastguard Worker if ((Prefix == "hi" || Prefix == "lo")) { // Parse hi/lo.
3442*9880d681SAndroid Build Coastguard Worker // No numeric characters follow "hi" or "lo".
3443*9880d681SAndroid Build Coastguard Worker if (R.second)
3444*9880d681SAndroid Build Coastguard Worker return std::make_pair(0U, nullptr);
3445*9880d681SAndroid Build Coastguard Worker
3446*9880d681SAndroid Build Coastguard Worker RC = TRI->getRegClass(Prefix == "hi" ?
3447*9880d681SAndroid Build Coastguard Worker Mips::HI32RegClassID : Mips::LO32RegClassID);
3448*9880d681SAndroid Build Coastguard Worker return std::make_pair(*(RC->begin()), RC);
3449*9880d681SAndroid Build Coastguard Worker } else if (Prefix.startswith("$msa")) {
3450*9880d681SAndroid Build Coastguard Worker // Parse $msa(ir|csr|access|save|modify|request|map|unmap)
3451*9880d681SAndroid Build Coastguard Worker
3452*9880d681SAndroid Build Coastguard Worker // No numeric characters follow the name.
3453*9880d681SAndroid Build Coastguard Worker if (R.second)
3454*9880d681SAndroid Build Coastguard Worker return std::make_pair(0U, nullptr);
3455*9880d681SAndroid Build Coastguard Worker
3456*9880d681SAndroid Build Coastguard Worker Reg = StringSwitch<unsigned long long>(Prefix)
3457*9880d681SAndroid Build Coastguard Worker .Case("$msair", Mips::MSAIR)
3458*9880d681SAndroid Build Coastguard Worker .Case("$msacsr", Mips::MSACSR)
3459*9880d681SAndroid Build Coastguard Worker .Case("$msaaccess", Mips::MSAAccess)
3460*9880d681SAndroid Build Coastguard Worker .Case("$msasave", Mips::MSASave)
3461*9880d681SAndroid Build Coastguard Worker .Case("$msamodify", Mips::MSAModify)
3462*9880d681SAndroid Build Coastguard Worker .Case("$msarequest", Mips::MSARequest)
3463*9880d681SAndroid Build Coastguard Worker .Case("$msamap", Mips::MSAMap)
3464*9880d681SAndroid Build Coastguard Worker .Case("$msaunmap", Mips::MSAUnmap)
3465*9880d681SAndroid Build Coastguard Worker .Default(0);
3466*9880d681SAndroid Build Coastguard Worker
3467*9880d681SAndroid Build Coastguard Worker if (!Reg)
3468*9880d681SAndroid Build Coastguard Worker return std::make_pair(0U, nullptr);
3469*9880d681SAndroid Build Coastguard Worker
3470*9880d681SAndroid Build Coastguard Worker RC = TRI->getRegClass(Mips::MSACtrlRegClassID);
3471*9880d681SAndroid Build Coastguard Worker return std::make_pair(Reg, RC);
3472*9880d681SAndroid Build Coastguard Worker }
3473*9880d681SAndroid Build Coastguard Worker
3474*9880d681SAndroid Build Coastguard Worker if (!R.second)
3475*9880d681SAndroid Build Coastguard Worker return std::make_pair(0U, nullptr);
3476*9880d681SAndroid Build Coastguard Worker
3477*9880d681SAndroid Build Coastguard Worker if (Prefix == "$f") { // Parse $f0-$f31.
3478*9880d681SAndroid Build Coastguard Worker // If the size of FP registers is 64-bit or Reg is an even number, select
3479*9880d681SAndroid Build Coastguard Worker // the 64-bit register class. Otherwise, select the 32-bit register class.
3480*9880d681SAndroid Build Coastguard Worker if (VT == MVT::Other)
3481*9880d681SAndroid Build Coastguard Worker VT = (Subtarget.isFP64bit() || !(Reg % 2)) ? MVT::f64 : MVT::f32;
3482*9880d681SAndroid Build Coastguard Worker
3483*9880d681SAndroid Build Coastguard Worker RC = getRegClassFor(VT);
3484*9880d681SAndroid Build Coastguard Worker
3485*9880d681SAndroid Build Coastguard Worker if (RC == &Mips::AFGR64RegClass) {
3486*9880d681SAndroid Build Coastguard Worker assert(Reg % 2 == 0);
3487*9880d681SAndroid Build Coastguard Worker Reg >>= 1;
3488*9880d681SAndroid Build Coastguard Worker }
3489*9880d681SAndroid Build Coastguard Worker } else if (Prefix == "$fcc") // Parse $fcc0-$fcc7.
3490*9880d681SAndroid Build Coastguard Worker RC = TRI->getRegClass(Mips::FCCRegClassID);
3491*9880d681SAndroid Build Coastguard Worker else if (Prefix == "$w") { // Parse $w0-$w31.
3492*9880d681SAndroid Build Coastguard Worker RC = getRegClassFor((VT == MVT::Other) ? MVT::v16i8 : VT);
3493*9880d681SAndroid Build Coastguard Worker } else { // Parse $0-$31.
3494*9880d681SAndroid Build Coastguard Worker assert(Prefix == "$");
3495*9880d681SAndroid Build Coastguard Worker RC = getRegClassFor((VT == MVT::Other) ? MVT::i32 : VT);
3496*9880d681SAndroid Build Coastguard Worker }
3497*9880d681SAndroid Build Coastguard Worker
3498*9880d681SAndroid Build Coastguard Worker assert(Reg < RC->getNumRegs());
3499*9880d681SAndroid Build Coastguard Worker return std::make_pair(*(RC->begin() + Reg), RC);
3500*9880d681SAndroid Build Coastguard Worker }
3501*9880d681SAndroid Build Coastguard Worker
3502*9880d681SAndroid Build Coastguard Worker /// Given a register class constraint, like 'r', if this corresponds directly
3503*9880d681SAndroid Build Coastguard Worker /// to an LLVM register class, return a register of 0 and the register class
3504*9880d681SAndroid Build Coastguard Worker /// pointer.
3505*9880d681SAndroid Build Coastguard Worker std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo * TRI,StringRef Constraint,MVT VT) const3506*9880d681SAndroid Build Coastguard Worker MipsTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
3507*9880d681SAndroid Build Coastguard Worker StringRef Constraint,
3508*9880d681SAndroid Build Coastguard Worker MVT VT) const {
3509*9880d681SAndroid Build Coastguard Worker if (Constraint.size() == 1) {
3510*9880d681SAndroid Build Coastguard Worker switch (Constraint[0]) {
3511*9880d681SAndroid Build Coastguard Worker case 'd': // Address register. Same as 'r' unless generating MIPS16 code.
3512*9880d681SAndroid Build Coastguard Worker case 'y': // Same as 'r'. Exists for compatibility.
3513*9880d681SAndroid Build Coastguard Worker case 'r':
3514*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) {
3515*9880d681SAndroid Build Coastguard Worker if (Subtarget.inMips16Mode())
3516*9880d681SAndroid Build Coastguard Worker return std::make_pair(0U, &Mips::CPU16RegsRegClass);
3517*9880d681SAndroid Build Coastguard Worker return std::make_pair(0U, &Mips::GPR32RegClass);
3518*9880d681SAndroid Build Coastguard Worker }
3519*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i64 && !Subtarget.isGP64bit())
3520*9880d681SAndroid Build Coastguard Worker return std::make_pair(0U, &Mips::GPR32RegClass);
3521*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i64 && Subtarget.isGP64bit())
3522*9880d681SAndroid Build Coastguard Worker return std::make_pair(0U, &Mips::GPR64RegClass);
3523*9880d681SAndroid Build Coastguard Worker // This will generate an error message
3524*9880d681SAndroid Build Coastguard Worker return std::make_pair(0U, nullptr);
3525*9880d681SAndroid Build Coastguard Worker case 'f': // FPU or MSA register
3526*9880d681SAndroid Build Coastguard Worker if (VT == MVT::v16i8)
3527*9880d681SAndroid Build Coastguard Worker return std::make_pair(0U, &Mips::MSA128BRegClass);
3528*9880d681SAndroid Build Coastguard Worker else if (VT == MVT::v8i16 || VT == MVT::v8f16)
3529*9880d681SAndroid Build Coastguard Worker return std::make_pair(0U, &Mips::MSA128HRegClass);
3530*9880d681SAndroid Build Coastguard Worker else if (VT == MVT::v4i32 || VT == MVT::v4f32)
3531*9880d681SAndroid Build Coastguard Worker return std::make_pair(0U, &Mips::MSA128WRegClass);
3532*9880d681SAndroid Build Coastguard Worker else if (VT == MVT::v2i64 || VT == MVT::v2f64)
3533*9880d681SAndroid Build Coastguard Worker return std::make_pair(0U, &Mips::MSA128DRegClass);
3534*9880d681SAndroid Build Coastguard Worker else if (VT == MVT::f32)
3535*9880d681SAndroid Build Coastguard Worker return std::make_pair(0U, &Mips::FGR32RegClass);
3536*9880d681SAndroid Build Coastguard Worker else if ((VT == MVT::f64) && (!Subtarget.isSingleFloat())) {
3537*9880d681SAndroid Build Coastguard Worker if (Subtarget.isFP64bit())
3538*9880d681SAndroid Build Coastguard Worker return std::make_pair(0U, &Mips::FGR64RegClass);
3539*9880d681SAndroid Build Coastguard Worker return std::make_pair(0U, &Mips::AFGR64RegClass);
3540*9880d681SAndroid Build Coastguard Worker }
3541*9880d681SAndroid Build Coastguard Worker break;
3542*9880d681SAndroid Build Coastguard Worker case 'c': // register suitable for indirect jump
3543*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i32)
3544*9880d681SAndroid Build Coastguard Worker return std::make_pair((unsigned)Mips::T9, &Mips::GPR32RegClass);
3545*9880d681SAndroid Build Coastguard Worker assert(VT == MVT::i64 && "Unexpected type.");
3546*9880d681SAndroid Build Coastguard Worker return std::make_pair((unsigned)Mips::T9_64, &Mips::GPR64RegClass);
3547*9880d681SAndroid Build Coastguard Worker case 'l': // register suitable for indirect jump
3548*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i32)
3549*9880d681SAndroid Build Coastguard Worker return std::make_pair((unsigned)Mips::LO0, &Mips::LO32RegClass);
3550*9880d681SAndroid Build Coastguard Worker return std::make_pair((unsigned)Mips::LO0_64, &Mips::LO64RegClass);
3551*9880d681SAndroid Build Coastguard Worker case 'x': // register suitable for indirect jump
3552*9880d681SAndroid Build Coastguard Worker // Fixme: Not triggering the use of both hi and low
3553*9880d681SAndroid Build Coastguard Worker // This will generate an error message
3554*9880d681SAndroid Build Coastguard Worker return std::make_pair(0U, nullptr);
3555*9880d681SAndroid Build Coastguard Worker }
3556*9880d681SAndroid Build Coastguard Worker }
3557*9880d681SAndroid Build Coastguard Worker
3558*9880d681SAndroid Build Coastguard Worker std::pair<unsigned, const TargetRegisterClass *> R;
3559*9880d681SAndroid Build Coastguard Worker R = parseRegForInlineAsmConstraint(Constraint, VT);
3560*9880d681SAndroid Build Coastguard Worker
3561*9880d681SAndroid Build Coastguard Worker if (R.second)
3562*9880d681SAndroid Build Coastguard Worker return R;
3563*9880d681SAndroid Build Coastguard Worker
3564*9880d681SAndroid Build Coastguard Worker return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
3565*9880d681SAndroid Build Coastguard Worker }
3566*9880d681SAndroid Build Coastguard Worker
3567*9880d681SAndroid Build Coastguard Worker /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
3568*9880d681SAndroid Build Coastguard Worker /// vector. If it is invalid, don't add anything to Ops.
LowerAsmOperandForConstraint(SDValue Op,std::string & Constraint,std::vector<SDValue> & Ops,SelectionDAG & DAG) const3569*9880d681SAndroid Build Coastguard Worker void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
3570*9880d681SAndroid Build Coastguard Worker std::string &Constraint,
3571*9880d681SAndroid Build Coastguard Worker std::vector<SDValue>&Ops,
3572*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
3573*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
3574*9880d681SAndroid Build Coastguard Worker SDValue Result;
3575*9880d681SAndroid Build Coastguard Worker
3576*9880d681SAndroid Build Coastguard Worker // Only support length 1 constraints for now.
3577*9880d681SAndroid Build Coastguard Worker if (Constraint.length() > 1) return;
3578*9880d681SAndroid Build Coastguard Worker
3579*9880d681SAndroid Build Coastguard Worker char ConstraintLetter = Constraint[0];
3580*9880d681SAndroid Build Coastguard Worker switch (ConstraintLetter) {
3581*9880d681SAndroid Build Coastguard Worker default: break; // This will fall through to the generic implementation
3582*9880d681SAndroid Build Coastguard Worker case 'I': // Signed 16 bit constant
3583*9880d681SAndroid Build Coastguard Worker // If this fails, the parent routine will give an error
3584*9880d681SAndroid Build Coastguard Worker if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
3585*9880d681SAndroid Build Coastguard Worker EVT Type = Op.getValueType();
3586*9880d681SAndroid Build Coastguard Worker int64_t Val = C->getSExtValue();
3587*9880d681SAndroid Build Coastguard Worker if (isInt<16>(Val)) {
3588*9880d681SAndroid Build Coastguard Worker Result = DAG.getTargetConstant(Val, DL, Type);
3589*9880d681SAndroid Build Coastguard Worker break;
3590*9880d681SAndroid Build Coastguard Worker }
3591*9880d681SAndroid Build Coastguard Worker }
3592*9880d681SAndroid Build Coastguard Worker return;
3593*9880d681SAndroid Build Coastguard Worker case 'J': // integer zero
3594*9880d681SAndroid Build Coastguard Worker if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
3595*9880d681SAndroid Build Coastguard Worker EVT Type = Op.getValueType();
3596*9880d681SAndroid Build Coastguard Worker int64_t Val = C->getZExtValue();
3597*9880d681SAndroid Build Coastguard Worker if (Val == 0) {
3598*9880d681SAndroid Build Coastguard Worker Result = DAG.getTargetConstant(0, DL, Type);
3599*9880d681SAndroid Build Coastguard Worker break;
3600*9880d681SAndroid Build Coastguard Worker }
3601*9880d681SAndroid Build Coastguard Worker }
3602*9880d681SAndroid Build Coastguard Worker return;
3603*9880d681SAndroid Build Coastguard Worker case 'K': // unsigned 16 bit immediate
3604*9880d681SAndroid Build Coastguard Worker if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
3605*9880d681SAndroid Build Coastguard Worker EVT Type = Op.getValueType();
3606*9880d681SAndroid Build Coastguard Worker uint64_t Val = (uint64_t)C->getZExtValue();
3607*9880d681SAndroid Build Coastguard Worker if (isUInt<16>(Val)) {
3608*9880d681SAndroid Build Coastguard Worker Result = DAG.getTargetConstant(Val, DL, Type);
3609*9880d681SAndroid Build Coastguard Worker break;
3610*9880d681SAndroid Build Coastguard Worker }
3611*9880d681SAndroid Build Coastguard Worker }
3612*9880d681SAndroid Build Coastguard Worker return;
3613*9880d681SAndroid Build Coastguard Worker case 'L': // signed 32 bit immediate where lower 16 bits are 0
3614*9880d681SAndroid Build Coastguard Worker if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
3615*9880d681SAndroid Build Coastguard Worker EVT Type = Op.getValueType();
3616*9880d681SAndroid Build Coastguard Worker int64_t Val = C->getSExtValue();
3617*9880d681SAndroid Build Coastguard Worker if ((isInt<32>(Val)) && ((Val & 0xffff) == 0)){
3618*9880d681SAndroid Build Coastguard Worker Result = DAG.getTargetConstant(Val, DL, Type);
3619*9880d681SAndroid Build Coastguard Worker break;
3620*9880d681SAndroid Build Coastguard Worker }
3621*9880d681SAndroid Build Coastguard Worker }
3622*9880d681SAndroid Build Coastguard Worker return;
3623*9880d681SAndroid Build Coastguard Worker case 'N': // immediate in the range of -65535 to -1 (inclusive)
3624*9880d681SAndroid Build Coastguard Worker if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
3625*9880d681SAndroid Build Coastguard Worker EVT Type = Op.getValueType();
3626*9880d681SAndroid Build Coastguard Worker int64_t Val = C->getSExtValue();
3627*9880d681SAndroid Build Coastguard Worker if ((Val >= -65535) && (Val <= -1)) {
3628*9880d681SAndroid Build Coastguard Worker Result = DAG.getTargetConstant(Val, DL, Type);
3629*9880d681SAndroid Build Coastguard Worker break;
3630*9880d681SAndroid Build Coastguard Worker }
3631*9880d681SAndroid Build Coastguard Worker }
3632*9880d681SAndroid Build Coastguard Worker return;
3633*9880d681SAndroid Build Coastguard Worker case 'O': // signed 15 bit immediate
3634*9880d681SAndroid Build Coastguard Worker if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
3635*9880d681SAndroid Build Coastguard Worker EVT Type = Op.getValueType();
3636*9880d681SAndroid Build Coastguard Worker int64_t Val = C->getSExtValue();
3637*9880d681SAndroid Build Coastguard Worker if ((isInt<15>(Val))) {
3638*9880d681SAndroid Build Coastguard Worker Result = DAG.getTargetConstant(Val, DL, Type);
3639*9880d681SAndroid Build Coastguard Worker break;
3640*9880d681SAndroid Build Coastguard Worker }
3641*9880d681SAndroid Build Coastguard Worker }
3642*9880d681SAndroid Build Coastguard Worker return;
3643*9880d681SAndroid Build Coastguard Worker case 'P': // immediate in the range of 1 to 65535 (inclusive)
3644*9880d681SAndroid Build Coastguard Worker if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
3645*9880d681SAndroid Build Coastguard Worker EVT Type = Op.getValueType();
3646*9880d681SAndroid Build Coastguard Worker int64_t Val = C->getSExtValue();
3647*9880d681SAndroid Build Coastguard Worker if ((Val <= 65535) && (Val >= 1)) {
3648*9880d681SAndroid Build Coastguard Worker Result = DAG.getTargetConstant(Val, DL, Type);
3649*9880d681SAndroid Build Coastguard Worker break;
3650*9880d681SAndroid Build Coastguard Worker }
3651*9880d681SAndroid Build Coastguard Worker }
3652*9880d681SAndroid Build Coastguard Worker return;
3653*9880d681SAndroid Build Coastguard Worker }
3654*9880d681SAndroid Build Coastguard Worker
3655*9880d681SAndroid Build Coastguard Worker if (Result.getNode()) {
3656*9880d681SAndroid Build Coastguard Worker Ops.push_back(Result);
3657*9880d681SAndroid Build Coastguard Worker return;
3658*9880d681SAndroid Build Coastguard Worker }
3659*9880d681SAndroid Build Coastguard Worker
3660*9880d681SAndroid Build Coastguard Worker TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);
3661*9880d681SAndroid Build Coastguard Worker }
3662*9880d681SAndroid Build Coastguard Worker
isLegalAddressingMode(const DataLayout & DL,const AddrMode & AM,Type * Ty,unsigned AS) const3663*9880d681SAndroid Build Coastguard Worker bool MipsTargetLowering::isLegalAddressingMode(const DataLayout &DL,
3664*9880d681SAndroid Build Coastguard Worker const AddrMode &AM, Type *Ty,
3665*9880d681SAndroid Build Coastguard Worker unsigned AS) const {
3666*9880d681SAndroid Build Coastguard Worker // No global is ever allowed as a base.
3667*9880d681SAndroid Build Coastguard Worker if (AM.BaseGV)
3668*9880d681SAndroid Build Coastguard Worker return false;
3669*9880d681SAndroid Build Coastguard Worker
3670*9880d681SAndroid Build Coastguard Worker switch (AM.Scale) {
3671*9880d681SAndroid Build Coastguard Worker case 0: // "r+i" or just "i", depending on HasBaseReg.
3672*9880d681SAndroid Build Coastguard Worker break;
3673*9880d681SAndroid Build Coastguard Worker case 1:
3674*9880d681SAndroid Build Coastguard Worker if (!AM.HasBaseReg) // allow "r+i".
3675*9880d681SAndroid Build Coastguard Worker break;
3676*9880d681SAndroid Build Coastguard Worker return false; // disallow "r+r" or "r+r+i".
3677*9880d681SAndroid Build Coastguard Worker default:
3678*9880d681SAndroid Build Coastguard Worker return false;
3679*9880d681SAndroid Build Coastguard Worker }
3680*9880d681SAndroid Build Coastguard Worker
3681*9880d681SAndroid Build Coastguard Worker return true;
3682*9880d681SAndroid Build Coastguard Worker }
3683*9880d681SAndroid Build Coastguard Worker
3684*9880d681SAndroid Build Coastguard Worker bool
isOffsetFoldingLegal(const GlobalAddressSDNode * GA) const3685*9880d681SAndroid Build Coastguard Worker MipsTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3686*9880d681SAndroid Build Coastguard Worker // The Mips target isn't yet aware of offsets.
3687*9880d681SAndroid Build Coastguard Worker return false;
3688*9880d681SAndroid Build Coastguard Worker }
3689*9880d681SAndroid Build Coastguard Worker
getOptimalMemOpType(uint64_t Size,unsigned DstAlign,unsigned SrcAlign,bool IsMemset,bool ZeroMemset,bool MemcpyStrSrc,MachineFunction & MF) const3690*9880d681SAndroid Build Coastguard Worker EVT MipsTargetLowering::getOptimalMemOpType(uint64_t Size, unsigned DstAlign,
3691*9880d681SAndroid Build Coastguard Worker unsigned SrcAlign,
3692*9880d681SAndroid Build Coastguard Worker bool IsMemset, bool ZeroMemset,
3693*9880d681SAndroid Build Coastguard Worker bool MemcpyStrSrc,
3694*9880d681SAndroid Build Coastguard Worker MachineFunction &MF) const {
3695*9880d681SAndroid Build Coastguard Worker if (Subtarget.hasMips64())
3696*9880d681SAndroid Build Coastguard Worker return MVT::i64;
3697*9880d681SAndroid Build Coastguard Worker
3698*9880d681SAndroid Build Coastguard Worker return MVT::i32;
3699*9880d681SAndroid Build Coastguard Worker }
3700*9880d681SAndroid Build Coastguard Worker
isFPImmLegal(const APFloat & Imm,EVT VT) const3701*9880d681SAndroid Build Coastguard Worker bool MipsTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const {
3702*9880d681SAndroid Build Coastguard Worker if (VT != MVT::f32 && VT != MVT::f64)
3703*9880d681SAndroid Build Coastguard Worker return false;
3704*9880d681SAndroid Build Coastguard Worker if (Imm.isNegZero())
3705*9880d681SAndroid Build Coastguard Worker return false;
3706*9880d681SAndroid Build Coastguard Worker return Imm.isZero();
3707*9880d681SAndroid Build Coastguard Worker }
3708*9880d681SAndroid Build Coastguard Worker
getJumpTableEncoding() const3709*9880d681SAndroid Build Coastguard Worker unsigned MipsTargetLowering::getJumpTableEncoding() const {
3710*9880d681SAndroid Build Coastguard Worker if (ABI.IsN64())
3711*9880d681SAndroid Build Coastguard Worker return MachineJumpTableInfo::EK_GPRel64BlockAddress;
3712*9880d681SAndroid Build Coastguard Worker
3713*9880d681SAndroid Build Coastguard Worker return TargetLowering::getJumpTableEncoding();
3714*9880d681SAndroid Build Coastguard Worker }
3715*9880d681SAndroid Build Coastguard Worker
useSoftFloat() const3716*9880d681SAndroid Build Coastguard Worker bool MipsTargetLowering::useSoftFloat() const {
3717*9880d681SAndroid Build Coastguard Worker return Subtarget.useSoftFloat();
3718*9880d681SAndroid Build Coastguard Worker }
3719*9880d681SAndroid Build Coastguard Worker
copyByValRegs(SDValue Chain,const SDLoc & DL,std::vector<SDValue> & OutChains,SelectionDAG & DAG,const ISD::ArgFlagsTy & Flags,SmallVectorImpl<SDValue> & InVals,const Argument * FuncArg,unsigned FirstReg,unsigned LastReg,const CCValAssign & VA,MipsCCState & State) const3720*9880d681SAndroid Build Coastguard Worker void MipsTargetLowering::copyByValRegs(
3721*9880d681SAndroid Build Coastguard Worker SDValue Chain, const SDLoc &DL, std::vector<SDValue> &OutChains,
3722*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG, const ISD::ArgFlagsTy &Flags,
3723*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<SDValue> &InVals, const Argument *FuncArg,
3724*9880d681SAndroid Build Coastguard Worker unsigned FirstReg, unsigned LastReg, const CCValAssign &VA,
3725*9880d681SAndroid Build Coastguard Worker MipsCCState &State) const {
3726*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = DAG.getMachineFunction();
3727*9880d681SAndroid Build Coastguard Worker MachineFrameInfo *MFI = MF.getFrameInfo();
3728*9880d681SAndroid Build Coastguard Worker unsigned GPRSizeInBytes = Subtarget.getGPRSizeInBytes();
3729*9880d681SAndroid Build Coastguard Worker unsigned NumRegs = LastReg - FirstReg;
3730*9880d681SAndroid Build Coastguard Worker unsigned RegAreaSize = NumRegs * GPRSizeInBytes;
3731*9880d681SAndroid Build Coastguard Worker unsigned FrameObjSize = std::max(Flags.getByValSize(), RegAreaSize);
3732*9880d681SAndroid Build Coastguard Worker int FrameObjOffset;
3733*9880d681SAndroid Build Coastguard Worker ArrayRef<MCPhysReg> ByValArgRegs = ABI.GetByValArgRegs();
3734*9880d681SAndroid Build Coastguard Worker
3735*9880d681SAndroid Build Coastguard Worker if (RegAreaSize)
3736*9880d681SAndroid Build Coastguard Worker FrameObjOffset =
3737*9880d681SAndroid Build Coastguard Worker (int)ABI.GetCalleeAllocdArgSizeInBytes(State.getCallingConv()) -
3738*9880d681SAndroid Build Coastguard Worker (int)((ByValArgRegs.size() - FirstReg) * GPRSizeInBytes);
3739*9880d681SAndroid Build Coastguard Worker else
3740*9880d681SAndroid Build Coastguard Worker FrameObjOffset = VA.getLocMemOffset();
3741*9880d681SAndroid Build Coastguard Worker
3742*9880d681SAndroid Build Coastguard Worker // Create frame object.
3743*9880d681SAndroid Build Coastguard Worker EVT PtrTy = getPointerTy(DAG.getDataLayout());
3744*9880d681SAndroid Build Coastguard Worker int FI = MFI->CreateFixedObject(FrameObjSize, FrameObjOffset, true);
3745*9880d681SAndroid Build Coastguard Worker SDValue FIN = DAG.getFrameIndex(FI, PtrTy);
3746*9880d681SAndroid Build Coastguard Worker InVals.push_back(FIN);
3747*9880d681SAndroid Build Coastguard Worker
3748*9880d681SAndroid Build Coastguard Worker if (!NumRegs)
3749*9880d681SAndroid Build Coastguard Worker return;
3750*9880d681SAndroid Build Coastguard Worker
3751*9880d681SAndroid Build Coastguard Worker // Copy arg registers.
3752*9880d681SAndroid Build Coastguard Worker MVT RegTy = MVT::getIntegerVT(GPRSizeInBytes * 8);
3753*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = getRegClassFor(RegTy);
3754*9880d681SAndroid Build Coastguard Worker
3755*9880d681SAndroid Build Coastguard Worker for (unsigned I = 0; I < NumRegs; ++I) {
3756*9880d681SAndroid Build Coastguard Worker unsigned ArgReg = ByValArgRegs[FirstReg + I];
3757*9880d681SAndroid Build Coastguard Worker unsigned VReg = addLiveIn(MF, ArgReg, RC);
3758*9880d681SAndroid Build Coastguard Worker unsigned Offset = I * GPRSizeInBytes;
3759*9880d681SAndroid Build Coastguard Worker SDValue StorePtr = DAG.getNode(ISD::ADD, DL, PtrTy, FIN,
3760*9880d681SAndroid Build Coastguard Worker DAG.getConstant(Offset, DL, PtrTy));
3761*9880d681SAndroid Build Coastguard Worker SDValue Store = DAG.getStore(Chain, DL, DAG.getRegister(VReg, RegTy),
3762*9880d681SAndroid Build Coastguard Worker StorePtr, MachinePointerInfo(FuncArg, Offset),
3763*9880d681SAndroid Build Coastguard Worker false, false, 0);
3764*9880d681SAndroid Build Coastguard Worker OutChains.push_back(Store);
3765*9880d681SAndroid Build Coastguard Worker }
3766*9880d681SAndroid Build Coastguard Worker }
3767*9880d681SAndroid Build Coastguard Worker
3768*9880d681SAndroid Build Coastguard Worker // Copy byVal arg to registers and stack.
passByValArg(SDValue Chain,const SDLoc & DL,std::deque<std::pair<unsigned,SDValue>> & RegsToPass,SmallVectorImpl<SDValue> & MemOpChains,SDValue StackPtr,MachineFrameInfo * MFI,SelectionDAG & DAG,SDValue Arg,unsigned FirstReg,unsigned LastReg,const ISD::ArgFlagsTy & Flags,bool isLittle,const CCValAssign & VA) const3769*9880d681SAndroid Build Coastguard Worker void MipsTargetLowering::passByValArg(
3770*9880d681SAndroid Build Coastguard Worker SDValue Chain, const SDLoc &DL,
3771*9880d681SAndroid Build Coastguard Worker std::deque<std::pair<unsigned, SDValue>> &RegsToPass,
3772*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<SDValue> &MemOpChains, SDValue StackPtr,
3773*9880d681SAndroid Build Coastguard Worker MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg, unsigned FirstReg,
3774*9880d681SAndroid Build Coastguard Worker unsigned LastReg, const ISD::ArgFlagsTy &Flags, bool isLittle,
3775*9880d681SAndroid Build Coastguard Worker const CCValAssign &VA) const {
3776*9880d681SAndroid Build Coastguard Worker unsigned ByValSizeInBytes = Flags.getByValSize();
3777*9880d681SAndroid Build Coastguard Worker unsigned OffsetInBytes = 0; // From beginning of struct
3778*9880d681SAndroid Build Coastguard Worker unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes();
3779*9880d681SAndroid Build Coastguard Worker unsigned Alignment = std::min(Flags.getByValAlign(), RegSizeInBytes);
3780*9880d681SAndroid Build Coastguard Worker EVT PtrTy = getPointerTy(DAG.getDataLayout()),
3781*9880d681SAndroid Build Coastguard Worker RegTy = MVT::getIntegerVT(RegSizeInBytes * 8);
3782*9880d681SAndroid Build Coastguard Worker unsigned NumRegs = LastReg - FirstReg;
3783*9880d681SAndroid Build Coastguard Worker
3784*9880d681SAndroid Build Coastguard Worker if (NumRegs) {
3785*9880d681SAndroid Build Coastguard Worker ArrayRef<MCPhysReg> ArgRegs = ABI.GetByValArgRegs();
3786*9880d681SAndroid Build Coastguard Worker bool LeftoverBytes = (NumRegs * RegSizeInBytes > ByValSizeInBytes);
3787*9880d681SAndroid Build Coastguard Worker unsigned I = 0;
3788*9880d681SAndroid Build Coastguard Worker
3789*9880d681SAndroid Build Coastguard Worker // Copy words to registers.
3790*9880d681SAndroid Build Coastguard Worker for (; I < NumRegs - LeftoverBytes; ++I, OffsetInBytes += RegSizeInBytes) {
3791*9880d681SAndroid Build Coastguard Worker SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg,
3792*9880d681SAndroid Build Coastguard Worker DAG.getConstant(OffsetInBytes, DL, PtrTy));
3793*9880d681SAndroid Build Coastguard Worker SDValue LoadVal = DAG.getLoad(RegTy, DL, Chain, LoadPtr,
3794*9880d681SAndroid Build Coastguard Worker MachinePointerInfo(), false, false, false,
3795*9880d681SAndroid Build Coastguard Worker Alignment);
3796*9880d681SAndroid Build Coastguard Worker MemOpChains.push_back(LoadVal.getValue(1));
3797*9880d681SAndroid Build Coastguard Worker unsigned ArgReg = ArgRegs[FirstReg + I];
3798*9880d681SAndroid Build Coastguard Worker RegsToPass.push_back(std::make_pair(ArgReg, LoadVal));
3799*9880d681SAndroid Build Coastguard Worker }
3800*9880d681SAndroid Build Coastguard Worker
3801*9880d681SAndroid Build Coastguard Worker // Return if the struct has been fully copied.
3802*9880d681SAndroid Build Coastguard Worker if (ByValSizeInBytes == OffsetInBytes)
3803*9880d681SAndroid Build Coastguard Worker return;
3804*9880d681SAndroid Build Coastguard Worker
3805*9880d681SAndroid Build Coastguard Worker // Copy the remainder of the byval argument with sub-word loads and shifts.
3806*9880d681SAndroid Build Coastguard Worker if (LeftoverBytes) {
3807*9880d681SAndroid Build Coastguard Worker SDValue Val;
3808*9880d681SAndroid Build Coastguard Worker
3809*9880d681SAndroid Build Coastguard Worker for (unsigned LoadSizeInBytes = RegSizeInBytes / 2, TotalBytesLoaded = 0;
3810*9880d681SAndroid Build Coastguard Worker OffsetInBytes < ByValSizeInBytes; LoadSizeInBytes /= 2) {
3811*9880d681SAndroid Build Coastguard Worker unsigned RemainingSizeInBytes = ByValSizeInBytes - OffsetInBytes;
3812*9880d681SAndroid Build Coastguard Worker
3813*9880d681SAndroid Build Coastguard Worker if (RemainingSizeInBytes < LoadSizeInBytes)
3814*9880d681SAndroid Build Coastguard Worker continue;
3815*9880d681SAndroid Build Coastguard Worker
3816*9880d681SAndroid Build Coastguard Worker // Load subword.
3817*9880d681SAndroid Build Coastguard Worker SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg,
3818*9880d681SAndroid Build Coastguard Worker DAG.getConstant(OffsetInBytes, DL,
3819*9880d681SAndroid Build Coastguard Worker PtrTy));
3820*9880d681SAndroid Build Coastguard Worker SDValue LoadVal = DAG.getExtLoad(
3821*9880d681SAndroid Build Coastguard Worker ISD::ZEXTLOAD, DL, RegTy, Chain, LoadPtr, MachinePointerInfo(),
3822*9880d681SAndroid Build Coastguard Worker MVT::getIntegerVT(LoadSizeInBytes * 8), false, false, false,
3823*9880d681SAndroid Build Coastguard Worker Alignment);
3824*9880d681SAndroid Build Coastguard Worker MemOpChains.push_back(LoadVal.getValue(1));
3825*9880d681SAndroid Build Coastguard Worker
3826*9880d681SAndroid Build Coastguard Worker // Shift the loaded value.
3827*9880d681SAndroid Build Coastguard Worker unsigned Shamt;
3828*9880d681SAndroid Build Coastguard Worker
3829*9880d681SAndroid Build Coastguard Worker if (isLittle)
3830*9880d681SAndroid Build Coastguard Worker Shamt = TotalBytesLoaded * 8;
3831*9880d681SAndroid Build Coastguard Worker else
3832*9880d681SAndroid Build Coastguard Worker Shamt = (RegSizeInBytes - (TotalBytesLoaded + LoadSizeInBytes)) * 8;
3833*9880d681SAndroid Build Coastguard Worker
3834*9880d681SAndroid Build Coastguard Worker SDValue Shift = DAG.getNode(ISD::SHL, DL, RegTy, LoadVal,
3835*9880d681SAndroid Build Coastguard Worker DAG.getConstant(Shamt, DL, MVT::i32));
3836*9880d681SAndroid Build Coastguard Worker
3837*9880d681SAndroid Build Coastguard Worker if (Val.getNode())
3838*9880d681SAndroid Build Coastguard Worker Val = DAG.getNode(ISD::OR, DL, RegTy, Val, Shift);
3839*9880d681SAndroid Build Coastguard Worker else
3840*9880d681SAndroid Build Coastguard Worker Val = Shift;
3841*9880d681SAndroid Build Coastguard Worker
3842*9880d681SAndroid Build Coastguard Worker OffsetInBytes += LoadSizeInBytes;
3843*9880d681SAndroid Build Coastguard Worker TotalBytesLoaded += LoadSizeInBytes;
3844*9880d681SAndroid Build Coastguard Worker Alignment = std::min(Alignment, LoadSizeInBytes);
3845*9880d681SAndroid Build Coastguard Worker }
3846*9880d681SAndroid Build Coastguard Worker
3847*9880d681SAndroid Build Coastguard Worker unsigned ArgReg = ArgRegs[FirstReg + I];
3848*9880d681SAndroid Build Coastguard Worker RegsToPass.push_back(std::make_pair(ArgReg, Val));
3849*9880d681SAndroid Build Coastguard Worker return;
3850*9880d681SAndroid Build Coastguard Worker }
3851*9880d681SAndroid Build Coastguard Worker }
3852*9880d681SAndroid Build Coastguard Worker
3853*9880d681SAndroid Build Coastguard Worker // Copy remainder of byval arg to it with memcpy.
3854*9880d681SAndroid Build Coastguard Worker unsigned MemCpySize = ByValSizeInBytes - OffsetInBytes;
3855*9880d681SAndroid Build Coastguard Worker SDValue Src = DAG.getNode(ISD::ADD, DL, PtrTy, Arg,
3856*9880d681SAndroid Build Coastguard Worker DAG.getConstant(OffsetInBytes, DL, PtrTy));
3857*9880d681SAndroid Build Coastguard Worker SDValue Dst = DAG.getNode(ISD::ADD, DL, PtrTy, StackPtr,
3858*9880d681SAndroid Build Coastguard Worker DAG.getIntPtrConstant(VA.getLocMemOffset(), DL));
3859*9880d681SAndroid Build Coastguard Worker Chain = DAG.getMemcpy(Chain, DL, Dst, Src,
3860*9880d681SAndroid Build Coastguard Worker DAG.getConstant(MemCpySize, DL, PtrTy),
3861*9880d681SAndroid Build Coastguard Worker Alignment, /*isVolatile=*/false, /*AlwaysInline=*/false,
3862*9880d681SAndroid Build Coastguard Worker /*isTailCall=*/false,
3863*9880d681SAndroid Build Coastguard Worker MachinePointerInfo(), MachinePointerInfo());
3864*9880d681SAndroid Build Coastguard Worker MemOpChains.push_back(Chain);
3865*9880d681SAndroid Build Coastguard Worker }
3866*9880d681SAndroid Build Coastguard Worker
writeVarArgRegs(std::vector<SDValue> & OutChains,SDValue Chain,const SDLoc & DL,SelectionDAG & DAG,CCState & State) const3867*9880d681SAndroid Build Coastguard Worker void MipsTargetLowering::writeVarArgRegs(std::vector<SDValue> &OutChains,
3868*9880d681SAndroid Build Coastguard Worker SDValue Chain, const SDLoc &DL,
3869*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG,
3870*9880d681SAndroid Build Coastguard Worker CCState &State) const {
3871*9880d681SAndroid Build Coastguard Worker ArrayRef<MCPhysReg> ArgRegs = ABI.GetVarArgRegs();
3872*9880d681SAndroid Build Coastguard Worker unsigned Idx = State.getFirstUnallocated(ArgRegs);
3873*9880d681SAndroid Build Coastguard Worker unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes();
3874*9880d681SAndroid Build Coastguard Worker MVT RegTy = MVT::getIntegerVT(RegSizeInBytes * 8);
3875*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = getRegClassFor(RegTy);
3876*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = DAG.getMachineFunction();
3877*9880d681SAndroid Build Coastguard Worker MachineFrameInfo *MFI = MF.getFrameInfo();
3878*9880d681SAndroid Build Coastguard Worker MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
3879*9880d681SAndroid Build Coastguard Worker
3880*9880d681SAndroid Build Coastguard Worker // Offset of the first variable argument from stack pointer.
3881*9880d681SAndroid Build Coastguard Worker int VaArgOffset;
3882*9880d681SAndroid Build Coastguard Worker
3883*9880d681SAndroid Build Coastguard Worker if (ArgRegs.size() == Idx)
3884*9880d681SAndroid Build Coastguard Worker VaArgOffset = alignTo(State.getNextStackOffset(), RegSizeInBytes);
3885*9880d681SAndroid Build Coastguard Worker else {
3886*9880d681SAndroid Build Coastguard Worker VaArgOffset =
3887*9880d681SAndroid Build Coastguard Worker (int)ABI.GetCalleeAllocdArgSizeInBytes(State.getCallingConv()) -
3888*9880d681SAndroid Build Coastguard Worker (int)(RegSizeInBytes * (ArgRegs.size() - Idx));
3889*9880d681SAndroid Build Coastguard Worker }
3890*9880d681SAndroid Build Coastguard Worker
3891*9880d681SAndroid Build Coastguard Worker // Record the frame index of the first variable argument
3892*9880d681SAndroid Build Coastguard Worker // which is a value necessary to VASTART.
3893*9880d681SAndroid Build Coastguard Worker int FI = MFI->CreateFixedObject(RegSizeInBytes, VaArgOffset, true);
3894*9880d681SAndroid Build Coastguard Worker MipsFI->setVarArgsFrameIndex(FI);
3895*9880d681SAndroid Build Coastguard Worker
3896*9880d681SAndroid Build Coastguard Worker // Copy the integer registers that have not been used for argument passing
3897*9880d681SAndroid Build Coastguard Worker // to the argument register save area. For O32, the save area is allocated
3898*9880d681SAndroid Build Coastguard Worker // in the caller's stack frame, while for N32/64, it is allocated in the
3899*9880d681SAndroid Build Coastguard Worker // callee's stack frame.
3900*9880d681SAndroid Build Coastguard Worker for (unsigned I = Idx; I < ArgRegs.size();
3901*9880d681SAndroid Build Coastguard Worker ++I, VaArgOffset += RegSizeInBytes) {
3902*9880d681SAndroid Build Coastguard Worker unsigned Reg = addLiveIn(MF, ArgRegs[I], RC);
3903*9880d681SAndroid Build Coastguard Worker SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegTy);
3904*9880d681SAndroid Build Coastguard Worker FI = MFI->CreateFixedObject(RegSizeInBytes, VaArgOffset, true);
3905*9880d681SAndroid Build Coastguard Worker SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
3906*9880d681SAndroid Build Coastguard Worker SDValue Store = DAG.getStore(Chain, DL, ArgValue, PtrOff,
3907*9880d681SAndroid Build Coastguard Worker MachinePointerInfo(), false, false, 0);
3908*9880d681SAndroid Build Coastguard Worker cast<StoreSDNode>(Store.getNode())->getMemOperand()->setValue(
3909*9880d681SAndroid Build Coastguard Worker (Value *)nullptr);
3910*9880d681SAndroid Build Coastguard Worker OutChains.push_back(Store);
3911*9880d681SAndroid Build Coastguard Worker }
3912*9880d681SAndroid Build Coastguard Worker }
3913*9880d681SAndroid Build Coastguard Worker
HandleByVal(CCState * State,unsigned & Size,unsigned Align) const3914*9880d681SAndroid Build Coastguard Worker void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size,
3915*9880d681SAndroid Build Coastguard Worker unsigned Align) const {
3916*9880d681SAndroid Build Coastguard Worker const TargetFrameLowering *TFL = Subtarget.getFrameLowering();
3917*9880d681SAndroid Build Coastguard Worker
3918*9880d681SAndroid Build Coastguard Worker assert(Size && "Byval argument's size shouldn't be 0.");
3919*9880d681SAndroid Build Coastguard Worker
3920*9880d681SAndroid Build Coastguard Worker Align = std::min(Align, TFL->getStackAlignment());
3921*9880d681SAndroid Build Coastguard Worker
3922*9880d681SAndroid Build Coastguard Worker unsigned FirstReg = 0;
3923*9880d681SAndroid Build Coastguard Worker unsigned NumRegs = 0;
3924*9880d681SAndroid Build Coastguard Worker
3925*9880d681SAndroid Build Coastguard Worker if (State->getCallingConv() != CallingConv::Fast) {
3926*9880d681SAndroid Build Coastguard Worker unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes();
3927*9880d681SAndroid Build Coastguard Worker ArrayRef<MCPhysReg> IntArgRegs = ABI.GetByValArgRegs();
3928*9880d681SAndroid Build Coastguard Worker // FIXME: The O32 case actually describes no shadow registers.
3929*9880d681SAndroid Build Coastguard Worker const MCPhysReg *ShadowRegs =
3930*9880d681SAndroid Build Coastguard Worker ABI.IsO32() ? IntArgRegs.data() : Mips64DPRegs;
3931*9880d681SAndroid Build Coastguard Worker
3932*9880d681SAndroid Build Coastguard Worker // We used to check the size as well but we can't do that anymore since
3933*9880d681SAndroid Build Coastguard Worker // CCState::HandleByVal() rounds up the size after calling this function.
3934*9880d681SAndroid Build Coastguard Worker assert(!(Align % RegSizeInBytes) &&
3935*9880d681SAndroid Build Coastguard Worker "Byval argument's alignment should be a multiple of"
3936*9880d681SAndroid Build Coastguard Worker "RegSizeInBytes.");
3937*9880d681SAndroid Build Coastguard Worker
3938*9880d681SAndroid Build Coastguard Worker FirstReg = State->getFirstUnallocated(IntArgRegs);
3939*9880d681SAndroid Build Coastguard Worker
3940*9880d681SAndroid Build Coastguard Worker // If Align > RegSizeInBytes, the first arg register must be even.
3941*9880d681SAndroid Build Coastguard Worker // FIXME: This condition happens to do the right thing but it's not the
3942*9880d681SAndroid Build Coastguard Worker // right way to test it. We want to check that the stack frame offset
3943*9880d681SAndroid Build Coastguard Worker // of the register is aligned.
3944*9880d681SAndroid Build Coastguard Worker if ((Align > RegSizeInBytes) && (FirstReg % 2)) {
3945*9880d681SAndroid Build Coastguard Worker State->AllocateReg(IntArgRegs[FirstReg], ShadowRegs[FirstReg]);
3946*9880d681SAndroid Build Coastguard Worker ++FirstReg;
3947*9880d681SAndroid Build Coastguard Worker }
3948*9880d681SAndroid Build Coastguard Worker
3949*9880d681SAndroid Build Coastguard Worker // Mark the registers allocated.
3950*9880d681SAndroid Build Coastguard Worker Size = alignTo(Size, RegSizeInBytes);
3951*9880d681SAndroid Build Coastguard Worker for (unsigned I = FirstReg; Size > 0 && (I < IntArgRegs.size());
3952*9880d681SAndroid Build Coastguard Worker Size -= RegSizeInBytes, ++I, ++NumRegs)
3953*9880d681SAndroid Build Coastguard Worker State->AllocateReg(IntArgRegs[I], ShadowRegs[I]);
3954*9880d681SAndroid Build Coastguard Worker }
3955*9880d681SAndroid Build Coastguard Worker
3956*9880d681SAndroid Build Coastguard Worker State->addInRegsParamInfo(FirstReg, FirstReg + NumRegs);
3957*9880d681SAndroid Build Coastguard Worker }
3958*9880d681SAndroid Build Coastguard Worker
emitPseudoSELECT(MachineInstr & MI,MachineBasicBlock * BB,bool isFPCmp,unsigned Opc) const3959*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MipsTargetLowering::emitPseudoSELECT(MachineInstr &MI,
3960*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *BB,
3961*9880d681SAndroid Build Coastguard Worker bool isFPCmp,
3962*9880d681SAndroid Build Coastguard Worker unsigned Opc) const {
3963*9880d681SAndroid Build Coastguard Worker assert(!(Subtarget.hasMips4() || Subtarget.hasMips32()) &&
3964*9880d681SAndroid Build Coastguard Worker "Subtarget already supports SELECT nodes with the use of"
3965*9880d681SAndroid Build Coastguard Worker "conditional-move instructions.");
3966*9880d681SAndroid Build Coastguard Worker
3967*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo *TII =
3968*9880d681SAndroid Build Coastguard Worker Subtarget.getInstrInfo();
3969*9880d681SAndroid Build Coastguard Worker DebugLoc DL = MI.getDebugLoc();
3970*9880d681SAndroid Build Coastguard Worker
3971*9880d681SAndroid Build Coastguard Worker // To "insert" a SELECT instruction, we actually have to insert the
3972*9880d681SAndroid Build Coastguard Worker // diamond control-flow pattern. The incoming instruction knows the
3973*9880d681SAndroid Build Coastguard Worker // destination vreg to set, the condition code register to branch on, the
3974*9880d681SAndroid Build Coastguard Worker // true/false values to select between, and a branch opcode to use.
3975*9880d681SAndroid Build Coastguard Worker const BasicBlock *LLVM_BB = BB->getBasicBlock();
3976*9880d681SAndroid Build Coastguard Worker MachineFunction::iterator It = ++BB->getIterator();
3977*9880d681SAndroid Build Coastguard Worker
3978*9880d681SAndroid Build Coastguard Worker // thisMBB:
3979*9880d681SAndroid Build Coastguard Worker // ...
3980*9880d681SAndroid Build Coastguard Worker // TrueVal = ...
3981*9880d681SAndroid Build Coastguard Worker // setcc r1, r2, r3
3982*9880d681SAndroid Build Coastguard Worker // bNE r1, r0, copy1MBB
3983*9880d681SAndroid Build Coastguard Worker // fallthrough --> copy0MBB
3984*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *thisMBB = BB;
3985*9880d681SAndroid Build Coastguard Worker MachineFunction *F = BB->getParent();
3986*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
3987*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
3988*9880d681SAndroid Build Coastguard Worker F->insert(It, copy0MBB);
3989*9880d681SAndroid Build Coastguard Worker F->insert(It, sinkMBB);
3990*9880d681SAndroid Build Coastguard Worker
3991*9880d681SAndroid Build Coastguard Worker // Transfer the remainder of BB and its successor edges to sinkMBB.
3992*9880d681SAndroid Build Coastguard Worker sinkMBB->splice(sinkMBB->begin(), BB,
3993*9880d681SAndroid Build Coastguard Worker std::next(MachineBasicBlock::iterator(MI)), BB->end());
3994*9880d681SAndroid Build Coastguard Worker sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
3995*9880d681SAndroid Build Coastguard Worker
3996*9880d681SAndroid Build Coastguard Worker // Next, add the true and fallthrough blocks as its successors.
3997*9880d681SAndroid Build Coastguard Worker BB->addSuccessor(copy0MBB);
3998*9880d681SAndroid Build Coastguard Worker BB->addSuccessor(sinkMBB);
3999*9880d681SAndroid Build Coastguard Worker
4000*9880d681SAndroid Build Coastguard Worker if (isFPCmp) {
4001*9880d681SAndroid Build Coastguard Worker // bc1[tf] cc, sinkMBB
4002*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Opc))
4003*9880d681SAndroid Build Coastguard Worker .addReg(MI.getOperand(1).getReg())
4004*9880d681SAndroid Build Coastguard Worker .addMBB(sinkMBB);
4005*9880d681SAndroid Build Coastguard Worker } else {
4006*9880d681SAndroid Build Coastguard Worker // bne rs, $0, sinkMBB
4007*9880d681SAndroid Build Coastguard Worker BuildMI(BB, DL, TII->get(Opc))
4008*9880d681SAndroid Build Coastguard Worker .addReg(MI.getOperand(1).getReg())
4009*9880d681SAndroid Build Coastguard Worker .addReg(Mips::ZERO)
4010*9880d681SAndroid Build Coastguard Worker .addMBB(sinkMBB);
4011*9880d681SAndroid Build Coastguard Worker }
4012*9880d681SAndroid Build Coastguard Worker
4013*9880d681SAndroid Build Coastguard Worker // copy0MBB:
4014*9880d681SAndroid Build Coastguard Worker // %FalseValue = ...
4015*9880d681SAndroid Build Coastguard Worker // # fallthrough to sinkMBB
4016*9880d681SAndroid Build Coastguard Worker BB = copy0MBB;
4017*9880d681SAndroid Build Coastguard Worker
4018*9880d681SAndroid Build Coastguard Worker // Update machine-CFG edges
4019*9880d681SAndroid Build Coastguard Worker BB->addSuccessor(sinkMBB);
4020*9880d681SAndroid Build Coastguard Worker
4021*9880d681SAndroid Build Coastguard Worker // sinkMBB:
4022*9880d681SAndroid Build Coastguard Worker // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
4023*9880d681SAndroid Build Coastguard Worker // ...
4024*9880d681SAndroid Build Coastguard Worker BB = sinkMBB;
4025*9880d681SAndroid Build Coastguard Worker
4026*9880d681SAndroid Build Coastguard Worker BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())
4027*9880d681SAndroid Build Coastguard Worker .addReg(MI.getOperand(2).getReg())
4028*9880d681SAndroid Build Coastguard Worker .addMBB(thisMBB)
4029*9880d681SAndroid Build Coastguard Worker .addReg(MI.getOperand(3).getReg())
4030*9880d681SAndroid Build Coastguard Worker .addMBB(copy0MBB);
4031*9880d681SAndroid Build Coastguard Worker
4032*9880d681SAndroid Build Coastguard Worker MI.eraseFromParent(); // The pseudo instruction is gone now.
4033*9880d681SAndroid Build Coastguard Worker
4034*9880d681SAndroid Build Coastguard Worker return BB;
4035*9880d681SAndroid Build Coastguard Worker }
4036*9880d681SAndroid Build Coastguard Worker
4037*9880d681SAndroid Build Coastguard Worker // FIXME? Maybe this could be a TableGen attribute on some registers and
4038*9880d681SAndroid Build Coastguard Worker // this table could be generated automatically from RegInfo.
getRegisterByName(const char * RegName,EVT VT,SelectionDAG & DAG) const4039*9880d681SAndroid Build Coastguard Worker unsigned MipsTargetLowering::getRegisterByName(const char* RegName, EVT VT,
4040*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
4041*9880d681SAndroid Build Coastguard Worker // Named registers is expected to be fairly rare. For now, just support $28
4042*9880d681SAndroid Build Coastguard Worker // since the linux kernel uses it.
4043*9880d681SAndroid Build Coastguard Worker if (Subtarget.isGP64bit()) {
4044*9880d681SAndroid Build Coastguard Worker unsigned Reg = StringSwitch<unsigned>(RegName)
4045*9880d681SAndroid Build Coastguard Worker .Case("$28", Mips::GP_64)
4046*9880d681SAndroid Build Coastguard Worker .Default(0);
4047*9880d681SAndroid Build Coastguard Worker if (Reg)
4048*9880d681SAndroid Build Coastguard Worker return Reg;
4049*9880d681SAndroid Build Coastguard Worker } else {
4050*9880d681SAndroid Build Coastguard Worker unsigned Reg = StringSwitch<unsigned>(RegName)
4051*9880d681SAndroid Build Coastguard Worker .Case("$28", Mips::GP)
4052*9880d681SAndroid Build Coastguard Worker .Default(0);
4053*9880d681SAndroid Build Coastguard Worker if (Reg)
4054*9880d681SAndroid Build Coastguard Worker return Reg;
4055*9880d681SAndroid Build Coastguard Worker }
4056*9880d681SAndroid Build Coastguard Worker report_fatal_error("Invalid register name global variable");
4057*9880d681SAndroid Build Coastguard Worker }
4058