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