CompilerTemplateAsm-armv5te.S revision ab875c79c56eacc510b09710d38a9b20f7337486
1/* 2 * This file was generated automatically by gen-template.py for 'armv5te'. 3 * 4 * --> DO NOT EDIT <-- 5 */ 6 7/* File: armv5te/header.S */ 8/* 9 * Copyright (C) 2008 The Android Open Source Project 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 */ 23 24#if defined(WITH_JIT) 25 26/* 27 * ARMv5 definitions and declarations. 28 */ 29 30/* 31ARM EABI general notes: 32 33r0-r3 hold first 4 args to a method; they are not preserved across method calls 34r4-r8 are available for general use 35r9 is given special treatment in some situations, but not for us 36r10 (sl) seems to be generally available 37r11 (fp) is used by gcc (unless -fomit-frame-pointer is set) 38r12 (ip) is scratch -- not preserved across method calls 39r13 (sp) should be managed carefully in case a signal arrives 40r14 (lr) must be preserved 41r15 (pc) can be tinkered with directly 42 43r0 holds returns of <= 4 bytes 44r0-r1 hold returns of 8 bytes, low word in r0 45 46Callee must save/restore r4+ (except r12) if it modifies them. 47 48Stack is "full descending". Only the arguments that don't fit in the first 4 49registers are placed on the stack. "sp" points at the first stacked argument 50(i.e. the 5th arg). 51 52VFP: single-precision results in s0, double-precision results in d0. 53 54In the EABI, "sp" must be 64-bit aligned on entry to a function, and any 5564-bit quantities (long long, double) must be 64-bit aligned. 56*/ 57 58/* 59JIT and ARM notes: 60 61The following registers have fixed assignments: 62 63 reg nick purpose 64 r5 rFP interpreted frame pointer, used for accessing locals and args 65 r6 rGLUE MterpGlue pointer 66 67The following registers have fixed assignments in mterp but are scratch 68registers in compiled code 69 70 reg nick purpose 71 r4 rPC interpreted program counter, used for fetching instructions 72 r7 rINST first 16-bit code unit of current instruction 73 r8 rIBASE interpreted instruction base pointer, used for computed goto 74 75Macros are provided for common operations. Each macro MUST emit only 76one instruction to make instruction-counting easier. They MUST NOT alter 77unspecified registers or condition codes. 78*/ 79 80/* single-purpose registers, given names for clarity */ 81#define rPC r4 82#define rFP r5 83#define rGLUE r6 84#define rINST r7 85#define rIBASE r8 86 87/* 88 * Given a frame pointer, find the stack save area. 89 * 90 * In C this is "((StackSaveArea*)(_fp) -1)". 91 */ 92#define SAVEAREA_FROM_FP(_reg, _fpreg) \ 93 sub _reg, _fpreg, #sizeofStackSaveArea 94 95#define EXPORT_PC() \ 96 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)] 97 98/* 99 * This is a #include, not a %include, because we want the C pre-processor 100 * to expand the macros into assembler assignment statements. 101 */ 102#include "../../../mterp/common/asm-constants.h" 103 104 105/* File: armv5te/platform.S */ 106/* 107 * =========================================================================== 108 * CPU-version-specific defines 109 * =========================================================================== 110 */ 111 112/* 113 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5. 114 * Jump to subroutine. 115 * 116 * May modify IP and LR. 117 */ 118.macro LDR_PC_LR source 119 mov lr, pc 120 ldr pc, \source 121.endm 122 123 124 .global dvmCompilerTemplateStart 125 .type dvmCompilerTemplateStart, %function 126 .text 127 128dvmCompilerTemplateStart: 129 130/* ------------------------------ */ 131 .balign 4 132 .global dvmCompiler_TEMPLATE_CMP_LONG 133dvmCompiler_TEMPLATE_CMP_LONG: 134/* File: armv5te/TEMPLATE_CMP_LONG.S */ 135 /* 136 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 137 * register based on the results of the comparison. 138 * 139 * We load the full values with LDM, but in practice many values could 140 * be resolved by only looking at the high word. This could be made 141 * faster or slower by splitting the LDM into a pair of LDRs. 142 * 143 * If we just wanted to set condition flags, we could do this: 144 * subs ip, r0, r2 145 * sbcs ip, r1, r3 146 * subeqs ip, r0, r2 147 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 148 * integer value, which we can do with 2 conditional mov/mvn instructions 149 * (set 1, set -1; if they're equal we already have 0 in ip), giving 150 * us a constant 5-cycle path plus a branch at the end to the 151 * instruction epilogue code. The multi-compare approach below needs 152 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 153 * in the worst case (the 64-bit values are equal). 154 */ 155 /* cmp-long vAA, vBB, vCC */ 156 cmp r1, r3 @ compare (vBB+1, vCC+1) 157 blt .LTEMPLATE_CMP_LONG_less @ signed compare on high part 158 bgt .LTEMPLATE_CMP_LONG_greater 159 subs r0, r0, r2 @ r0<- r0 - r2 160 bxeq lr 161 bhi .LTEMPLATE_CMP_LONG_greater @ unsigned compare on low part 162.LTEMPLATE_CMP_LONG_less: 163 mvn r0, #0 @ r0<- -1 164 bx lr 165.LTEMPLATE_CMP_LONG_greater: 166 mov r0, #1 @ r0<- 1 167 bx lr 168 169 170/* ------------------------------ */ 171 .balign 4 172 .global dvmCompiler_TEMPLATE_RETURN 173dvmCompiler_TEMPLATE_RETURN: 174/* File: armv5te/TEMPLATE_RETURN.S */ 175 /* 176 * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX. 177 * If the stored value in returnAddr 178 * is non-zero, the caller is compiled by the JIT thus return to the 179 * address in the code cache following the invoke instruction. Otherwise 180 * return to the special dvmJitToInterpNoChain entry point. 181 */ 182 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 183 ldr r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame 184 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 185 ldr rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc 186#if !defined(WITH_SELF_VERIFICATION) 187 ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret 188#else 189 mov r9, #0 @ disable chaining 190#endif 191 ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)] 192 @ r2<- method we're returning to 193 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 194 cmp r2, #0 @ break frame? 195#if !defined(WITH_SELF_VERIFICATION) 196 beq 1f @ bail to interpreter 197#else 198 blxeq lr @ punt to interpreter and compare state 199#endif 200 ldr r1, .LdvmJitToInterpNoChain @ defined in footer.S 201 mov rFP, r10 @ publish new FP 202 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 203 ldr r8, [r8] @ r8<- suspendCount 204 205 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 206 ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex 207 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 208 add rPC, rPC, #6 @ publish new rPC (advance 6 bytes) 209 str r0, [rGLUE, #offGlue_methodClassDex] 210 cmp r8, #0 @ check the suspendCount 211 movne r9, #0 @ clear the chaining cell address 212 cmp r9, #0 @ chaining cell exists? 213 blxne r9 @ jump to the chaining cell 214#if defined(EXIT_STATS) 215 mov r0, #kCallsiteInterpreted 216#endif 217 mov pc, r1 @ callsite is interpreted 2181: 219 stmia rGLUE, {rPC, rFP} @ SAVE_PC_FP_TO_GLUE() 220 ldr r2, .LdvmMterpStdBail @ defined in footer.S 221 mov r1, #0 @ changeInterp = false 222 mov r0, rGLUE @ Expecting rGLUE in r0 223 blx r2 @ exit the interpreter 224 225/* ------------------------------ */ 226 .balign 4 227 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT 228dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT: 229/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */ 230 /* 231 * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC 232 * into rPC then jump to dvmJitToInterpNoChain to dispatch the 233 * runtime-resolved callee. 234 */ 235 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 236 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 237 ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize 238 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 239 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 240 add r3, r1, #1 @ Thumb addr is odd 241 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 242 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 243 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 244 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize) 245 ldr r8, [r8] @ r3<- suspendCount (int) 246 cmp r10, r9 @ bottom < interpStackEnd? 247 bxlt lr @ return to raise stack overflow excep. 248 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 249 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz 250 ldr r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags 251 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 252 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 253 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns 254 255 256 @ set up newSaveArea 257 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 258 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 259 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 260 cmp r8, #0 @ suspendCount != 0 261 bxne lr @ bail to the interpreter 262 tst r10, #ACC_NATIVE 263#if !defined(WITH_SELF_VERIFICATION) 264 bne .LinvokeNative 265#else 266 bxne lr @ bail to the interpreter 267#endif 268 269 ldr r10, .LdvmJitToInterpNoChain 270 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 271 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 272 273 @ Update "glue" values for the new method 274 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 275 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 276 mov rFP, r1 @ fp = newFp 277 str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp 278 279 @ Start executing the callee 280#if defined(EXIT_STATS) 281 mov r0, #kInlineCacheMiss 282#endif 283 mov pc, r10 @ dvmJitToInterpNoChain 284 285/* ------------------------------ */ 286 .balign 4 287 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN 288dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN: 289/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */ 290 /* 291 * For monomorphic callsite, setup the Dalvik frame and return to the 292 * Thumb code through the link register to transfer control to the callee 293 * method through a dedicated chaining cell. 294 */ 295 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 296 @ methodToCall is guaranteed to be non-native 297.LinvokeChain: 298 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 299 ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize 300 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 301 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 302 add r3, r1, #1 @ Thumb addr is odd 303 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 304 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 305 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 306 add r12, lr, #2 @ setup the punt-to-interp address 307 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize) 308 ldr r8, [r8] @ r3<- suspendCount (int) 309 cmp r10, r9 @ bottom < interpStackEnd? 310 bxlt r12 @ return to raise stack overflow excep. 311 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 312 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz 313 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 314 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 315 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns 316 317 318 @ set up newSaveArea 319 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 320 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 321 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 322 cmp r8, #0 @ suspendCount != 0 323 bxne r12 @ bail to the interpreter 324 325 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 326 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 327 328 @ Update "glue" values for the new method 329 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 330 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 331 mov rFP, r1 @ fp = newFp 332 str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp 333 334 bx lr @ return to the callee-chaining cell 335 336 337 338/* ------------------------------ */ 339 .balign 4 340 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN 341dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN: 342/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */ 343 /* 344 * For polymorphic callsite, check whether the cached class pointer matches 345 * the current one. If so setup the Dalvik frame and return to the 346 * Thumb code through the link register to transfer control to the callee 347 * method through a dedicated chaining cell. 348 * 349 * The predicted chaining cell is declared in ArmLIR.h with the 350 * following layout: 351 * 352 * typedef struct PredictedChainingCell { 353 * u4 branch; 354 * const ClassObject *clazz; 355 * const Method *method; 356 * u4 counter; 357 * } PredictedChainingCell; 358 * 359 * Upon returning to the callsite: 360 * - lr : to branch to the chaining cell 361 * - lr+2: to punt to the interpreter 362 * - lr+4: to fully resolve the callee and may rechain. 363 * r3 <- class 364 * r9 <- counter 365 */ 366 @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite 367 ldr r3, [r0, #offObject_clazz] @ r3 <- this->class 368 ldr r8, [r2, #4] @ r8 <- predictedChainCell->clazz 369 ldr r0, [r2, #8] @ r0 <- predictedChainCell->method 370 ldr r9, [r2, #12] @ r9 <- predictedChainCell->counter 371 cmp r3, r8 @ predicted class == actual class? 372 beq .LinvokeChain @ predicted chain is valid 373 ldr r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable 374 sub r1, r9, #1 @ count-- 375 str r1, [r2, #12] @ write back to PredictedChainingCell->counter 376 add lr, lr, #4 @ return to fully-resolve landing pad 377 /* 378 * r1 <- count 379 * r2 <- &predictedChainCell 380 * r3 <- this->class 381 * r4 <- dPC 382 * r7 <- this->class->vtable 383 */ 384 bx lr 385 386/* ------------------------------ */ 387 .balign 4 388 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE 389dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE: 390/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */ 391 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 392 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 393 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 394 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 395 add r3, r1, #1 @ Thumb addr is odd 396 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 397 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 398 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 399 ldr r8, [r8] @ r3<- suspendCount (int) 400 cmp r10, r9 @ bottom < interpStackEnd? 401 bxlt lr @ return to raise stack overflow excep. 402 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 403 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 404 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 405 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns 406 407 408 @ set up newSaveArea 409 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 410 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 411 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 412 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 413 cmp r8, #0 @ suspendCount != 0 414 ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc 415#if !defined(WITH_SELF_VERIFICATION) 416 bxne lr @ bail to the interpreter 417#else 418 bx lr @ bail to interpreter unconditionally 419#endif 420 421 @ go ahead and transfer control to the native code 422 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 423 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 424 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)] 425 @ newFp->localRefCookie=top 426 mov r9, r3 @ r9<- glue->self (preserve) 427 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area 428 429 mov r2, r0 @ r2<- methodToCall 430 mov r0, r1 @ r0<- newFP 431 add r1, rGLUE, #offGlue_retval @ r1<- &retval 432 433 blx r8 @ off to the native code 434 435 @ native return; r9=self, r10=newSaveArea 436 @ equivalent to dvmPopJniLocals 437 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret 438 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top 439 ldr r1, [r9, #offThread_exception] @ check for exception 440 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 441 cmp r1, #0 @ null? 442 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 443 bne .LhandleException @ no, handle exception 444 bx r2 445 446 447/* ------------------------------ */ 448 .balign 4 449 .global dvmCompiler_TEMPLATE_CMPG_DOUBLE 450dvmCompiler_TEMPLATE_CMPG_DOUBLE: 451/* File: armv5te/TEMPLATE_CMPG_DOUBLE.S */ 452/* File: armv5te/TEMPLATE_CMPL_DOUBLE.S */ 453 /* 454 * For the JIT: incoming arguments in r0-r1, r2-r3 455 * result in r0 456 * 457 * Compare two floating-point values. Puts 0, 1, or -1 into the 458 * destination register based on the results of the comparison. 459 * 460 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 461 * on what value we'd like to return when one of the operands is NaN. 462 * 463 * See OP_CMPL_FLOAT for an explanation. 464 * 465 * For: cmpl-double, cmpg-double 466 */ 467 /* op vAA, vBB, vCC */ 468 push {r0-r3} @ save operands 469 mov r11, lr @ save return address 470 LDR_PC_LR ".L__aeabi_cdcmple" @ PIC way of "bl __aeabi_cdcmple" 471 bhi .LTEMPLATE_CMPG_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate 472 mvncc r0, #0 @ (less than) r1<- -1 473 moveq r0, #0 @ (equal) r1<- 0, trumps less than 474 add sp, #16 @ drop unused operands 475 bx r11 476 477 @ Test for NaN with a second comparison. EABI forbids testing bit 478 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 479 @ make the library call. 480.LTEMPLATE_CMPG_DOUBLE_gt_or_nan: 481 pop {r2-r3} @ restore operands in reverse order 482 pop {r0-r1} @ restore operands in reverse order 483 LDR_PC_LR ".L__aeabi_cdcmple" @ r0<- Z set if eq, C clear if < 484 movcc r0, #1 @ (greater than) r1<- 1 485 bxcc r11 486 mov r0, #1 @ r1<- 1 or -1 for NaN 487 bx r11 488 489 490 491/* ------------------------------ */ 492 .balign 4 493 .global dvmCompiler_TEMPLATE_CMPL_DOUBLE 494dvmCompiler_TEMPLATE_CMPL_DOUBLE: 495/* File: armv5te/TEMPLATE_CMPL_DOUBLE.S */ 496 /* 497 * For the JIT: incoming arguments in r0-r1, r2-r3 498 * result in r0 499 * 500 * Compare two floating-point values. Puts 0, 1, or -1 into the 501 * destination register based on the results of the comparison. 502 * 503 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 504 * on what value we'd like to return when one of the operands is NaN. 505 * 506 * See OP_CMPL_FLOAT for an explanation. 507 * 508 * For: cmpl-double, cmpg-double 509 */ 510 /* op vAA, vBB, vCC */ 511 push {r0-r3} @ save operands 512 mov r11, lr @ save return address 513 LDR_PC_LR ".L__aeabi_cdcmple" @ PIC way of "bl __aeabi_cdcmple" 514 bhi .LTEMPLATE_CMPL_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate 515 mvncc r0, #0 @ (less than) r1<- -1 516 moveq r0, #0 @ (equal) r1<- 0, trumps less than 517 add sp, #16 @ drop unused operands 518 bx r11 519 520 @ Test for NaN with a second comparison. EABI forbids testing bit 521 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 522 @ make the library call. 523.LTEMPLATE_CMPL_DOUBLE_gt_or_nan: 524 pop {r2-r3} @ restore operands in reverse order 525 pop {r0-r1} @ restore operands in reverse order 526 LDR_PC_LR ".L__aeabi_cdcmple" @ r0<- Z set if eq, C clear if < 527 movcc r0, #1 @ (greater than) r1<- 1 528 bxcc r11 529 mvn r0, #0 @ r1<- 1 or -1 for NaN 530 bx r11 531 532 533/* ------------------------------ */ 534 .balign 4 535 .global dvmCompiler_TEMPLATE_CMPG_FLOAT 536dvmCompiler_TEMPLATE_CMPG_FLOAT: 537/* File: armv5te/TEMPLATE_CMPG_FLOAT.S */ 538/* File: armv5te/TEMPLATE_CMPL_FLOAT.S */ 539 /* 540 * For the JIT: incoming arguments in r0-r1, r2-r3 541 * result in r0 542 * 543 * Compare two floating-point values. Puts 0, 1, or -1 into the 544 * destination register based on the results of the comparison. 545 * 546 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 547 * on what value we'd like to return when one of the operands is NaN. 548 * 549 * The operation we're implementing is: 550 * if (x == y) 551 * return 0; 552 * else if (x < y) 553 * return -1; 554 * else if (x > y) 555 * return 1; 556 * else 557 * return {-1,1}; // one or both operands was NaN 558 * 559 * The straightforward implementation requires 3 calls to functions 560 * that return a result in r0. We can do it with two calls if our 561 * EABI library supports __aeabi_cfcmple (only one if we want to check 562 * for NaN directly): 563 * check x <= y 564 * if <, return -1 565 * if ==, return 0 566 * check y <= x 567 * if <, return 1 568 * return {-1,1} 569 * 570 * for: cmpl-float, cmpg-float 571 */ 572 /* op vAA, vBB, vCC */ 573 mov r9, r0 @ Save copies - we may need to redo 574 mov r10, r1 575 mov r11, lr @ save return address 576 LDR_PC_LR ".L__aeabi_cfcmple" @ cmp <=: C clear if <, Z set if eq 577 bhi .LTEMPLATE_CMPG_FLOAT_gt_or_nan @ C set and Z clear, disambiguate 578 mvncc r0, #0 @ (less than) r0<- -1 579 moveq r0, #0 @ (equal) r0<- 0, trumps less than 580 bx r11 581 @ Test for NaN with a second comparison. EABI forbids testing bit 582 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 583 @ make the library call. 584.LTEMPLATE_CMPG_FLOAT_gt_or_nan: 585 mov r0, r10 @ restore in reverse order 586 mov r1, r9 587 LDR_PC_LR ".L__aeabi_cfcmple" @ r0<- Z set if eq, C clear if < 588 movcc r0, #1 @ (greater than) r1<- 1 589 bxcc r11 590 mov r0, #1 @ r1<- 1 or -1 for NaN 591 bx r11 592 593 594 595 596/* ------------------------------ */ 597 .balign 4 598 .global dvmCompiler_TEMPLATE_CMPL_FLOAT 599dvmCompiler_TEMPLATE_CMPL_FLOAT: 600/* File: armv5te/TEMPLATE_CMPL_FLOAT.S */ 601 /* 602 * For the JIT: incoming arguments in r0-r1, r2-r3 603 * result in r0 604 * 605 * Compare two floating-point values. Puts 0, 1, or -1 into the 606 * destination register based on the results of the comparison. 607 * 608 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 609 * on what value we'd like to return when one of the operands is NaN. 610 * 611 * The operation we're implementing is: 612 * if (x == y) 613 * return 0; 614 * else if (x < y) 615 * return -1; 616 * else if (x > y) 617 * return 1; 618 * else 619 * return {-1,1}; // one or both operands was NaN 620 * 621 * The straightforward implementation requires 3 calls to functions 622 * that return a result in r0. We can do it with two calls if our 623 * EABI library supports __aeabi_cfcmple (only one if we want to check 624 * for NaN directly): 625 * check x <= y 626 * if <, return -1 627 * if ==, return 0 628 * check y <= x 629 * if <, return 1 630 * return {-1,1} 631 * 632 * for: cmpl-float, cmpg-float 633 */ 634 /* op vAA, vBB, vCC */ 635 mov r9, r0 @ Save copies - we may need to redo 636 mov r10, r1 637 mov r11, lr @ save return address 638 LDR_PC_LR ".L__aeabi_cfcmple" @ cmp <=: C clear if <, Z set if eq 639 bhi .LTEMPLATE_CMPL_FLOAT_gt_or_nan @ C set and Z clear, disambiguate 640 mvncc r0, #0 @ (less than) r0<- -1 641 moveq r0, #0 @ (equal) r0<- 0, trumps less than 642 bx r11 643 @ Test for NaN with a second comparison. EABI forbids testing bit 644 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 645 @ make the library call. 646.LTEMPLATE_CMPL_FLOAT_gt_or_nan: 647 mov r0, r10 @ restore in reverse order 648 mov r1, r9 649 LDR_PC_LR ".L__aeabi_cfcmple" @ r0<- Z set if eq, C clear if < 650 movcc r0, #1 @ (greater than) r1<- 1 651 bxcc r11 652 mvn r0, #0 @ r1<- 1 or -1 for NaN 653 bx r11 654 655 656 657/* ------------------------------ */ 658 .balign 4 659 .global dvmCompiler_TEMPLATE_MUL_LONG 660dvmCompiler_TEMPLATE_MUL_LONG: 661/* File: armv5te/TEMPLATE_MUL_LONG.S */ 662 /* 663 * Signed 64-bit integer multiply. 664 * 665 * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1 666 * 667 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 668 * WX 669 * x YZ 670 * -------- 671 * ZW ZX 672 * YW YX 673 * 674 * The low word of the result holds ZX, the high word holds 675 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 676 * it doesn't fit in the low 64 bits. 677 * 678 * Unlike most ARM math operations, multiply instructions have 679 * restrictions on using the same register more than once (Rd and Rm 680 * cannot be the same). 681 */ 682 /* mul-long vAA, vBB, vCC */ 683 mul ip, r2, r1 @ ip<- ZxW 684 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 685 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 686 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 687 mov r0,r9 688 mov r1,r10 689 bx lr 690 691/* ------------------------------ */ 692 .balign 4 693 .global dvmCompiler_TEMPLATE_SHL_LONG 694dvmCompiler_TEMPLATE_SHL_LONG: 695/* File: armv5te/TEMPLATE_SHL_LONG.S */ 696 /* 697 * Long integer shift. This is different from the generic 32/64-bit 698 * binary operations because vAA/vBB are 64-bit but vCC (the shift 699 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 700 * 6 bits. 701 */ 702 /* shl-long vAA, vBB, vCC */ 703 and r2, r2, #63 @ r2<- r2 & 0x3f 704 mov r1, r1, asl r2 @ r1<- r1 << r2 705 rsb r3, r2, #32 @ r3<- 32 - r2 706 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 707 subs ip, r2, #32 @ ip<- r2 - 32 708 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 709 mov r0, r0, asl r2 @ r0<- r0 << r2 710 bx lr 711 712/* ------------------------------ */ 713 .balign 4 714 .global dvmCompiler_TEMPLATE_SHR_LONG 715dvmCompiler_TEMPLATE_SHR_LONG: 716/* File: armv5te/TEMPLATE_SHR_LONG.S */ 717 /* 718 * Long integer shift. This is different from the generic 32/64-bit 719 * binary operations because vAA/vBB are 64-bit but vCC (the shift 720 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 721 * 6 bits. 722 */ 723 /* shr-long vAA, vBB, vCC */ 724 and r2, r2, #63 @ r0<- r0 & 0x3f 725 mov r0, r0, lsr r2 @ r0<- r2 >> r2 726 rsb r3, r2, #32 @ r3<- 32 - r2 727 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 728 subs ip, r2, #32 @ ip<- r2 - 32 729 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 730 mov r1, r1, asr r2 @ r1<- r1 >> r2 731 bx lr 732 733 734/* ------------------------------ */ 735 .balign 4 736 .global dvmCompiler_TEMPLATE_USHR_LONG 737dvmCompiler_TEMPLATE_USHR_LONG: 738/* File: armv5te/TEMPLATE_USHR_LONG.S */ 739 /* 740 * Long integer shift. This is different from the generic 32/64-bit 741 * binary operations because vAA/vBB are 64-bit but vCC (the shift 742 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 743 * 6 bits. 744 */ 745 /* ushr-long vAA, vBB, vCC */ 746 and r2, r2, #63 @ r0<- r0 & 0x3f 747 mov r0, r0, lsr r2 @ r0<- r2 >> r2 748 rsb r3, r2, #32 @ r3<- 32 - r2 749 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 750 subs ip, r2, #32 @ ip<- r2 - 32 751 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 752 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 753 bx lr 754 755 756/* ------------------------------ */ 757 .balign 4 758 .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON 759dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON: 760/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */ 761 /* 762 * Throw an exception from JIT'ed code. 763 * On entry: 764 * r0 Dalvik PC that raises the exception 765 */ 766 b .LhandleException 767 768/* ------------------------------ */ 769 .balign 4 770 .global dvmCompiler_TEMPLATE_SAVE_STATE 771dvmCompiler_TEMPLATE_SAVE_STATE: 772/* File: armv5te/TEMPLATE_SAVE_STATE.S */ 773 /* 774 * This handler performs a register save for selfVerification mode. 775 * On entry: 776 * Top of stack + 4: r7 value to save 777 * Top of stack + 0: r0 value to save 778 * r0 - offset from rGLUE to the beginning of the heapArgSpace record 779 * r7 - the value of regMap 780 * 781 * The handler must save regMap, r0-r12 and then return with r0-r12 782 * with their original values (note that this means r0 and r7 must take 783 * the values on the stack - not the ones in those registers on entry. 784 * Finally, the two registers previously pushed must be popped. 785 */ 786 add r0, r0, rGLUE @ pointer to heapArgSpace 787 stmia r0!, {r7} @ save regMap 788 ldr r7, [r13, #0] @ recover r0 value 789 stmia r0!, {r7} @ save r0 790 ldr r7, [r13, #4] @ recover r7 value 791 stmia r0!, {r1-r12} 792 pop {r0, r7} @ recover r0, r7 793 bx lr 794 795/* ------------------------------ */ 796 .balign 4 797 .global dvmCompiler_TEMPLATE_RESTORE_STATE 798dvmCompiler_TEMPLATE_RESTORE_STATE: 799/* File: armv5te/TEMPLATE_RESTORE_STATE.S */ 800 /* 801 * This handler restores state following a selfVerification memory access. 802 * On entry: 803 * r0 - offset from rGLUE to the 1st element of the coreRegs save array. 804 */ 805 add r0, r0, rGLUE @ pointer to heapArgSpace.coreRegs[0] 806 ldmia r0, {r0-r12} 807 bx lr 808 809/* ------------------------------ */ 810 .balign 4 811 .global dvmCompiler_TEMPLATE_STRING_COMPARETO 812dvmCompiler_TEMPLATE_STRING_COMPARETO: 813/* File: armv5te/TEMPLATE_STRING_COMPARETO.S */ 814 /* 815 * String's compareTo. 816 * 817 * Requires r0/r1 to have been previously checked for null. Will 818 * return negative if this's string is < comp, 0 if they are the 819 * same and positive if >. 820 * 821 * IMPORTANT NOTE: 822 * 823 * This code relies on hard-coded offsets for string objects, and must be 824 * kept in sync with definitions in UtfString.h. See asm-constants.h 825 * 826 * On entry: 827 * r0: this object pointer 828 * r1: comp object pointer 829 * 830 */ 831 832 mov r2, r0 @ this to r2, opening up r0 for return value 833 subs r0, r2, r1 @ Same? 834 bxeq lr 835 836 ldr r4, [r2, #STRING_FIELDOFF_OFFSET] 837 ldr r9, [r1, #STRING_FIELDOFF_OFFSET] 838 ldr r7, [r2, #STRING_FIELDOFF_COUNT] 839 ldr r10, [r1, #STRING_FIELDOFF_COUNT] 840 ldr r2, [r2, #STRING_FIELDOFF_VALUE] 841 ldr r1, [r1, #STRING_FIELDOFF_VALUE] 842 843 /* 844 * At this point, we have: 845 * value: r2/r1 846 * offset: r4/r9 847 * count: r7/r10 848 * We're going to compute 849 * r11 <- countDiff 850 * r10 <- minCount 851 */ 852 subs r11, r7, r10 853 movls r10, r7 854 855 /* Now, build pointers to the string data */ 856 add r2, r2, r4, lsl #1 857 add r1, r1, r9, lsl #1 858 /* 859 * Note: data pointers point to previous element so we can use pre-index 860 * mode with base writeback. 861 */ 862 add r2, #16-2 @ offset to contents[-1] 863 add r1, #16-2 @ offset to contents[-1] 864 865 /* 866 * At this point we have: 867 * r2: *this string data 868 * r1: *comp string data 869 * r10: iteration count for comparison 870 * r11: value to return if the first part of the string is equal 871 * r0: reserved for result 872 * r3, r4, r7, r8, r9, r12 available for loading string data 873 */ 874 875 subs r10, #2 876 blt do_remainder2 877 878 /* 879 * Unroll the first two checks so we can quickly catch early mismatch 880 * on long strings (but preserve incoming alignment) 881 */ 882 883 ldrh r3, [r2, #2]! 884 ldrh r4, [r1, #2]! 885 ldrh r7, [r2, #2]! 886 ldrh r8, [r1, #2]! 887 subs r0, r3, r4 888 subeqs r0, r7, r8 889 bxne lr 890 cmp r10, #28 891 bgt do_memcmp16 892 subs r10, #3 893 blt do_remainder 894 895loopback_triple: 896 ldrh r3, [r2, #2]! 897 ldrh r4, [r1, #2]! 898 ldrh r7, [r2, #2]! 899 ldrh r8, [r1, #2]! 900 ldrh r9, [r2, #2]! 901 ldrh r12,[r1, #2]! 902 subs r0, r3, r4 903 subeqs r0, r7, r8 904 subeqs r0, r9, r12 905 bxne lr 906 subs r10, #3 907 bge loopback_triple 908 909do_remainder: 910 adds r10, #3 911 beq returnDiff 912 913loopback_single: 914 ldrh r3, [r2, #2]! 915 ldrh r4, [r1, #2]! 916 subs r0, r3, r4 917 bxne lr 918 subs r10, #1 919 bne loopback_single 920 921returnDiff: 922 mov r0, r11 923 bx lr 924 925do_remainder2: 926 adds r10, #2 927 bne loopback_single 928 mov r0, r11 929 bx lr 930 931 /* Long string case */ 932do_memcmp16: 933 mov r4, lr 934 ldr lr, .Lmemcmp16 935 mov r7, r11 936 add r0, r2, #2 937 add r1, r1, #2 938 mov r2, r10 939 blx lr 940 cmp r0, #0 941 bxne r4 942 mov r0, r7 943 bx r4 944 945.Lmemcmp16: 946 .word __memcmp16 947 948 949/* ------------------------------ */ 950 .balign 4 951 .global dvmCompiler_TEMPLATE_STRING_INDEXOF 952dvmCompiler_TEMPLATE_STRING_INDEXOF: 953/* File: armv5te/TEMPLATE_STRING_INDEXOF.S */ 954 /* 955 * String's indexOf. 956 * 957 * Requires r0 to have been previously checked for null. Will 958 * return index of match of r1 in r0. 959 * 960 * IMPORTANT NOTE: 961 * 962 * This code relies on hard-coded offsets for string objects, and must be 963 * kept in sync wth definitions in UtfString.h See asm-constants.h 964 * 965 * On entry: 966 * r0: string object pointer 967 * r1: char to match 968 * r2: Starting offset in string data 969 */ 970 971 ldr r7, [r0, #STRING_FIELDOFF_OFFSET] 972 ldr r8, [r0, #STRING_FIELDOFF_COUNT] 973 ldr r0, [r0, #STRING_FIELDOFF_VALUE] 974 975 /* 976 * At this point, we have: 977 * r0: object pointer 978 * r1: char to match 979 * r2: starting offset 980 * r7: offset 981 * r8: string length 982 */ 983 984 /* Build pointer to start of string data */ 985 add r0, #16 986 add r0, r0, r7, lsl #1 987 988 /* Save a copy of starting data in r7 */ 989 mov r7, r0 990 991 /* Clamp start to [0..count] */ 992 cmp r2, #0 993 movlt r2, #0 994 cmp r2, r8 995 movgt r2, r8 996 997 /* Build pointer to start of data to compare and pre-bias */ 998 add r0, r0, r2, lsl #1 999 sub r0, #2 1000 1001 /* Compute iteration count */ 1002 sub r8, r2 1003 1004 /* 1005 * At this point we have: 1006 * r0: start of data to test 1007 * r1: chat to compare 1008 * r8: iteration count 1009 * r7: original start of string 1010 * r3, r4, r9, r10, r11, r12 available for loading string data 1011 */ 1012 1013 subs r8, #4 1014 blt indexof_remainder 1015 1016indexof_loop4: 1017 ldrh r3, [r0, #2]! 1018 ldrh r4, [r0, #2]! 1019 ldrh r10, [r0, #2]! 1020 ldrh r11, [r0, #2]! 1021 cmp r3, r1 1022 beq match_0 1023 cmp r4, r1 1024 beq match_1 1025 cmp r10, r1 1026 beq match_2 1027 cmp r11, r1 1028 beq match_3 1029 subs r8, #4 1030 bge indexof_loop4 1031 1032indexof_remainder: 1033 adds r8, #4 1034 beq indexof_nomatch 1035 1036indexof_loop1: 1037 ldrh r3, [r0, #2]! 1038 cmp r3, r1 1039 beq match_3 1040 subs r8, #1 1041 bne indexof_loop1 1042 1043indexof_nomatch: 1044 mov r0, #-1 1045 bx lr 1046 1047match_0: 1048 sub r0, #6 1049 sub r0, r7 1050 asr r0, r0, #1 1051 bx lr 1052match_1: 1053 sub r0, #4 1054 sub r0, r7 1055 asr r0, r0, #1 1056 bx lr 1057match_2: 1058 sub r0, #2 1059 sub r0, r7 1060 asr r0, r0, #1 1061 bx lr 1062match_3: 1063 sub r0, r7 1064 asr r0, r0, #1 1065 bx lr 1066 1067 1068/* ------------------------------ */ 1069 .balign 4 1070 .global dvmCompiler_TEMPLATE_INTERPRET 1071dvmCompiler_TEMPLATE_INTERPRET: 1072/* File: armv5te/TEMPLATE_INTERPRET.S */ 1073 /* 1074 * This handler transfers control to the interpeter without performing 1075 * any lookups. It may be called either as part of a normal chaining 1076 * operation, or from the transition code in header.S. We distinquish 1077 * the two cases by looking at the link register. If called from a 1078 * translation chain, it will point to the chaining Dalvik PC + 1. 1079 * On entry: 1080 * lr - if NULL: 1081 * r1 - the Dalvik PC to begin interpretation. 1082 * else 1083 * [lr, #-1] contains Dalvik PC to begin interpretation 1084 * rGLUE - pointer to interpState 1085 * rFP - Dalvik frame pointer 1086 */ 1087 cmp lr, #0 1088 ldrne r1,[lr, #-1] 1089 ldr r2, .LinterpPunt 1090 mov r0, r1 @ set Dalvik PC 1091 bx r2 1092 @ doesn't return 1093 1094.LinterpPunt: 1095 .word dvmJitToInterpPunt 1096 1097 .size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart 1098/* File: armv5te/footer.S */ 1099/* 1100 * =========================================================================== 1101 * Common subroutines and data 1102 * =========================================================================== 1103 */ 1104 1105 .text 1106 .align 2 1107.LinvokeNative: 1108 @ Prep for the native call 1109 @ r1 = newFP, r0 = methodToCall 1110 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 1111 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 1112 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 1113 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)] 1114 @ newFp->localRefCookie=top 1115 mov r9, r3 @ r9<- glue->self (preserve) 1116 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area 1117 1118 mov r2, r0 @ r2<- methodToCall 1119 mov r0, r1 @ r0<- newFP 1120 add r1, rGLUE, #offGlue_retval @ r1<- &retval 1121 1122 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 1123 1124 @ native return; r9=self, r10=newSaveArea 1125 @ equivalent to dvmPopJniLocals 1126 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret 1127 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top 1128 ldr r1, [r9, #offThread_exception] @ check for exception 1129 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 1130 cmp r1, #0 @ null? 1131 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 1132 ldr r0, [r10, #offStackSaveArea_savedPc] @ reload rPC 1133 bne .LhandleException @ no, handle exception 1134 bx r2 1135 1136/* 1137 * On entry: 1138 * r0 Faulting Dalvik PC 1139 */ 1140.LhandleException: 1141 ldr r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func 1142 ldr rIBASE, .LdvmAsmInstructionStart @ same as above 1143 mov rPC, r0 @ reload the faulting Dalvik address 1144 mov pc, r1 @ branch to dvmMterpCommonExceptionThrown 1145 1146 .align 2 1147.LdvmAsmInstructionStart: 1148 .word dvmAsmInstructionStart 1149.LdvmJitToInterpNoChain: 1150 .word dvmJitToInterpNoChain 1151.LdvmMterpStdBail: 1152 .word dvmMterpStdBail 1153.LdvmMterpCommonExceptionThrown: 1154 .word dvmMterpCommonExceptionThrown 1155.L__aeabi_cdcmple: 1156 .word __aeabi_cdcmple 1157.L__aeabi_cfcmple: 1158 .word __aeabi_cfcmple 1159 1160 .global dmvCompilerTemplateEnd 1161dmvCompilerTemplateEnd: 1162 1163#endif /* WITH_JIT */ 1164 1165