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