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