blob: 9f36e35f5e2940d03ce1a36a21de516118f55d32 [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);
47 if (promotion_map_[pmap_index].fp_location == kLocPhysReg) {
48 // Now, determine if this vreg is ever used as a reference. If not, we're done.
49 bool used_as_reference = false;
50 int base_vreg = mir_graph_->SRegToVReg(rl_dest.s_reg_low);
51 for (int i = 0; !used_as_reference && (i < mir_graph_->GetNumSSARegs()); i++) {
52 if (mir_graph_->SRegToVReg(mir_graph_->reg_location_[i].s_reg_low) == base_vreg) {
53 used_as_reference |= mir_graph_->reg_location_[i].ref;
54 }
55 }
56 if (!used_as_reference) {
57 return;
58 }
buzbee2700f7e2014-03-07 09:46:20 -080059 RegStorage temp_reg = zero_reg;
60 if (!temp_reg.Valid()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070061 temp_reg = AllocTemp();
62 LoadConstant(temp_reg, 0);
63 }
64 if (promotion_map_[pmap_index].core_location == kLocPhysReg) {
65 // Promoted - just copy in a zero
buzbee2700f7e2014-03-07 09:46:20 -080066 OpRegCopy(RegStorage::Solo32(promotion_map_[pmap_index].core_reg), temp_reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -070067 } else {
68 // Lives in the frame, need to store.
Vladimir Marko8dea81c2014-06-06 14:50:36 +010069 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
Chao-ying Fua77ee512014-07-01 17:43:41 -070070 StoreBaseDisp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), temp_reg, k32, kNotVolatile);
Brian Carlstrom7940e442013-07-12 13:46:57 -070071 }
buzbee2700f7e2014-03-07 09:46:20 -080072 if (!zero_reg.Valid()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070073 FreeTemp(temp_reg);
74 }
75 }
76 }
77}
78
Brian Carlstrom7940e442013-07-12 13:46:57 -070079/*
80 * Load a Dalvik register into a physical register. 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 */
buzbee2700f7e2014-03-07 09:46:20 -080084void Mir2Lir::LoadValueDirect(RegLocation rl_src, RegStorage r_dest) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070085 rl_src = UpdateLoc(rl_src);
86 if (rl_src.location == kLocPhysReg) {
buzbee2700f7e2014-03-07 09:46:20 -080087 OpRegCopy(r_dest, rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -070088 } else if (IsInexpensiveConstant(rl_src)) {
buzbee695d13a2014-04-19 13:32:20 -070089 // On 64-bit targets, will sign extend. Make sure constant reference is always NULL.
90 DCHECK(!rl_src.ref || (mir_graph_->ConstantValue(rl_src) == 0));
Brian Carlstrom7940e442013-07-12 13:46:57 -070091 LoadConstantNoClobber(r_dest, mir_graph_->ConstantValue(rl_src));
92 } else {
93 DCHECK((rl_src.location == kLocDalvikFrame) ||
94 (rl_src.location == kLocCompilerTemp));
Vladimir Marko8dea81c2014-06-06 14:50:36 +010095 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
buzbee695d13a2014-04-19 13:32:20 -070096 if (rl_src.ref) {
Chao-ying Fua77ee512014-07-01 17:43:41 -070097 LoadRefDisp(TargetPtrReg(kSp), SRegOffset(rl_src.s_reg_low), r_dest, kNotVolatile);
buzbee695d13a2014-04-19 13:32:20 -070098 } else {
Chao-ying Fua77ee512014-07-01 17:43:41 -070099 Load32Disp(TargetPtrReg(kSp), SRegOffset(rl_src.s_reg_low), r_dest);
buzbee695d13a2014-04-19 13:32:20 -0700100 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700101 }
102}
103
104/*
105 * Similar to LoadValueDirect, but clobbers and allocates the target
106 * register. Should be used when loading to a fixed register (for example,
107 * loading arguments to an out of line call.
108 */
buzbee2700f7e2014-03-07 09:46:20 -0800109void Mir2Lir::LoadValueDirectFixed(RegLocation rl_src, RegStorage r_dest) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700110 Clobber(r_dest);
111 MarkInUse(r_dest);
112 LoadValueDirect(rl_src, r_dest);
113}
114
115/*
116 * Load a Dalvik register pair into a physical register[s]. Take care when
117 * using this routine, as it doesn't perform any bookkeeping regarding
118 * register liveness. That is the responsibility of the caller.
119 */
buzbee2700f7e2014-03-07 09:46:20 -0800120void Mir2Lir::LoadValueDirectWide(RegLocation rl_src, RegStorage r_dest) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700121 rl_src = UpdateLocWide(rl_src);
122 if (rl_src.location == kLocPhysReg) {
buzbee2700f7e2014-03-07 09:46:20 -0800123 OpRegCopyWide(r_dest, rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700124 } else if (IsInexpensiveConstant(rl_src)) {
buzbee2700f7e2014-03-07 09:46:20 -0800125 LoadConstantWide(r_dest, mir_graph_->ConstantValueWide(rl_src));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700126 } else {
127 DCHECK((rl_src.location == kLocDalvikFrame) ||
128 (rl_src.location == kLocCompilerTemp));
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100129 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
Chao-ying Fua77ee512014-07-01 17:43:41 -0700130 LoadBaseDisp(TargetPtrReg(kSp), SRegOffset(rl_src.s_reg_low), r_dest, k64, kNotVolatile);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700131 }
132}
133
134/*
135 * Similar to LoadValueDirect, but clobbers and allocates the target
136 * registers. Should be used when loading to a fixed registers (for example,
137 * loading arguments to an out of line call.
138 */
buzbee2700f7e2014-03-07 09:46:20 -0800139void Mir2Lir::LoadValueDirectWideFixed(RegLocation rl_src, RegStorage r_dest) {
140 Clobber(r_dest);
141 MarkInUse(r_dest);
142 LoadValueDirectWide(rl_src, r_dest);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700143}
144
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700145RegLocation Mir2Lir::LoadValue(RegLocation rl_src, RegisterClass op_kind) {
buzbeea0cd2d72014-06-01 09:33:49 -0700146 DCHECK(!rl_src.ref || op_kind == kRefReg);
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100147 rl_src = UpdateLoc(rl_src);
148 if (rl_src.location == kLocPhysReg) {
149 if (!RegClassMatches(op_kind, rl_src.reg)) {
150 // Wrong register class, realloc, copy and transfer ownership.
151 RegStorage new_reg = AllocTypedTemp(rl_src.fp, op_kind);
152 OpRegCopy(new_reg, rl_src.reg);
Serguei Katkov02c637e2014-10-29 13:48:02 +0600153 // Clobber the old regs and free it.
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100154 Clobber(rl_src.reg);
Serguei Katkov02c637e2014-10-29 13:48:02 +0600155 FreeTemp(rl_src.reg);
buzbee082833c2014-05-17 23:16:26 -0700156 // ...and mark the new one live.
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100157 rl_src.reg = new_reg;
buzbee082833c2014-05-17 23:16:26 -0700158 MarkLive(rl_src);
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100159 }
160 return rl_src;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700161 }
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100162
163 DCHECK_NE(rl_src.s_reg_low, INVALID_SREG);
164 rl_src.reg = AllocTypedTemp(rl_src.fp, op_kind);
165 LoadValueDirect(rl_src, rl_src.reg);
166 rl_src.location = kLocPhysReg;
167 MarkLive(rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700168 return rl_src;
169}
170
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700171void Mir2Lir::StoreValue(RegLocation rl_dest, RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700172 /*
173 * Sanity checking - should never try to store to the same
174 * ssa name during the compilation of a single instruction
175 * without an intervening ClobberSReg().
176 */
177 if (kIsDebugBuild) {
178 DCHECK((live_sreg_ == INVALID_SREG) ||
179 (rl_dest.s_reg_low != live_sreg_));
180 live_sreg_ = rl_dest.s_reg_low;
181 }
182 LIR* def_start;
183 LIR* def_end;
184 DCHECK(!rl_dest.wide);
185 DCHECK(!rl_src.wide);
186 rl_src = UpdateLoc(rl_src);
187 rl_dest = UpdateLoc(rl_dest);
188 if (rl_src.location == kLocPhysReg) {
buzbee2700f7e2014-03-07 09:46:20 -0800189 if (IsLive(rl_src.reg) ||
190 IsPromoted(rl_src.reg) ||
Brian Carlstrom7940e442013-07-12 13:46:57 -0700191 (rl_dest.location == kLocPhysReg)) {
192 // Src is live/promoted or Dest has assigned reg.
Andreas Gampe4b537a82014-06-30 22:24:53 -0700193 rl_dest = EvalLoc(rl_dest, rl_dest.ref || rl_src.ref ? kRefReg : kAnyReg, false);
buzbee2700f7e2014-03-07 09:46:20 -0800194 OpRegCopy(rl_dest.reg, rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700195 } else {
196 // Just re-assign the registers. Dest gets Src's regs
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000197 rl_dest.reg = rl_src.reg;
buzbee2700f7e2014-03-07 09:46:20 -0800198 Clobber(rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700199 }
200 } else {
201 // Load Src either into promoted Dest or temps allocated for Dest
Andreas Gampe4b537a82014-06-30 22:24:53 -0700202 rl_dest = EvalLoc(rl_dest, rl_dest.ref ? kRefReg : kAnyReg, false);
buzbee2700f7e2014-03-07 09:46:20 -0800203 LoadValueDirect(rl_src, rl_dest.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700204 }
205
206 // Dest is now live and dirty (until/if we flush it to home location)
buzbee091cc402014-03-31 10:14:40 -0700207 MarkLive(rl_dest);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700208 MarkDirty(rl_dest);
209
210
211 ResetDefLoc(rl_dest);
buzbee091cc402014-03-31 10:14:40 -0700212 if (IsDirty(rl_dest.reg) && LiveOut(rl_dest.s_reg_low)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700213 def_start = last_lir_insn_;
Ian Rogerse98297b2014-06-22 07:47:53 +0000214 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
Andreas Gampe2073e752014-06-23 15:39:00 +0000215 if (rl_dest.ref) {
Chao-ying Fua77ee512014-07-01 17:43:41 -0700216 StoreRefDisp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg, kNotVolatile);
Andreas Gampe2073e752014-06-23 15:39:00 +0000217 } else {
Chao-ying Fua77ee512014-07-01 17:43:41 -0700218 Store32Disp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg);
Andreas Gampe2073e752014-06-23 15:39:00 +0000219 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700220 MarkClean(rl_dest);
221 def_end = last_lir_insn_;
222 if (!rl_dest.ref) {
223 // Exclude references from store elimination
224 MarkDef(rl_dest, def_start, def_end);
225 }
226 }
227}
228
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700229RegLocation Mir2Lir::LoadValueWide(RegLocation rl_src, RegisterClass op_kind) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700230 DCHECK(rl_src.wide);
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100231 rl_src = UpdateLocWide(rl_src);
232 if (rl_src.location == kLocPhysReg) {
233 if (!RegClassMatches(op_kind, rl_src.reg)) {
234 // Wrong register class, realloc, copy and transfer ownership.
235 RegStorage new_regs = AllocTypedTempWide(rl_src.fp, op_kind);
236 OpRegCopyWide(new_regs, rl_src.reg);
Serguei Katkov02c637e2014-10-29 13:48:02 +0600237 // Clobber the old regs and free it.
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100238 Clobber(rl_src.reg);
Serguei Katkov02c637e2014-10-29 13:48:02 +0600239 FreeTemp(rl_src.reg);
buzbee082833c2014-05-17 23:16:26 -0700240 // ...and mark the new ones live.
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100241 rl_src.reg = new_regs;
buzbee082833c2014-05-17 23:16:26 -0700242 MarkLive(rl_src);
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100243 }
244 return rl_src;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700245 }
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100246
247 DCHECK_NE(rl_src.s_reg_low, INVALID_SREG);
248 DCHECK_NE(GetSRegHi(rl_src.s_reg_low), INVALID_SREG);
249 rl_src.reg = AllocTypedTempWide(rl_src.fp, op_kind);
250 LoadValueDirectWide(rl_src, rl_src.reg);
251 rl_src.location = kLocPhysReg;
252 MarkLive(rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700253 return rl_src;
254}
255
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700256void Mir2Lir::StoreValueWide(RegLocation rl_dest, RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700257 /*
258 * Sanity checking - should never try to store to the same
259 * ssa name during the compilation of a single instruction
260 * without an intervening ClobberSReg().
261 */
262 if (kIsDebugBuild) {
263 DCHECK((live_sreg_ == INVALID_SREG) ||
264 (rl_dest.s_reg_low != live_sreg_));
265 live_sreg_ = rl_dest.s_reg_low;
266 }
267 LIR* def_start;
268 LIR* def_end;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700269 DCHECK(rl_dest.wide);
270 DCHECK(rl_src.wide);
Alexei Zavjalovc17ebe82014-02-26 10:38:23 +0700271 rl_src = UpdateLocWide(rl_src);
272 rl_dest = UpdateLocWide(rl_dest);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700273 if (rl_src.location == kLocPhysReg) {
buzbee2700f7e2014-03-07 09:46:20 -0800274 if (IsLive(rl_src.reg) ||
275 IsPromoted(rl_src.reg) ||
Brian Carlstrom7940e442013-07-12 13:46:57 -0700276 (rl_dest.location == kLocPhysReg)) {
buzbee30adc732014-05-09 15:10:18 -0700277 /*
278 * If src reg[s] are tied to the original Dalvik vreg via liveness or promotion, we
279 * can't repurpose them. Similarly, if the dest reg[s] are tied to Dalvik vregs via
280 * promotion, we can't just re-assign. In these cases, we have to copy.
281 */
Brian Carlstrom7940e442013-07-12 13:46:57 -0700282 rl_dest = EvalLoc(rl_dest, kAnyReg, false);
buzbee2700f7e2014-03-07 09:46:20 -0800283 OpRegCopyWide(rl_dest.reg, rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700284 } else {
285 // Just re-assign the registers. Dest gets Src's regs
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000286 rl_dest.reg = rl_src.reg;
buzbee2700f7e2014-03-07 09:46:20 -0800287 Clobber(rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700288 }
289 } else {
290 // Load Src either into promoted Dest or temps allocated for Dest
291 rl_dest = EvalLoc(rl_dest, kAnyReg, false);
buzbee2700f7e2014-03-07 09:46:20 -0800292 LoadValueDirectWide(rl_src, rl_dest.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700293 }
294
295 // Dest is now live and dirty (until/if we flush it to home location)
buzbee091cc402014-03-31 10:14:40 -0700296 MarkLive(rl_dest);
297 MarkWide(rl_dest.reg);
298 MarkDirty(rl_dest);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700299
300 ResetDefLocWide(rl_dest);
buzbee091cc402014-03-31 10:14:40 -0700301 if (IsDirty(rl_dest.reg) && (LiveOut(rl_dest.s_reg_low) ||
302 LiveOut(GetSRegHi(rl_dest.s_reg_low)))) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700303 def_start = last_lir_insn_;
304 DCHECK_EQ((mir_graph_->SRegToVReg(rl_dest.s_reg_low)+1),
305 mir_graph_->SRegToVReg(GetSRegHi(rl_dest.s_reg_low)));
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100306 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
Chao-ying Fua77ee512014-07-01 17:43:41 -0700307 StoreBaseDisp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg, k64, kNotVolatile);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700308 MarkClean(rl_dest);
309 def_end = last_lir_insn_;
310 MarkDefWide(rl_dest, def_start, def_end);
311 }
312}
313
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800314void Mir2Lir::StoreFinalValue(RegLocation rl_dest, RegLocation rl_src) {
315 DCHECK_EQ(rl_src.location, kLocPhysReg);
316
317 if (rl_dest.location == kLocPhysReg) {
buzbee2700f7e2014-03-07 09:46:20 -0800318 OpRegCopy(rl_dest.reg, rl_src.reg);
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800319 } else {
320 // Just re-assign the register. Dest gets Src's reg.
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800321 rl_dest.location = kLocPhysReg;
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000322 rl_dest.reg = rl_src.reg;
buzbee2700f7e2014-03-07 09:46:20 -0800323 Clobber(rl_src.reg);
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800324 }
325
326 // Dest is now live and dirty (until/if we flush it to home location)
buzbee091cc402014-03-31 10:14:40 -0700327 MarkLive(rl_dest);
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800328 MarkDirty(rl_dest);
329
330
331 ResetDefLoc(rl_dest);
buzbee091cc402014-03-31 10:14:40 -0700332 if (IsDirty(rl_dest.reg) && LiveOut(rl_dest.s_reg_low)) {
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800333 LIR *def_start = last_lir_insn_;
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100334 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
Chao-ying Fua77ee512014-07-01 17:43:41 -0700335 Store32Disp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg);
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800336 MarkClean(rl_dest);
337 LIR *def_end = last_lir_insn_;
338 if (!rl_dest.ref) {
339 // Exclude references from store elimination
340 MarkDef(rl_dest, def_start, def_end);
341 }
342 }
343}
344
Mark Mendelle02d48f2014-01-15 11:19:23 -0800345void Mir2Lir::StoreFinalValueWide(RegLocation rl_dest, RegLocation rl_src) {
Mark Mendelle02d48f2014-01-15 11:19:23 -0800346 DCHECK(rl_dest.wide);
347 DCHECK(rl_src.wide);
348 DCHECK_EQ(rl_src.location, kLocPhysReg);
349
350 if (rl_dest.location == kLocPhysReg) {
buzbee2700f7e2014-03-07 09:46:20 -0800351 OpRegCopyWide(rl_dest.reg, rl_src.reg);
Mark Mendelle02d48f2014-01-15 11:19:23 -0800352 } else {
353 // Just re-assign the registers. Dest gets Src's regs.
Mark Mendelle02d48f2014-01-15 11:19:23 -0800354 rl_dest.location = kLocPhysReg;
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000355 rl_dest.reg = rl_src.reg;
buzbee091cc402014-03-31 10:14:40 -0700356 Clobber(rl_src.reg);
Mark Mendelle02d48f2014-01-15 11:19:23 -0800357 }
358
359 // Dest is now live and dirty (until/if we flush it to home location).
buzbee091cc402014-03-31 10:14:40 -0700360 MarkLive(rl_dest);
361 MarkWide(rl_dest.reg);
362 MarkDirty(rl_dest);
Mark Mendelle02d48f2014-01-15 11:19:23 -0800363
364 ResetDefLocWide(rl_dest);
buzbee091cc402014-03-31 10:14:40 -0700365 if (IsDirty(rl_dest.reg) && (LiveOut(rl_dest.s_reg_low) ||
366 LiveOut(GetSRegHi(rl_dest.s_reg_low)))) {
Mark Mendelle02d48f2014-01-15 11:19:23 -0800367 LIR *def_start = last_lir_insn_;
368 DCHECK_EQ((mir_graph_->SRegToVReg(rl_dest.s_reg_low)+1),
369 mir_graph_->SRegToVReg(GetSRegHi(rl_dest.s_reg_low)));
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100370 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
Chao-ying Fua77ee512014-07-01 17:43:41 -0700371 StoreBaseDisp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg, k64, kNotVolatile);
Mark Mendelle02d48f2014-01-15 11:19:23 -0800372 MarkClean(rl_dest);
373 LIR *def_end = last_lir_insn_;
374 MarkDefWide(rl_dest, def_start, def_end);
375 }
376}
377
Brian Carlstrom7940e442013-07-12 13:46:57 -0700378/* Utilities to load the current Method* */
buzbee2700f7e2014-03-07 09:46:20 -0800379void Mir2Lir::LoadCurrMethodDirect(RegStorage r_tgt) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700380 LoadValueDirectFixed(mir_graph_->GetMethodLoc(), r_tgt);
381}
382
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700383RegLocation Mir2Lir::LoadCurrMethod() {
buzbeea0cd2d72014-06-01 09:33:49 -0700384 return LoadValue(mir_graph_->GetMethodLoc(), kRefReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700385}
386
Mark Mendelle02d48f2014-01-15 11:19:23 -0800387RegLocation Mir2Lir::ForceTemp(RegLocation loc) {
388 DCHECK(!loc.wide);
389 DCHECK(loc.location == kLocPhysReg);
buzbee091cc402014-03-31 10:14:40 -0700390 DCHECK(!loc.reg.IsFloat());
buzbee2700f7e2014-03-07 09:46:20 -0800391 if (IsTemp(loc.reg)) {
392 Clobber(loc.reg);
Mark Mendelle02d48f2014-01-15 11:19:23 -0800393 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800394 RegStorage temp_low = AllocTemp();
395 OpRegCopy(temp_low, loc.reg);
396 loc.reg = temp_low;
Mark Mendelle02d48f2014-01-15 11:19:23 -0800397 }
398
399 // Ensure that this doesn't represent the original SR any more.
400 loc.s_reg_low = INVALID_SREG;
401 return loc;
402}
403
404RegLocation Mir2Lir::ForceTempWide(RegLocation loc) {
405 DCHECK(loc.wide);
406 DCHECK(loc.location == kLocPhysReg);
buzbee091cc402014-03-31 10:14:40 -0700407 DCHECK(!loc.reg.IsFloat());
Chao-ying Fue0ccdc02014-06-06 17:32:37 -0700408
409 if (!loc.reg.IsPair()) {
410 if (IsTemp(loc.reg)) {
411 Clobber(loc.reg);
412 } else {
413 RegStorage temp = AllocTempWide();
414 OpRegCopy(temp, loc.reg);
415 loc.reg = temp;
416 }
Mark Mendelle02d48f2014-01-15 11:19:23 -0800417 } else {
Chao-ying Fue0ccdc02014-06-06 17:32:37 -0700418 if (IsTemp(loc.reg.GetLow())) {
419 Clobber(loc.reg.GetLow());
420 } else {
421 RegStorage temp_low = AllocTemp();
422 OpRegCopy(temp_low, loc.reg.GetLow());
423 loc.reg.SetLowReg(temp_low.GetReg());
424 }
425 if (IsTemp(loc.reg.GetHigh())) {
426 Clobber(loc.reg.GetHigh());
427 } else {
428 RegStorage temp_high = AllocTemp();
429 OpRegCopy(temp_high, loc.reg.GetHigh());
430 loc.reg.SetHighReg(temp_high.GetReg());
431 }
Mark Mendelle02d48f2014-01-15 11:19:23 -0800432 }
433
434 // Ensure that this doesn't represent the original SR any more.
435 loc.s_reg_low = INVALID_SREG;
436 return loc;
437}
438
Brian Carlstrom7940e442013-07-12 13:46:57 -0700439} // namespace art