1/* 2 * This file was generated automatically by gen-template.py for 'armv7-a'. 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/* 96 * This is a #include, not a %include, because we want the C pre-processor 97 * to expand the macros into assembler assignment statements. 98 */ 99#include "../../../mterp/common/asm-constants.h" 100 101 102/* File: armv5te/platform.S */ 103/* 104 * =========================================================================== 105 * CPU-version-specific defines 106 * =========================================================================== 107 */ 108 109/* 110 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5. 111 * Jump to subroutine. 112 * 113 * May modify IP and LR. 114 */ 115.macro LDR_PC_LR source 116 mov lr, pc 117 ldr pc, \source 118.endm 119 120 121 .global dvmCompilerTemplateStart 122 .type dvmCompilerTemplateStart, %function 123 .text 124 125dvmCompilerTemplateStart: 126 127/* ------------------------------ */ 128 .balign 4 129 .global dvmCompiler_TEMPLATE_CMP_LONG 130dvmCompiler_TEMPLATE_CMP_LONG: 131/* File: armv5te/TEMPLATE_CMP_LONG.S */ 132 /* 133 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 134 * register based on the results of the comparison. 135 * 136 * We load the full values with LDM, but in practice many values could 137 * be resolved by only looking at the high word. This could be made 138 * faster or slower by splitting the LDM into a pair of LDRs. 139 * 140 * If we just wanted to set condition flags, we could do this: 141 * subs ip, r0, r2 142 * sbcs ip, r1, r3 143 * subeqs ip, r0, r2 144 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 145 * integer value, which we can do with 2 conditional mov/mvn instructions 146 * (set 1, set -1; if they're equal we already have 0 in ip), giving 147 * us a constant 5-cycle path plus a branch at the end to the 148 * instruction epilogue code. The multi-compare approach below needs 149 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 150 * in the worst case (the 64-bit values are equal). 151 */ 152 /* cmp-long vAA, vBB, vCC */ 153 cmp r1, r3 @ compare (vBB+1, vCC+1) 154 blt .LTEMPLATE_CMP_LONG_less @ signed compare on high part 155 bgt .LTEMPLATE_CMP_LONG_greater 156 subs r0, r0, r2 @ r0<- r0 - r2 157 bxeq lr 158 bhi .LTEMPLATE_CMP_LONG_greater @ unsigned compare on low part 159.LTEMPLATE_CMP_LONG_less: 160 mvn r0, #0 @ r0<- -1 161 bx lr 162.LTEMPLATE_CMP_LONG_greater: 163 mov r0, #1 @ r0<- 1 164 bx lr 165 166 167/* ------------------------------ */ 168 .balign 4 169 .global dvmCompiler_TEMPLATE_RETURN 170dvmCompiler_TEMPLATE_RETURN: 171/* File: armv5te/TEMPLATE_RETURN.S */ 172 /* 173 * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX. 174 * If the stored value in returnAddr 175 * is non-zero, the caller is compiled by the JIT thus return to the 176 * address in the code cache following the invoke instruction. Otherwise 177 * return to the special dvmJitToInterpNoChain entry point. 178 */ 179 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 180 ldr r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame 181 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 182 ldr rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc 183 ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret 184 ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)] 185 @ r2<- method we're returning to 186 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 187 cmp r2, #0 @ break frame? 188 beq 1f @ bail to interpreter 189 ldr r0, .LdvmJitToInterpNoChain @ defined in footer.S 190 mov rFP, r10 @ publish new FP 191 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 192 ldr r8, [r8] @ r8<- suspendCount 193 194 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 195 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 196 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 197 add rPC, rPC, #6 @ publish new rPC (advance 6 bytes) 198 str r1, [rGLUE, #offGlue_methodClassDex] 199 cmp r8, #0 @ check the suspendCount 200 movne r9, #0 @ clear the chaining cell address 201 cmp r9, #0 @ chaining cell exists? 202 blxne r9 @ jump to the chaining cell 203 mov pc, r0 @ callsite is interpreted 2041: 205 stmia rGLUE, {rPC, rFP} @ SAVE_PC_FP_TO_GLUE() 206 ldr r2, .LdvmMterpStdBail @ defined in footer.S 207 mov r1, #0 @ changeInterp = false 208 mov r0, rGLUE @ Expecting rGLUE in r0 209 blx r2 @ exit the interpreter 210 211/* ------------------------------ */ 212 .balign 4 213 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT 214dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT: 215/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */ 216 /* 217 * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC 218 * into rPC then jump to dvmJitToInterpNoChain to dispatch the 219 * runtime-resolved callee. 220 */ 221 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 222 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 223 ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize 224 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 225 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 226 add r3, r1, #1 @ Thumb addr is odd 227 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 228 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 229 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 230 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize) 231 ldr r8, [r8] @ r3<- suspendCount (int) 232 cmp r10, r9 @ bottom < interpStackEnd? 233 bxlt lr @ return to raise stack overflow excep. 234 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 235 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz 236 ldr r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags 237 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 238 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 239 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns 240 241 242 @ set up newSaveArea 243 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 244 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 245 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 246 cmp r8, #0 @ suspendCount != 0 247 bxne lr @ bail to the interpreter 248 tst r10, #ACC_NATIVE 249 bne .LinvokeNative 250 251 ldr r10, .LdvmJitToInterpNoChain 252 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 253 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 254 255 @ Update "glue" values for the new method 256 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 257 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 258 mov rFP, r1 @ fp = newFp 259 str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp 260 261 @ Start executing the callee 262 mov pc, r10 @ dvmJitToInterpNoChain 263 264/* ------------------------------ */ 265 .balign 4 266 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN 267dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN: 268/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */ 269 /* 270 * For monomorphic callsite, setup the Dalvik frame and return to the 271 * Thumb code through the link register to transfer control to the callee 272 * method through a dedicated chaining cell. 273 */ 274 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 275 @ methodToCall is guaranteed to be non-native 276.LinvokeChain: 277 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 278 ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize 279 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 280 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 281 add r3, r1, #1 @ Thumb addr is odd 282 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 283 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 284 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 285 add r12, lr, #2 @ setup the punt-to-interp address 286 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize) 287 ldr r8, [r8] @ r3<- suspendCount (int) 288 cmp r10, r9 @ bottom < interpStackEnd? 289 bxlt r12 @ return to raise stack overflow excep. 290 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 291 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz 292 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 293 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 294 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns 295 296 297 @ set up newSaveArea 298 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 299 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 300 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 301 cmp r8, #0 @ suspendCount != 0 302 bxne r12 @ bail to the interpreter 303 304 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 305 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 306 307 @ Update "glue" values for the new method 308 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 309 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 310 mov rFP, r1 @ fp = newFp 311 str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp 312 313 bx lr @ return to the callee-chaining cell 314 315 316 317/* ------------------------------ */ 318 .balign 4 319 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN 320dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN: 321/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */ 322 /* 323 * For polymorphic callsite, check whether the cached class pointer matches 324 * the current one. If so setup the Dalvik frame and return to the 325 * Thumb code through the link register to transfer control to the callee 326 * method through a dedicated chaining cell. 327 * 328 * The predicted chaining cell is declared in ArmLIR.h with the 329 * following layout: 330 * 331 * typedef struct PredictedChainingCell { 332 * u4 branch; 333 * const ClassObject *clazz; 334 * const Method *method; 335 * u4 counter; 336 * } PredictedChainingCell; 337 * 338 * Upon returning to the callsite: 339 * - lr : to branch to the chaining cell 340 * - lr+2: to punt to the interpreter 341 * - lr+4: to fully resolve the callee and may rechain. 342 * r3 <- class 343 * r9 <- counter 344 */ 345 @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite 346 ldr r3, [r0, #offObject_clazz] @ r3 <- this->class 347 ldr r8, [r2, #4] @ r8 <- predictedChainCell->clazz 348 ldr r0, [r2, #8] @ r0 <- predictedChainCell->method 349 ldr r9, [r2, #12] @ r9 <- predictedChainCell->counter 350 cmp r3, r8 @ predicted class == actual class? 351 beq .LinvokeChain @ predicted chain is valid 352 ldr r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable 353 sub r1, r9, #1 @ count-- 354 str r1, [r2, #12] @ write back to PredictedChainingCell->counter 355 add lr, lr, #4 @ return to fully-resolve landing pad 356 /* 357 * r1 <- count 358 * r2 <- &predictedChainCell 359 * r3 <- this->class 360 * r4 <- dPC 361 * r7 <- this->class->vtable 362 */ 363 bx lr 364 365/* ------------------------------ */ 366 .balign 4 367 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE 368dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE: 369/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */ 370 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 371 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 372 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 373 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 374 add r3, r1, #1 @ Thumb addr is odd 375 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 376 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 377 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 378 ldr r8, [r8] @ r3<- suspendCount (int) 379 cmp r10, r9 @ bottom < interpStackEnd? 380 bxlt lr @ return to raise stack overflow excep. 381 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 382 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 383 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 384 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns 385 386 387 @ set up newSaveArea 388 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 389 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 390 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 391 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 392 cmp r8, #0 @ suspendCount != 0 393 ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc 394 bxne lr @ bail to the interpreter 395 396 @ go ahead and transfer control to the native code 397 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 398 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 399 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)] 400 @ newFp->localRefCookie=top 401 mov r9, r3 @ r9<- glue->self (preserve) 402 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area 403 404 mov r2, r0 @ r2<- methodToCall 405 mov r0, r1 @ r0<- newFP 406 add r1, rGLUE, #offGlue_retval @ r1<- &retval 407 408 blx r8 @ off to the native code 409 410 @ native return; r9=self, r10=newSaveArea 411 @ equivalent to dvmPopJniLocals 412 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret 413 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top 414 ldr r1, [r9, #offThread_exception] @ check for exception 415 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 416 cmp r1, #0 @ null? 417 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 418 bne .LhandleException @ no, handle exception 419 bx r2 420 421 422/* ------------------------------ */ 423 .balign 4 424 .global dvmCompiler_TEMPLATE_MUL_LONG 425dvmCompiler_TEMPLATE_MUL_LONG: 426/* File: armv5te/TEMPLATE_MUL_LONG.S */ 427 /* 428 * Signed 64-bit integer multiply. 429 * 430 * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1 431 * 432 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 433 * WX 434 * x YZ 435 * -------- 436 * ZW ZX 437 * YW YX 438 * 439 * The low word of the result holds ZX, the high word holds 440 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 441 * it doesn't fit in the low 64 bits. 442 * 443 * Unlike most ARM math operations, multiply instructions have 444 * restrictions on using the same register more than once (Rd and Rm 445 * cannot be the same). 446 */ 447 /* mul-long vAA, vBB, vCC */ 448 mul ip, r2, r1 @ ip<- ZxW 449 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 450 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 451 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 452 mov r0,r9 453 mov r1,r10 454 bx lr 455 456/* ------------------------------ */ 457 .balign 4 458 .global dvmCompiler_TEMPLATE_SHL_LONG 459dvmCompiler_TEMPLATE_SHL_LONG: 460/* File: armv5te/TEMPLATE_SHL_LONG.S */ 461 /* 462 * Long integer shift. This is different from the generic 32/64-bit 463 * binary operations because vAA/vBB are 64-bit but vCC (the shift 464 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 465 * 6 bits. 466 */ 467 /* shl-long vAA, vBB, vCC */ 468 and r2, r2, #63 @ r2<- r2 & 0x3f 469 mov r1, r1, asl r2 @ r1<- r1 << r2 470 rsb r3, r2, #32 @ r3<- 32 - r2 471 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 472 subs ip, r2, #32 @ ip<- r2 - 32 473 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 474 mov r0, r0, asl r2 @ r0<- r0 << r2 475 bx lr 476 477/* ------------------------------ */ 478 .balign 4 479 .global dvmCompiler_TEMPLATE_SHR_LONG 480dvmCompiler_TEMPLATE_SHR_LONG: 481/* File: armv5te/TEMPLATE_SHR_LONG.S */ 482 /* 483 * Long integer shift. This is different from the generic 32/64-bit 484 * binary operations because vAA/vBB are 64-bit but vCC (the shift 485 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 486 * 6 bits. 487 */ 488 /* shr-long vAA, vBB, vCC */ 489 and r2, r2, #63 @ r0<- r0 & 0x3f 490 mov r0, r0, lsr r2 @ r0<- r2 >> r2 491 rsb r3, r2, #32 @ r3<- 32 - r2 492 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 493 subs ip, r2, #32 @ ip<- r2 - 32 494 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 495 mov r1, r1, asr r2 @ r1<- r1 >> r2 496 bx lr 497 498 499/* ------------------------------ */ 500 .balign 4 501 .global dvmCompiler_TEMPLATE_USHR_LONG 502dvmCompiler_TEMPLATE_USHR_LONG: 503/* File: armv5te/TEMPLATE_USHR_LONG.S */ 504 /* 505 * Long integer shift. This is different from the generic 32/64-bit 506 * binary operations because vAA/vBB are 64-bit but vCC (the shift 507 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 508 * 6 bits. 509 */ 510 /* ushr-long vAA, vBB, vCC */ 511 and r2, r2, #63 @ r0<- r0 & 0x3f 512 mov r0, r0, lsr r2 @ r0<- r2 >> r2 513 rsb r3, r2, #32 @ r3<- 32 - r2 514 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 515 subs ip, r2, #32 @ ip<- r2 - 32 516 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 517 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 518 bx lr 519 520 521/* ------------------------------ */ 522 .balign 4 523 .global dvmCompiler_TEMPLATE_ADD_FLOAT_VFP 524dvmCompiler_TEMPLATE_ADD_FLOAT_VFP: 525/* File: armv5te-vfp/TEMPLATE_ADD_FLOAT_VFP.S */ 526/* File: armv5te-vfp/fbinop.S */ 527 /* 528 * Generic 32-bit floating point operation. Provide an "instr" line that 529 * specifies an instruction that performs s2 = s0 op s1. 530 * 531 * On entry: 532 * r0 = target dalvik register address 533 * r1 = op1 address 534 * r2 = op2 address 535 */ 536 flds s0,[r1] 537 flds s1,[r2] 538 fadds s2, s0, s1 539 fsts s2,[r0] 540 bx lr 541 542 543/* ------------------------------ */ 544 .balign 4 545 .global dvmCompiler_TEMPLATE_SUB_FLOAT_VFP 546dvmCompiler_TEMPLATE_SUB_FLOAT_VFP: 547/* File: armv5te-vfp/TEMPLATE_SUB_FLOAT_VFP.S */ 548/* File: armv5te-vfp/fbinop.S */ 549 /* 550 * Generic 32-bit floating point operation. Provide an "instr" line that 551 * specifies an instruction that performs s2 = s0 op s1. 552 * 553 * On entry: 554 * r0 = target dalvik register address 555 * r1 = op1 address 556 * r2 = op2 address 557 */ 558 flds s0,[r1] 559 flds s1,[r2] 560 fsubs s2, s0, s1 561 fsts s2,[r0] 562 bx lr 563 564 565/* ------------------------------ */ 566 .balign 4 567 .global dvmCompiler_TEMPLATE_MUL_FLOAT_VFP 568dvmCompiler_TEMPLATE_MUL_FLOAT_VFP: 569/* File: armv5te-vfp/TEMPLATE_MUL_FLOAT_VFP.S */ 570/* File: armv5te-vfp/fbinop.S */ 571 /* 572 * Generic 32-bit floating point operation. Provide an "instr" line that 573 * specifies an instruction that performs s2 = s0 op s1. 574 * 575 * On entry: 576 * r0 = target dalvik register address 577 * r1 = op1 address 578 * r2 = op2 address 579 */ 580 flds s0,[r1] 581 flds s1,[r2] 582 fmuls s2, s0, s1 583 fsts s2,[r0] 584 bx lr 585 586 587/* ------------------------------ */ 588 .balign 4 589 .global dvmCompiler_TEMPLATE_DIV_FLOAT_VFP 590dvmCompiler_TEMPLATE_DIV_FLOAT_VFP: 591/* File: armv5te-vfp/TEMPLATE_DIV_FLOAT_VFP.S */ 592/* File: armv5te-vfp/fbinop.S */ 593 /* 594 * Generic 32-bit floating point operation. Provide an "instr" line that 595 * specifies an instruction that performs s2 = s0 op s1. 596 * 597 * On entry: 598 * r0 = target dalvik register address 599 * r1 = op1 address 600 * r2 = op2 address 601 */ 602 flds s0,[r1] 603 flds s1,[r2] 604 fdivs s2, s0, s1 605 fsts s2,[r0] 606 bx lr 607 608 609/* ------------------------------ */ 610 .balign 4 611 .global dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP 612dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP: 613/* File: armv5te-vfp/TEMPLATE_ADD_DOUBLE_VFP.S */ 614/* File: armv5te-vfp/fbinopWide.S */ 615 /* 616 * Generic 64-bit floating point operation. Provide an "instr" line that 617 * specifies an instruction that performs s2 = s0 op s1. 618 * 619 * On entry: 620 * r0 = target dalvik register address 621 * r1 = op1 address 622 * r2 = op2 address 623 */ 624 fldd d0,[r1] 625 fldd d1,[r2] 626 faddd d2, d0, d1 627 fstd d2,[r0] 628 bx lr 629 630 631/* ------------------------------ */ 632 .balign 4 633 .global dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP 634dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP: 635/* File: armv5te-vfp/TEMPLATE_SUB_DOUBLE_VFP.S */ 636/* File: armv5te-vfp/fbinopWide.S */ 637 /* 638 * Generic 64-bit floating point operation. Provide an "instr" line that 639 * specifies an instruction that performs s2 = s0 op s1. 640 * 641 * On entry: 642 * r0 = target dalvik register address 643 * r1 = op1 address 644 * r2 = op2 address 645 */ 646 fldd d0,[r1] 647 fldd d1,[r2] 648 fsubd d2, d0, d1 649 fstd d2,[r0] 650 bx lr 651 652 653/* ------------------------------ */ 654 .balign 4 655 .global dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP 656dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP: 657/* File: armv5te-vfp/TEMPLATE_MUL_DOUBLE_VFP.S */ 658/* File: armv5te-vfp/fbinopWide.S */ 659 /* 660 * Generic 64-bit floating point operation. Provide an "instr" line that 661 * specifies an instruction that performs s2 = s0 op s1. 662 * 663 * On entry: 664 * r0 = target dalvik register address 665 * r1 = op1 address 666 * r2 = op2 address 667 */ 668 fldd d0,[r1] 669 fldd d1,[r2] 670 fmuld d2, d0, d1 671 fstd d2,[r0] 672 bx lr 673 674 675/* ------------------------------ */ 676 .balign 4 677 .global dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP 678dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP: 679/* File: armv5te-vfp/TEMPLATE_DIV_DOUBLE_VFP.S */ 680/* File: armv5te-vfp/fbinopWide.S */ 681 /* 682 * Generic 64-bit floating point operation. Provide an "instr" line that 683 * specifies an instruction that performs s2 = s0 op s1. 684 * 685 * On entry: 686 * r0 = target dalvik register address 687 * r1 = op1 address 688 * r2 = op2 address 689 */ 690 fldd d0,[r1] 691 fldd d1,[r2] 692 fdivd d2, d0, d1 693 fstd d2,[r0] 694 bx lr 695 696 697/* ------------------------------ */ 698 .balign 4 699 .global dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP 700dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP: 701/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_FLOAT_VFP.S */ 702/* File: armv5te-vfp/funopNarrower.S */ 703 /* 704 * Generic 64bit-to-32bit floating point unary operation. Provide an 705 * "instr" line that specifies an instruction that performs "s0 = op d0". 706 * 707 * For: double-to-int, double-to-float 708 * 709 * On entry: 710 * r0 = target dalvik register address 711 * r1 = src dalvik register address 712 */ 713 /* unop vA, vB */ 714 fldd d0, [r1] @ d0<- vB 715 fcvtsd s0, d0 @ s0<- op d0 716 fsts s0, [r0] @ vA<- s0 717 bx lr 718 719 720/* ------------------------------ */ 721 .balign 4 722 .global dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP 723dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP: 724/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_INT_VFP.S */ 725/* File: armv5te-vfp/funopNarrower.S */ 726 /* 727 * Generic 64bit-to-32bit floating point unary operation. Provide an 728 * "instr" line that specifies an instruction that performs "s0 = op d0". 729 * 730 * For: double-to-int, double-to-float 731 * 732 * On entry: 733 * r0 = target dalvik register address 734 * r1 = src dalvik register address 735 */ 736 /* unop vA, vB */ 737 fldd d0, [r1] @ d0<- vB 738 ftosizd s0, d0 @ s0<- op d0 739 fsts s0, [r0] @ vA<- s0 740 bx lr 741 742 743/* ------------------------------ */ 744 .balign 4 745 .global dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP 746dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP: 747/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_DOUBLE_VFP.S */ 748/* File: armv5te-vfp/funopWider.S */ 749 /* 750 * Generic 32bit-to-64bit floating point unary operation. Provide an 751 * "instr" line that specifies an instruction that performs "d0 = op s0". 752 * 753 * For: int-to-double, float-to-double 754 * 755 * On entry: 756 * r0 = target dalvik register address 757 * r1 = src dalvik register address 758 */ 759 /* unop vA, vB */ 760 flds s0, [r1] @ s0<- vB 761 fcvtds d0, s0 @ d0<- op s0 762 fstd d0, [r0] @ vA<- d0 763 bx lr 764 765 766/* ------------------------------ */ 767 .balign 4 768 .global dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP 769dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP: 770/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_INT_VFP.S */ 771/* File: armv5te-vfp/funop.S */ 772 /* 773 * Generic 32bit-to-32bit floating point unary operation. Provide an 774 * "instr" line that specifies an instruction that performs "s1 = op s0". 775 * 776 * For: float-to-int, int-to-float 777 * 778 * On entry: 779 * r0 = target dalvik register address 780 * r1 = src dalvik register address 781 */ 782 /* unop vA, vB */ 783 flds s0, [r1] @ s0<- vB 784 ftosizs s1, s0 @ s1<- op s0 785 fsts s1, [r0] @ vA<- s1 786 bx lr 787 788 789/* ------------------------------ */ 790 .balign 4 791 .global dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP 792dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP: 793/* File: armv5te-vfp/TEMPLATE_INT_TO_DOUBLE_VFP.S */ 794/* File: armv5te-vfp/funopWider.S */ 795 /* 796 * Generic 32bit-to-64bit floating point unary operation. Provide an 797 * "instr" line that specifies an instruction that performs "d0 = op s0". 798 * 799 * For: int-to-double, float-to-double 800 * 801 * On entry: 802 * r0 = target dalvik register address 803 * r1 = src dalvik register address 804 */ 805 /* unop vA, vB */ 806 flds s0, [r1] @ s0<- vB 807 fsitod d0, s0 @ d0<- op s0 808 fstd d0, [r0] @ vA<- d0 809 bx lr 810 811 812/* ------------------------------ */ 813 .balign 4 814 .global dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP 815dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP: 816/* File: armv5te-vfp/TEMPLATE_INT_TO_FLOAT_VFP.S */ 817/* File: armv5te-vfp/funop.S */ 818 /* 819 * Generic 32bit-to-32bit floating point unary operation. Provide an 820 * "instr" line that specifies an instruction that performs "s1 = op s0". 821 * 822 * For: float-to-int, int-to-float 823 * 824 * On entry: 825 * r0 = target dalvik register address 826 * r1 = src dalvik register address 827 */ 828 /* unop vA, vB */ 829 flds s0, [r1] @ s0<- vB 830 fsitos s1, s0 @ s1<- op s0 831 fsts s1, [r0] @ vA<- s1 832 bx lr 833 834 835/* ------------------------------ */ 836 .balign 4 837 .global dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP 838dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP: 839/* File: armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S */ 840 /* 841 * Compare two floating-point values. Puts 0, 1, or -1 into the 842 * destination register based on the results of the comparison. 843 * 844 * int compare(x, y) { 845 * if (x == y) { 846 * return 0; 847 * } else if (x < y) { 848 * return -1; 849 * } else if (x > y) { 850 * return 1; 851 * } else { 852 * return 1; 853 * } 854 * } 855 * 856 * On entry: 857 * r0 = &op1 [vBB] 858 * r1 = &op2 [vCC] 859 */ 860 /* op vAA, vBB, vCC */ 861 fldd d0, [r0] @ d0<- vBB 862 fldd d1, [r1] @ d1<- vCC 863 fcmped d0, d1 @ compare (vBB, vCC) 864 mov r0, #1 @ r0<- 1 (default) 865 fmstat @ export status flags 866 mvnmi r0, #0 @ (less than) r0<- -1 867 moveq r0, #0 @ (equal) r0<- 0 868 bx lr 869 870 871/* ------------------------------ */ 872 .balign 4 873 .global dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP 874dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP: 875/* File: armv5te-vfp/TEMPLATE_CMPL_DOUBLE_VFP.S */ 876 /* 877 * Compare two floating-point values. Puts 0, 1, or -1 into the 878 * destination register based on the results of the comparison. 879 * 880 * int compare(x, y) { 881 * if (x == y) { 882 * return 0; 883 * } else if (x > y) { 884 * return 1; 885 * } else if (x < y) { 886 * return -1; 887 * } else { 888 * return -1; 889 * } 890 * } 891 * On entry: 892 * r0 = &op1 [vBB] 893 * r1 = &op2 [vCC] 894 */ 895 /* op vAA, vBB, vCC */ 896 fldd d0, [r0] @ d0<- vBB 897 fldd d1, [r1] @ d1<- vCC 898 fcmped d0, d1 @ compare (vBB, vCC) 899 mvn r0, #0 @ r0<- -1 (default) 900 fmstat @ export status flags 901 movgt r0, #1 @ (greater than) r0<- 1 902 moveq r0, #0 @ (equal) r0<- 0 903 bx lr 904 905/* ------------------------------ */ 906 .balign 4 907 .global dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP 908dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP: 909/* File: armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S */ 910 /* 911 * Compare two floating-point values. Puts 0, 1, or -1 into the 912 * destination register based on the results of the comparison. 913 * 914 * int compare(x, y) { 915 * if (x == y) { 916 * return 0; 917 * } else if (x < y) { 918 * return -1; 919 * } else if (x > y) { 920 * return 1; 921 * } else { 922 * return 1; 923 * } 924 * } 925 * On entry: 926 * r0 = &op1 [vBB] 927 * r1 = &op2 [vCC] 928 */ 929 /* op vAA, vBB, vCC */ 930 flds s0, [r0] @ d0<- vBB 931 flds s1, [r1] @ d1<- vCC 932 fcmpes s0, s1 @ compare (vBB, vCC) 933 mov r0, #1 @ r0<- 1 (default) 934 fmstat @ export status flags 935 mvnmi r0, #0 @ (less than) r0<- -1 936 moveq r0, #0 @ (equal) r0<- 0 937 bx lr 938 939/* ------------------------------ */ 940 .balign 4 941 .global dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP 942dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP: 943/* File: armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S */ 944 /* 945 * Compare two floating-point values. Puts 0, 1, or -1 into the 946 * destination register based on the results of the comparison. 947 * 948 * int compare(x, y) { 949 * if (x == y) { 950 * return 0; 951 * } else if (x > y) { 952 * return 1; 953 * } else if (x < y) { 954 * return -1; 955 * } else { 956 * return -1; 957 * } 958 * } 959 * On entry: 960 * r0 = &op1 [vBB] 961 * r1 = &op2 [vCC] 962 */ 963 /* op vAA, vBB, vCC */ 964 flds s0, [r0] @ d0<- vBB 965 flds s1, [r1] @ d1<- vCC 966 fcmpes s0, s1 @ compare (vBB, vCC) 967 mvn r0, #0 @ r0<- -1 (default) 968 fmstat @ export status flags 969 movgt r0, #1 @ (greater than) r0<- 1 970 moveq r0, #0 @ (equal) r0<- 0 971 bx lr 972 973/* ------------------------------ */ 974 .balign 4 975 .global dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP 976dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP: 977/* File: armv5te-vfp/TEMPLATE_SQRT_DOUBLE_VFP.S */ 978 /* 979 * 64-bit floating point vfp sqrt operation. 980 * If the result is a NaN, bail out to library code to do 981 * the right thing. 982 * 983 * On entry: 984 * r2 src addr of op1 985 * On exit: 986 * r0,r1 = res 987 */ 988 fldd d0, [r2] 989 fsqrtd d1, d0 990 fcmpd d1, d1 991 fmstat 992 fmrrd r0, r1, d1 993 bxeq lr @ Result OK - return 994 ldr r2, .Lsqrt 995 fmrrd r0, r1, d0 @ reload orig operand 996 bx r2 @ tail call to sqrt library routine 997 998.Lsqrt: 999 .word sqrt 1000 1001 .size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart 1002/* File: armv5te/footer.S */ 1003/* 1004 * =========================================================================== 1005 * Common subroutines and data 1006 * =========================================================================== 1007 */ 1008 1009 .text 1010 .align 2 1011.LinvokeNative: 1012 @ Prep for the native call 1013 @ r1 = newFP, r0 = methodToCall 1014 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 1015 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 1016 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 1017 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)] 1018 @ newFp->localRefCookie=top 1019 mov r9, r3 @ r9<- glue->self (preserve) 1020 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area 1021 1022 mov r2, r0 @ r2<- methodToCall 1023 mov r0, r1 @ r0<- newFP 1024 add r1, rGLUE, #offGlue_retval @ r1<- &retval 1025 1026 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 1027 1028 @ native return; r9=self, r10=newSaveArea 1029 @ equivalent to dvmPopJniLocals 1030 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret 1031 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top 1032 ldr r1, [r9, #offThread_exception] @ check for exception 1033 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 1034 cmp r1, #0 @ null? 1035 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 1036 bne .LhandleException @ no, handle exception 1037 bx r2 1038 1039/* NOTE - this path can be exercised if the JIT threshold is set to 5 */ 1040.LhandleException: 1041 ldr r0, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func 1042 ldr rIBASE, .LdvmAsmInstructionStart @ same as above 1043 ldr rPC, [r10, #offStackSaveArea_savedPc] @ reload rPC 1044 mov pc, r0 @ branch to dvmMterpCommonExceptionThrown 1045 1046 .align 2 1047.LdvmAsmInstructionStart: 1048 .word dvmAsmInstructionStart 1049.LdvmJitToInterpNoChain: 1050 .word dvmJitToInterpNoChain 1051.LdvmMterpStdBail: 1052 .word dvmMterpStdBail 1053.LdvmMterpCommonExceptionThrown: 1054 .word dvmMterpCommonExceptionThrown 1055.L__aeabi_cdcmple: 1056 .word __aeabi_cdcmple 1057.L__aeabi_cfcmple: 1058 .word __aeabi_cfcmple 1059 1060 .global dmvCompilerTemplateEnd 1061dmvCompilerTemplateEnd: 1062 1063#endif /* WITH_JIT */ 1064 1065