• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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 
17 /*
18  * This file contains target-independent codegen and support, and is
19  * included by:
20  *
21  *        $(TARGET_ARCH)/Codegen-$(TARGET_ARCH_VARIANT).c
22  *
23  * which combines this common code with specific support found in the
24  * applicable directories below this one.
25  *
26  * Prior to including this file, TGT_LIR should be #defined.
27  * For example, for arm:
28  *    #define TGT_LIR ArmLIR
29  * and for x86:
30  *    #define TGT_LIR X86LIR
31  */
32 
33 
34 /* Load a word at base + displacement.  Displacement must be word multiple */
loadWordDisp(CompilationUnit * cUnit,int rBase,int displacement,int rDest)35 static TGT_LIR *loadWordDisp(CompilationUnit *cUnit, int rBase,
36                              int displacement, int rDest)
37 {
38     return loadBaseDisp(cUnit, NULL, rBase, displacement, rDest, kWord,
39                         INVALID_SREG);
40 }
41 
storeWordDisp(CompilationUnit * cUnit,int rBase,int displacement,int rSrc)42 static TGT_LIR *storeWordDisp(CompilationUnit *cUnit, int rBase,
43                              int displacement, int rSrc)
44 {
45     return storeBaseDisp(cUnit, rBase, displacement, rSrc, kWord);
46 }
47 
48 /*
49  * Load a Dalvik register into a physical register.  Take care when
50  * using this routine, as it doesn't perform any bookkeeping regarding
51  * register liveness.  That is the responsibility of the caller.
52  */
loadValueDirect(CompilationUnit * cUnit,RegLocation rlSrc,int reg1)53 static void loadValueDirect(CompilationUnit *cUnit, RegLocation rlSrc,
54                             int reg1)
55 {
56     rlSrc = dvmCompilerUpdateLoc(cUnit, rlSrc);
57     if (rlSrc.location == kLocPhysReg) {
58         genRegCopy(cUnit, reg1, rlSrc.lowReg);
59     } else  if (rlSrc.location == kLocRetval) {
60         loadWordDisp(cUnit, rSELF, offsetof(Thread, interpSave.retval), reg1);
61     } else {
62         assert(rlSrc.location == kLocDalvikFrame);
63         loadWordDisp(cUnit, rFP, dvmCompilerS2VReg(cUnit, rlSrc.sRegLow) << 2,
64                      reg1);
65     }
66 }
67 
68 /*
69  * Similar to loadValueDirect, but clobbers and allocates the target
70  * register.  Should be used when loading to a fixed register (for example,
71  * loading arguments to an out of line call.
72  */
loadValueDirectFixed(CompilationUnit * cUnit,RegLocation rlSrc,int reg1)73 static void loadValueDirectFixed(CompilationUnit *cUnit, RegLocation rlSrc,
74                                  int reg1)
75 {
76     dvmCompilerClobber(cUnit, reg1);
77     dvmCompilerMarkInUse(cUnit, reg1);
78     loadValueDirect(cUnit, rlSrc, reg1);
79 }
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  */
loadValueDirectWide(CompilationUnit * cUnit,RegLocation rlSrc,int regLo,int regHi)86 static void loadValueDirectWide(CompilationUnit *cUnit, RegLocation rlSrc,
87                                 int regLo, int regHi)
88 {
89     rlSrc = dvmCompilerUpdateLocWide(cUnit, rlSrc);
90     if (rlSrc.location == kLocPhysReg) {
91         genRegCopyWide(cUnit, regLo, regHi, rlSrc.lowReg, rlSrc.highReg);
92     } else if (rlSrc.location == kLocRetval) {
93         loadBaseDispWide(cUnit, NULL, rSELF,
94                          offsetof(Thread, interpSave.retval),
95                          regLo, regHi, INVALID_SREG);
96     } else {
97         assert(rlSrc.location == kLocDalvikFrame);
98             loadBaseDispWide(cUnit, NULL, rFP,
99                              dvmCompilerS2VReg(cUnit, rlSrc.sRegLow) << 2,
100                              regLo, regHi, INVALID_SREG);
101     }
102 }
103 
104 /*
105  * Similar to loadValueDirect, but clobbers and allocates the target
106  * registers.  Should be used when loading to a fixed registers (for example,
107  * loading arguments to an out of line call.
108  */
loadValueDirectWideFixed(CompilationUnit * cUnit,RegLocation rlSrc,int regLo,int regHi)109 static void loadValueDirectWideFixed(CompilationUnit *cUnit, RegLocation rlSrc,
110                                      int regLo, int regHi)
111 {
112     dvmCompilerClobber(cUnit, regLo);
113     dvmCompilerClobber(cUnit, regHi);
114     dvmCompilerMarkInUse(cUnit, regLo);
115     dvmCompilerMarkInUse(cUnit, regHi);
116     loadValueDirectWide(cUnit, rlSrc, regLo, regHi);
117 }
118 
loadValue(CompilationUnit * cUnit,RegLocation rlSrc,RegisterClass opKind)119 static RegLocation loadValue(CompilationUnit *cUnit, RegLocation rlSrc,
120                              RegisterClass opKind)
121 {
122     rlSrc = dvmCompilerEvalLoc(cUnit, rlSrc, opKind, false);
123     if (rlSrc.location == kLocDalvikFrame) {
124         loadValueDirect(cUnit, rlSrc, rlSrc.lowReg);
125         rlSrc.location = kLocPhysReg;
126         dvmCompilerMarkLive(cUnit, rlSrc.lowReg, rlSrc.sRegLow);
127     } else if (rlSrc.location == kLocRetval) {
128         loadWordDisp(cUnit, rSELF, offsetof(Thread, interpSave.retval),
129                      rlSrc.lowReg);
130         rlSrc.location = kLocPhysReg;
131         dvmCompilerClobber(cUnit, rlSrc.lowReg);
132     }
133     return rlSrc;
134 }
135 
storeValue(CompilationUnit * cUnit,RegLocation rlDest,RegLocation rlSrc)136 static void storeValue(CompilationUnit *cUnit, RegLocation rlDest,
137                        RegLocation rlSrc)
138 {
139     LIR *defStart;
140     LIR *defEnd;
141     assert(!rlDest.wide);
142     assert(!rlSrc.wide);
143     dvmCompilerKillNullCheckedLoc(cUnit, rlDest);
144     rlSrc = dvmCompilerUpdateLoc(cUnit, rlSrc);
145     rlDest = dvmCompilerUpdateLoc(cUnit, rlDest);
146     if (rlSrc.location == kLocPhysReg) {
147         if (dvmCompilerIsLive(cUnit, rlSrc.lowReg) ||
148             (rlDest.location == kLocPhysReg)) {
149             // Src is live or Dest has assigned reg.
150             rlDest = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, false);
151             genRegCopy(cUnit, rlDest.lowReg, rlSrc.lowReg);
152         } else {
153             // Just re-assign the registers.  Dest gets Src's regs
154             rlDest.lowReg = rlSrc.lowReg;
155             dvmCompilerClobber(cUnit, rlSrc.lowReg);
156         }
157     } else {
158         // Load Src either into promoted Dest or temps allocated for Dest
159         rlDest = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, false);
160         loadValueDirect(cUnit, rlSrc, rlDest.lowReg);
161     }
162 
163     // Dest is now live and dirty (until/if we flush it to home location)
164     dvmCompilerMarkLive(cUnit, rlDest.lowReg, rlDest.sRegLow);
165     dvmCompilerMarkDirty(cUnit, rlDest.lowReg);
166 
167 
168     if (rlDest.location == kLocRetval) {
169         storeBaseDisp(cUnit, rSELF, offsetof(Thread, interpSave.retval),
170                       rlDest.lowReg, kWord);
171         dvmCompilerClobber(cUnit, rlDest.lowReg);
172     } else {
173         dvmCompilerResetDefLoc(cUnit, rlDest);
174         if (dvmCompilerLiveOut(cUnit, rlDest.sRegLow)) {
175             defStart = (LIR *)cUnit->lastLIRInsn;
176             int vReg = dvmCompilerS2VReg(cUnit, rlDest.sRegLow);
177             storeBaseDisp(cUnit, rFP, vReg << 2, rlDest.lowReg, kWord);
178             dvmCompilerMarkClean(cUnit, rlDest.lowReg);
179             defEnd = (LIR *)cUnit->lastLIRInsn;
180             dvmCompilerMarkDef(cUnit, rlDest, defStart, defEnd);
181         }
182     }
183 }
184 
loadValueWide(CompilationUnit * cUnit,RegLocation rlSrc,RegisterClass opKind)185 static RegLocation loadValueWide(CompilationUnit *cUnit, RegLocation rlSrc,
186                                  RegisterClass opKind)
187 {
188     assert(rlSrc.wide);
189     rlSrc = dvmCompilerEvalLoc(cUnit, rlSrc, opKind, false);
190     if (rlSrc.location == kLocDalvikFrame) {
191         loadValueDirectWide(cUnit, rlSrc, rlSrc.lowReg, rlSrc.highReg);
192         rlSrc.location = kLocPhysReg;
193         dvmCompilerMarkLive(cUnit, rlSrc.lowReg, rlSrc.sRegLow);
194         dvmCompilerMarkLive(cUnit, rlSrc.highReg,
195                             dvmCompilerSRegHi(rlSrc.sRegLow));
196     } else if (rlSrc.location == kLocRetval) {
197         loadBaseDispWide(cUnit, NULL, rSELF,
198                          offsetof(Thread, interpSave.retval),
199                          rlSrc.lowReg, rlSrc.highReg, INVALID_SREG);
200         rlSrc.location = kLocPhysReg;
201         dvmCompilerClobber(cUnit, rlSrc.lowReg);
202         dvmCompilerClobber(cUnit, rlSrc.highReg);
203     }
204     return rlSrc;
205 }
206 
storeValueWide(CompilationUnit * cUnit,RegLocation rlDest,RegLocation rlSrc)207 static void storeValueWide(CompilationUnit *cUnit, RegLocation rlDest,
208                            RegLocation rlSrc)
209 {
210     LIR *defStart;
211     LIR *defEnd;
212     assert(FPREG(rlSrc.lowReg)==FPREG(rlSrc.highReg));
213     assert(rlDest.wide);
214     assert(rlSrc.wide);
215     dvmCompilerKillNullCheckedLoc(cUnit, rlDest);
216     if (rlSrc.location == kLocPhysReg) {
217         if (dvmCompilerIsLive(cUnit, rlSrc.lowReg) ||
218             dvmCompilerIsLive(cUnit, rlSrc.highReg) ||
219             (rlDest.location == kLocPhysReg)) {
220             // Src is live or Dest has assigned reg.
221             rlDest = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, false);
222             genRegCopyWide(cUnit, rlDest.lowReg, rlDest.highReg,
223                            rlSrc.lowReg, rlSrc.highReg);
224         } else {
225             // Just re-assign the registers.  Dest gets Src's regs
226             rlDest.lowReg = rlSrc.lowReg;
227             rlDest.highReg = rlSrc.highReg;
228             dvmCompilerClobber(cUnit, rlSrc.lowReg);
229             dvmCompilerClobber(cUnit, rlSrc.highReg);
230         }
231     } else {
232         // Load Src either into promoted Dest or temps allocated for Dest
233         rlDest = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, false);
234         loadValueDirectWide(cUnit, rlSrc, rlDest.lowReg,
235                             rlDest.highReg);
236     }
237 
238     // Dest is now live and dirty (until/if we flush it to home location)
239     dvmCompilerMarkLive(cUnit, rlDest.lowReg, rlDest.sRegLow);
240     dvmCompilerMarkLive(cUnit, rlDest.highReg,
241                         dvmCompilerSRegHi(rlDest.sRegLow));
242     dvmCompilerMarkDirty(cUnit, rlDest.lowReg);
243     dvmCompilerMarkDirty(cUnit, rlDest.highReg);
244     dvmCompilerMarkPair(cUnit, rlDest.lowReg, rlDest.highReg);
245 
246 
247     if (rlDest.location == kLocRetval) {
248         storeBaseDispWide(cUnit, rSELF, offsetof(Thread, interpSave.retval),
249                           rlDest.lowReg, rlDest.highReg);
250         dvmCompilerClobber(cUnit, rlDest.lowReg);
251         dvmCompilerClobber(cUnit, rlDest.highReg);
252     } else {
253         dvmCompilerResetDefLocWide(cUnit, rlDest);
254         if (dvmCompilerLiveOut(cUnit, rlDest.sRegLow) ||
255             dvmCompilerLiveOut(cUnit, dvmCompilerSRegHi(rlDest.sRegLow))) {
256             defStart = (LIR *)cUnit->lastLIRInsn;
257             int vReg = dvmCompilerS2VReg(cUnit, rlDest.sRegLow);
258             assert((vReg+1) == dvmCompilerS2VReg(cUnit,
259                                      dvmCompilerSRegHi(rlDest.sRegLow)));
260             storeBaseDispWide(cUnit, rFP, vReg << 2, rlDest.lowReg,
261                               rlDest.highReg);
262             dvmCompilerMarkClean(cUnit, rlDest.lowReg);
263             dvmCompilerMarkClean(cUnit, rlDest.highReg);
264             defEnd = (LIR *)cUnit->lastLIRInsn;
265             dvmCompilerMarkDefWide(cUnit, rlDest, defStart, defEnd);
266         }
267     }
268 }
269