blob: ec9b4b14a02cdcd2db55e5793fba703750be5303 [file] [log] [blame]
buzbeee88dfbf2012-03-05 11:19:57 -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/*
buzbeea7678db2012-03-05 15:35:46 -080018 * This file contains X86-specific register allocation support.
buzbeee88dfbf2012-03-05 11:19:57 -080019 */
20
21#include "../../CompilerUtility.h"
22#include "../../CompilerIR.h"
23#include "../..//Dataflow.h"
buzbeea7678db2012-03-05 15:35:46 -080024#include "X86LIR.h"
buzbeee88dfbf2012-03-05 11:19:57 -080025#include "Codegen.h"
26#include "../Ralloc.h"
27
28namespace art {
29
30/*
31 * 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 UNIMPLEMENTED(WARNING) << "oatAdjustSpillMask";
39#if 0
40 cUnit->coreSpillMask |= (1 << r_RA);
41 cUnit->numCoreSpills++;
42#endif
43}
44
45/*
46 * Mark a callee-save fp register as promoted. Note that
47 * vpush/vpop uses contiguous register lists so we must
48 * include any holes in the mask. Associate holes with
49 * Dalvik register INVALID_VREG (0xFFFFU).
50 */
51void oatMarkPreservedSingle(CompilationUnit* cUnit, int sReg, int reg)
52{
53 UNIMPLEMENTED(WARNING) << "oatMarkPreservedSingle";
54#if 0
55 LOG(FATAL) << "No support yet for promoted FP regs";
56#endif
57}
58
59void oatFlushRegWide(CompilationUnit* cUnit, int reg1, int reg2)
60{
61 RegisterInfo* info1 = oatGetRegInfo(cUnit, reg1);
62 RegisterInfo* info2 = oatGetRegInfo(cUnit, reg2);
63 DCHECK(info1 && info2 && info1->pair && info2->pair &&
64 (info1->partner == info2->reg) &&
65 (info2->partner == info1->reg));
66 if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
67 if (!(info1->isTemp && info2->isTemp)) {
68 /* Should not happen. If it does, there's a problem in evalLoc */
69 LOG(FATAL) << "Long half-temp, half-promoted";
70 }
71
72 info1->dirty = false;
73 info2->dirty = false;
74 if (oatS2VReg(cUnit, info2->sReg) <
75 oatS2VReg(cUnit, info1->sReg))
76 info1 = info2;
77 int vReg = oatS2VReg(cUnit, info1->sReg);
78 oatFlushRegWideImpl(cUnit, rSP,
79 oatVRegOffset(cUnit, vReg),
80 info1->reg, info1->partner);
81 }
82}
83
84void oatFlushReg(CompilationUnit* cUnit, int reg)
85{
86 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
87 if (info->live && info->dirty) {
88 info->dirty = false;
89 int vReg = oatS2VReg(cUnit, info->sReg);
90 oatFlushRegImpl(cUnit, rSP,
91 oatVRegOffset(cUnit, vReg),
92 reg, kWord);
93 }
94}
95
96/* Give access to the target-dependent FP register encoding to common code */
97bool oatIsFpReg(int reg) {
98 return FPREG(reg);
99}
100
101uint32_t oatFpRegMask() {
102 return FP_REG_MASK;
103}
104
105/* Clobber all regs that might be used by an external C call */
106extern void oatClobberCalleeSave(CompilationUnit *cUnit)
107{
108 UNIMPLEMENTED(WARNING) << "oatClobberCalleeSave";
109#if 0
110 oatClobber(cUnit, r_ZERO);
111 oatClobber(cUnit, r_AT);
112 oatClobber(cUnit, r_V0);
113 oatClobber(cUnit, r_V1);
114 oatClobber(cUnit, r_A0);
115 oatClobber(cUnit, r_A1);
116 oatClobber(cUnit, r_A2);
117 oatClobber(cUnit, r_A3);
118 oatClobber(cUnit, r_T0);
119 oatClobber(cUnit, r_T1);
120 oatClobber(cUnit, r_T2);
121 oatClobber(cUnit, r_T3);
122 oatClobber(cUnit, r_T4);
123 oatClobber(cUnit, r_T5);
124 oatClobber(cUnit, r_T6);
125 oatClobber(cUnit, r_T7);
126 oatClobber(cUnit, r_T8);
127 oatClobber(cUnit, r_T9);
128 oatClobber(cUnit, r_K0);
129 oatClobber(cUnit, r_K1);
130 oatClobber(cUnit, r_GP);
131 oatClobber(cUnit, r_FP);
132 oatClobber(cUnit, r_RA);
133 oatClobber(cUnit, r_F0);
134 oatClobber(cUnit, r_F1);
135 oatClobber(cUnit, r_F2);
136 oatClobber(cUnit, r_F3);
137 oatClobber(cUnit, r_F4);
138 oatClobber(cUnit, r_F5);
139 oatClobber(cUnit, r_F6);
140 oatClobber(cUnit, r_F7);
141 oatClobber(cUnit, r_F8);
142 oatClobber(cUnit, r_F9);
143 oatClobber(cUnit, r_F10);
144 oatClobber(cUnit, r_F11);
145 oatClobber(cUnit, r_F12);
146 oatClobber(cUnit, r_F13);
147 oatClobber(cUnit, r_F14);
148 oatClobber(cUnit, r_F15);
149#endif
150}
151
152extern RegLocation oatGetReturnWide(CompilationUnit* cUnit)
153{
154 RegLocation res = LOC_C_RETURN_WIDE;
155 oatClobber(cUnit, res.lowReg);
156 oatClobber(cUnit, res.highReg);
157 oatMarkInUse(cUnit, res.lowReg);
158 oatMarkInUse(cUnit, res.highReg);
159 oatMarkPair(cUnit, res.lowReg, res.highReg);
160 return res;
161}
162
163extern RegLocation oatGetReturnWideAlt(CompilationUnit* cUnit)
164{
buzbeea7678db2012-03-05 15:35:46 -0800165 UNIMPLEMENTED(WARNING) << "oatGetReturnWideAlt";
166 return oatGetReturnWide(cUnit);
167#if 0
168 // May not need this - it is used when calling a combined
169 // div/rem helper. Quotient in regular return, remainder in alt regs
buzbeee88dfbf2012-03-05 11:19:57 -0800170 RegLocation res = LOC_C_RETURN_WIDE_ALT;
171 oatClobber(cUnit, res.lowReg);
172 oatClobber(cUnit, res.highReg);
173 oatMarkInUse(cUnit, res.lowReg);
174 oatMarkInUse(cUnit, res.highReg);
175 oatMarkPair(cUnit, res.lowReg, res.highReg);
176 return res;
buzbeea7678db2012-03-05 15:35:46 -0800177#endif
buzbeee88dfbf2012-03-05 11:19:57 -0800178}
179
180extern RegLocation oatGetReturn(CompilationUnit* cUnit)
181{
182 RegLocation res = LOC_C_RETURN;
183 oatClobber(cUnit, res.lowReg);
184 oatMarkInUse(cUnit, res.lowReg);
185 return res;
186}
187
188extern RegLocation oatGetReturnAlt(CompilationUnit* cUnit)
189{
buzbeea7678db2012-03-05 15:35:46 -0800190 UNIMPLEMENTED(WARNING) << "oatGetReturnWideAlt";
191 return oatGetReturn(cUnit);
192#if 0
193 // May not need this - it is used when calling a combined
194 // div/rem helper. Quotient in regular return, remainder in alt regs
buzbeee88dfbf2012-03-05 11:19:57 -0800195 RegLocation res = LOC_C_RETURN_ALT;
196 oatClobber(cUnit, res.lowReg);
197 oatMarkInUse(cUnit, res.lowReg);
198 return res;
buzbeea7678db2012-03-05 15:35:46 -0800199#endif
buzbeee88dfbf2012-03-05 11:19:57 -0800200}
201
202extern RegisterInfo* oatGetRegInfo(CompilationUnit* cUnit, int reg)
203{
204 return FPREG(reg) ? &cUnit->regPool->FPRegs[reg & FP_REG_MASK]
205 : &cUnit->regPool->coreRegs[reg];
206}
207
208/* To be used when explicitly managing register use */
209extern void oatLockCallTemps(CompilationUnit* cUnit)
210{
211 UNIMPLEMENTED(WARNING) << "oatLockCallTemps";
212#if 0
213 oatLockTemp(cUnit, rARG0);
214 oatLockTemp(cUnit, rARG1);
215 oatLockTemp(cUnit, rARG2);
216 oatLockTemp(cUnit, rARG3);
217#endif
218}
219
220/* To be used when explicitly managing register use */
221extern void oatFreeCallTemps(CompilationUnit* cUnit)
222{
223 UNIMPLEMENTED(WARNING) << "oatFreeCallTemps";
224#if 0
225 oatFreeTemp(cUnit, rARG0);
226 oatFreeTemp(cUnit, rARG1);
227 oatFreeTemp(cUnit, rARG2);
228 oatFreeTemp(cUnit, rARG3);
229#endif
230}
231
232/* Convert an instruction to a NOP */
233void oatNopLIR( LIR* lir)
234{
235 ((LIR*)lir)->flags.isNop = true;
236}
237
238} // namespace art