blob: 438a16bd8660d02a949694d8f3776773f684d277 [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 */
buzbeefa57c472012-11-21 12:06:18 -080029LIR* 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 */
buzbeefa57c472012-11-21 12:06:18 -080039LIR* LoadWordDisp(CompilationUnit* cu, int rBase, int displacement,
40 int r_dest)
buzbee67bf8852011-08-17 17:51:35 -070041{
buzbeefa57c472012-11-21 12:06:18 -080042 return LoadBaseDisp(cu, rBase, displacement, r_dest, kWord,
Bill Buzbeea114add2012-05-03 15:00:40 -070043 INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -070044}
45
buzbeefa57c472012-11-21 12:06:18 -080046LIR* StoreWordDisp(CompilationUnit* cu, int rBase, int displacement,
47 int r_src)
buzbee67bf8852011-08-17 17:51:35 -070048{
buzbeefa57c472012-11-21 12:06:18 -080049 return StoreBaseDisp(cu, rBase, displacement, r_src, kWord);
buzbee67bf8852011-08-17 17:51:35 -070050}
51
52/*
53 * Load a Dalvik register into a physical register. Take care when
54 * using this routine, as it doesn't perform any bookkeeping regarding
55 * register liveness. That is the responsibility of the caller.
56 */
buzbeefa57c472012-11-21 12:06:18 -080057void LoadValueDirect(CompilationUnit* cu, RegLocation rl_src, int r_dest)
buzbee67bf8852011-08-17 17:51:35 -070058{
buzbeefa57c472012-11-21 12:06:18 -080059 rl_src = UpdateLoc(cu, rl_src);
60 if (rl_src.location == kLocPhysReg) {
61 OpRegCopy(cu, r_dest, rl_src.low_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -070062 } else {
buzbeefa57c472012-11-21 12:06:18 -080063 DCHECK((rl_src.location == kLocDalvikFrame) ||
64 (rl_src.location == kLocCompilerTemp));
65 LoadWordDisp(cu, TargetReg(kSp), SRegOffset(cu, rl_src.s_reg_low), r_dest);
Bill Buzbeea114add2012-05-03 15:00:40 -070066 }
buzbee67bf8852011-08-17 17:51:35 -070067}
68
69/*
buzbee52a77fc2012-11-20 19:50:46 -080070 * Similar to LoadValueDirect, but clobbers and allocates the target
buzbee67bf8852011-08-17 17:51:35 -070071 * register. Should be used when loading to a fixed register (for example,
72 * loading arguments to an out of line call.
73 */
buzbeefa57c472012-11-21 12:06:18 -080074void LoadValueDirectFixed(CompilationUnit* cu, RegLocation rl_src, int r_dest)
buzbee67bf8852011-08-17 17:51:35 -070075{
buzbeefa57c472012-11-21 12:06:18 -080076 Clobber(cu, r_dest);
77 MarkInUse(cu, r_dest);
78 LoadValueDirect(cu, rl_src, r_dest);
buzbee67bf8852011-08-17 17:51:35 -070079}
80
81/*
82 * Load a Dalvik register pair into a physical register[s]. Take care when
83 * using this routine, as it doesn't perform any bookkeeping regarding
84 * register liveness. That is the responsibility of the caller.
85 */
buzbeefa57c472012-11-21 12:06:18 -080086void LoadValueDirectWide(CompilationUnit* cu, RegLocation rl_src, int reg_lo,
87 int reg_hi)
buzbee67bf8852011-08-17 17:51:35 -070088{
buzbeefa57c472012-11-21 12:06:18 -080089 rl_src = UpdateLocWide(cu, rl_src);
90 if (rl_src.location == kLocPhysReg) {
91 OpRegCopyWide(cu, reg_lo, reg_hi, rl_src.low_reg, rl_src.high_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -070092 } else {
buzbeefa57c472012-11-21 12:06:18 -080093 DCHECK((rl_src.location == kLocDalvikFrame) ||
94 (rl_src.location == kLocCompilerTemp));
95 LoadBaseDispWide(cu, TargetReg(kSp), SRegOffset(cu, rl_src.s_reg_low),
96 reg_lo, reg_hi, INVALID_SREG);
Bill Buzbeea114add2012-05-03 15:00:40 -070097 }
buzbee67bf8852011-08-17 17:51:35 -070098}
99
100/*
buzbee52a77fc2012-11-20 19:50:46 -0800101 * Similar to LoadValueDirect, but clobbers and allocates the target
buzbee67bf8852011-08-17 17:51:35 -0700102 * registers. Should be used when loading to a fixed registers (for example,
103 * loading arguments to an out of line call.
104 */
buzbeefa57c472012-11-21 12:06:18 -0800105void LoadValueDirectWideFixed(CompilationUnit* cu, RegLocation rl_src,
106 int reg_lo, int reg_hi)
buzbee67bf8852011-08-17 17:51:35 -0700107{
buzbeefa57c472012-11-21 12:06:18 -0800108 Clobber(cu, reg_lo);
109 Clobber(cu, reg_hi);
110 MarkInUse(cu, reg_lo);
111 MarkInUse(cu, reg_hi);
112 LoadValueDirectWide(cu, rl_src, reg_lo, reg_hi);
buzbee67bf8852011-08-17 17:51:35 -0700113}
114
buzbeefa57c472012-11-21 12:06:18 -0800115RegLocation LoadValue(CompilationUnit* cu, RegLocation rl_src,
116 RegisterClass op_kind)
buzbee67bf8852011-08-17 17:51:35 -0700117{
buzbeefa57c472012-11-21 12:06:18 -0800118 rl_src = EvalLoc(cu, rl_src, op_kind, false);
119 if (rl_src.location != kLocPhysReg) {
120 DCHECK((rl_src.location == kLocDalvikFrame) ||
121 (rl_src.location == kLocCompilerTemp));
122 LoadValueDirect(cu, rl_src, rl_src.low_reg);
123 rl_src.location = kLocPhysReg;
124 MarkLive(cu, rl_src.low_reg, rl_src.s_reg_low);
Bill Buzbeea114add2012-05-03 15:00:40 -0700125 }
buzbeefa57c472012-11-21 12:06:18 -0800126 return rl_src;
buzbee67bf8852011-08-17 17:51:35 -0700127}
128
buzbeefa57c472012-11-21 12:06:18 -0800129void StoreValue(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src)
buzbee67bf8852011-08-17 17:51:35 -0700130{
buzbee3d661942012-03-14 17:37:27 -0700131#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700132 /*
133 * Sanity checking - should never try to store to the same
134 * ssa name during the compilation of a single instruction
buzbee52a77fc2012-11-20 19:50:46 -0800135 * without an intervening ClobberSReg().
Bill Buzbeea114add2012-05-03 15:00:40 -0700136 */
buzbeefa57c472012-11-21 12:06:18 -0800137 DCHECK((cu->live_sreg == INVALID_SREG) ||
138 (rl_dest.s_reg_low != cu->live_sreg));
139 cu->live_sreg = rl_dest.s_reg_low;
buzbee3d661942012-03-14 17:37:27 -0700140#endif
buzbeefa57c472012-11-21 12:06:18 -0800141 LIR* def_start;
142 LIR* def_end;
143 DCHECK(!rl_dest.wide);
144 DCHECK(!rl_src.wide);
145 rl_src = UpdateLoc(cu, rl_src);
146 rl_dest = UpdateLoc(cu, rl_dest);
147 if (rl_src.location == kLocPhysReg) {
148 if (IsLive(cu, rl_src.low_reg) ||
149 IsPromoted(cu, rl_src.low_reg) ||
150 (rl_dest.location == kLocPhysReg)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700151 // Src is live/promoted or Dest has assigned reg.
buzbeefa57c472012-11-21 12:06:18 -0800152 rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false);
153 OpRegCopy(cu, rl_dest.low_reg, rl_src.low_reg);
buzbee67bf8852011-08-17 17:51:35 -0700154 } else {
Bill Buzbeea114add2012-05-03 15:00:40 -0700155 // Just re-assign the registers. Dest gets Src's regs
buzbeefa57c472012-11-21 12:06:18 -0800156 rl_dest.low_reg = rl_src.low_reg;
157 Clobber(cu, rl_src.low_reg);
buzbee67bf8852011-08-17 17:51:35 -0700158 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700159 } else {
160 // Load Src either into promoted Dest or temps allocated for Dest
buzbeefa57c472012-11-21 12:06:18 -0800161 rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false);
162 LoadValueDirect(cu, rl_src, rl_dest.low_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700163 }
buzbee67bf8852011-08-17 17:51:35 -0700164
Bill Buzbeea114add2012-05-03 15:00:40 -0700165 // Dest is now live and dirty (until/if we flush it to home location)
buzbeefa57c472012-11-21 12:06:18 -0800166 MarkLive(cu, rl_dest.low_reg, rl_dest.s_reg_low);
167 MarkDirty(cu, rl_dest);
buzbee67bf8852011-08-17 17:51:35 -0700168
169
buzbeefa57c472012-11-21 12:06:18 -0800170 ResetDefLoc(cu, rl_dest);
171 if (IsDirty(cu, rl_dest.low_reg) &&
172 oat_live_out(cu, rl_dest.s_reg_low)) {
173 def_start = cu->last_lir_insn;
174 StoreBaseDisp(cu, TargetReg(kSp), SRegOffset(cu, rl_dest.s_reg_low),
175 rl_dest.low_reg, kWord);
176 MarkClean(cu, rl_dest);
177 def_end = cu->last_lir_insn;
178 MarkDef(cu, rl_dest, def_start, def_end);
Bill Buzbeea114add2012-05-03 15:00:40 -0700179 }
buzbee67bf8852011-08-17 17:51:35 -0700180}
181
buzbeefa57c472012-11-21 12:06:18 -0800182RegLocation LoadValueWide(CompilationUnit* cu, RegLocation rl_src,
183 RegisterClass op_kind)
buzbee67bf8852011-08-17 17:51:35 -0700184{
buzbeefa57c472012-11-21 12:06:18 -0800185 DCHECK(rl_src.wide);
186 rl_src = EvalLoc(cu, rl_src, op_kind, false);
187 if (rl_src.location != kLocPhysReg) {
188 DCHECK((rl_src.location == kLocDalvikFrame) ||
189 (rl_src.location == kLocCompilerTemp));
190 LoadValueDirectWide(cu, rl_src, rl_src.low_reg, rl_src.high_reg);
191 rl_src.location = kLocPhysReg;
192 MarkLive(cu, rl_src.low_reg, rl_src.s_reg_low);
193 MarkLive(cu, rl_src.high_reg,
194 GetSRegHi(rl_src.s_reg_low));
Bill Buzbeea114add2012-05-03 15:00:40 -0700195 }
buzbeefa57c472012-11-21 12:06:18 -0800196 return rl_src;
buzbee67bf8852011-08-17 17:51:35 -0700197}
198
buzbeefa57c472012-11-21 12:06:18 -0800199void StoreValueWide(CompilationUnit* cu, RegLocation rl_dest,
200 RegLocation rl_src)
buzbee67bf8852011-08-17 17:51:35 -0700201{
buzbee3d661942012-03-14 17:37:27 -0700202#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700203 /*
204 * Sanity checking - should never try to store to the same
205 * ssa name during the compilation of a single instruction
buzbee52a77fc2012-11-20 19:50:46 -0800206 * without an intervening ClobberSReg().
Bill Buzbeea114add2012-05-03 15:00:40 -0700207 */
buzbeefa57c472012-11-21 12:06:18 -0800208 DCHECK((cu->live_sreg == INVALID_SREG) ||
209 (rl_dest.s_reg_low != cu->live_sreg));
210 cu->live_sreg = rl_dest.s_reg_low;
buzbee3d661942012-03-14 17:37:27 -0700211#endif
buzbeefa57c472012-11-21 12:06:18 -0800212 LIR* def_start;
213 LIR* def_end;
214 DCHECK_EQ(FpReg(rl_src.low_reg), FpReg(rl_src.high_reg));
215 DCHECK(rl_dest.wide);
216 DCHECK(rl_src.wide);
217 if (rl_src.location == kLocPhysReg) {
218 if (IsLive(cu, rl_src.low_reg) ||
219 IsLive(cu, rl_src.high_reg) ||
220 IsPromoted(cu, rl_src.low_reg) ||
221 IsPromoted(cu, rl_src.high_reg) ||
222 (rl_dest.location == kLocPhysReg)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700223 // Src is live or promoted or Dest has assigned reg.
buzbeefa57c472012-11-21 12:06:18 -0800224 rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false);
225 OpRegCopyWide(cu, rl_dest.low_reg, rl_dest.high_reg,
226 rl_src.low_reg, rl_src.high_reg);
buzbee67bf8852011-08-17 17:51:35 -0700227 } else {
Bill Buzbeea114add2012-05-03 15:00:40 -0700228 // Just re-assign the registers. Dest gets Src's regs
buzbeefa57c472012-11-21 12:06:18 -0800229 rl_dest.low_reg = rl_src.low_reg;
230 rl_dest.high_reg = rl_src.high_reg;
231 Clobber(cu, rl_src.low_reg);
232 Clobber(cu, rl_src.high_reg);
buzbee67bf8852011-08-17 17:51:35 -0700233 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700234 } else {
235 // Load Src either into promoted Dest or temps allocated for Dest
buzbeefa57c472012-11-21 12:06:18 -0800236 rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false);
237 LoadValueDirectWide(cu, rl_src, rl_dest.low_reg, rl_dest.high_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700238 }
buzbee67bf8852011-08-17 17:51:35 -0700239
Bill Buzbeea114add2012-05-03 15:00:40 -0700240 // Dest is now live and dirty (until/if we flush it to home location)
buzbeefa57c472012-11-21 12:06:18 -0800241 MarkLive(cu, rl_dest.low_reg, rl_dest.s_reg_low);
242 MarkLive(cu, rl_dest.high_reg, GetSRegHi(rl_dest.s_reg_low));
243 MarkDirty(cu, rl_dest);
244 MarkPair(cu, rl_dest.low_reg, rl_dest.high_reg);
buzbee67bf8852011-08-17 17:51:35 -0700245
246
buzbeefa57c472012-11-21 12:06:18 -0800247 ResetDefLocWide(cu, rl_dest);
248 if ((IsDirty(cu, rl_dest.low_reg) ||
249 IsDirty(cu, rl_dest.high_reg)) &&
250 (oat_live_out(cu, rl_dest.s_reg_low) ||
251 oat_live_out(cu, GetSRegHi(rl_dest.s_reg_low)))) {
252 def_start = cu->last_lir_insn;
253 DCHECK_EQ((SRegToVReg(cu, rl_dest.s_reg_low)+1),
254 SRegToVReg(cu, GetSRegHi(rl_dest.s_reg_low)));
255 StoreBaseDispWide(cu, TargetReg(kSp), SRegOffset(cu, rl_dest.s_reg_low),
256 rl_dest.low_reg, rl_dest.high_reg);
257 MarkClean(cu, rl_dest);
258 def_end = cu->last_lir_insn;
259 MarkDefWide(cu, rl_dest, def_start, def_end);
Bill Buzbeea114add2012-05-03 15:00:40 -0700260 }
buzbee67bf8852011-08-17 17:51:35 -0700261}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800262
buzbeee1965672012-03-11 18:39:19 -0700263/* Utilities to load the current Method* */
buzbeefa57c472012-11-21 12:06:18 -0800264void LoadCurrMethodDirect(CompilationUnit *cu, int r_tgt)
buzbee31a4a6f2012-02-28 15:36:15 -0800265{
buzbeefa57c472012-11-21 12:06:18 -0800266 LoadValueDirectFixed(cu, cu->method_loc, r_tgt);
buzbee31a4a6f2012-02-28 15:36:15 -0800267}
268
buzbeefa57c472012-11-21 12:06:18 -0800269RegLocation LoadCurrMethod(CompilationUnit *cu)
buzbee31a4a6f2012-02-28 15:36:15 -0800270{
buzbeefa57c472012-11-21 12:06:18 -0800271 return LoadValue(cu, cu->method_loc, kCoreReg);
buzbee31a4a6f2012-02-28 15:36:15 -0800272}
273
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800274} // namespace art