blob: 7d28e1be3e897218c0343b15f4dd99c7b8604f0a [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
buzbee1bc37c62012-11-20 13:35:41 -080017#include "../compiler_ir.h"
18#include "ralloc_util.h"
19#include "codegen_util.h"
20
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080021namespace art {
22
buzbeeb046e162012-10-30 15:48:42 -070023/* This file contains target-independent codegen and support. */
buzbee67bf8852011-08-17 17:51:35 -070024
buzbee31a4a6f2012-02-28 15:36:15 -080025/*
26 * Load an immediate value into a fixed or temp register. Target
buzbeefa57c472012-11-21 12:06:18 -080027 * register is clobbered, and marked in_use.
buzbee31a4a6f2012-02-28 15:36:15 -080028 */
buzbee02031b12012-11-23 09:41:35 -080029LIR* Codegen::LoadConstant(CompilationUnit* cu, int r_dest, int value)
buzbee31a4a6f2012-02-28 15:36:15 -080030{
buzbeefa57c472012-11-21 12:06:18 -080031 if (IsTemp(cu, r_dest)) {
32 Clobber(cu, r_dest);
33 MarkInUse(cu, r_dest);
Bill Buzbeea114add2012-05-03 15:00:40 -070034 }
buzbeefa57c472012-11-21 12:06:18 -080035 return LoadConstantNoClobber(cu, r_dest, value);
buzbee31a4a6f2012-02-28 15:36:15 -080036}
buzbee67bf8852011-08-17 17:51:35 -070037
38/* Load a word at base + displacement. Displacement must be word multiple */
buzbee02031b12012-11-23 09:41:35 -080039LIR* Codegen::LoadWordDisp(CompilationUnit* cu, int rBase, int displacement, int r_dest)
buzbee67bf8852011-08-17 17:51:35 -070040{
buzbeefa57c472012-11-21 12:06:18 -080041 return LoadBaseDisp(cu, rBase, displacement, r_dest, kWord,
Bill Buzbeea114add2012-05-03 15:00:40 -070042 INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -070043}
44
buzbee02031b12012-11-23 09:41:35 -080045LIR* Codegen::StoreWordDisp(CompilationUnit* cu, int rBase, int displacement, int r_src)
buzbee67bf8852011-08-17 17:51:35 -070046{
buzbeefa57c472012-11-21 12:06:18 -080047 return StoreBaseDisp(cu, rBase, displacement, r_src, kWord);
buzbee67bf8852011-08-17 17:51:35 -070048}
49
50/*
51 * Load a Dalvik register into a physical register. Take care when
52 * using this routine, as it doesn't perform any bookkeeping regarding
53 * register liveness. That is the responsibility of the caller.
54 */
buzbee02031b12012-11-23 09:41:35 -080055void Codegen::LoadValueDirect(CompilationUnit* cu, RegLocation rl_src, int r_dest)
buzbee67bf8852011-08-17 17:51:35 -070056{
buzbeefa57c472012-11-21 12:06:18 -080057 rl_src = UpdateLoc(cu, rl_src);
58 if (rl_src.location == kLocPhysReg) {
59 OpRegCopy(cu, r_dest, rl_src.low_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -070060 } else {
buzbeefa57c472012-11-21 12:06:18 -080061 DCHECK((rl_src.location == kLocDalvikFrame) ||
62 (rl_src.location == kLocCompilerTemp));
63 LoadWordDisp(cu, TargetReg(kSp), SRegOffset(cu, rl_src.s_reg_low), r_dest);
Bill Buzbeea114add2012-05-03 15:00:40 -070064 }
buzbee67bf8852011-08-17 17:51:35 -070065}
66
67/*
buzbee52a77fc2012-11-20 19:50:46 -080068 * Similar to LoadValueDirect, but clobbers and allocates the target
buzbee67bf8852011-08-17 17:51:35 -070069 * register. Should be used when loading to a fixed register (for example,
70 * loading arguments to an out of line call.
71 */
buzbee02031b12012-11-23 09:41:35 -080072void Codegen::LoadValueDirectFixed(CompilationUnit* cu, RegLocation rl_src, int r_dest)
buzbee67bf8852011-08-17 17:51:35 -070073{
buzbeefa57c472012-11-21 12:06:18 -080074 Clobber(cu, r_dest);
75 MarkInUse(cu, r_dest);
76 LoadValueDirect(cu, rl_src, r_dest);
buzbee67bf8852011-08-17 17:51:35 -070077}
78
79/*
80 * Load a Dalvik register pair into a physical register[s]. Take care when
81 * using this routine, as it doesn't perform any bookkeeping regarding
82 * register liveness. That is the responsibility of the caller.
83 */
buzbee02031b12012-11-23 09:41:35 -080084void Codegen::LoadValueDirectWide(CompilationUnit* cu, RegLocation rl_src, int reg_lo,
buzbeefa57c472012-11-21 12:06:18 -080085 int reg_hi)
buzbee67bf8852011-08-17 17:51:35 -070086{
buzbeefa57c472012-11-21 12:06:18 -080087 rl_src = UpdateLocWide(cu, rl_src);
88 if (rl_src.location == kLocPhysReg) {
89 OpRegCopyWide(cu, reg_lo, reg_hi, rl_src.low_reg, rl_src.high_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -070090 } else {
buzbeefa57c472012-11-21 12:06:18 -080091 DCHECK((rl_src.location == kLocDalvikFrame) ||
92 (rl_src.location == kLocCompilerTemp));
93 LoadBaseDispWide(cu, TargetReg(kSp), SRegOffset(cu, rl_src.s_reg_low),
94 reg_lo, reg_hi, INVALID_SREG);
Bill Buzbeea114add2012-05-03 15:00:40 -070095 }
buzbee67bf8852011-08-17 17:51:35 -070096}
97
98/*
buzbee52a77fc2012-11-20 19:50:46 -080099 * Similar to LoadValueDirect, but clobbers and allocates the target
buzbee67bf8852011-08-17 17:51:35 -0700100 * registers. Should be used when loading to a fixed registers (for example,
101 * loading arguments to an out of line call.
102 */
buzbee02031b12012-11-23 09:41:35 -0800103void Codegen::LoadValueDirectWideFixed(CompilationUnit* cu, RegLocation rl_src, int reg_lo,
104 int reg_hi)
buzbee67bf8852011-08-17 17:51:35 -0700105{
buzbeefa57c472012-11-21 12:06:18 -0800106 Clobber(cu, reg_lo);
107 Clobber(cu, reg_hi);
108 MarkInUse(cu, reg_lo);
109 MarkInUse(cu, reg_hi);
110 LoadValueDirectWide(cu, rl_src, reg_lo, reg_hi);
buzbee67bf8852011-08-17 17:51:35 -0700111}
112
buzbee02031b12012-11-23 09:41:35 -0800113RegLocation Codegen::LoadValue(CompilationUnit* cu, RegLocation rl_src, RegisterClass op_kind)
buzbee67bf8852011-08-17 17:51:35 -0700114{
buzbeefa57c472012-11-21 12:06:18 -0800115 rl_src = EvalLoc(cu, rl_src, op_kind, false);
116 if (rl_src.location != kLocPhysReg) {
117 DCHECK((rl_src.location == kLocDalvikFrame) ||
118 (rl_src.location == kLocCompilerTemp));
119 LoadValueDirect(cu, rl_src, rl_src.low_reg);
120 rl_src.location = kLocPhysReg;
121 MarkLive(cu, rl_src.low_reg, rl_src.s_reg_low);
Bill Buzbeea114add2012-05-03 15:00:40 -0700122 }
buzbeefa57c472012-11-21 12:06:18 -0800123 return rl_src;
buzbee67bf8852011-08-17 17:51:35 -0700124}
125
buzbee02031b12012-11-23 09:41:35 -0800126void Codegen::StoreValue(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src)
buzbee67bf8852011-08-17 17:51:35 -0700127{
buzbee3d661942012-03-14 17:37:27 -0700128#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700129 /*
130 * Sanity checking - should never try to store to the same
131 * ssa name during the compilation of a single instruction
buzbee52a77fc2012-11-20 19:50:46 -0800132 * without an intervening ClobberSReg().
Bill Buzbeea114add2012-05-03 15:00:40 -0700133 */
buzbeefa57c472012-11-21 12:06:18 -0800134 DCHECK((cu->live_sreg == INVALID_SREG) ||
135 (rl_dest.s_reg_low != cu->live_sreg));
136 cu->live_sreg = rl_dest.s_reg_low;
buzbee3d661942012-03-14 17:37:27 -0700137#endif
buzbeefa57c472012-11-21 12:06:18 -0800138 LIR* def_start;
139 LIR* def_end;
140 DCHECK(!rl_dest.wide);
141 DCHECK(!rl_src.wide);
142 rl_src = UpdateLoc(cu, rl_src);
143 rl_dest = UpdateLoc(cu, rl_dest);
144 if (rl_src.location == kLocPhysReg) {
145 if (IsLive(cu, rl_src.low_reg) ||
146 IsPromoted(cu, rl_src.low_reg) ||
147 (rl_dest.location == kLocPhysReg)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700148 // Src is live/promoted or Dest has assigned reg.
buzbeefa57c472012-11-21 12:06:18 -0800149 rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false);
150 OpRegCopy(cu, rl_dest.low_reg, rl_src.low_reg);
buzbee67bf8852011-08-17 17:51:35 -0700151 } else {
Bill Buzbeea114add2012-05-03 15:00:40 -0700152 // Just re-assign the registers. Dest gets Src's regs
buzbeefa57c472012-11-21 12:06:18 -0800153 rl_dest.low_reg = rl_src.low_reg;
154 Clobber(cu, rl_src.low_reg);
buzbee67bf8852011-08-17 17:51:35 -0700155 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700156 } else {
157 // Load Src either into promoted Dest or temps allocated for Dest
buzbeefa57c472012-11-21 12:06:18 -0800158 rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false);
159 LoadValueDirect(cu, rl_src, rl_dest.low_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700160 }
buzbee67bf8852011-08-17 17:51:35 -0700161
Bill Buzbeea114add2012-05-03 15:00:40 -0700162 // Dest is now live and dirty (until/if we flush it to home location)
buzbeefa57c472012-11-21 12:06:18 -0800163 MarkLive(cu, rl_dest.low_reg, rl_dest.s_reg_low);
164 MarkDirty(cu, rl_dest);
buzbee67bf8852011-08-17 17:51:35 -0700165
166
buzbeefa57c472012-11-21 12:06:18 -0800167 ResetDefLoc(cu, rl_dest);
168 if (IsDirty(cu, rl_dest.low_reg) &&
169 oat_live_out(cu, rl_dest.s_reg_low)) {
170 def_start = cu->last_lir_insn;
171 StoreBaseDisp(cu, TargetReg(kSp), SRegOffset(cu, rl_dest.s_reg_low),
172 rl_dest.low_reg, kWord);
173 MarkClean(cu, rl_dest);
174 def_end = cu->last_lir_insn;
175 MarkDef(cu, rl_dest, def_start, def_end);
Bill Buzbeea114add2012-05-03 15:00:40 -0700176 }
buzbee67bf8852011-08-17 17:51:35 -0700177}
178
buzbee02031b12012-11-23 09:41:35 -0800179RegLocation Codegen::LoadValueWide(CompilationUnit* cu, RegLocation rl_src, RegisterClass op_kind)
buzbee67bf8852011-08-17 17:51:35 -0700180{
buzbeefa57c472012-11-21 12:06:18 -0800181 DCHECK(rl_src.wide);
182 rl_src = EvalLoc(cu, rl_src, op_kind, false);
183 if (rl_src.location != kLocPhysReg) {
184 DCHECK((rl_src.location == kLocDalvikFrame) ||
185 (rl_src.location == kLocCompilerTemp));
186 LoadValueDirectWide(cu, rl_src, rl_src.low_reg, rl_src.high_reg);
187 rl_src.location = kLocPhysReg;
188 MarkLive(cu, rl_src.low_reg, rl_src.s_reg_low);
189 MarkLive(cu, rl_src.high_reg,
190 GetSRegHi(rl_src.s_reg_low));
Bill Buzbeea114add2012-05-03 15:00:40 -0700191 }
buzbeefa57c472012-11-21 12:06:18 -0800192 return rl_src;
buzbee67bf8852011-08-17 17:51:35 -0700193}
194
buzbee02031b12012-11-23 09:41:35 -0800195void Codegen::StoreValueWide(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src)
buzbee67bf8852011-08-17 17:51:35 -0700196{
buzbee3d661942012-03-14 17:37:27 -0700197#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700198 /*
199 * Sanity checking - should never try to store to the same
200 * ssa name during the compilation of a single instruction
buzbee52a77fc2012-11-20 19:50:46 -0800201 * without an intervening ClobberSReg().
Bill Buzbeea114add2012-05-03 15:00:40 -0700202 */
buzbeefa57c472012-11-21 12:06:18 -0800203 DCHECK((cu->live_sreg == INVALID_SREG) ||
204 (rl_dest.s_reg_low != cu->live_sreg));
205 cu->live_sreg = rl_dest.s_reg_low;
buzbee3d661942012-03-14 17:37:27 -0700206#endif
buzbeefa57c472012-11-21 12:06:18 -0800207 LIR* def_start;
208 LIR* def_end;
buzbee02031b12012-11-23 09:41:35 -0800209 DCHECK_EQ(IsFpReg(rl_src.low_reg), IsFpReg(rl_src.high_reg));
buzbeefa57c472012-11-21 12:06:18 -0800210 DCHECK(rl_dest.wide);
211 DCHECK(rl_src.wide);
212 if (rl_src.location == kLocPhysReg) {
213 if (IsLive(cu, rl_src.low_reg) ||
214 IsLive(cu, rl_src.high_reg) ||
215 IsPromoted(cu, rl_src.low_reg) ||
216 IsPromoted(cu, rl_src.high_reg) ||
217 (rl_dest.location == kLocPhysReg)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700218 // Src is live or promoted or Dest has assigned reg.
buzbeefa57c472012-11-21 12:06:18 -0800219 rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false);
220 OpRegCopyWide(cu, rl_dest.low_reg, rl_dest.high_reg,
221 rl_src.low_reg, rl_src.high_reg);
buzbee67bf8852011-08-17 17:51:35 -0700222 } else {
Bill Buzbeea114add2012-05-03 15:00:40 -0700223 // Just re-assign the registers. Dest gets Src's regs
buzbeefa57c472012-11-21 12:06:18 -0800224 rl_dest.low_reg = rl_src.low_reg;
225 rl_dest.high_reg = rl_src.high_reg;
226 Clobber(cu, rl_src.low_reg);
227 Clobber(cu, rl_src.high_reg);
buzbee67bf8852011-08-17 17:51:35 -0700228 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700229 } else {
230 // Load Src either into promoted Dest or temps allocated for Dest
buzbeefa57c472012-11-21 12:06:18 -0800231 rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false);
232 LoadValueDirectWide(cu, rl_src, rl_dest.low_reg, rl_dest.high_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700233 }
buzbee67bf8852011-08-17 17:51:35 -0700234
Bill Buzbeea114add2012-05-03 15:00:40 -0700235 // Dest is now live and dirty (until/if we flush it to home location)
buzbeefa57c472012-11-21 12:06:18 -0800236 MarkLive(cu, rl_dest.low_reg, rl_dest.s_reg_low);
237 MarkLive(cu, rl_dest.high_reg, GetSRegHi(rl_dest.s_reg_low));
238 MarkDirty(cu, rl_dest);
239 MarkPair(cu, rl_dest.low_reg, rl_dest.high_reg);
buzbee67bf8852011-08-17 17:51:35 -0700240
241
buzbeefa57c472012-11-21 12:06:18 -0800242 ResetDefLocWide(cu, rl_dest);
243 if ((IsDirty(cu, rl_dest.low_reg) ||
244 IsDirty(cu, rl_dest.high_reg)) &&
245 (oat_live_out(cu, rl_dest.s_reg_low) ||
246 oat_live_out(cu, GetSRegHi(rl_dest.s_reg_low)))) {
247 def_start = cu->last_lir_insn;
248 DCHECK_EQ((SRegToVReg(cu, rl_dest.s_reg_low)+1),
249 SRegToVReg(cu, GetSRegHi(rl_dest.s_reg_low)));
250 StoreBaseDispWide(cu, TargetReg(kSp), SRegOffset(cu, rl_dest.s_reg_low),
251 rl_dest.low_reg, rl_dest.high_reg);
252 MarkClean(cu, rl_dest);
253 def_end = cu->last_lir_insn;
254 MarkDefWide(cu, rl_dest, def_start, def_end);
Bill Buzbeea114add2012-05-03 15:00:40 -0700255 }
buzbee67bf8852011-08-17 17:51:35 -0700256}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800257
buzbeee1965672012-03-11 18:39:19 -0700258/* Utilities to load the current Method* */
buzbee02031b12012-11-23 09:41:35 -0800259void Codegen::LoadCurrMethodDirect(CompilationUnit *cu, int r_tgt)
buzbee31a4a6f2012-02-28 15:36:15 -0800260{
buzbeefa57c472012-11-21 12:06:18 -0800261 LoadValueDirectFixed(cu, cu->method_loc, r_tgt);
buzbee31a4a6f2012-02-28 15:36:15 -0800262}
263
buzbee02031b12012-11-23 09:41:35 -0800264RegLocation Codegen::LoadCurrMethod(CompilationUnit *cu)
buzbee31a4a6f2012-02-28 15:36:15 -0800265{
buzbeefa57c472012-11-21 12:06:18 -0800266 return LoadValue(cu, cu->method_loc, kCoreReg);
buzbee31a4a6f2012-02-28 15:36:15 -0800267}
268
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800269} // namespace art