OSDN Git Service

732172aeb4e14d86c514f921b3b014c84f96b7e2
[android-x86/dalvik.git] / vm / compiler / codegen / arm / armv5te-vfp / ArchVariant.c
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 is included by Codegen-armv5te-vfp.c, and implements architecture
19  * variant-specific code.
20  */
21
22 #define USE_IN_CACHE_HANDLER 1
23
24 /*
25  * Determine the initial instruction set to be used for this trace.
26  * Later components may decide to change this.
27  */
28 JitInstructionSetType dvmCompilerInstructionSet(CompilationUnit *cUnit)
29 {
30     return DALVIK_JIT_THUMB;
31 }
32
33 /*
34  * Jump to the out-of-line handler in ARM mode to finish executing the
35  * remaining of more complex instructions.
36  */
37 static void genDispatchToHandler(CompilationUnit *cUnit, TemplateOpCode opCode)
38 {
39 #if USE_IN_CACHE_HANDLER
40     /*
41      * NOTE - In practice BLX only needs one operand, but since the assembler
42      * may abort itself and retry due to other out-of-range conditions we
43      * cannot really use operand[0] to store the absolute target address since
44      * it may get clobbered by the final relative offset. Therefore,
45      * we fake BLX_1 is a two operand instruction and the absolute target
46      * address is stored in operand[1].
47      */
48     newLIR2(cUnit, THUMB_BLX_1,
49             (int) gDvmJit.codeCache + templateEntryOffsets[opCode],
50             (int) gDvmJit.codeCache + templateEntryOffsets[opCode]);
51     newLIR2(cUnit, THUMB_BLX_2,
52             (int) gDvmJit.codeCache + templateEntryOffsets[opCode],
53             (int) gDvmJit.codeCache + templateEntryOffsets[opCode]);
54 #else
55     /*
56      * In case we want to access the statically compiled handlers for
57      * debugging purposes, define USE_IN_CACHE_HANDLER to 0
58      */
59     void *templatePtr;
60
61 #define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
62 #include "../../../template/armv5te-vfp/TemplateOpList.h"
63 #undef JIT_TEMPLATE
64     switch (opCode) {
65 #define JIT_TEMPLATE(X) \
66         case TEMPLATE_##X: { templatePtr = dvmCompiler_TEMPLATE_##X; break; }
67 #include "../../../template/armv5te-vfp/TemplateOpList.h"
68 #undef JIT_TEMPLATE
69         default: templatePtr = NULL;
70     }
71     loadConstant(cUnit, r7, (int) templatePtr);
72     newLIR1(cUnit, THUMB_BLX_R, r7);
73 #endif
74 }
75
76 /* Architecture-specific initializations and checks go here */
77 bool dvmCompilerArchInit(void)
78 {
79     /* First, declare dvmCompiler_TEMPLATE_XXX for each template */
80 #define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
81 #include "../../../template/armv5te-vfp/TemplateOpList.h"
82 #undef JIT_TEMPLATE
83
84     int i = 0;
85     extern void dvmCompilerTemplateStart(void);
86
87     /*
88      * Then, populate the templateEntryOffsets array with the offsets from the
89      * the dvmCompilerTemplateStart symbol for each template.
90      */
91 #define JIT_TEMPLATE(X) templateEntryOffsets[i++] = \
92     (intptr_t) dvmCompiler_TEMPLATE_##X - (intptr_t) dvmCompilerTemplateStart;
93 #include "../../../template/armv5te-vfp/TemplateOpList.h"
94 #undef JIT_TEMPLATE
95
96     /* Codegen-specific assumptions */
97     assert(offsetof(ClassObject, vtable) < 128 &&
98            (offsetof(ClassObject, vtable) & 0x3) == 0);
99     assert(offsetof(ArrayObject, length) < 128 &&
100            (offsetof(ArrayObject, length) & 0x3) == 0);
101     assert(offsetof(ArrayObject, contents) < 256);
102
103     /* Up to 5 args are pushed on top of FP - sizeofStackSaveArea */
104     assert(sizeof(StackSaveArea) < 236);
105
106     /*
107      * EA is calculated by doing "Rn + imm5 << 2", and there are 5 entry points
108      * that codegen may access, make sure that the offset from the top of the
109      * struct is less than 108.
110      */
111     assert(offsetof(InterpState, jitToInterpEntries) < 108);
112     return true;
113 }
114
115 static bool genInlineSqrt(CompilationUnit *cUnit, MIR *mir)
116 {
117     int offset = offsetof(InterpState, retval);
118     OpCode opCode = mir->dalvikInsn.opCode;
119     int vSrc = mir->dalvikInsn.vA;
120     loadValueAddress(cUnit, vSrc, r2);
121     genDispatchToHandler(cUnit, TEMPLATE_SQRT_DOUBLE_VFP);
122     newLIR3(cUnit, THUMB_STR_RRI5, r0, rGLUE, offset >> 2);
123     newLIR3(cUnit, THUMB_STR_RRI5, r1, rGLUE, (offset >> 2) + 1);
124     return false;
125 }
126
127 static bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir, int vDest,
128                                 int vSrc1, int vSrc2)
129 {
130     TemplateOpCode opCode;
131
132     /*
133      * Don't attempt to optimize register usage since these opcodes call out to
134      * the handlers.
135      */
136     switch (mir->dalvikInsn.opCode) {
137         case OP_ADD_FLOAT_2ADDR:
138         case OP_ADD_FLOAT:
139             opCode = TEMPLATE_ADD_FLOAT_VFP;
140             break;
141         case OP_SUB_FLOAT_2ADDR:
142         case OP_SUB_FLOAT:
143             opCode = TEMPLATE_SUB_FLOAT_VFP;
144             break;
145         case OP_DIV_FLOAT_2ADDR:
146         case OP_DIV_FLOAT:
147             opCode = TEMPLATE_DIV_FLOAT_VFP;
148             break;
149         case OP_MUL_FLOAT_2ADDR:
150         case OP_MUL_FLOAT:
151             opCode = TEMPLATE_MUL_FLOAT_VFP;
152             break;
153         case OP_REM_FLOAT_2ADDR:
154         case OP_REM_FLOAT:
155         case OP_NEG_FLOAT: {
156             return genArithOpFloatPortable(cUnit, mir, vDest,
157                                                       vSrc1, vSrc2);
158         }
159         default:
160             return true;
161     }
162     loadValueAddress(cUnit, vDest, r0);
163     loadValueAddress(cUnit, vSrc1, r1);
164     loadValueAddress(cUnit, vSrc2, r2);
165     genDispatchToHandler(cUnit, opCode);
166     return false;
167 }
168
169 static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir, int vDest,
170                              int vSrc1, int vSrc2)
171 {
172     TemplateOpCode opCode;
173
174     /*
175      * Don't attempt to optimize register usage since these opcodes call out to
176      * the handlers.
177      */
178     switch (mir->dalvikInsn.opCode) {
179         case OP_ADD_DOUBLE_2ADDR:
180         case OP_ADD_DOUBLE:
181             opCode = TEMPLATE_ADD_DOUBLE_VFP;
182             break;
183         case OP_SUB_DOUBLE_2ADDR:
184         case OP_SUB_DOUBLE:
185             opCode = TEMPLATE_SUB_DOUBLE_VFP;
186             break;
187         case OP_DIV_DOUBLE_2ADDR:
188         case OP_DIV_DOUBLE:
189             opCode = TEMPLATE_DIV_DOUBLE_VFP;
190             break;
191         case OP_MUL_DOUBLE_2ADDR:
192         case OP_MUL_DOUBLE:
193             opCode = TEMPLATE_MUL_DOUBLE_VFP;
194             break;
195         case OP_REM_DOUBLE_2ADDR:
196         case OP_REM_DOUBLE:
197         case OP_NEG_DOUBLE: {
198             return genArithOpDoublePortable(cUnit, mir, vDest,
199                                                        vSrc1, vSrc2);
200         }
201         default:
202             return true;
203     }
204     loadValueAddress(cUnit, vDest, r0);
205     loadValueAddress(cUnit, vSrc1, r1);
206     loadValueAddress(cUnit, vSrc2, r2);
207     genDispatchToHandler(cUnit, opCode);
208     return false;
209 }
210
211 static bool genConversion(CompilationUnit *cUnit, MIR *mir)
212 {
213     OpCode opCode = mir->dalvikInsn.opCode;
214     int vSrc1Dest = mir->dalvikInsn.vA;
215     int vSrc2 = mir->dalvikInsn.vB;
216     TemplateOpCode template;
217
218     switch (opCode) {
219         case OP_INT_TO_FLOAT:
220             template = TEMPLATE_INT_TO_FLOAT_VFP;
221             break;
222         case OP_FLOAT_TO_INT:
223             template = TEMPLATE_FLOAT_TO_INT_VFP;
224             break;
225         case OP_DOUBLE_TO_FLOAT:
226             template = TEMPLATE_DOUBLE_TO_FLOAT_VFP;
227             break;
228         case OP_FLOAT_TO_DOUBLE:
229             template = TEMPLATE_FLOAT_TO_DOUBLE_VFP;
230             break;
231         case OP_INT_TO_DOUBLE:
232             template = TEMPLATE_INT_TO_DOUBLE_VFP;
233             break;
234         case OP_DOUBLE_TO_INT:
235             template = TEMPLATE_DOUBLE_TO_INT_VFP;
236             break;
237         case OP_FLOAT_TO_LONG:
238         case OP_LONG_TO_FLOAT:
239         case OP_DOUBLE_TO_LONG:
240         case OP_LONG_TO_DOUBLE:
241             return genConversionPortable(cUnit, mir);
242         default:
243             return true;
244     }
245     loadValueAddress(cUnit, vSrc1Dest, r0);
246     loadValueAddress(cUnit, vSrc2, r1);
247     genDispatchToHandler(cUnit, template);
248     return false;
249 }
250
251 static bool genCmpX(CompilationUnit *cUnit, MIR *mir, int vDest, int vSrc1,
252                     int vSrc2)
253 {
254     TemplateOpCode template;
255
256     /*
257      * Don't attempt to optimize register usage since these opcodes call out to
258      * the handlers.
259      */
260     switch(mir->dalvikInsn.opCode) {
261         case OP_CMPL_FLOAT:
262             template = TEMPLATE_CMPL_FLOAT_VFP;
263             break;
264         case OP_CMPG_FLOAT:
265             template = TEMPLATE_CMPG_FLOAT_VFP;
266             break;
267         case OP_CMPL_DOUBLE:
268             template = TEMPLATE_CMPL_DOUBLE_VFP;
269             break;
270         case OP_CMPG_DOUBLE:
271             template = TEMPLATE_CMPG_DOUBLE_VFP;
272             break;
273         default:
274             return true;
275     }
276     loadValueAddress(cUnit, vSrc1, r0);
277     loadValueAddress(cUnit, vSrc2, r1);
278     genDispatchToHandler(cUnit, template);
279     storeValue(cUnit, r0, vDest, r1);
280     return false;
281 }