2 * Copyright (C) 2009 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * This file is included by Codegen-armv5te-vfp.c, and implements architecture
19 * variant-specific code.
22 #define USE_IN_CACHE_HANDLER 1
25 * Determine the initial instruction set to be used for this trace.
26 * Later components may decide to change this.
28 JitInstructionSetType dvmCompilerInstructionSet(CompilationUnit *cUnit)
30 return DALVIK_JIT_THUMB;
34 * Jump to the out-of-line handler in ARM mode to finish executing the
35 * remaining of more complex instructions.
37 static void genDispatchToHandler(CompilationUnit *cUnit, TemplateOpCode opCode)
39 #if USE_IN_CACHE_HANDLER
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].
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]);
56 * In case we want to access the statically compiled handlers for
57 * debugging purposes, define USE_IN_CACHE_HANDLER to 0
61 #define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
62 #include "../../../template/armv5te-vfp/TemplateOpList.h"
65 #define JIT_TEMPLATE(X) \
66 case TEMPLATE_##X: { templatePtr = dvmCompiler_TEMPLATE_##X; break; }
67 #include "../../../template/armv5te-vfp/TemplateOpList.h"
69 default: templatePtr = NULL;
71 loadConstant(cUnit, r7, (int) templatePtr);
72 newLIR1(cUnit, THUMB_BLX_R, r7);
76 /* Architecture-specific initializations and checks go here */
77 bool dvmCompilerArchInit(void)
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"
85 extern void dvmCompilerTemplateStart(void);
88 * Then, populate the templateEntryOffsets array with the offsets from the
89 * the dvmCompilerTemplateStart symbol for each template.
91 #define JIT_TEMPLATE(X) templateEntryOffsets[i++] = \
92 (intptr_t) dvmCompiler_TEMPLATE_##X - (intptr_t) dvmCompilerTemplateStart;
93 #include "../../../template/armv5te-vfp/TemplateOpList.h"
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);
103 /* Up to 5 args are pushed on top of FP - sizeofStackSaveArea */
104 assert(sizeof(StackSaveArea) < 236);
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.
111 assert(offsetof(InterpState, jitToInterpEntries) < 108);
115 static bool genInlineSqrt(CompilationUnit *cUnit, MIR *mir)
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);
127 static bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir, int vDest,
128 int vSrc1, int vSrc2)
130 TemplateOpCode opCode;
133 * Don't attempt to optimize register usage since these opcodes call out to
136 switch (mir->dalvikInsn.opCode) {
137 case OP_ADD_FLOAT_2ADDR:
139 opCode = TEMPLATE_ADD_FLOAT_VFP;
141 case OP_SUB_FLOAT_2ADDR:
143 opCode = TEMPLATE_SUB_FLOAT_VFP;
145 case OP_DIV_FLOAT_2ADDR:
147 opCode = TEMPLATE_DIV_FLOAT_VFP;
149 case OP_MUL_FLOAT_2ADDR:
151 opCode = TEMPLATE_MUL_FLOAT_VFP;
153 case OP_REM_FLOAT_2ADDR:
156 return genArithOpFloatPortable(cUnit, mir, vDest,
162 loadValueAddress(cUnit, vDest, r0);
163 loadValueAddress(cUnit, vSrc1, r1);
164 loadValueAddress(cUnit, vSrc2, r2);
165 genDispatchToHandler(cUnit, opCode);
169 static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir, int vDest,
170 int vSrc1, int vSrc2)
172 TemplateOpCode opCode;
175 * Don't attempt to optimize register usage since these opcodes call out to
178 switch (mir->dalvikInsn.opCode) {
179 case OP_ADD_DOUBLE_2ADDR:
181 opCode = TEMPLATE_ADD_DOUBLE_VFP;
183 case OP_SUB_DOUBLE_2ADDR:
185 opCode = TEMPLATE_SUB_DOUBLE_VFP;
187 case OP_DIV_DOUBLE_2ADDR:
189 opCode = TEMPLATE_DIV_DOUBLE_VFP;
191 case OP_MUL_DOUBLE_2ADDR:
193 opCode = TEMPLATE_MUL_DOUBLE_VFP;
195 case OP_REM_DOUBLE_2ADDR:
197 case OP_NEG_DOUBLE: {
198 return genArithOpDoublePortable(cUnit, mir, vDest,
204 loadValueAddress(cUnit, vDest, r0);
205 loadValueAddress(cUnit, vSrc1, r1);
206 loadValueAddress(cUnit, vSrc2, r2);
207 genDispatchToHandler(cUnit, opCode);
211 static bool genConversion(CompilationUnit *cUnit, MIR *mir)
213 OpCode opCode = mir->dalvikInsn.opCode;
214 int vSrc1Dest = mir->dalvikInsn.vA;
215 int vSrc2 = mir->dalvikInsn.vB;
216 TemplateOpCode template;
219 case OP_INT_TO_FLOAT:
220 template = TEMPLATE_INT_TO_FLOAT_VFP;
222 case OP_FLOAT_TO_INT:
223 template = TEMPLATE_FLOAT_TO_INT_VFP;
225 case OP_DOUBLE_TO_FLOAT:
226 template = TEMPLATE_DOUBLE_TO_FLOAT_VFP;
228 case OP_FLOAT_TO_DOUBLE:
229 template = TEMPLATE_FLOAT_TO_DOUBLE_VFP;
231 case OP_INT_TO_DOUBLE:
232 template = TEMPLATE_INT_TO_DOUBLE_VFP;
234 case OP_DOUBLE_TO_INT:
235 template = TEMPLATE_DOUBLE_TO_INT_VFP;
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);
245 loadValueAddress(cUnit, vSrc1Dest, r0);
246 loadValueAddress(cUnit, vSrc2, r1);
247 genDispatchToHandler(cUnit, template);
251 static bool genCmpX(CompilationUnit *cUnit, MIR *mir, int vDest, int vSrc1,
254 TemplateOpCode template;
257 * Don't attempt to optimize register usage since these opcodes call out to
260 switch(mir->dalvikInsn.opCode) {
262 template = TEMPLATE_CMPL_FLOAT_VFP;
265 template = TEMPLATE_CMPG_FLOAT_VFP;
268 template = TEMPLATE_CMPL_DOUBLE_VFP;
271 template = TEMPLATE_CMPG_DOUBLE_VFP;
276 loadValueAddress(cUnit, vSrc1, r0);
277 loadValueAddress(cUnit, vSrc2, r1);
278 genDispatchToHandler(cUnit, template);
279 storeValue(cUnit, r0, vDest, r1);