blob: 3a7cb82a02d2fed054d34c34b5e8374dec427b72 [file] [log] [blame]
buzbee67bf8852011-08-17 17:51:35 -07001/*
2 * Copyright (C) 2011 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
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080017namespace art {
18
buzbee67bf8852011-08-17 17:51:35 -070019/*
20 * This file contains target-independent codegen and support, and is
21 * included by:
22 *
23 * $(TARGET_ARCH)/Codegen-$(TARGET_ARCH_VARIANT).c
24 *
25 * which combines this common code with specific support found in the
26 * applicable directories below this one.
27 *
buzbee67bf8852011-08-17 17:51:35 -070028 */
29
buzbee31a4a6f2012-02-28 15:36:15 -080030/*
31 * Load an immediate value into a fixed or temp register. Target
32 * register is clobbered, and marked inUse.
33 */
34LIR* loadConstant(CompilationUnit* cUnit, int rDest, int value)
35{
Bill Buzbeea114add2012-05-03 15:00:40 -070036 if (oatIsTemp(cUnit, rDest)) {
37 oatClobber(cUnit, rDest);
38 oatMarkInUse(cUnit, rDest);
39 }
40 return loadConstantNoClobber(cUnit, rDest, value);
buzbee31a4a6f2012-02-28 15:36:15 -080041}
buzbee67bf8852011-08-17 17:51:35 -070042
43/* Load a word at base + displacement. Displacement must be word multiple */
buzbee31a4a6f2012-02-28 15:36:15 -080044LIR* loadWordDisp(CompilationUnit* cUnit, int rBase, int displacement,
45 int rDest)
buzbee67bf8852011-08-17 17:51:35 -070046{
Bill Buzbeea114add2012-05-03 15:00:40 -070047 return loadBaseDisp(cUnit, NULL, rBase, displacement, rDest, kWord,
48 INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -070049}
50
buzbee31a4a6f2012-02-28 15:36:15 -080051LIR* storeWordDisp(CompilationUnit* cUnit, int rBase, int displacement,
52 int rSrc)
buzbee67bf8852011-08-17 17:51:35 -070053{
Bill Buzbeea114add2012-05-03 15:00:40 -070054 return storeBaseDisp(cUnit, rBase, displacement, rSrc, kWord);
buzbee67bf8852011-08-17 17:51:35 -070055}
56
57/*
58 * Load a Dalvik register into a physical register. Take care when
59 * using this routine, as it doesn't perform any bookkeeping regarding
60 * register liveness. That is the responsibility of the caller.
61 */
Ian Rogersab2b55d2012-03-18 00:06:11 -070062void loadValueDirect(CompilationUnit* cUnit, RegLocation rlSrc, int rDest)
buzbee67bf8852011-08-17 17:51:35 -070063{
Bill Buzbeea114add2012-05-03 15:00:40 -070064 rlSrc = oatUpdateLoc(cUnit, rlSrc);
65 if (rlSrc.location == kLocPhysReg) {
66 opRegCopy(cUnit, rDest, rlSrc.lowReg);
67 } else {
68 DCHECK((rlSrc.location == kLocDalvikFrame) ||
69 (rlSrc.location == kLocCompilerTemp));
70 loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, rlSrc.sRegLow), rDest);
71 }
buzbee67bf8852011-08-17 17:51:35 -070072}
73
74/*
75 * Similar to loadValueDirect, but clobbers and allocates the target
76 * register. Should be used when loading to a fixed register (for example,
77 * loading arguments to an out of line call.
78 */
Ian Rogersab2b55d2012-03-18 00:06:11 -070079void loadValueDirectFixed(CompilationUnit* cUnit, RegLocation rlSrc, int rDest)
buzbee67bf8852011-08-17 17:51:35 -070080{
Bill Buzbeea114add2012-05-03 15:00:40 -070081 oatClobber(cUnit, rDest);
82 oatMarkInUse(cUnit, rDest);
83 loadValueDirect(cUnit, rlSrc, rDest);
buzbee67bf8852011-08-17 17:51:35 -070084}
85
86/*
87 * Load a Dalvik register pair into a physical register[s]. Take care when
88 * using this routine, as it doesn't perform any bookkeeping regarding
89 * register liveness. That is the responsibility of the caller.
90 */
buzbee31a4a6f2012-02-28 15:36:15 -080091void loadValueDirectWide(CompilationUnit* cUnit, RegLocation rlSrc, int regLo,
Bill Buzbeea114add2012-05-03 15:00:40 -070092 int regHi)
buzbee67bf8852011-08-17 17:51:35 -070093{
Bill Buzbeea114add2012-05-03 15:00:40 -070094 rlSrc = oatUpdateLocWide(cUnit, rlSrc);
95 if (rlSrc.location == kLocPhysReg) {
96 opRegCopyWide(cUnit, regLo, regHi, rlSrc.lowReg, rlSrc.highReg);
97 } else {
98 DCHECK((rlSrc.location == kLocDalvikFrame) ||
99 (rlSrc.location == kLocCompilerTemp));
100 loadBaseDispWide(cUnit, NULL, rSP, oatSRegOffset(cUnit, rlSrc.sRegLow),
101 regLo, regHi, INVALID_SREG);
102 }
buzbee67bf8852011-08-17 17:51:35 -0700103}
104
105/*
106 * Similar to loadValueDirect, but clobbers and allocates the target
107 * registers. Should be used when loading to a fixed registers (for example,
108 * loading arguments to an out of line call.
109 */
buzbee31a4a6f2012-02-28 15:36:15 -0800110void loadValueDirectWideFixed(CompilationUnit* cUnit, RegLocation rlSrc,
111 int regLo, int regHi)
buzbee67bf8852011-08-17 17:51:35 -0700112{
Bill Buzbeea114add2012-05-03 15:00:40 -0700113 oatClobber(cUnit, regLo);
114 oatClobber(cUnit, regHi);
115 oatMarkInUse(cUnit, regLo);
116 oatMarkInUse(cUnit, regHi);
117 loadValueDirectWide(cUnit, rlSrc, regLo, regHi);
buzbee67bf8852011-08-17 17:51:35 -0700118}
119
buzbee31a4a6f2012-02-28 15:36:15 -0800120RegLocation loadValue(CompilationUnit* cUnit, RegLocation rlSrc,
121 RegisterClass opKind)
buzbee67bf8852011-08-17 17:51:35 -0700122{
Bill Buzbeea114add2012-05-03 15:00:40 -0700123 rlSrc = oatEvalLoc(cUnit, rlSrc, opKind, false);
124 if (rlSrc.location != kLocPhysReg) {
125 DCHECK((rlSrc.location == kLocDalvikFrame) ||
126 (rlSrc.location == kLocCompilerTemp));
127 loadValueDirect(cUnit, rlSrc, rlSrc.lowReg);
128 rlSrc.location = kLocPhysReg;
129 oatMarkLive(cUnit, rlSrc.lowReg, rlSrc.sRegLow);
130 }
131 return rlSrc;
buzbee67bf8852011-08-17 17:51:35 -0700132}
133
buzbee31a4a6f2012-02-28 15:36:15 -0800134void storeValue(CompilationUnit* cUnit, RegLocation rlDest, RegLocation rlSrc)
buzbee67bf8852011-08-17 17:51:35 -0700135{
buzbee3d661942012-03-14 17:37:27 -0700136#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700137 /*
138 * Sanity checking - should never try to store to the same
139 * ssa name during the compilation of a single instruction
140 * without an intervening oatClobberSReg().
141 */
142 DCHECK((cUnit->liveSReg == INVALID_SREG) ||
143 (rlDest.sRegLow != cUnit->liveSReg));
144 cUnit->liveSReg = rlDest.sRegLow;
buzbee3d661942012-03-14 17:37:27 -0700145#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 LIR* defStart;
147 LIR* defEnd;
148 DCHECK(!rlDest.wide);
149 DCHECK(!rlSrc.wide);
150 rlSrc = oatUpdateLoc(cUnit, rlSrc);
151 rlDest = oatUpdateLoc(cUnit, rlDest);
152 if (rlSrc.location == kLocPhysReg) {
153 if (oatIsLive(cUnit, rlSrc.lowReg) ||
154 oatIsPromoted(cUnit, rlSrc.lowReg) ||
155 (rlDest.location == kLocPhysReg)) {
156 // Src is live/promoted or Dest has assigned reg.
157 rlDest = oatEvalLoc(cUnit, rlDest, kAnyReg, false);
158 opRegCopy(cUnit, rlDest.lowReg, rlSrc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700159 } else {
Bill Buzbeea114add2012-05-03 15:00:40 -0700160 // Just re-assign the registers. Dest gets Src's regs
161 rlDest.lowReg = rlSrc.lowReg;
162 oatClobber(cUnit, rlSrc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700163 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700164 } else {
165 // Load Src either into promoted Dest or temps allocated for Dest
166 rlDest = oatEvalLoc(cUnit, rlDest, kAnyReg, false);
167 loadValueDirect(cUnit, rlSrc, rlDest.lowReg);
168 }
buzbee67bf8852011-08-17 17:51:35 -0700169
Bill Buzbeea114add2012-05-03 15:00:40 -0700170 // Dest is now live and dirty (until/if we flush it to home location)
171 oatMarkLive(cUnit, rlDest.lowReg, rlDest.sRegLow);
172 oatMarkDirty(cUnit, rlDest);
buzbee67bf8852011-08-17 17:51:35 -0700173
174
Bill Buzbeea114add2012-05-03 15:00:40 -0700175 oatResetDefLoc(cUnit, rlDest);
176 if (oatIsDirty(cUnit, rlDest.lowReg) &&
177 oatLiveOut(cUnit, rlDest.sRegLow)) {
178 defStart = (LIR* )cUnit->lastLIRInsn;
179 storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, rlDest.sRegLow),
180 rlDest.lowReg, kWord);
181 oatMarkClean(cUnit, rlDest);
182 defEnd = (LIR* )cUnit->lastLIRInsn;
183 oatMarkDef(cUnit, rlDest, defStart, defEnd);
184 }
buzbee67bf8852011-08-17 17:51:35 -0700185}
186
buzbee31a4a6f2012-02-28 15:36:15 -0800187RegLocation loadValueWide(CompilationUnit* cUnit, RegLocation rlSrc,
Bill Buzbeea114add2012-05-03 15:00:40 -0700188 RegisterClass opKind)
buzbee67bf8852011-08-17 17:51:35 -0700189{
Bill Buzbeea114add2012-05-03 15:00:40 -0700190 DCHECK(rlSrc.wide);
191 rlSrc = oatEvalLoc(cUnit, rlSrc, opKind, false);
192 if (rlSrc.location != kLocPhysReg) {
193 DCHECK((rlSrc.location == kLocDalvikFrame) ||
194 (rlSrc.location == kLocCompilerTemp));
195 loadValueDirectWide(cUnit, rlSrc, rlSrc.lowReg, rlSrc.highReg);
196 rlSrc.location = kLocPhysReg;
197 oatMarkLive(cUnit, rlSrc.lowReg, rlSrc.sRegLow);
198 oatMarkLive(cUnit, rlSrc.highReg,
199 oatSRegHi(rlSrc.sRegLow));
200 }
201 return rlSrc;
buzbee67bf8852011-08-17 17:51:35 -0700202}
203
buzbee31a4a6f2012-02-28 15:36:15 -0800204void storeValueWide(CompilationUnit* cUnit, RegLocation rlDest,
Bill Buzbeea114add2012-05-03 15:00:40 -0700205 RegLocation rlSrc)
buzbee67bf8852011-08-17 17:51:35 -0700206{
buzbee3d661942012-03-14 17:37:27 -0700207#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700208 /*
209 * Sanity checking - should never try to store to the same
210 * ssa name during the compilation of a single instruction
211 * without an intervening oatClobberSReg().
212 */
213 DCHECK((cUnit->liveSReg == INVALID_SREG) ||
214 (rlDest.sRegLow != cUnit->liveSReg));
215 cUnit->liveSReg = rlDest.sRegLow;
buzbee3d661942012-03-14 17:37:27 -0700216#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700217 LIR* defStart;
218 LIR* defEnd;
219 DCHECK_EQ(FPREG(rlSrc.lowReg), FPREG(rlSrc.highReg));
220 DCHECK(rlDest.wide);
221 DCHECK(rlSrc.wide);
222 if (rlSrc.location == kLocPhysReg) {
223 if (oatIsLive(cUnit, rlSrc.lowReg) ||
224 oatIsLive(cUnit, rlSrc.highReg) ||
225 oatIsPromoted(cUnit, rlSrc.lowReg) ||
226 oatIsPromoted(cUnit, rlSrc.highReg) ||
227 (rlDest.location == kLocPhysReg)) {
228 // Src is live or promoted or Dest has assigned reg.
229 rlDest = oatEvalLoc(cUnit, rlDest, kAnyReg, false);
230 opRegCopyWide(cUnit, rlDest.lowReg, rlDest.highReg,
231 rlSrc.lowReg, rlSrc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700232 } else {
Bill Buzbeea114add2012-05-03 15:00:40 -0700233 // Just re-assign the registers. Dest gets Src's regs
234 rlDest.lowReg = rlSrc.lowReg;
235 rlDest.highReg = rlSrc.highReg;
236 oatClobber(cUnit, rlSrc.lowReg);
237 oatClobber(cUnit, rlSrc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700238 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700239 } else {
240 // Load Src either into promoted Dest or temps allocated for Dest
241 rlDest = oatEvalLoc(cUnit, rlDest, kAnyReg, false);
242 loadValueDirectWide(cUnit, rlSrc, rlDest.lowReg, rlDest.highReg);
243 }
buzbee67bf8852011-08-17 17:51:35 -0700244
Bill Buzbeea114add2012-05-03 15:00:40 -0700245 // Dest is now live and dirty (until/if we flush it to home location)
246 oatMarkLive(cUnit, rlDest.lowReg, rlDest.sRegLow);
247 oatMarkLive(cUnit, rlDest.highReg, oatSRegHi(rlDest.sRegLow));
248 oatMarkDirty(cUnit, rlDest);
249 oatMarkPair(cUnit, rlDest.lowReg, rlDest.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700250
251
Bill Buzbeea114add2012-05-03 15:00:40 -0700252 oatResetDefLocWide(cUnit, rlDest);
253 if ((oatIsDirty(cUnit, rlDest.lowReg) ||
254 oatIsDirty(cUnit, rlDest.highReg)) &&
255 (oatLiveOut(cUnit, rlDest.sRegLow) ||
256 oatLiveOut(cUnit, oatSRegHi(rlDest.sRegLow)))) {
257 defStart = (LIR*)cUnit->lastLIRInsn;
258 DCHECK_EQ((SRegToVReg(cUnit, rlDest.sRegLow)+1),
259 SRegToVReg(cUnit, oatSRegHi(rlDest.sRegLow)));
260 storeBaseDispWide(cUnit, rSP, oatSRegOffset(cUnit, rlDest.sRegLow),
261 rlDest.lowReg, rlDest.highReg);
262 oatMarkClean(cUnit, rlDest);
263 defEnd = (LIR*)cUnit->lastLIRInsn;
264 oatMarkDefWide(cUnit, rlDest, defStart, defEnd);
265 }
buzbee67bf8852011-08-17 17:51:35 -0700266}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800267
buzbee31a4a6f2012-02-28 15:36:15 -0800268/*
269 * Mark garbage collection card. Skip if the value we're storing is null.
270 */
271void markGCCard(CompilationUnit* cUnit, int valReg, int tgtAddrReg)
272{
Bill Buzbeea114add2012-05-03 15:00:40 -0700273 int regCardBase = oatAllocTemp(cUnit);
274 int regCardNo = oatAllocTemp(cUnit);
275 LIR* branchOver = opCmpImmBranch(cUnit, kCondEq, valReg, 0, NULL);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700276#if !defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700277 loadWordDisp(cUnit, rSELF, Thread::CardTableOffset().Int32Value(),
278 regCardBase);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700279#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700280 newLIR2(cUnit, kX86Mov32RT, regCardBase,
281 Thread::CardTableOffset().Int32Value());
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700282#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700283 opRegRegImm(cUnit, kOpLsr, regCardNo, tgtAddrReg, GC_CARD_SHIFT);
284 storeBaseIndexed(cUnit, regCardBase, regCardNo, regCardBase, 0,
285 kUnsignedByte);
286 LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
287 branchOver->target = (LIR*)target;
288 oatFreeTemp(cUnit, regCardBase);
289 oatFreeTemp(cUnit, regCardNo);
buzbee31a4a6f2012-02-28 15:36:15 -0800290}
291
buzbeee1965672012-03-11 18:39:19 -0700292/* Utilities to load the current Method* */
buzbee31a4a6f2012-02-28 15:36:15 -0800293void loadCurrMethodDirect(CompilationUnit *cUnit, int rTgt)
294{
Bill Buzbeea114add2012-05-03 15:00:40 -0700295 loadValueDirectFixed(cUnit, cUnit->regLocation[cUnit->methodSReg], rTgt);
buzbee31a4a6f2012-02-28 15:36:15 -0800296}
297
buzbeee1965672012-03-11 18:39:19 -0700298RegLocation loadCurrMethod(CompilationUnit *cUnit)
buzbee31a4a6f2012-02-28 15:36:15 -0800299{
Bill Buzbeea114add2012-05-03 15:00:40 -0700300 return loadValue(cUnit, cUnit->regLocation[cUnit->methodSReg], kCoreReg);
buzbee31a4a6f2012-02-28 15:36:15 -0800301}
302
buzbee9c044ce2012-03-18 13:24:07 -0700303bool methodStarInReg(CompilationUnit* cUnit)
304{
Bill Buzbeea114add2012-05-03 15:00:40 -0700305 return (cUnit->regLocation[cUnit->methodSReg].location == kLocPhysReg);
buzbee9c044ce2012-03-18 13:24:07 -0700306}
307
buzbee31a4a6f2012-02-28 15:36:15 -0800308
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800309} // namespace art