blob: 0dfbfa5065f03615ccb7b56b461b152df735534d [file] [log] [blame]
buzbeee3acd072012-02-25 17:03:10 -08001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * This file contains Mips-specific register allocation support.
19 */
20
21#include "../../CompilerUtility.h"
22#include "../../CompilerIR.h"
23#include "../..//Dataflow.h"
24#include "MipsLIR.h"
25#include "Codegen.h"
26#include "../Ralloc.h"
27
28namespace art {
29
30/*
buzbee31a4a6f2012-02-28 15:36:15 -080031 * TUNING: is leaf? Can't just use "hasInvoke" to determine as some
32 * instructions might call out to C/assembly helper functions. Until
33 * machinery is in place, always spill lr.
34 */
35
36void oatAdjustSpillMask(CompilationUnit* cUnit)
37{
38 cUnit->coreSpillMask |= (1 << r_RA);
39 cUnit->numCoreSpills++;
40}
41
42/*
buzbeee3acd072012-02-25 17:03:10 -080043 * Mark a callee-save fp register as promoted. Note that
44 * vpush/vpop uses contiguous register lists so we must
45 * include any holes in the mask. Associate holes with
46 * Dalvik register INVALID_VREG (0xFFFFU).
47 */
buzbee31a4a6f2012-02-28 15:36:15 -080048void oatMarkPreservedSingle(CompilationUnit* cUnit, int sReg, int reg)
buzbeee3acd072012-02-25 17:03:10 -080049{
50 UNIMPLEMENTED(FATAL) << "No support yet for promoted FP regs";
51#if 0
52 DCHECK_GE(reg, FP_REG_MASK + FP_CALLEE_SAVE_BASE);
53 reg = (reg & FP_REG_MASK) - FP_CALLEE_SAVE_BASE;
54 // Ensure fpVmapTable is large enough
55 int tableSize = cUnit->fpVmapTable.size();
56 for (int i = tableSize; i < (reg + 1); i++) {
57 cUnit->fpVmapTable.push_back(INVALID_VREG);
58 }
59 // Add the current mapping
60 cUnit->fpVmapTable[reg] = sReg;
61 // Size of fpVmapTable is high-water mark, use to set mask
62 cUnit->numFPSpills = cUnit->fpVmapTable.size();
63 cUnit->fpSpillMask = ((1 << cUnit->numFPSpills) - 1) << FP_CALLEE_SAVE_BASE;
64#endif
65}
66
67void oatFlushRegWide(CompilationUnit* cUnit, int reg1, int reg2)
68{
69 RegisterInfo* info1 = oatGetRegInfo(cUnit, reg1);
70 RegisterInfo* info2 = oatGetRegInfo(cUnit, reg2);
71 DCHECK(info1 && info2 && info1->pair && info2->pair &&
72 (info1->partner == info2->reg) &&
73 (info2->partner == info1->reg));
74 if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
75 if (!(info1->isTemp && info2->isTemp)) {
76 /* Should not happen. If it does, there's a problem in evalLoc */
77 LOG(FATAL) << "Long half-temp, half-promoted";
78 }
79
80 info1->dirty = false;
81 info2->dirty = false;
82 if (oatS2VReg(cUnit, info2->sReg) <
83 oatS2VReg(cUnit, info1->sReg))
84 info1 = info2;
85 int vReg = oatS2VReg(cUnit, info1->sReg);
86 oatFlushRegWideImpl(cUnit, rSP,
87 oatVRegOffset(cUnit, vReg),
88 info1->reg, info1->partner);
89 }
90}
91
92void oatFlushReg(CompilationUnit* cUnit, int reg)
93{
94 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
95 if (info->live && info->dirty) {
96 info->dirty = false;
97 int vReg = oatS2VReg(cUnit, info->sReg);
98 oatFlushRegImpl(cUnit, rSP,
99 oatVRegOffset(cUnit, vReg),
100 reg, kWord);
101 }
102}
103
104/* Give access to the target-dependent FP register encoding to common code */
105bool oatIsFpReg(int reg) {
106 return FPREG(reg);
107}
108
109uint32_t oatFpRegMask() {
110 return FP_REG_MASK;
111}
112
113/* Clobber all regs that might be used by an external C call */
114extern void oatClobberCalleeSave(CompilationUnit *cUnit)
115{
116 oatClobber(cUnit, r_ZERO);
117 oatClobber(cUnit, r_AT);
118 oatClobber(cUnit, r_V0);
119 oatClobber(cUnit, r_V1);
120 oatClobber(cUnit, r_A0);
121 oatClobber(cUnit, r_A1);
122 oatClobber(cUnit, r_A2);
123 oatClobber(cUnit, r_A3);
124 oatClobber(cUnit, r_T0);
125 oatClobber(cUnit, r_T1);
126 oatClobber(cUnit, r_T2);
127 oatClobber(cUnit, r_T3);
128 oatClobber(cUnit, r_T4);
129 oatClobber(cUnit, r_T5);
130 oatClobber(cUnit, r_T6);
131 oatClobber(cUnit, r_T7);
132 oatClobber(cUnit, r_T8);
133 oatClobber(cUnit, r_T9);
134 oatClobber(cUnit, r_K0);
135 oatClobber(cUnit, r_K1);
136 oatClobber(cUnit, r_GP);
137 oatClobber(cUnit, r_FP);
138 oatClobber(cUnit, r_RA);
139 oatClobber(cUnit, r_HI);
140 oatClobber(cUnit, r_LO);
141 oatClobber(cUnit, r_F0);
142 oatClobber(cUnit, r_F1);
143 oatClobber(cUnit, r_F2);
144 oatClobber(cUnit, r_F3);
145 oatClobber(cUnit, r_F4);
146 oatClobber(cUnit, r_F5);
147 oatClobber(cUnit, r_F6);
148 oatClobber(cUnit, r_F7);
149 oatClobber(cUnit, r_F8);
150 oatClobber(cUnit, r_F9);
151 oatClobber(cUnit, r_F10);
152 oatClobber(cUnit, r_F11);
153 oatClobber(cUnit, r_F12);
154 oatClobber(cUnit, r_F13);
155 oatClobber(cUnit, r_F14);
156 oatClobber(cUnit, r_F15);
157}
158
159extern RegLocation oatGetReturnWide(CompilationUnit* cUnit)
160{
161 RegLocation res = LOC_C_RETURN_WIDE;
162 oatClobber(cUnit, r_V0);
163 oatClobber(cUnit, r_V1);
164 oatMarkInUse(cUnit, r_V0);
165 oatMarkInUse(cUnit, r_V1);
166 oatMarkPair(cUnit, res.lowReg, res.highReg);
167 return res;
168}
169
170extern RegLocation oatGetReturnWideAlt(CompilationUnit* cUnit)
171{
172 RegLocation res = LOC_C_RETURN_WIDE_ALT;
173 oatClobber(cUnit, r_F0);
174 oatClobber(cUnit, r_F1);
175 oatMarkInUse(cUnit, r_F0);
176 oatMarkInUse(cUnit, r_F1);
177 oatMarkPair(cUnit, res.lowReg, res.highReg);
178 return res;
179}
180
181extern RegLocation oatGetReturn(CompilationUnit* cUnit)
182{
183 RegLocation res = LOC_C_RETURN;
184 oatClobber(cUnit, r_V0);
185 oatMarkInUse(cUnit, r_V0);
186 return res;
187}
188
189extern RegLocation oatGetReturnAlt(CompilationUnit* cUnit)
190{
191 RegLocation res = LOC_C_RETURN_ALT;
192 oatClobber(cUnit, r_F0);
193 oatMarkInUse(cUnit, r_F0);
194 return res;
195}
196
197extern RegisterInfo* oatGetRegInfo(CompilationUnit* cUnit, int reg)
198{
199 return FPREG(reg) ? &cUnit->regPool->FPRegs[reg & FP_REG_MASK]
200 : &cUnit->regPool->coreRegs[reg];
201}
202
203/* To be used when explicitly managing register use */
204extern void oatLockCallTemps(CompilationUnit* cUnit)
205{
206 oatLockTemp(cUnit, r_A0);
207 oatLockTemp(cUnit, r_A1);
208 oatLockTemp(cUnit, r_A2);
209 oatLockTemp(cUnit, r_A3);
210}
211
212/* To be used when explicitly managing register use */
213extern void oatFreeCallTemps(CompilationUnit* cUnit)
214{
215 oatFreeTemp(cUnit, r_A0);
216 oatFreeTemp(cUnit, r_A1);
217 oatFreeTemp(cUnit, r_A2);
218 oatFreeTemp(cUnit, r_A3);
219}
220
buzbee31a4a6f2012-02-28 15:36:15 -0800221/* Convert an instruction to a NOP */
222STATIC void oatNopLIR( LIR* lir)
223{
224 ((MipsLIR*)lir)->flags.isNop = true;
225}
226
buzbeee3acd072012-02-25 17:03:10 -0800227} // namespace art