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