blob: db844bcde946d1391f8fc68a92c350f4f33afac9 [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -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
Andreas Gampe0b9203e2015-01-22 20:39:27 -080017#include "mir_to_lir-inl.h"
18
Brian Carlstrom7940e442013-07-12 13:46:57 -070019#include "dex/compiler_ir.h"
Andreas Gampe0b9203e2015-01-22 20:39:27 -080020#include "dex/mir_graph.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070021#include "invoke_type.h"
22
23namespace art {
24
25/* This file contains target-independent codegen and support. */
26
27/*
28 * Load an immediate value into a fixed or temp register. Target
29 * register is clobbered, and marked in_use.
30 */
buzbee2700f7e2014-03-07 09:46:20 -080031LIR* Mir2Lir::LoadConstant(RegStorage r_dest, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070032 if (IsTemp(r_dest)) {
33 Clobber(r_dest);
34 MarkInUse(r_dest);
35 }
36 return LoadConstantNoClobber(r_dest, value);
37}
38
39/*
40 * Temporary workaround for Issue 7250540. If we're loading a constant zero into a
41 * promoted floating point register, also copy a zero into the int/ref identity of
42 * that sreg.
43 */
buzbee2700f7e2014-03-07 09:46:20 -080044void Mir2Lir::Workaround7250540(RegLocation rl_dest, RegStorage zero_reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070045 if (rl_dest.fp) {
46 int pmap_index = SRegToPMap(rl_dest.s_reg_low);
Vladimir0d5fd492015-02-11 14:11:19 +060047 const bool is_fp_promoted = promotion_map_[pmap_index].fp_location == kLocPhysReg;
48 const bool is_core_promoted = promotion_map_[pmap_index].core_location == kLocPhysReg;
49 if (is_fp_promoted || is_core_promoted) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070050 // Now, determine if this vreg is ever used as a reference. If not, we're done.
51 bool used_as_reference = false;
52 int base_vreg = mir_graph_->SRegToVReg(rl_dest.s_reg_low);
53 for (int i = 0; !used_as_reference && (i < mir_graph_->GetNumSSARegs()); i++) {
54 if (mir_graph_->SRegToVReg(mir_graph_->reg_location_[i].s_reg_low) == base_vreg) {
55 used_as_reference |= mir_graph_->reg_location_[i].ref;
56 }
57 }
58 if (!used_as_reference) {
59 return;
60 }
buzbee2700f7e2014-03-07 09:46:20 -080061 RegStorage temp_reg = zero_reg;
62 if (!temp_reg.Valid()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070063 temp_reg = AllocTemp();
64 LoadConstant(temp_reg, 0);
65 }
Vladimir0d5fd492015-02-11 14:11:19 +060066 if (is_core_promoted) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070067 // Promoted - just copy in a zero
buzbee2700f7e2014-03-07 09:46:20 -080068 OpRegCopy(RegStorage::Solo32(promotion_map_[pmap_index].core_reg), temp_reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -070069 } else {
70 // Lives in the frame, need to store.
Vladimir Marko8dea81c2014-06-06 14:50:36 +010071 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
Chao-ying Fua77ee512014-07-01 17:43:41 -070072 StoreBaseDisp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), temp_reg, k32, kNotVolatile);
Brian Carlstrom7940e442013-07-12 13:46:57 -070073 }
buzbee2700f7e2014-03-07 09:46:20 -080074 if (!zero_reg.Valid()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070075 FreeTemp(temp_reg);
76 }
77 }
78 }
79}
80
Brian Carlstrom7940e442013-07-12 13:46:57 -070081/*
82 * Load a Dalvik register into a physical register. 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 */
buzbee2700f7e2014-03-07 09:46:20 -080086void Mir2Lir::LoadValueDirect(RegLocation rl_src, RegStorage r_dest) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070087 rl_src = UpdateLoc(rl_src);
88 if (rl_src.location == kLocPhysReg) {
buzbee2700f7e2014-03-07 09:46:20 -080089 OpRegCopy(r_dest, rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -070090 } else if (IsInexpensiveConstant(rl_src)) {
buzbee695d13a2014-04-19 13:32:20 -070091 // On 64-bit targets, will sign extend. Make sure constant reference is always NULL.
92 DCHECK(!rl_src.ref || (mir_graph_->ConstantValue(rl_src) == 0));
Brian Carlstrom7940e442013-07-12 13:46:57 -070093 LoadConstantNoClobber(r_dest, mir_graph_->ConstantValue(rl_src));
94 } else {
95 DCHECK((rl_src.location == kLocDalvikFrame) ||
96 (rl_src.location == kLocCompilerTemp));
Vladimir Marko8dea81c2014-06-06 14:50:36 +010097 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
buzbee695d13a2014-04-19 13:32:20 -070098 if (rl_src.ref) {
Chao-ying Fua77ee512014-07-01 17:43:41 -070099 LoadRefDisp(TargetPtrReg(kSp), SRegOffset(rl_src.s_reg_low), r_dest, kNotVolatile);
buzbee695d13a2014-04-19 13:32:20 -0700100 } else {
Chao-ying Fua77ee512014-07-01 17:43:41 -0700101 Load32Disp(TargetPtrReg(kSp), SRegOffset(rl_src.s_reg_low), r_dest);
buzbee695d13a2014-04-19 13:32:20 -0700102 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700103 }
104}
105
106/*
107 * Similar to LoadValueDirect, but clobbers and allocates the target
108 * register. Should be used when loading to a fixed register (for example,
109 * loading arguments to an out of line call.
110 */
buzbee2700f7e2014-03-07 09:46:20 -0800111void Mir2Lir::LoadValueDirectFixed(RegLocation rl_src, RegStorage r_dest) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700112 Clobber(r_dest);
113 MarkInUse(r_dest);
114 LoadValueDirect(rl_src, r_dest);
115}
116
117/*
118 * Load a Dalvik register pair into a physical register[s]. Take care when
119 * using this routine, as it doesn't perform any bookkeeping regarding
120 * register liveness. That is the responsibility of the caller.
121 */
buzbee2700f7e2014-03-07 09:46:20 -0800122void Mir2Lir::LoadValueDirectWide(RegLocation rl_src, RegStorage r_dest) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700123 rl_src = UpdateLocWide(rl_src);
124 if (rl_src.location == kLocPhysReg) {
buzbee2700f7e2014-03-07 09:46:20 -0800125 OpRegCopyWide(r_dest, rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700126 } else if (IsInexpensiveConstant(rl_src)) {
buzbee2700f7e2014-03-07 09:46:20 -0800127 LoadConstantWide(r_dest, mir_graph_->ConstantValueWide(rl_src));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700128 } else {
129 DCHECK((rl_src.location == kLocDalvikFrame) ||
130 (rl_src.location == kLocCompilerTemp));
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100131 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
Chao-ying Fua77ee512014-07-01 17:43:41 -0700132 LoadBaseDisp(TargetPtrReg(kSp), SRegOffset(rl_src.s_reg_low), r_dest, k64, kNotVolatile);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700133 }
134}
135
136/*
137 * Similar to LoadValueDirect, but clobbers and allocates the target
138 * registers. Should be used when loading to a fixed registers (for example,
139 * loading arguments to an out of line call.
140 */
buzbee2700f7e2014-03-07 09:46:20 -0800141void Mir2Lir::LoadValueDirectWideFixed(RegLocation rl_src, RegStorage r_dest) {
142 Clobber(r_dest);
143 MarkInUse(r_dest);
144 LoadValueDirectWide(rl_src, r_dest);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700145}
146
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700147RegLocation Mir2Lir::LoadValue(RegLocation rl_src, RegisterClass op_kind) {
buzbeea0cd2d72014-06-01 09:33:49 -0700148 DCHECK(!rl_src.ref || op_kind == kRefReg);
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100149 rl_src = UpdateLoc(rl_src);
150 if (rl_src.location == kLocPhysReg) {
151 if (!RegClassMatches(op_kind, rl_src.reg)) {
152 // Wrong register class, realloc, copy and transfer ownership.
153 RegStorage new_reg = AllocTypedTemp(rl_src.fp, op_kind);
154 OpRegCopy(new_reg, rl_src.reg);
Serguei Katkov02c637e2014-10-29 13:48:02 +0600155 // Clobber the old regs and free it.
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100156 Clobber(rl_src.reg);
Serguei Katkov02c637e2014-10-29 13:48:02 +0600157 FreeTemp(rl_src.reg);
buzbee082833c2014-05-17 23:16:26 -0700158 // ...and mark the new one live.
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100159 rl_src.reg = new_reg;
buzbee082833c2014-05-17 23:16:26 -0700160 MarkLive(rl_src);
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100161 }
162 return rl_src;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700163 }
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100164
165 DCHECK_NE(rl_src.s_reg_low, INVALID_SREG);
166 rl_src.reg = AllocTypedTemp(rl_src.fp, op_kind);
167 LoadValueDirect(rl_src, rl_src.reg);
168 rl_src.location = kLocPhysReg;
169 MarkLive(rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700170 return rl_src;
171}
172
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700173void Mir2Lir::StoreValue(RegLocation rl_dest, RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700174 /*
175 * Sanity checking - should never try to store to the same
176 * ssa name during the compilation of a single instruction
177 * without an intervening ClobberSReg().
178 */
179 if (kIsDebugBuild) {
180 DCHECK((live_sreg_ == INVALID_SREG) ||
181 (rl_dest.s_reg_low != live_sreg_));
182 live_sreg_ = rl_dest.s_reg_low;
183 }
184 LIR* def_start;
185 LIR* def_end;
186 DCHECK(!rl_dest.wide);
187 DCHECK(!rl_src.wide);
188 rl_src = UpdateLoc(rl_src);
189 rl_dest = UpdateLoc(rl_dest);
190 if (rl_src.location == kLocPhysReg) {
buzbee2700f7e2014-03-07 09:46:20 -0800191 if (IsLive(rl_src.reg) ||
192 IsPromoted(rl_src.reg) ||
Brian Carlstrom7940e442013-07-12 13:46:57 -0700193 (rl_dest.location == kLocPhysReg)) {
194 // Src is live/promoted or Dest has assigned reg.
Andreas Gampe4b537a82014-06-30 22:24:53 -0700195 rl_dest = EvalLoc(rl_dest, rl_dest.ref || rl_src.ref ? kRefReg : kAnyReg, false);
buzbee2700f7e2014-03-07 09:46:20 -0800196 OpRegCopy(rl_dest.reg, rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700197 } else {
198 // Just re-assign the registers. Dest gets Src's regs
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000199 rl_dest.reg = rl_src.reg;
buzbee2700f7e2014-03-07 09:46:20 -0800200 Clobber(rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700201 }
202 } else {
203 // Load Src either into promoted Dest or temps allocated for Dest
Andreas Gampe4b537a82014-06-30 22:24:53 -0700204 rl_dest = EvalLoc(rl_dest, rl_dest.ref ? kRefReg : kAnyReg, false);
buzbee2700f7e2014-03-07 09:46:20 -0800205 LoadValueDirect(rl_src, rl_dest.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700206 }
207
208 // Dest is now live and dirty (until/if we flush it to home location)
buzbee091cc402014-03-31 10:14:40 -0700209 MarkLive(rl_dest);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700210 MarkDirty(rl_dest);
211
212
213 ResetDefLoc(rl_dest);
buzbee091cc402014-03-31 10:14:40 -0700214 if (IsDirty(rl_dest.reg) && LiveOut(rl_dest.s_reg_low)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700215 def_start = last_lir_insn_;
Ian Rogerse98297b2014-06-22 07:47:53 +0000216 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
Andreas Gampe2073e752014-06-23 15:39:00 +0000217 if (rl_dest.ref) {
Chao-ying Fua77ee512014-07-01 17:43:41 -0700218 StoreRefDisp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg, kNotVolatile);
Andreas Gampe2073e752014-06-23 15:39:00 +0000219 } else {
Chao-ying Fua77ee512014-07-01 17:43:41 -0700220 Store32Disp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg);
Andreas Gampe2073e752014-06-23 15:39:00 +0000221 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700222 MarkClean(rl_dest);
223 def_end = last_lir_insn_;
224 if (!rl_dest.ref) {
225 // Exclude references from store elimination
226 MarkDef(rl_dest, def_start, def_end);
227 }
228 }
229}
230
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700231RegLocation Mir2Lir::LoadValueWide(RegLocation rl_src, RegisterClass op_kind) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700232 DCHECK(rl_src.wide);
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100233 rl_src = UpdateLocWide(rl_src);
234 if (rl_src.location == kLocPhysReg) {
235 if (!RegClassMatches(op_kind, rl_src.reg)) {
236 // Wrong register class, realloc, copy and transfer ownership.
237 RegStorage new_regs = AllocTypedTempWide(rl_src.fp, op_kind);
238 OpRegCopyWide(new_regs, rl_src.reg);
Serguei Katkov02c637e2014-10-29 13:48:02 +0600239 // Clobber the old regs and free it.
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100240 Clobber(rl_src.reg);
Serguei Katkov02c637e2014-10-29 13:48:02 +0600241 FreeTemp(rl_src.reg);
buzbee082833c2014-05-17 23:16:26 -0700242 // ...and mark the new ones live.
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100243 rl_src.reg = new_regs;
buzbee082833c2014-05-17 23:16:26 -0700244 MarkLive(rl_src);
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100245 }
246 return rl_src;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700247 }
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100248
249 DCHECK_NE(rl_src.s_reg_low, INVALID_SREG);
250 DCHECK_NE(GetSRegHi(rl_src.s_reg_low), INVALID_SREG);
251 rl_src.reg = AllocTypedTempWide(rl_src.fp, op_kind);
252 LoadValueDirectWide(rl_src, rl_src.reg);
253 rl_src.location = kLocPhysReg;
254 MarkLive(rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700255 return rl_src;
256}
257
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700258void Mir2Lir::StoreValueWide(RegLocation rl_dest, RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700259 /*
260 * Sanity checking - should never try to store to the same
261 * ssa name during the compilation of a single instruction
262 * without an intervening ClobberSReg().
263 */
264 if (kIsDebugBuild) {
265 DCHECK((live_sreg_ == INVALID_SREG) ||
266 (rl_dest.s_reg_low != live_sreg_));
267 live_sreg_ = rl_dest.s_reg_low;
268 }
269 LIR* def_start;
270 LIR* def_end;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700271 DCHECK(rl_dest.wide);
272 DCHECK(rl_src.wide);
Alexei Zavjalovc17ebe82014-02-26 10:38:23 +0700273 rl_src = UpdateLocWide(rl_src);
274 rl_dest = UpdateLocWide(rl_dest);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700275 if (rl_src.location == kLocPhysReg) {
buzbee2700f7e2014-03-07 09:46:20 -0800276 if (IsLive(rl_src.reg) ||
277 IsPromoted(rl_src.reg) ||
Brian Carlstrom7940e442013-07-12 13:46:57 -0700278 (rl_dest.location == kLocPhysReg)) {
buzbee30adc732014-05-09 15:10:18 -0700279 /*
280 * If src reg[s] are tied to the original Dalvik vreg via liveness or promotion, we
281 * can't repurpose them. Similarly, if the dest reg[s] are tied to Dalvik vregs via
282 * promotion, we can't just re-assign. In these cases, we have to copy.
283 */
Brian Carlstrom7940e442013-07-12 13:46:57 -0700284 rl_dest = EvalLoc(rl_dest, kAnyReg, false);
buzbee2700f7e2014-03-07 09:46:20 -0800285 OpRegCopyWide(rl_dest.reg, rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700286 } else {
287 // Just re-assign the registers. Dest gets Src's regs
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000288 rl_dest.reg = rl_src.reg;
buzbee2700f7e2014-03-07 09:46:20 -0800289 Clobber(rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700290 }
291 } else {
292 // Load Src either into promoted Dest or temps allocated for Dest
293 rl_dest = EvalLoc(rl_dest, kAnyReg, false);
buzbee2700f7e2014-03-07 09:46:20 -0800294 LoadValueDirectWide(rl_src, rl_dest.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700295 }
296
297 // Dest is now live and dirty (until/if we flush it to home location)
buzbee091cc402014-03-31 10:14:40 -0700298 MarkLive(rl_dest);
299 MarkWide(rl_dest.reg);
300 MarkDirty(rl_dest);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700301
302 ResetDefLocWide(rl_dest);
buzbee091cc402014-03-31 10:14:40 -0700303 if (IsDirty(rl_dest.reg) && (LiveOut(rl_dest.s_reg_low) ||
304 LiveOut(GetSRegHi(rl_dest.s_reg_low)))) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700305 def_start = last_lir_insn_;
306 DCHECK_EQ((mir_graph_->SRegToVReg(rl_dest.s_reg_low)+1),
307 mir_graph_->SRegToVReg(GetSRegHi(rl_dest.s_reg_low)));
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100308 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
Chao-ying Fua77ee512014-07-01 17:43:41 -0700309 StoreBaseDisp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg, k64, kNotVolatile);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700310 MarkClean(rl_dest);
311 def_end = last_lir_insn_;
312 MarkDefWide(rl_dest, def_start, def_end);
313 }
314}
315
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800316void Mir2Lir::StoreFinalValue(RegLocation rl_dest, RegLocation rl_src) {
317 DCHECK_EQ(rl_src.location, kLocPhysReg);
318
319 if (rl_dest.location == kLocPhysReg) {
buzbee2700f7e2014-03-07 09:46:20 -0800320 OpRegCopy(rl_dest.reg, rl_src.reg);
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800321 } else {
322 // Just re-assign the register. Dest gets Src's reg.
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800323 rl_dest.location = kLocPhysReg;
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000324 rl_dest.reg = rl_src.reg;
buzbee2700f7e2014-03-07 09:46:20 -0800325 Clobber(rl_src.reg);
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800326 }
327
328 // Dest is now live and dirty (until/if we flush it to home location)
buzbee091cc402014-03-31 10:14:40 -0700329 MarkLive(rl_dest);
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800330 MarkDirty(rl_dest);
331
332
333 ResetDefLoc(rl_dest);
buzbee091cc402014-03-31 10:14:40 -0700334 if (IsDirty(rl_dest.reg) && LiveOut(rl_dest.s_reg_low)) {
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800335 LIR *def_start = last_lir_insn_;
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100336 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
Chao-ying Fua77ee512014-07-01 17:43:41 -0700337 Store32Disp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg);
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800338 MarkClean(rl_dest);
339 LIR *def_end = last_lir_insn_;
340 if (!rl_dest.ref) {
341 // Exclude references from store elimination
342 MarkDef(rl_dest, def_start, def_end);
343 }
344 }
345}
346
Mark Mendelle02d48f2014-01-15 11:19:23 -0800347void Mir2Lir::StoreFinalValueWide(RegLocation rl_dest, RegLocation rl_src) {
Mark Mendelle02d48f2014-01-15 11:19:23 -0800348 DCHECK(rl_dest.wide);
349 DCHECK(rl_src.wide);
350 DCHECK_EQ(rl_src.location, kLocPhysReg);
351
352 if (rl_dest.location == kLocPhysReg) {
buzbee2700f7e2014-03-07 09:46:20 -0800353 OpRegCopyWide(rl_dest.reg, rl_src.reg);
Mark Mendelle02d48f2014-01-15 11:19:23 -0800354 } else {
355 // Just re-assign the registers. Dest gets Src's regs.
Mark Mendelle02d48f2014-01-15 11:19:23 -0800356 rl_dest.location = kLocPhysReg;
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000357 rl_dest.reg = rl_src.reg;
buzbee091cc402014-03-31 10:14:40 -0700358 Clobber(rl_src.reg);
Mark Mendelle02d48f2014-01-15 11:19:23 -0800359 }
360
361 // Dest is now live and dirty (until/if we flush it to home location).
buzbee091cc402014-03-31 10:14:40 -0700362 MarkLive(rl_dest);
363 MarkWide(rl_dest.reg);
364 MarkDirty(rl_dest);
Mark Mendelle02d48f2014-01-15 11:19:23 -0800365
366 ResetDefLocWide(rl_dest);
buzbee091cc402014-03-31 10:14:40 -0700367 if (IsDirty(rl_dest.reg) && (LiveOut(rl_dest.s_reg_low) ||
368 LiveOut(GetSRegHi(rl_dest.s_reg_low)))) {
Mark Mendelle02d48f2014-01-15 11:19:23 -0800369 LIR *def_start = last_lir_insn_;
370 DCHECK_EQ((mir_graph_->SRegToVReg(rl_dest.s_reg_low)+1),
371 mir_graph_->SRegToVReg(GetSRegHi(rl_dest.s_reg_low)));
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100372 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
Chao-ying Fua77ee512014-07-01 17:43:41 -0700373 StoreBaseDisp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg, k64, kNotVolatile);
Mark Mendelle02d48f2014-01-15 11:19:23 -0800374 MarkClean(rl_dest);
375 LIR *def_end = last_lir_insn_;
376 MarkDefWide(rl_dest, def_start, def_end);
377 }
378}
379
Brian Carlstrom7940e442013-07-12 13:46:57 -0700380/* Utilities to load the current Method* */
buzbee2700f7e2014-03-07 09:46:20 -0800381void Mir2Lir::LoadCurrMethodDirect(RegStorage r_tgt) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700382 LoadValueDirectFixed(mir_graph_->GetMethodLoc(), r_tgt);
383}
384
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700385RegLocation Mir2Lir::LoadCurrMethod() {
buzbeea0cd2d72014-06-01 09:33:49 -0700386 return LoadValue(mir_graph_->GetMethodLoc(), kRefReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700387}
388
Mark Mendelle02d48f2014-01-15 11:19:23 -0800389RegLocation Mir2Lir::ForceTemp(RegLocation loc) {
390 DCHECK(!loc.wide);
391 DCHECK(loc.location == kLocPhysReg);
buzbee091cc402014-03-31 10:14:40 -0700392 DCHECK(!loc.reg.IsFloat());
buzbee2700f7e2014-03-07 09:46:20 -0800393 if (IsTemp(loc.reg)) {
394 Clobber(loc.reg);
Mark Mendelle02d48f2014-01-15 11:19:23 -0800395 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800396 RegStorage temp_low = AllocTemp();
397 OpRegCopy(temp_low, loc.reg);
398 loc.reg = temp_low;
Mark Mendelle02d48f2014-01-15 11:19:23 -0800399 }
400
401 // Ensure that this doesn't represent the original SR any more.
402 loc.s_reg_low = INVALID_SREG;
403 return loc;
404}
405
406RegLocation Mir2Lir::ForceTempWide(RegLocation loc) {
407 DCHECK(loc.wide);
408 DCHECK(loc.location == kLocPhysReg);
buzbee091cc402014-03-31 10:14:40 -0700409 DCHECK(!loc.reg.IsFloat());
Chao-ying Fue0ccdc02014-06-06 17:32:37 -0700410
411 if (!loc.reg.IsPair()) {
412 if (IsTemp(loc.reg)) {
413 Clobber(loc.reg);
414 } else {
415 RegStorage temp = AllocTempWide();
416 OpRegCopy(temp, loc.reg);
417 loc.reg = temp;
418 }
Mark Mendelle02d48f2014-01-15 11:19:23 -0800419 } else {
Chao-ying Fue0ccdc02014-06-06 17:32:37 -0700420 if (IsTemp(loc.reg.GetLow())) {
421 Clobber(loc.reg.GetLow());
422 } else {
423 RegStorage temp_low = AllocTemp();
424 OpRegCopy(temp_low, loc.reg.GetLow());
425 loc.reg.SetLowReg(temp_low.GetReg());
426 }
427 if (IsTemp(loc.reg.GetHigh())) {
428 Clobber(loc.reg.GetHigh());
429 } else {
430 RegStorage temp_high = AllocTemp();
431 OpRegCopy(temp_high, loc.reg.GetHigh());
432 loc.reg.SetHighReg(temp_high.GetReg());
433 }
Mark Mendelle02d48f2014-01-15 11:19:23 -0800434 }
435
436 // Ensure that this doesn't represent the original SR any more.
437 loc.s_reg_low = INVALID_SREG;
438 return loc;
439}
440
Brian Carlstrom7940e442013-07-12 13:46:57 -0700441} // namespace art