1 /* 2 * Copyright (C) 2012 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 #include "asm_support_mips.S" 18 19 #include "arch/quick_alloc_entrypoints.S" 20 21 .set noreorder 22 .balign 4 23 24 /* Deliver the given exception */ 25 .extern artDeliverExceptionFromCode 26 /* Deliver an exception pending on a thread */ 27 .extern artDeliverPendingExceptionFromCode 28 29 /* 30 * Macro that sets up the callee save frame to conform with 31 * Runtime::CreateCalleeSaveMethod(kSaveAll) 32 * callee-save: $s0-$s8 + $gp + $ra, 11 total + 1 word padding + 4 open words for args 33 */ 34 .macro SETUP_SAVE_ALL_CALLEE_SAVE_FRAME 35 addiu $sp, $sp, -64 36 .cfi_adjust_cfa_offset 64 37 38 // Ugly compile-time check, but we only have the preprocessor. 39 #if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVE != 64) 40 #error "SAVE_ALL_CALLEE_SAVE_FRAME(MIPS) size not as expected." 41 #endif 42 43 sw $ra, 60($sp) 44 .cfi_rel_offset 31, 60 45 sw $s8, 56($sp) 46 .cfi_rel_offset 30, 56 47 sw $gp, 52($sp) 48 .cfi_rel_offset 28, 52 49 sw $s7, 48($sp) 50 .cfi_rel_offset 23, 48 51 sw $s6, 44($sp) 52 .cfi_rel_offset 22, 44 53 sw $s5, 40($sp) 54 .cfi_rel_offset 21, 40 55 sw $s4, 36($sp) 56 .cfi_rel_offset 20, 36 57 sw $s3, 32($sp) 58 .cfi_rel_offset 19, 32 59 sw $s2, 28($sp) 60 .cfi_rel_offset 18, 28 61 sw $s1, 24($sp) 62 .cfi_rel_offset 17, 24 63 sw $s0, 20($sp) 64 .cfi_rel_offset 16, 20 65 # 1 word for alignment, 4 open words for args $a0-$a3, bottom will hold Method* 66 .endm 67 68 /* 69 * Macro that sets up the callee save frame to conform with 70 * Runtime::CreateCalleeSaveMethod(kRefsOnly). Restoration assumes non-moving GC. 71 * Does not include rSUSPEND or rSELF 72 * callee-save: $s2-$s8 + $gp + $ra, 9 total + 3 words padding + 4 open words for args 73 */ 74 .macro SETUP_REF_ONLY_CALLEE_SAVE_FRAME 75 addiu $sp, $sp, -64 76 .cfi_adjust_cfa_offset 64 77 78 // Ugly compile-time check, but we only have the preprocessor. 79 #if (FRAME_SIZE_REFS_ONLY_CALLEE_SAVE != 64) 80 #error "REFS_ONLY_CALLEE_SAVE_FRAME(MIPS) size not as expected." 81 #endif 82 83 sw $ra, 60($sp) 84 .cfi_rel_offset 31, 60 85 sw $s8, 56($sp) 86 .cfi_rel_offset 30, 56 87 sw $gp, 52($sp) 88 .cfi_rel_offset 28, 52 89 sw $s7, 48($sp) 90 .cfi_rel_offset 23, 48 91 sw $s6, 44($sp) 92 .cfi_rel_offset 22, 44 93 sw $s5, 40($sp) 94 .cfi_rel_offset 21, 40 95 sw $s4, 36($sp) 96 .cfi_rel_offset 20, 36 97 sw $s3, 32($sp) 98 .cfi_rel_offset 19, 32 99 sw $s2, 28($sp) 100 .cfi_rel_offset 18, 28 101 # 3 words for alignment and extra args, 4 open words for args $a0-$a3, bottom will hold Method* 102 .endm 103 104 .macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME 105 lw $ra, 60($sp) 106 .cfi_restore 31 107 lw $s8, 56($sp) 108 .cfi_restore 30 109 lw $gp, 52($sp) 110 .cfi_restore 28 111 lw $s7, 48($sp) 112 .cfi_restore 23 113 lw $s6, 44($sp) 114 .cfi_restore 22 115 lw $s5, 40($sp) 116 .cfi_restore 21 117 lw $s4, 36($sp) 118 .cfi_restore 20 119 lw $s3, 32($sp) 120 .cfi_restore 19 121 lw $s2, 28($sp) 122 .cfi_restore 18 123 addiu $sp, $sp, 64 124 .cfi_adjust_cfa_offset -64 125 .endm 126 127 .macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN 128 lw $ra, 60($sp) 129 .cfi_restore 31 130 lw $s8, 56($sp) 131 .cfi_restore 30 132 lw $gp, 52($sp) 133 .cfi_restore 28 134 lw $s7, 48($sp) 135 .cfi_restore 23 136 lw $s6, 44($sp) 137 .cfi_restore 22 138 lw $s5, 40($sp) 139 .cfi_restore 21 140 lw $s4, 36($sp) 141 .cfi_restore 20 142 lw $s3, 32($sp) 143 .cfi_restore 19 144 lw $s2, 28($sp) 145 .cfi_restore 18 146 jr $ra 147 addiu $sp, $sp, 64 148 .cfi_adjust_cfa_offset -64 149 .endm 150 151 /* 152 * Macro that sets up the callee save frame to conform with 153 * Runtime::CreateCalleeSaveMethod(kRefsAndArgs). Restoration assumes non-moving GC. 154 * callee-save: $a1-$a3, $s2-$s8 + $gp + $ra, 12 total + 3 words padding + method* 155 */ 156 .macro SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME 157 addiu $sp, $sp, -64 158 .cfi_adjust_cfa_offset 64 159 160 // Ugly compile-time check, but we only have the preprocessor. 161 #if (FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE != 64) 162 #error "REFS_AND_ARGS_CALLEE_SAVE_FRAME(MIPS) size not as expected." 163 #endif 164 165 sw $ra, 60($sp) 166 .cfi_rel_offset 31, 60 167 sw $s8, 56($sp) 168 .cfi_rel_offset 30, 56 169 sw $gp, 52($sp) 170 .cfi_rel_offset 28, 52 171 sw $s7, 48($sp) 172 .cfi_rel_offset 23, 48 173 sw $s6, 44($sp) 174 .cfi_rel_offset 22, 44 175 sw $s5, 40($sp) 176 .cfi_rel_offset 21, 40 177 sw $s4, 36($sp) 178 .cfi_rel_offset 20, 36 179 sw $s3, 32($sp) 180 .cfi_rel_offset 19, 32 181 sw $s2, 28($sp) 182 .cfi_rel_offset 18, 28 183 sw $a3, 12($sp) 184 .cfi_rel_offset 7, 12 185 sw $a2, 8($sp) 186 .cfi_rel_offset 6, 8 187 sw $a1, 4($sp) 188 .cfi_rel_offset 5, 4 189 # bottom will hold Method* 190 .endm 191 192 .macro RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME 193 lw $ra, 60($sp) 194 .cfi_restore 31 195 lw $s8, 56($sp) 196 .cfi_restore 30 197 lw $gp, 52($sp) 198 .cfi_restore 28 199 lw $s7, 48($sp) 200 .cfi_restore 23 201 lw $s6, 44($sp) 202 .cfi_restore 22 203 lw $s5, 40($sp) 204 .cfi_restore 21 205 lw $s4, 36($sp) 206 .cfi_restore 20 207 lw $s3, 32($sp) 208 .cfi_restore 19 209 lw $s2, 28($sp) 210 .cfi_restore 18 211 lw $a3, 12($sp) 212 .cfi_restore 7 213 lw $a2, 8($sp) 214 .cfi_restore 6 215 lw $a1, 4($sp) 216 .cfi_restore 5 217 addiu $sp, $sp, 64 # pop frame 218 .cfi_adjust_cfa_offset -64 219 .endm 220 221 /* 222 * Macro that set calls through to artDeliverPendingExceptionFromCode, where the pending 223 * exception is Thread::Current()->exception_ 224 */ 225 .macro DELIVER_PENDING_EXCEPTION 226 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME # save callee saves for throw 227 move $a0, rSELF # pass Thread::Current 228 la $t9, artDeliverPendingExceptionFromCode 229 jr $t9 # artDeliverPendingExceptionFromCode(Thread*, $sp) 230 move $a1, $sp # pass $sp 231 .endm 232 233 .macro RETURN_IF_NO_EXCEPTION 234 lw $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_ 235 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME 236 bnez $t0, 1f # success if no exception is pending 237 nop 238 jr $ra 239 nop 240 1: 241 DELIVER_PENDING_EXCEPTION 242 .endm 243 244 .macro RETURN_IF_ZERO 245 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME 246 bnez $v0, 1f # success? 247 nop 248 jr $ra # return on success 249 nop 250 1: 251 DELIVER_PENDING_EXCEPTION 252 .endm 253 254 .macro RETURN_IF_RESULT_IS_NON_ZERO 255 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME 256 beqz $v0, 1f # success? 257 nop 258 jr $ra # return on success 259 nop 260 1: 261 DELIVER_PENDING_EXCEPTION 262 .endm 263 264 /* 265 * On entry $a0 is uint32_t* gprs_ and $a1 is uint32_t* fprs_ 266 * FIXME: just guessing about the shape of the jmpbuf. Where will pc be? 267 */ 268 ENTRY art_quick_do_long_jump 269 l.s $f0, 0($a1) 270 l.s $f1, 4($a1) 271 l.s $f2, 8($a1) 272 l.s $f3, 12($a1) 273 l.s $f4, 16($a1) 274 l.s $f5, 20($a1) 275 l.s $f6, 24($a1) 276 l.s $f7, 28($a1) 277 l.s $f8, 32($a1) 278 l.s $f9, 36($a1) 279 l.s $f10, 40($a1) 280 l.s $f11, 44($a1) 281 l.s $f12, 48($a1) 282 l.s $f13, 52($a1) 283 l.s $f14, 56($a1) 284 l.s $f15, 60($a1) 285 l.s $f16, 64($a1) 286 l.s $f17, 68($a1) 287 l.s $f18, 72($a1) 288 l.s $f19, 76($a1) 289 l.s $f20, 80($a1) 290 l.s $f21, 84($a1) 291 l.s $f22, 88($a1) 292 l.s $f23, 92($a1) 293 l.s $f24, 96($a1) 294 l.s $f25, 100($a1) 295 l.s $f26, 104($a1) 296 l.s $f27, 108($a1) 297 l.s $f28, 112($a1) 298 l.s $f29, 116($a1) 299 l.s $f30, 120($a1) 300 l.s $f31, 124($a1) 301 .set push 302 .set nomacro 303 .set noat 304 lw $at, 4($a0) 305 .set pop 306 lw $v0, 8($a0) 307 lw $v1, 12($a0) 308 lw $a1, 20($a0) 309 lw $a2, 24($a0) 310 lw $a3, 28($a0) 311 lw $t0, 32($a0) 312 lw $t1, 36($a0) 313 lw $t2, 40($a0) 314 lw $t3, 44($a0) 315 lw $t4, 48($a0) 316 lw $t5, 52($a0) 317 lw $t6, 56($a0) 318 lw $t7, 60($a0) 319 lw $s0, 64($a0) 320 lw $s1, 68($a0) 321 lw $s2, 72($a0) 322 lw $s3, 76($a0) 323 lw $s4, 80($a0) 324 lw $s5, 84($a0) 325 lw $s6, 88($a0) 326 lw $s7, 92($a0) 327 lw $t8, 96($a0) 328 lw $t9, 100($a0) 329 lw $gp, 112($a0) 330 lw $sp, 116($a0) 331 lw $fp, 120($a0) 332 lw $ra, 124($a0) 333 lw $a0, 16($a0) 334 move $v0, $zero # clear result registers r0 and r1 335 jr $ra # do long jump 336 move $v1, $zero 337 END art_quick_do_long_jump 338 339 /* 340 * Called by managed code, saves most registers (forms basis of long jump context) and passes 341 * the bottom of the stack. artDeliverExceptionFromCode will place the callee save Method* at 342 * the bottom of the thread. On entry r0 holds Throwable* 343 */ 344 ENTRY art_quick_deliver_exception 345 GENERATE_GLOBAL_POINTER 346 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME 347 move $a1, rSELF # pass Thread::Current 348 la $t9, artDeliverExceptionFromCode 349 jr $t9 # artDeliverExceptionFromCode(Throwable*, Thread*, $sp) 350 move $a2, $sp # pass $sp 351 END art_quick_deliver_exception 352 353 /* 354 * Called by managed code to create and deliver a NullPointerException 355 */ 356 .extern artThrowNullPointerExceptionFromCode 357 ENTRY art_quick_throw_null_pointer_exception 358 GENERATE_GLOBAL_POINTER 359 .Lart_quick_throw_null_pointer_exception_gp_set: 360 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME 361 move $a0, rSELF # pass Thread::Current 362 la $t9, artThrowNullPointerExceptionFromCode 363 jr $t9 # artThrowNullPointerExceptionFromCode(Thread*, $sp) 364 move $a1, $sp # pass $sp 365 END art_quick_throw_null_pointer_exception 366 367 /* 368 * Called by managed code to create and deliver an ArithmeticException 369 */ 370 .extern artThrowDivZeroFromCode 371 ENTRY art_quick_throw_div_zero 372 GENERATE_GLOBAL_POINTER 373 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME 374 move $a0, rSELF # pass Thread::Current 375 la $t9, artThrowDivZeroFromCode 376 jr $t9 # artThrowDivZeroFromCode(Thread*, $sp) 377 move $a1, $sp # pass $sp 378 END art_quick_throw_div_zero 379 380 /* 381 * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException 382 */ 383 .extern artThrowArrayBoundsFromCode 384 ENTRY art_quick_throw_array_bounds 385 GENERATE_GLOBAL_POINTER 386 .Lart_quick_throw_array_bounds_gp_set: 387 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME 388 move $a2, rSELF # pass Thread::Current 389 la $t9, artThrowArrayBoundsFromCode 390 jr $t9 # artThrowArrayBoundsFromCode(index, limit, Thread*, $sp) 391 move $a3, $sp # pass $sp 392 END art_quick_throw_array_bounds 393 394 /* 395 * Called by managed code to create and deliver a StackOverflowError. 396 */ 397 .extern artThrowStackOverflowFromCode 398 ENTRY art_quick_throw_stack_overflow 399 GENERATE_GLOBAL_POINTER 400 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME 401 move $a0, rSELF # pass Thread::Current 402 la $t9, artThrowStackOverflowFromCode 403 jr $t9 # artThrowStackOverflowFromCode(Thread*, $sp) 404 move $a1, $sp # pass $sp 405 END art_quick_throw_stack_overflow 406 407 /* 408 * Called by managed code to create and deliver a NoSuchMethodError. 409 */ 410 .extern artThrowNoSuchMethodFromCode 411 ENTRY art_quick_throw_no_such_method 412 GENERATE_GLOBAL_POINTER 413 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME 414 move $a1, rSELF # pass Thread::Current 415 la $t9, artThrowNoSuchMethodFromCode 416 jr $t9 # artThrowNoSuchMethodFromCode(method_idx, Thread*, $sp) 417 move $a2, $sp # pass $sp 418 END art_quick_throw_no_such_method 419 420 /* 421 * All generated callsites for interface invokes and invocation slow paths will load arguments 422 * as usual - except instead of loading arg0/$a0 with the target Method*, arg0/$a0 will contain 423 * the method_idx. This wrapper will save arg1-arg3, load the caller's Method*, align the 424 * stack and call the appropriate C helper. 425 * NOTE: "this" is first visable argument of the target, and so can be found in arg1/$a1. 426 * 427 * The helper will attempt to locate the target and return a 64-bit result in $v0/$v1 consisting 428 * of the target Method* in $v0 and method->code_ in $v1. 429 * 430 * If unsuccessful, the helper will return NULL/NULL. There will be a pending exception in the 431 * thread and we branch to another stub to deliver it. 432 * 433 * On success this wrapper will restore arguments and *jump* to the target, leaving the lr 434 * pointing back to the original caller. 435 */ 436 .macro INVOKE_TRAMPOLINE c_name, cxx_name 437 .extern \cxx_name 438 ENTRY \c_name 439 GENERATE_GLOBAL_POINTER 440 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME # save callee saves in case allocation triggers GC 441 lw $a2, 64($sp) # pass caller Method* 442 move $t0, $sp # save $sp 443 addiu $sp, $sp, -32 # make space for extra args 444 .cfi_adjust_cfa_offset 32 445 move $a3, rSELF # pass Thread::Current 446 .cfi_rel_offset 28, 12 447 jal \cxx_name # (method_idx, this, caller, Thread*, $sp) 448 sw $t0, 16($sp) # pass $sp 449 addiu $sp, $sp, 32 # release out args 450 .cfi_adjust_cfa_offset -32 451 move $a0, $v0 # save target Method* 452 move $t9, $v1 # save $v0->code_ 453 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME 454 beqz $v0, 1f 455 nop 456 jr $t9 457 nop 458 1: 459 DELIVER_PENDING_EXCEPTION 460 END \c_name 461 .endm 462 463 INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline, artInvokeInterfaceTrampoline 464 INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck 465 466 INVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck 467 INVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck 468 INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck 469 INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck 470 471 /* 472 * Invocation stub for quick code. 473 * On entry: 474 * a0 = method pointer 475 * a1 = argument array or NULL for no argument methods 476 * a2 = size of argument array in bytes 477 * a3 = (managed) thread pointer 478 * [sp + 16] = JValue* result 479 * [sp + 20] = shorty 480 */ 481 ENTRY art_quick_invoke_stub 482 GENERATE_GLOBAL_POINTER 483 sw $a0, 0($sp) # save out a0 484 addiu $sp, $sp, -16 # spill s0, s1, fp, ra 485 .cfi_adjust_cfa_offset 16 486 sw $ra, 12($sp) 487 .cfi_rel_offset 31, 12 488 sw $fp, 8($sp) 489 .cfi_rel_offset 30, 8 490 sw $s1, 4($sp) 491 .cfi_rel_offset 17, 4 492 sw $s0, 0($sp) 493 .cfi_rel_offset 16, 0 494 move $fp, $sp # save sp in fp 495 .cfi_def_cfa_register 30 496 move $s1, $a3 # move managed thread pointer into s1 497 addiu $s0, $zero, SUSPEND_CHECK_INTERVAL # reset s0 to suspend check interval 498 addiu $t0, $a2, 16 # create space for method pointer in frame 499 srl $t0, $t0, 4 # shift the frame size right 4 500 sll $t0, $t0, 4 # shift the frame size left 4 to align to 16 bytes 501 subu $sp, $sp, $t0 # reserve stack space for argument array 502 addiu $a0, $sp, 4 # pass stack pointer + method ptr as dest for memcpy 503 jal memcpy # (dest, src, bytes) 504 addiu $sp, $sp, -16 # make space for argument slots for memcpy 505 addiu $sp, $sp, 16 # restore stack after memcpy 506 lw $a0, 16($fp) # restore method* 507 lw $a1, 4($sp) # copy arg value for a1 508 lw $a2, 8($sp) # copy arg value for a2 509 lw $a3, 12($sp) # copy arg value for a3 510 lw $t9, METHOD_QUICK_CODE_OFFSET_32($a0) # get pointer to the code 511 jalr $t9 # call the method 512 sw $zero, 0($sp) # store NULL for method* at bottom of frame 513 move $sp, $fp # restore the stack 514 lw $s0, 0($sp) 515 .cfi_restore 16 516 lw $s1, 4($sp) 517 .cfi_restore 17 518 lw $fp, 8($sp) 519 .cfi_restore 30 520 lw $ra, 12($sp) 521 .cfi_restore 31 522 addiu $sp, $sp, 16 523 .cfi_adjust_cfa_offset -16 524 lw $t0, 16($sp) # get result pointer 525 lw $t1, 20($sp) # get shorty 526 lb $t1, 0($t1) # get result type char 527 li $t2, 68 # put char 'D' into t2 528 beq $t1, $t2, 1f # branch if result type char == 'D' 529 li $t3, 70 # put char 'F' into t3 530 beq $t1, $t3, 1f # branch if result type char == 'F' 531 sw $v0, 0($t0) # store the result 532 jr $ra 533 sw $v1, 4($t0) # store the other half of the result 534 1: 535 s.s $f0, 0($t0) # store floating point result 536 jr $ra 537 s.s $f1, 4($t0) # store other half of floating point result 538 END art_quick_invoke_stub 539 540 /* 541 * Entry from managed code that calls artHandleFillArrayDataFromCode and delivers exception on 542 * failure. 543 */ 544 .extern artHandleFillArrayDataFromCode 545 ENTRY art_quick_handle_fill_data 546 GENERATE_GLOBAL_POINTER 547 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case exception allocation triggers GC 548 move $a2, rSELF # pass Thread::Current 549 jal artHandleFillArrayDataFromCode # (Array*, const DexFile::Payload*, Thread*, $sp) 550 move $a3, $sp # pass $sp 551 RETURN_IF_ZERO 552 END art_quick_handle_fill_data 553 554 /* 555 * Entry from managed code that calls artLockObjectFromCode, may block for GC. 556 */ 557 .extern artLockObjectFromCode 558 ENTRY art_quick_lock_object 559 GENERATE_GLOBAL_POINTER 560 beqz $a0, .Lart_quick_throw_null_pointer_exception_gp_set 561 nop 562 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case we block 563 move $a1, rSELF # pass Thread::Current 564 jal artLockObjectFromCode # (Object* obj, Thread*, $sp) 565 move $a2, $sp # pass $sp 566 RETURN_IF_ZERO 567 END art_quick_lock_object 568 569 /* 570 * Entry from managed code that calls artUnlockObjectFromCode and delivers exception on failure. 571 */ 572 .extern artUnlockObjectFromCode 573 ENTRY art_quick_unlock_object 574 GENERATE_GLOBAL_POINTER 575 beqz $a0, .Lart_quick_throw_null_pointer_exception_gp_set 576 nop 577 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case exception allocation triggers GC 578 move $a1, rSELF # pass Thread::Current 579 jal artUnlockObjectFromCode # (Object* obj, Thread*, $sp) 580 move $a2, $sp # pass $sp 581 RETURN_IF_ZERO 582 END art_quick_unlock_object 583 584 /* 585 * Entry from managed code that calls artCheckCastFromCode and delivers exception on failure. 586 */ 587 .extern artThrowClassCastException 588 ENTRY art_quick_check_cast 589 GENERATE_GLOBAL_POINTER 590 addiu $sp, $sp, -16 591 .cfi_adjust_cfa_offset 16 592 sw $ra, 12($sp) 593 .cfi_rel_offset 31, 12 594 sw $t9, 8($sp) 595 sw $a1, 4($sp) 596 sw $a0, 0($sp) 597 jal artIsAssignableFromCode 598 nop 599 beqz $v0, .Lthrow_class_cast_exception 600 lw $ra, 12($sp) 601 jr $ra 602 addiu $sp, $sp, 16 603 .cfi_adjust_cfa_offset -16 604 .Lthrow_class_cast_exception: 605 lw $t9, 8($sp) 606 lw $a1, 4($sp) 607 lw $a0, 0($sp) 608 addiu $sp, $sp, 16 609 .cfi_adjust_cfa_offset -16 610 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME 611 move $a2, rSELF # pass Thread::Current 612 la $t9, artThrowClassCastException 613 jr $t9 # artThrowClassCastException (Class*, Class*, Thread*, SP) 614 move $a3, $sp # pass $sp 615 END art_quick_check_cast 616 617 /* 618 * Entry from managed code for array put operations of objects where the value being stored 619 * needs to be checked for compatibility. 620 * a0 = array, a1 = index, a2 = value 621 */ 622 ENTRY art_quick_aput_obj_with_null_and_bound_check 623 GENERATE_GLOBAL_POINTER 624 bnez $a0, .Lart_quick_aput_obj_with_bound_check_gp_set 625 nop 626 b .Lart_quick_throw_null_pointer_exception_gp_set 627 nop 628 END art_quick_aput_obj_with_null_and_bound_check 629 630 ENTRY art_quick_aput_obj_with_bound_check 631 GENERATE_GLOBAL_POINTER 632 .Lart_quick_aput_obj_with_bound_check_gp_set: 633 lw $t0, ARRAY_LENGTH_OFFSET($a0) 634 sltu $t1, $a1, $t0 635 bnez $t1, .Lart_quick_aput_obj_gp_set 636 nop 637 move $a0, $a1 638 b .Lart_quick_throw_array_bounds_gp_set 639 move $a1, $t0 640 END art_quick_aput_obj_with_bound_check 641 642 ENTRY art_quick_aput_obj 643 GENERATE_GLOBAL_POINTER 644 .Lart_quick_aput_obj_gp_set: 645 beqz $a2, .Ldo_aput_null 646 nop 647 lw $t0, CLASS_OFFSET($a0) 648 lw $t1, CLASS_OFFSET($a2) 649 lw $t0, CLASS_COMPONENT_TYPE_OFFSET($t0) 650 bne $t1, $t0, .Lcheck_assignability # value's type == array's component type - trivial assignability 651 nop 652 .Ldo_aput: 653 sll $a1, $a1, 2 654 add $t0, $a0, $a1 655 sw $a2, OBJECT_ARRAY_DATA_OFFSET($t0) 656 lw $t0, THREAD_CARD_TABLE_OFFSET(rSELF) 657 srl $t1, $a0, 7 658 add $t1, $t1, $t0 659 sb $t0, ($t1) 660 jr $ra 661 nop 662 .Ldo_aput_null: 663 sll $a1, $a1, 2 664 add $t0, $a0, $a1 665 sw $a2, OBJECT_ARRAY_DATA_OFFSET($t0) 666 jr $ra 667 nop 668 .Lcheck_assignability: 669 addiu $sp, $sp, -32 670 .cfi_adjust_cfa_offset 32 671 sw $ra, 28($sp) 672 .cfi_rel_offset 31, 28 673 sw $t9, 12($sp) 674 sw $a2, 8($sp) 675 sw $a1, 4($sp) 676 sw $a0, 0($sp) 677 move $a1, $t1 678 move $a0, $t0 679 jal artIsAssignableFromCode # (Class*, Class*) 680 nop 681 lw $ra, 28($sp) 682 lw $t9, 12($sp) 683 lw $a2, 8($sp) 684 lw $a1, 4($sp) 685 lw $a0, 0($sp) 686 add $sp, 32 687 .cfi_adjust_cfa_offset -32 688 bnez $v0, .Ldo_aput 689 nop 690 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME 691 move $a1, $a2 692 move $a2, rSELF # pass Thread::Current 693 la $t9, artThrowArrayStoreException 694 jr $t9 # artThrowArrayStoreException(Class*, Class*, Thread*, SP) 695 move $a3, $sp # pass $sp 696 END art_quick_aput_obj 697 698 /* 699 * Entry from managed code when uninitialized static storage, this stub will run the class 700 * initializer and deliver the exception on error. On success the static storage base is 701 * returned. 702 */ 703 .extern artInitializeStaticStorageFromCode 704 ENTRY art_quick_initialize_static_storage 705 GENERATE_GLOBAL_POINTER 706 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC 707 move $a2, rSELF # pass Thread::Current 708 # artInitializeStaticStorageFromCode(uint32_t type_idx, Method* referrer, Thread*, $sp) 709 jal artInitializeStaticStorageFromCode 710 move $a3, $sp # pass $sp 711 RETURN_IF_RESULT_IS_NON_ZERO 712 END art_quick_initialize_static_storage 713 714 /* 715 * Entry from managed code when dex cache misses for a type_idx. 716 */ 717 .extern artInitializeTypeFromCode 718 ENTRY art_quick_initialize_type 719 GENERATE_GLOBAL_POINTER 720 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC 721 move $a2, rSELF # pass Thread::Current 722 # artInitializeTypeFromCode(uint32_t type_idx, Method* referrer, Thread*, $sp) 723 jal artInitializeTypeFromCode 724 move $a3, $sp # pass $sp 725 RETURN_IF_RESULT_IS_NON_ZERO 726 END art_quick_initialize_type 727 728 /* 729 * Entry from managed code when type_idx needs to be checked for access and dex cache may also 730 * miss. 731 */ 732 .extern artInitializeTypeAndVerifyAccessFromCode 733 ENTRY art_quick_initialize_type_and_verify_access 734 GENERATE_GLOBAL_POINTER 735 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC 736 move $a2, rSELF # pass Thread::Current 737 # artInitializeTypeFromCode(uint32_t type_idx, Method* referrer, Thread*, $sp) 738 jal artInitializeTypeAndVerifyAccessFromCode 739 move $a3, $sp # pass $sp 740 RETURN_IF_RESULT_IS_NON_ZERO 741 END art_quick_initialize_type_and_verify_access 742 743 /* 744 * Called by managed code to resolve a static field and load a 32-bit primitive value. 745 */ 746 .extern artGet32StaticFromCode 747 ENTRY art_quick_get32_static 748 GENERATE_GLOBAL_POINTER 749 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC 750 lw $a1, 64($sp) # pass referrer's Method* 751 move $a2, rSELF # pass Thread::Current 752 jal artGet32StaticFromCode # (uint32_t field_idx, const Method* referrer, Thread*, $sp) 753 move $a3, $sp # pass $sp 754 RETURN_IF_NO_EXCEPTION 755 END art_quick_get32_static 756 757 /* 758 * Called by managed code to resolve a static field and load a 64-bit primitive value. 759 */ 760 .extern artGet64StaticFromCode 761 ENTRY art_quick_get64_static 762 GENERATE_GLOBAL_POINTER 763 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC 764 lw $a1, 64($sp) # pass referrer's Method* 765 move $a2, rSELF # pass Thread::Current 766 jal artGet64StaticFromCode # (uint32_t field_idx, const Method* referrer, Thread*, $sp) 767 move $a3, $sp # pass $sp 768 RETURN_IF_NO_EXCEPTION 769 END art_quick_get64_static 770 771 /* 772 * Called by managed code to resolve a static field and load an object reference. 773 */ 774 .extern artGetObjStaticFromCode 775 ENTRY art_quick_get_obj_static 776 GENERATE_GLOBAL_POINTER 777 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC 778 lw $a1, 64($sp) # pass referrer's Method* 779 move $a2, rSELF # pass Thread::Current 780 jal artGetObjStaticFromCode # (uint32_t field_idx, const Method* referrer, Thread*, $sp) 781 move $a3, $sp # pass $sp 782 RETURN_IF_NO_EXCEPTION 783 END art_quick_get_obj_static 784 785 /* 786 * Called by managed code to resolve an instance field and load a 32-bit primitive value. 787 */ 788 .extern artGet32InstanceFromCode 789 ENTRY art_quick_get32_instance 790 GENERATE_GLOBAL_POINTER 791 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC 792 lw $a2, 64($sp) # pass referrer's Method* 793 move $a3, rSELF # pass Thread::Current 794 jal artGet32InstanceFromCode # (field_idx, Object*, referrer, Thread*, $sp) 795 sw $sp, 16($sp) # pass $sp 796 RETURN_IF_NO_EXCEPTION 797 END art_quick_get32_instance 798 799 /* 800 * Called by managed code to resolve an instance field and load a 64-bit primitive value. 801 */ 802 .extern artGet64InstanceFromCode 803 ENTRY art_quick_get64_instance 804 GENERATE_GLOBAL_POINTER 805 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC 806 lw $a2, 64($sp) # pass referrer's Method* 807 move $a3, rSELF # pass Thread::Current 808 jal artGet64InstanceFromCode # (field_idx, Object*, referrer, Thread*, $sp) 809 sw $sp, 16($sp) # pass $sp 810 RETURN_IF_NO_EXCEPTION 811 END art_quick_get64_instance 812 813 /* 814 * Called by managed code to resolve an instance field and load an object reference. 815 */ 816 .extern artGetObjInstanceFromCode 817 ENTRY art_quick_get_obj_instance 818 GENERATE_GLOBAL_POINTER 819 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC 820 lw $a2, 64($sp) # pass referrer's Method* 821 move $a3, rSELF # pass Thread::Current 822 jal artGetObjInstanceFromCode # (field_idx, Object*, referrer, Thread*, $sp) 823 sw $sp, 16($sp) # pass $sp 824 RETURN_IF_NO_EXCEPTION 825 END art_quick_get_obj_instance 826 827 /* 828 * Called by managed code to resolve a static field and store a 32-bit primitive value. 829 */ 830 .extern artSet32StaticFromCode 831 ENTRY art_quick_set32_static 832 GENERATE_GLOBAL_POINTER 833 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC 834 lw $a2, 64($sp) # pass referrer's Method* 835 move $a3, rSELF # pass Thread::Current 836 jal artSet32StaticFromCode # (field_idx, new_val, referrer, Thread*, $sp) 837 sw $sp, 16($sp) # pass $sp 838 RETURN_IF_ZERO 839 END art_quick_set32_static 840 841 /* 842 * Called by managed code to resolve a static field and store a 64-bit primitive value. 843 */ 844 .extern artSet32StaticFromCode 845 ENTRY art_quick_set64_static 846 GENERATE_GLOBAL_POINTER 847 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC 848 lw $a1, 64($sp) # pass referrer's Method* 849 sw rSELF, 16($sp) # pass Thread::Current 850 jal artSet64StaticFromCode # (field_idx, referrer, new_val, Thread*, $sp) 851 sw $sp, 20($sp) # pass $sp 852 RETURN_IF_ZERO 853 END art_quick_set64_static 854 855 /* 856 * Called by managed code to resolve a static field and store an object reference. 857 */ 858 .extern artSetObjStaticFromCode 859 ENTRY art_quick_set_obj_static 860 GENERATE_GLOBAL_POINTER 861 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC 862 lw $a2, 64($sp) # pass referrer's Method* 863 move $a3, rSELF # pass Thread::Current 864 jal artSetObjStaticFromCode # (field_idx, new_val, referrer, Thread*, $sp) 865 sw $sp, 16($sp) # pass $sp 866 RETURN_IF_ZERO 867 END art_quick_set_obj_static 868 869 /* 870 * Called by managed code to resolve an instance field and store a 32-bit primitive value. 871 */ 872 .extern artSet32InstanceFromCode 873 ENTRY art_quick_set32_instance 874 GENERATE_GLOBAL_POINTER 875 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC 876 lw $a3, 64($sp) # pass referrer's Method* 877 sw rSELF, 16($sp) # pass Thread::Current 878 jal artSet32InstanceFromCode # (field_idx, Object*, new_val, referrer, Thread*, $sp) 879 sw $sp, 20($sp) # pass $sp 880 RETURN_IF_ZERO 881 END art_quick_set32_instance 882 883 /* 884 * Called by managed code to resolve an instance field and store a 64-bit primitive value. 885 */ 886 .extern artSet32InstanceFromCode 887 ENTRY art_quick_set64_instance 888 GENERATE_GLOBAL_POINTER 889 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC 890 sw rSELF, 16($sp) # pass Thread::Current 891 jal artSet64InstanceFromCode # (field_idx, Object*, new_val, Thread*, $sp) 892 sw $sp, 20($sp) # pass $sp 893 RETURN_IF_ZERO 894 END art_quick_set64_instance 895 896 /* 897 * Called by managed code to resolve an instance field and store an object reference. 898 */ 899 .extern artSetObjInstanceFromCode 900 ENTRY art_quick_set_obj_instance 901 GENERATE_GLOBAL_POINTER 902 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC 903 lw $a3, 64($sp) # pass referrer's Method* 904 sw rSELF, 16($sp) # pass Thread::Current 905 jal artSetObjInstanceFromCode # (field_idx, Object*, new_val, referrer, Thread*, $sp) 906 sw $sp, 20($sp) # pass $sp 907 RETURN_IF_ZERO 908 END art_quick_set_obj_instance 909 910 /* 911 * Entry from managed code to resolve a string, this stub will allocate a String and deliver an 912 * exception on error. On success the String is returned. R0 holds the referring method, 913 * R1 holds the string index. The fast path check for hit in strings cache has already been 914 * performed. 915 */ 916 .extern artResolveStringFromCode 917 ENTRY art_quick_resolve_string 918 GENERATE_GLOBAL_POINTER 919 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC 920 move $a2, rSELF # pass Thread::Current 921 # artResolveStringFromCode(Method* referrer, uint32_t string_idx, Thread*, $sp) 922 jal artResolveStringFromCode 923 move $a3, $sp # pass $sp 924 RETURN_IF_RESULT_IS_NON_ZERO 925 END art_quick_resolve_string 926 927 928 // Macro to facilitate adding new allocation entrypoints. 929 .macro TWO_ARG_DOWNCALL name, entrypoint, return 930 .extern \entrypoint 931 ENTRY \name 932 GENERATE_GLOBAL_POINTER 933 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC 934 move $a2, rSELF # pass Thread::Current 935 jal \entrypoint 936 move $a3, $sp # pass $sp 937 \return 938 END \name 939 .endm 940 941 .macro THREE_ARG_DOWNCALL name, entrypoint, return 942 .extern \entrypoint 943 ENTRY \name 944 GENERATE_GLOBAL_POINTER 945 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC 946 move $a3, rSELF # pass Thread::Current 947 jal \entrypoint 948 sw $sp, 16($sp) # pass $sp 949 \return 950 END \name 951 .endm 952 953 // Generate the allocation entrypoints for each allocator. 954 GENERATE_ALL_ALLOC_ENTRYPOINTS 955 956 /* 957 * Called by managed code when the value in rSUSPEND has been decremented to 0. 958 */ 959 .extern artTestSuspendFromCode 960 ENTRY art_quick_test_suspend 961 GENERATE_GLOBAL_POINTER 962 lh $a0, THREAD_FLAGS_OFFSET(rSELF) 963 bnez $a0, 1f 964 addi rSUSPEND, $zero, SUSPEND_CHECK_INTERVAL # reset rSUSPEND to SUSPEND_CHECK_INTERVAL 965 jr $ra 966 nop 967 1: 968 move $a0, rSELF 969 SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves for stack crawl 970 jal artTestSuspendFromCode # (Thread*, $sp) 971 move $a1, $sp 972 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN 973 END art_quick_test_suspend 974 975 /* 976 * Called by managed code that is attempting to call a method on a proxy class. On entry 977 * r0 holds the proxy method; r1, r2 and r3 may contain arguments. 978 */ 979 .extern artQuickProxyInvokeHandler 980 ENTRY art_quick_proxy_invoke_handler 981 GENERATE_GLOBAL_POINTER 982 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME 983 sw $a0, 0($sp) # place proxy method at bottom of frame 984 move $a2, rSELF # pass Thread::Current 985 jal artQuickProxyInvokeHandler # (Method* proxy method, receiver, Thread*, SP) 986 move $a3, $sp # pass $sp 987 lw $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_ 988 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME 989 bnez $t0, 1f 990 mtc1 $v0, $f0 # place return value to FP return value 991 jr $ra 992 mtc1 $v1, $f1 # place return value to FP return value 993 1: 994 DELIVER_PENDING_EXCEPTION 995 END art_quick_proxy_invoke_handler 996 997 /* 998 * Called to resolve an imt conflict. t0 is a hidden argument that holds the target method's 999 * dex method index. 1000 */ 1001 ENTRY art_quick_imt_conflict_trampoline 1002 GENERATE_GLOBAL_POINTER 1003 lw $a0, 0($sp) # load caller Method* 1004 lw $a0, METHOD_DEX_CACHE_METHODS_OFFSET($a0) # load dex_cache_resolved_methods 1005 sll $t0, 2 # convert target method offset to bytes 1006 add $a0, $t0 # get address of target method 1007 lw $a0, OBJECT_ARRAY_DATA_OFFSET($a0) # load the target method 1008 la $t9, art_quick_invoke_interface_trampoline 1009 jr $t9 1010 END art_quick_imt_conflict_trampoline 1011 1012 .extern artQuickResolutionTrampoline 1013 ENTRY art_quick_resolution_trampoline 1014 GENERATE_GLOBAL_POINTER 1015 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME 1016 move $a2, rSELF # pass Thread::Current 1017 jal artQuickResolutionTrampoline # (Method* called, receiver, Thread*, SP) 1018 move $a3, $sp # pass $sp 1019 beqz $v0, 1f 1020 lw $a0, 0($sp) # load resolved method to $a0 1021 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME 1022 move $t9, $v0 # code pointer must be in $t9 to generate the global pointer 1023 jr $v0 # tail call to method 1024 nop 1025 1: 1026 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME 1027 DELIVER_PENDING_EXCEPTION 1028 END art_quick_resolution_trampoline 1029 1030 UNIMPLEMENTED art_quick_generic_jni_trampoline 1031 1032 .extern artQuickToInterpreterBridge 1033 ENTRY art_quick_to_interpreter_bridge 1034 GENERATE_GLOBAL_POINTER 1035 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME 1036 move $a1, rSELF # pass Thread::Current 1037 jal artQuickToInterpreterBridge # (Method* method, Thread*, SP) 1038 move $a2, $sp # pass $sp 1039 lw $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_ 1040 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME 1041 bnez $t0, 1f 1042 mtc1 $v0, $f0 # place return value to FP return value 1043 jr $ra 1044 mtc1 $v1, $f1 # place return value to FP return value 1045 1: 1046 DELIVER_PENDING_EXCEPTION 1047 END art_quick_to_interpreter_bridge 1048 1049 /* 1050 * Routine that intercepts method calls and returns. 1051 */ 1052 .extern artInstrumentationMethodEntryFromCode 1053 .extern artInstrumentationMethodExitFromCode 1054 ENTRY art_quick_instrumentation_entry 1055 GENERATE_GLOBAL_POINTER 1056 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME 1057 move $t0, $sp # remember bottom of caller's frame 1058 addiu $sp, $sp, -32 # space for args, pad (3 words), arguments (5 words) 1059 .cfi_adjust_cfa_offset 32 1060 sw $a0, 28($sp) # save arg0 1061 sw $ra, 16($sp) # pass $ra 1062 move $a3, $t0 # pass $sp 1063 jal artInstrumentationMethodEntryFromCode # (Method*, Object*, Thread*, SP, LR) 1064 move $a2, rSELF # pass Thread::Current 1065 move $t9, $v0 # $t9 holds reference to code 1066 lw $a0, 28($sp) # restore arg0 1067 addiu $sp, $sp, 32 # remove args 1068 .cfi_adjust_cfa_offset -32 1069 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME 1070 jalr $t9 # call method 1071 nop 1072 END art_quick_instrumentation_entry 1073 /* intentional fallthrough */ 1074 .global art_quick_instrumentation_exit 1075 art_quick_instrumentation_exit: 1076 .cfi_startproc 1077 addiu $t9, $ra, 4 # put current address into $t9 to rebuild $gp 1078 GENERATE_GLOBAL_POINTER 1079 move $ra, $zero # link register is to here, so clobber with 0 for later checks 1080 SETUP_REF_ONLY_CALLEE_SAVE_FRAME 1081 move $t0, $sp # remember bottom of caller's frame 1082 addiu $sp, $sp, -48 # save return values and set up args 1083 .cfi_adjust_cfa_offset 48 1084 sw $v0, 32($sp) 1085 .cfi_rel_offset 2, 32 1086 sw $v1, 36($sp) 1087 .cfi_rel_offset 3, 36 1088 s.s $f0, 40($sp) 1089 s.s $f1, 44($sp) 1090 s.s $f0, 16($sp) # pass fpr result 1091 s.s $f1, 20($sp) 1092 move $a2, $v0 # pass gpr result 1093 move $a3, $v1 1094 move $a1, $t0 # pass $sp 1095 jal artInstrumentationMethodExitFromCode # (Thread*, SP, gpr_res, fpr_res) 1096 move $a0, rSELF # pass Thread::Current 1097 move $t0, $v0 # set aside returned link register 1098 move $ra, $v1 # set link register for deoptimization 1099 lw $v0, 32($sp) # restore return values 1100 lw $v1, 36($sp) 1101 l.s $f0, 40($sp) 1102 l.s $f1, 44($sp) 1103 jr $t0 # return 1104 addiu $sp, $sp, 112 # 48 bytes of args + 64 bytes of callee save frame 1105 .cfi_adjust_cfa_offset -112 1106 END art_quick_instrumentation_exit 1107 1108 /* 1109 * Instrumentation has requested that we deoptimize into the interpreter. The deoptimization 1110 * will long jump to the upcall with a special exception of -1. 1111 */ 1112 .extern artDeoptimize 1113 .extern artEnterInterpreterFromDeoptimize 1114 ENTRY art_quick_deoptimize 1115 GENERATE_GLOBAL_POINTER 1116 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME 1117 move $a0, rSELF # pass Thread::current 1118 jal artDeoptimize # artDeoptimize(Thread*, SP) 1119 # Returns caller method's frame size. 1120 move $a1, $sp # pass $sp 1121 END art_quick_deoptimize 1122 1123 /* 1124 * Long integer shift. This is different from the generic 32/64-bit 1125 * binary operations because vAA/vBB are 64-bit but vCC (the shift 1126 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 1127 * 6 bits. 1128 * On entry: 1129 * $a0: low word 1130 * $a1: high word 1131 * $a2: shift count 1132 */ 1133 ENTRY art_quick_shl_long 1134 /* shl-long vAA, vBB, vCC */ 1135 sll $v0, $a0, $a2 # rlo<- alo << (shift&31) 1136 not $v1, $a2 # rhi<- 31-shift (shift is 5b) 1137 srl $a0, 1 1138 srl $a0, $v1 # alo<- alo >> (32-(shift&31)) 1139 sll $v1, $a1, $a2 # rhi<- ahi << (shift&31) 1140 or $v1, $a0 # rhi<- rhi | alo 1141 andi $a2, 0x20 # shift< shift & 0x20 1142 movn $v1, $v0, $a2 # rhi<- rlo (if shift&0x20) 1143 jr $ra 1144 movn $v0, $zero, $a2 # rlo<- 0 (if shift&0x20) 1145 END art_quick_shl_long 1146 1147 /* 1148 * Long integer shift. This is different from the generic 32/64-bit 1149 * binary operations because vAA/vBB are 64-bit but vCC (the shift 1150 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 1151 * 6 bits. 1152 * On entry: 1153 * $a0: low word 1154 * $a1: high word 1155 * $a2: shift count 1156 */ 1157 .global art_quick_shr_long 1158 ENTRY art_quick_shr_long 1159 sra $v1, $a1, $a2 # rhi<- ahi >> (shift&31) 1160 srl $v0, $a0, $a2 # rlo<- alo >> (shift&31) 1161 sra $a3, $a1, 31 # $a3<- sign(ah) 1162 not $a0, $a2 # alo<- 31-shift (shift is 5b) 1163 sll $a1, 1 1164 sll $a1, $a0 # ahi<- ahi << (32-(shift&31)) 1165 or $v0, $a1 # rlo<- rlo | ahi 1166 andi $a2, 0x20 # shift & 0x20 1167 movn $v0, $v1, $a2 # rlo<- rhi (if shift&0x20) 1168 jr $ra 1169 movn $v1, $a3, $a2 # rhi<- sign(ahi) (if shift&0x20) 1170 END art_quick_shr_long 1171 1172 /* 1173 * Long integer shift. This is different from the generic 32/64-bit 1174 * binary operations because vAA/vBB are 64-bit but vCC (the shift 1175 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 1176 * 6 bits. 1177 * On entry: 1178 * r0: low word 1179 * r1: high word 1180 * r2: shift count 1181 */ 1182 /* ushr-long vAA, vBB, vCC */ 1183 .global art_quick_ushr_long 1184 ENTRY art_quick_ushr_long 1185 srl $v1, $a1, $a2 # rhi<- ahi >> (shift&31) 1186 srl $v0, $a0, $a2 # rlo<- alo >> (shift&31) 1187 not $a0, $a2 # alo<- 31-shift (shift is 5b) 1188 sll $a1, 1 1189 sll $a1, $a0 # ahi<- ahi << (32-(shift&31)) 1190 or $v0, $a1 # rlo<- rlo | ahi 1191 andi $a2, 0x20 # shift & 0x20 1192 movn $v0, $v1, $a2 # rlo<- rhi (if shift&0x20) 1193 jr $ra 1194 movn $v1, $zero, $a2 # rhi<- 0 (if shift&0x20) 1195 END art_quick_ushr_long 1196 1197 ENTRY art_quick_indexof 1198 jr $ra 1199 nop 1200 END art_quick_indexof 1201 1202 ENTRY art_quick_string_compareto 1203 jr $ra 1204 nop 1205 END art_quick_string_compareto 1206