quick_entrypoints_mips.S revision 30a3317577d84feafa859b3e39d1545a995f0b7c
1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Copyright (C) 2012 The Android Open Source Project
3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
427f654740f2a26ad62a5c155af9199af9e69b889claireho * Licensed under the Apache License, Version 2.0 (the "License");
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * you may not use this file except in compliance with the License.
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * You may obtain a copy of the License at
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *      http://www.apache.org/licenses/LICENSE-2.0
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Unless required by applicable law or agreed to in writing, software
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * distributed under the License is distributed on an "AS IS" BASIS,
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * See the License for the specific language governing permissions and
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * limitations under the License.
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "asm_support.h"
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    .set noreorder
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    .balign 4
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Deliver the given exception */
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    .extern artDeliverExceptionFromCode
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Deliver an exception pending on a thread */
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    .extern artDeliverPendingException
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Cache alignment for function entry */
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru.macro ALIGN_FUNCTION_ENTRY
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    .balign 16
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru.endm
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * Macro that sets up the callee save frame to conform with
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * Runtime::CreateCalleeSaveMethod(kSaveAll)
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * callee-save: $s0-$s8 + $ra, 10 total + 4 words
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru.macro SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    addiu  $sp, $sp, -64
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sw     $ra, 60($sp)
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sw     $s8, 56($sp)
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sw     $s7, 52($sp)
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sw     $s6, 48($sp)
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sw     $s5, 44($sp)
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sw     $s4, 40($sp)
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sw     $s3, 36($sp)
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sw     $s2, 32($sp)
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sw     $s1, 28($sp)
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sw     $s0, 24($sp)
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    # 2 words for alignment, 4 open words for args $a0-$a3, bottom will hold Method*
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru.endm
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * Macro that sets up the callee save frame to conform with
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * Runtime::CreateCalleeSaveMethod(kRefsOnly). Restoration assumes non-moving GC.
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * Does not include rSUSPEND or rSELF
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * callee-save: $s2-$s8 + $ra, 8 total + 4 words + extra args + gp
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru.macro SETUP_REF_ONLY_CALLEE_SAVE_FRAME
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    addiu  $sp, $sp, -64
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sw     $ra, 60($sp)
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sw     $s8, 56($sp)
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sw     $s7, 52($sp)
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sw     $s6, 48($sp)
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sw     $s5, 44($sp)
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sw     $s4, 40($sp)
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sw     $s3, 36($sp)
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sw     $s2, 32($sp)
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sw     $gp, 28($sp)
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    # 3 words for alignment and extra args, 4 open words for args $a0-$a3, bottom will hold Method*
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru.endm
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru.macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw     $gp, 28($sp)
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw     $ra, 60($sp)
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    addiu  $sp, $sp, 64
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru.endm
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru.macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw     $ra, 60($sp)
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    jr     $ra
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    addiu  $sp, $sp, 64
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru.endm
8327f654740f2a26ad62a5c155af9199af9e69b889claireho
8427f654740f2a26ad62a5c155af9199af9e69b889claireho    /*
8527f654740f2a26ad62a5c155af9199af9e69b889claireho     * Macro that sets up the callee save frame to conform with
8627f654740f2a26ad62a5c155af9199af9e69b889claireho     * Runtime::CreateCalleeSaveMethod(kRefsAndArgs). Restoration assumes non-moving GC.
8727f654740f2a26ad62a5c155af9199af9e69b889claireho     * $a1-$a3, $s2-$s8, $ra, 11 total + Method*
8827f654740f2a26ad62a5c155af9199af9e69b889claireho     */
8927f654740f2a26ad62a5c155af9199af9e69b889claireho.macro SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
9027f654740f2a26ad62a5c155af9199af9e69b889claireho    addiu  $sp, $sp, -48
9127f654740f2a26ad62a5c155af9199af9e69b889claireho    sw     $ra, 44($sp)
9227f654740f2a26ad62a5c155af9199af9e69b889claireho    sw     $s8, 40($sp)
9327f654740f2a26ad62a5c155af9199af9e69b889claireho    sw     $s7, 36($sp)
9427f654740f2a26ad62a5c155af9199af9e69b889claireho    sw     $s6, 32($sp)
9527f654740f2a26ad62a5c155af9199af9e69b889claireho    sw     $s5, 28($sp)
9627f654740f2a26ad62a5c155af9199af9e69b889claireho    sw     $s4, 24($sp)
9727f654740f2a26ad62a5c155af9199af9e69b889claireho    sw     $s3, 20($sp)
9827f654740f2a26ad62a5c155af9199af9e69b889claireho    sw     $s2, 16($sp)
9927f654740f2a26ad62a5c155af9199af9e69b889claireho    sw     $a3, 12($sp)
10027f654740f2a26ad62a5c155af9199af9e69b889claireho    sw     $a2, 8($sp)
10127f654740f2a26ad62a5c155af9199af9e69b889claireho    sw     $a1, 4($sp)
10227f654740f2a26ad62a5c155af9199af9e69b889claireho    # bottom will hold Method*
10327f654740f2a26ad62a5c155af9199af9e69b889claireho.endm
10427f654740f2a26ad62a5c155af9199af9e69b889claireho
10527f654740f2a26ad62a5c155af9199af9e69b889claireho.macro RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw     $ra, 44($sp)           # restore $ra
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw     $a1, 4($sp)            # restore non-callee save $a1
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw     $a2, 8($sp)            # restore non-callee save $a2
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw     $a3, 12($sp)           # restore non-callee save $a3
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    addiu  $sp, $sp, 48           # strip frame
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru.endm
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * Macro that set calls through to artDeliverPendingExceptionFromCode, where the pending
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * exception is Thread::Current()->exception_
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru.macro DELIVER_PENDING_EXCEPTION
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME            # save callee saves for throw
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    move    $a0, rSELF                          # pass Thread::Current
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    jal     artDeliverPendingExceptionFromCode  # artDeliverPendingExceptionFromCode(Thread*, $sp)
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    move    $a1, $sp                            # pass $sp
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru.endm
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru.macro RETURN_IF_NO_EXCEPTION
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw     $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    bnez   $t0, 1f                        # success if no exception is pending
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    nop
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    jr     $ra
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    nop
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru1:
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DELIVER_PENDING_EXCEPTION
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru.endm
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru.macro RETURN_IF_ZERO
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    bnez   $v0, 1f                       # success?
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    nop
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    jr     $ra                           # return on success
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    nop
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru1:
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DELIVER_PENDING_EXCEPTION
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru.endm
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru.macro RETURN_IF_NONZERO
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    beqz   $v0, 1f                       # success?
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    nop
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    jr     $ra                           # return on success
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    nop
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru1:
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DELIVER_PENDING_EXCEPTION
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru.endm
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    .global art_update_debugger
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    .extern artUpdateDebuggerFromCode
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * On entry, $a0 and $a1 must be preserved, $a2 is dex PC
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ALIGN_FUNCTION_ENTRY
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruart_update_debugger:
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    .cpload $25
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    move    $a3, $a0        # stash away $a0 so that it's saved as if it were an argument
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    move    $a0, $a2        # arg0 is dex PC
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    move    $a1, rSELF      # arg1 is Thread*
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    move    $a2, $sp        # arg2 is $sp
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    jal     artUpdateDebuggerFromCode      # artUpdateDebuggerFromCode(int32_t, Thread*, Method**)
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    jr      $ra
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    move    $a0, $a3        # restore original $a0
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    .global art_do_long_jump
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * On entry $a0 is uint32_t* gprs_ and $a1 is uint32_t* fprs_
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * FIXME: just guessing about the shape of the jmpbuf.  Where will pc be?
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ALIGN_FUNCTION_ENTRY
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruart_do_long_jump:
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f0, 0($a1)
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f1, 4($a1)
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f2, 8($a1)
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f3, 12($a1)
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f4, 16($a1)
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f5, 20($a1)
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f6, 24($a1)
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f7, 28($a1)
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f8, 32($a1)
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f9, 36($a1)
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f10, 40($a1)
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f11, 44($a1)
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f12, 48($a1)
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f13, 52($a1)
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f14, 56($a1)
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f15, 60($a1)
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f16, 64($a1)
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f17, 68($a1)
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f18, 72($a1)
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f19, 76($a1)
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f20, 80($a1)
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f21, 84($a1)
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f22, 88($a1)
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f23, 92($a1)
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f24, 96($a1)
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f25, 100($a1)
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f26, 104($a1)
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f27, 108($a1)
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f28, 112($a1)
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f29, 116($a1)
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f30, 120($a1)
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    l.s     $f31, 124($a1)
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $at, 4($a0)
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $v0, 8($a0)
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $v1, 12($a0)
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $a1, 20($a0)
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $a2, 24($a0)
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $a3, 28($a0)
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $t0, 32($a0)
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $t1, 36($a0)
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $t2, 40($a0)
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $t3, 44($a0)
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $t4, 48($a0)
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $t5, 52($a0)
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $t6, 56($a0)
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $t7, 60($a0)
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $s0, 64($a0)
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $s1, 68($a0)
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $s2, 72($a0)
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $s3, 76($a0)
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $s4, 80($a0)
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $s5, 84($a0)
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $s6, 88($a0)
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $s7, 92($a0)
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $t8, 96($a0)
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $t9, 100($a0)
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $k0, 104($a0)
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $k1, 108($a0)
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $gp, 112($a0)
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $sp, 116($a0)
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $fp, 120($a0)
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $ra, 124($a0)
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lw      $a0, 16($a0)
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    move    $v0, $zero          # clear result registers r0 and r1
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    jr      $ra                 # do long jump
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    move    $v1, $zero
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    .global art_deliver_exception_from_code
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * Called by managed code, saves most registers (forms basis of long jump context) and passes
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * the bottom of the stack. artDeliverExceptionFromCode will place the callee save Method* at
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * the bottom of the thread. On entry r0 holds Throwable*
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ALIGN_FUNCTION_ENTRY
254art_deliver_exception_from_code:
255    .cpload $25
256    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
257    move $a1, rSELF                     # pass Thread::Current
258    jal  artDeliverExceptionFromCode    # artDeliverExceptionFromCode(Throwable*, Thread*, $sp)
259    move $a2, $sp                       # pass $sp
260
261    .global art_throw_null_pointer_exception_from_code
262    .extern artThrowNullPointerExceptionFromCode
263    /*
264     * Called by managed code to create and deliver a NullPointerException
265     */
266    ALIGN_FUNCTION_ENTRY
267art_throw_null_pointer_exception_from_code:
268    .cpload $25
269    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
270    move $a0, rSELF                           # pass Thread::Current
271    jal  artThrowNullPointerExceptionFromCode  # artThrowNullPointerExceptionFromCode(Thread*, $sp)
272    move $a1, $sp                             # pass $sp
273
274    .global art_throw_div_zero_from_code
275    .extern artThrowDivZeroFromCode
276    /*
277     * Called by managed code to create and deliver an ArithmeticException
278     */
279    ALIGN_FUNCTION_ENTRY
280art_throw_div_zero_from_code:
281    .cpload $25
282    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
283    move $a0, rSELF                 # pass Thread::Current
284    jal  artThrowDivZeroFromCode     # artThrowDivZeroFromCode(Thread*, $sp)
285    move $a1, $sp                   # pass $sp
286
287    .global art_throw_array_bounds_from_code
288    .extern artThrowArrayBoundsFromCode
289    /*
290     * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException
291     */
292    ALIGN_FUNCTION_ENTRY
293art_throw_array_bounds_from_code:
294    .cpload $25
295    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
296    move $a2, rSELF                  # pass Thread::Current
297    jal artThrowArrayBoundsFromCode  # artThrowArrayBoundsFromCode(index, limit, Thread*, $sp)
298    move $a3, $sp                    # pass $sp
299
300    .global art_throw_stack_overflow_from_code
301    .extern artThrowStackOverflowFromCode
302    /*
303     * Called by managed code to create and deliver a StackOverflowError.
304     */
305    ALIGN_FUNCTION_ENTRY
306art_throw_stack_overflow_from_code:
307    .cpload $25
308    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
309    move $a0, rSELF                    # pass Thread::Current
310    jal artThrowStackOverflowFromCode  # artThrowStackOverflowFromCode(Thread*, $sp)
311    move $a1, $sp                      # pass $sp
312
313    .global art_throw_no_such_method_from_code
314    .extern artThrowNoSuchMethodFromCode
315    /*
316     * Called by managed code to create and deliver a NoSuchMethodError.
317     */
318    ALIGN_FUNCTION_ENTRY
319art_throw_no_such_method_from_code:
320    .cpload $25
321    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
322    move $a1, rSELF                       # pass Thread::Current
323    jal artThrowNoSuchMethodFromCode      # artThrowNoSuchMethodFromCode(method_idx, Thread*, $sp)
324    move $a2, $sp                         # pass $sp
325
326    /*
327     * All generated callsites for interface invokes and invocation slow paths will load arguments
328     * as usual - except instead of loading arg0/$a0 with the target Method*, arg0/$a0 will contain
329     * the method_idx.  This wrapper will save arg1-arg3, load the caller's Method*, align the
330     * stack and call the appropriate C helper.
331     * NOTE: "this" is first visable argument of the target, and so can be found in arg1/$a1.
332     *
333     * The helper will attempt to locate the target and return a 64-bit result in $v0/$v1 consisting
334     * of the target Method* in $v0 and method->code_ in $v1.
335     *
336     * If unsuccessful, the helper will return NULL/NULL. There will be a pending exception in the
337     * thread and we branch to another stub to deliver it.
338     *
339     * On success this wrapper will restore arguments and *jump* to the target, leaving the lr
340     * pointing back to the original caller.
341     */
342.macro INVOKE_TRAMPOLINE c_name, cxx_name
343    .global \c_name
344    .extern \cxx_name
345\c_name:
346    .cpload $25
347    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME  # save callee saves in case allocation triggers GC
348    lw    $a2, 48($sp)                    # pass caller Method*
349    move  $t0, $sp                        # save $sp
350    addiu $sp, $sp, -16                   # make space for extra args
351    move  $a3, rSELF                      # pass Thread::Current
352    jal   \cxx_name                       # (method_idx, this, caller, Thread*, $sp)
353    sw    $t0, 16($sp)                    # pass $sp
354    addiu $sp, $sp, 16                    # release out args
355    move  $a0, $v0                        # save target Method*
356    move  $t9, $v1                        # save $v0->code_
357    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
358    beqz  $v0, 1f
359    nop
360    jr    $t9
361    nop
3621:
363    DELIVER_PENDING_EXCEPTION
364.endm
365
366INVOKE_TRAMPOLINE art_invoke_interface_trampoline, artInvokeInterfaceTrampoline
367INVOKE_TRAMPOLINE art_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck
368
369INVOKE_TRAMPOLINE art_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck
370INVOKE_TRAMPOLINE art_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck
371INVOKE_TRAMPOLINE art_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
372INVOKE_TRAMPOLINE art_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
373
374    .global art_work_around_app_jni_bugs
375    .extern artWorkAroundAppJniBugs
376    /*
377     * Entry point of native methods when JNI bug compatibility is enabled.
378     */
379    ALIGN_FUNCTION_ENTRY
380art_work_around_app_jni_bugs:
381    .cpload $25
382    # save registers that may contain arguments and LR that will be crushed by a call
383    addiu    $sp, $sp, -32
384    sw       $ra, 28($sp)
385    sw       $a3, 24($sp)
386    sw       $a2, 20($sp)
387    sw       $a1, 16($sp)
388    sw       $a0, 12($sp)
389    move     $a0, rSELF       # pass Thread::Current
390    jal      artWorkAroundAppJniBugs  # (Thread*, $sp)
391    move     $a1, $sp         # pass $sp
392    move     $t9, $v0         # save target address
393    lw       $a0, 12($sp)
394    lw       $a1, 16($sp)
395    lw       $a2, 20($sp)
396    lw       $a3, 24($sp)
397    lw       $ra, 28($sp)
398    jr       $t9              # tail call into JNI routine
399    addiu    $sp, $sp, 32
400
401    .global art_handle_fill_data_from_code
402    .extern artHandleFillArrayDataFromCode
403    /*
404     * Entry from managed code that calls artHandleFillArrayDataFromCode and delivers exception on
405     * failure.
406     */
407    ALIGN_FUNCTION_ENTRY
408art_handle_fill_data_from_code:
409    .cpload $25
410    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case exception allocation triggers GC
411    move    $a2, rSELF                         # pass Thread::Current
412    jal     artHandleFillArrayDataFromCode     # (Array*, const DexFile::Payload*, Thread*, $sp)
413    move    $a3, $sp                           # pass $sp
414    RETURN_IF_ZERO
415
416    .global art_lock_object_from_code
417    .extern artLockObjectFromCode
418    /*
419     * Entry from managed code that calls artLockObjectFromCode, may block for GC.
420     */
421    ALIGN_FUNCTION_ENTRY
422art_lock_object_from_code:
423    .cpload $25
424    SETUP_REF_ONLY_CALLEE_SAVE_FRAME      # save callee saves in case we block
425    move    $a1, rSELF                    # pass Thread::Current
426    jal     artLockObjectFromCode         # (Object* obj, Thread*, $sp)
427    move    $a2, $sp                      # pass $sp
428    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
429
430    .global art_unlock_object_from_code
431    .extern artUnlockObjectFromCode
432    /*
433     * Entry from managed code that calls artUnlockObjectFromCode and delivers exception on failure.
434     */
435    ALIGN_FUNCTION_ENTRY
436art_unlock_object_from_code:
437    .cpload $25
438    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case exception allocation triggers GC
439    move    $a1, rSELF                # pass Thread::Current
440    jal     artUnlockObjectFromCode   # (Object* obj, Thread*, $sp)
441    move    $a2, $sp                  # pass $sp
442    RETURN_IF_ZERO
443
444    .global art_check_cast_from_code
445    .extern artCheckCastFromCode
446    /*
447     * Entry from managed code that calls artCheckCastFromCode and delivers exception on failure.
448     */
449    ALIGN_FUNCTION_ENTRY
450art_check_cast_from_code:
451    .cpload $25
452    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case exception allocation triggers GC
453    move    $a2, rSELF                # pass Thread::Current
454    jal     artCheckCastFromCode      # (Class* a, Class* b, Thread*, $sp)
455    move    $a3, $sp                  # pass $sp
456    RETURN_IF_ZERO
457
458    .global art_can_put_array_element_from_code
459    .extern artCanPutArrayElementFromCode
460    /*
461     * Entry from managed code that calls artCanPutArrayElementFromCode and delivers exception on
462     * failure.
463     */
464    ALIGN_FUNCTION_ENTRY
465art_can_put_array_element_from_code:
466    .cpload $25
467    SETUP_REF_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case exception allocation triggers GC
468    move    $a2, rSELF                     # pass Thread::Current
469    jal     artCanPutArrayElementFromCode  # (Object* element, Class* array_class, Thread*, $sp)
470    move    $a3, $sp                       # pass $sp
471    RETURN_IF_ZERO
472
473    .global art_initialize_static_storage_from_code
474    .extern artInitializeStaticStorageFromCode
475    /*
476     * Entry from managed code when uninitialized static storage, this stub will run the class
477     * initializer and deliver the exception on error. On success the static storage base is
478     * returned.
479     */
480    ALIGN_FUNCTION_ENTRY
481art_initialize_static_storage_from_code:
482    .cpload $25
483    SETUP_REF_ONLY_CALLEE_SAVE_FRAME            # save callee saves in case of GC
484    move    $a2, rSELF                          # pass Thread::Current
485    # artInitializeStaticStorageFromCode(uint32_t type_idx, Method* referrer, Thread*, $sp)
486    jal     artInitializeStaticStorageFromCode
487    move    $a3, $sp                            # pass $sp
488    RETURN_IF_NONZERO
489
490    .global art_initialize_type_from_code
491    .extern artInitializeTypeFromCode
492    /*
493     * Entry from managed code when dex cache misses for a type_idx.
494     */
495    ALIGN_FUNCTION_ENTRY
496art_initialize_type_from_code:
497    .cpload $25
498    SETUP_REF_ONLY_CALLEE_SAVE_FRAME           # save callee saves in case of GC
499    move    $a2, rSELF                         # pass Thread::Current
500    # artInitializeTypeFromCode(uint32_t type_idx, Method* referrer, Thread*, $sp)
501    jal     artInitializeTypeFromCode
502    move    $a3, $sp                           # pass $sp
503    RETURN_IF_NONZERO
504
505    .global art_initialize_type_and_verify_access_from_code
506    .extern artInitializeTypeAndVerifyAccessFromCode
507    /*
508     * Entry from managed code when type_idx needs to be checked for access and dex cache may also
509     * miss.
510     */
511    ALIGN_FUNCTION_ENTRY
512art_initialize_type_and_verify_access_from_code:
513    .cpload $25
514    SETUP_REF_ONLY_CALLEE_SAVE_FRAME           # save callee saves in case of GC
515    move    $a2, rSELF                         # pass Thread::Current
516    # artInitializeTypeFromCode(uint32_t type_idx, Method* referrer, Thread*, $sp)
517    jal     artInitializeTypeAndVerifyAccessFromCode
518    move    $a3, $sp                           # pass $sp
519    RETURN_IF_NONZERO
520
521    .global art_get32_static_from_code
522    .extern artGet32StaticFromCode
523    /*
524     * Called by managed code to resolve a static field and load a 32-bit primitive value.
525     */
526    ALIGN_FUNCTION_ENTRY
527art_get32_static_from_code:
528    .cpload $25
529    SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
530    lw     $a1, 64($sp)                  # pass referrer's Method*
531    move   $a2, rSELF                    # pass Thread::Current
532    jal    artGet32StaticFromCode        # (uint32_t field_idx, const Method* referrer, Thread*, $sp)
533    move   $a3, $sp                      # pass $sp
534    RETURN_IF_NO_EXCEPTION
535
536    .global art_get64_static_from_code
537    .extern artGet64StaticFromCode
538    /*
539     * Called by managed code to resolve a static field and load a 64-bit primitive value.
540     */
541    ALIGN_FUNCTION_ENTRY
542art_get64_static_from_code:
543    .cpload $25
544    SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
545    lw     $a1, 64($sp)                  # pass referrer's Method*
546    move   $a2, rSELF                    # pass Thread::Current
547    jal    artGet64StaticFromCode        # (uint32_t field_idx, const Method* referrer, Thread*, $sp)
548    move   $a3, $sp                      # pass $sp
549    RETURN_IF_NO_EXCEPTION
550
551    .global art_get_obj_static_from_code
552    .extern artGetObjStaticFromCode
553    /*
554     * Called by managed code to resolve a static field and load an object reference.
555     */
556    ALIGN_FUNCTION_ENTRY
557art_get_obj_static_from_code:
558    .cpload $25
559    SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
560    lw     $a1, 64($sp)                  # pass referrer's Method*
561    move   $a2, rSELF                    # pass Thread::Current
562    jal    artGetObjStaticFromCode       # (uint32_t field_idx, const Method* referrer, Thread*, $sp)
563    move   $a3, $sp                      # pass $sp
564    RETURN_IF_NO_EXCEPTION
565
566    .global art_get32_instance_from_code
567    .extern artGet32InstanceFromCode
568    /*
569     * Called by managed code to resolve an instance field and load a 32-bit primitive value.
570     */
571    ALIGN_FUNCTION_ENTRY
572art_get32_instance_from_code:
573    .cpload $25
574    SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
575    lw     $a2, 64($sp)                  # pass referrer's Method*
576    move   $a3, rSELF                    # pass Thread::Current
577    jal    artGet32InstanceFromCode      # (field_idx, Object*, referrer, Thread*, $sp)
578    sw     $sp, 16($sp)                  # pass $sp
579    RETURN_IF_NO_EXCEPTION
580
581    .global art_get64_instance_from_code
582    .extern artGet64InstanceFromCode
583    /*
584     * Called by managed code to resolve an instance field and load a 64-bit primitive value.
585     */
586    ALIGN_FUNCTION_ENTRY
587art_get64_instance_from_code:
588    .cpload $25
589    SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
590    lw     $a2, 64($sp)                  # pass referrer's Method*
591    move   $a3, rSELF                    # pass Thread::Current
592    jal    artGet64InstanceFromCode      # (field_idx, Object*, referrer, Thread*, $sp)
593    sw     $sp, 16($sp)                  # pass $sp
594    RETURN_IF_NO_EXCEPTION
595
596    .global art_get_obj_instance_from_code
597    .extern artGetObjInstanceFromCode
598    /*
599     * Called by managed code to resolve an instance field and load an object reference.
600     */
601    ALIGN_FUNCTION_ENTRY
602art_get_obj_instance_from_code:
603    .cpload $25
604    SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
605    lw     $a2, 64($sp)                  # pass referrer's Method*
606    move   $a3, rSELF                    # pass Thread::Current
607    jal    artGetObjInstanceFromCode     # (field_idx, Object*, referrer, Thread*, $sp)
608    sw     $sp, 16($sp)                  # pass $sp
609    RETURN_IF_NO_EXCEPTION
610
611    .global art_set32_static_from_code
612    .extern artSet32StaticFromCode
613    /*
614     * Called by managed code to resolve a static field and store a 32-bit primitive value.
615     */
616    ALIGN_FUNCTION_ENTRY
617art_set32_static_from_code:
618    .cpload $25
619    SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
620    lw     $a2, 64($sp)                  # pass referrer's Method*
621    move   $a3, rSELF                    # pass Thread::Current
622    jal    artSet32StaticFromCode        # (field_idx, new_val, referrer, Thread*, $sp)
623    sw     $sp, 16($sp)                  # pass $sp
624    RETURN_IF_ZERO
625
626    .global art_set64_static_from_code
627    .extern artSet32StaticFromCode
628    /*
629     * Called by managed code to resolve a static field and store a 64-bit primitive value.
630     */
631    ALIGN_FUNCTION_ENTRY
632art_set64_static_from_code:
633    .cpload $25
634    SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
635    lw     $a1, 64($sp)                  # pass referrer's Method*
636    sw     rSELF, 16($sp)                # pass Thread::Current
637    jal    artSet64StaticFromCode        # (field_idx, referrer, new_val, Thread*, $sp)
638    sw     $sp, 20($sp)                  # pass $sp
639    RETURN_IF_ZERO
640
641    .global art_set_obj_static_from_code
642    .extern artSetObjStaticFromCode
643    /*
644     * Called by managed code to resolve a static field and store an object reference.
645     */
646    ALIGN_FUNCTION_ENTRY
647art_set_obj_static_from_code:
648    .cpload $25
649    SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
650    lw     $a2, 64($sp)                  # pass referrer's Method*
651    move   $a3, rSELF                    # pass Thread::Current
652    jal    artSetObjStaticFromCode       # (field_idx, new_val, referrer, Thread*, $sp)
653    sw     $sp, 16($sp)                  # pass $sp
654    RETURN_IF_ZERO
655
656    .global art_set32_instance_from_code
657    .extern artSet32InstanceFromCode
658    /*
659     * Called by managed code to resolve an instance field and store a 32-bit primitive value.
660     */
661    ALIGN_FUNCTION_ENTRY
662art_set32_instance_from_code:
663    .cpload $25
664    SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
665    lw     $a3, 64($sp)                  # pass referrer's Method*
666    sw     rSELF, 16($sp)                # pass Thread::Current
667    jal    artSet32InstanceFromCode      # (field_idx, Object*, new_val, referrer, Thread*, $sp)
668    sw     $sp, 20($sp)                  # pass $sp
669    RETURN_IF_ZERO
670
671    .global art_set64_instance_from_code
672    .extern artSet32InstanceFromCode
673    /*
674     * Called by managed code to resolve an instance field and store a 64-bit primitive value.
675     */
676    ALIGN_FUNCTION_ENTRY
677art_set64_instance_from_code:
678    .cpload $25
679    SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
680    sw     rSELF, 16($sp)                # pass Thread::Current
681    jal    artSet64InstanceFromCode      # (field_idx, Object*, new_val, Thread*, $sp)
682    sw     $sp, 20($sp)                  # pass $sp
683    RETURN_IF_ZERO
684
685    .global art_set_obj_instance_from_code
686    .extern artSetObjInstanceFromCode
687    /*
688     * Called by managed code to resolve an instance field and store an object reference.
689     */
690    ALIGN_FUNCTION_ENTRY
691art_set_obj_instance_from_code:
692    .cpload $25
693    SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
694    lw     $a3, 64($sp)                  # pass referrer's Method*
695    sw     rSELF, 16($sp)                # pass Thread::Current
696    jal    artSetObjInstanceFromCode     # (field_idx, Object*, new_val, referrer, Thread*, $sp)
697    sw     $sp, 20($sp)                  # pass $sp
698    RETURN_IF_ZERO
699
700    .global art_resolve_string_from_code
701    .extern artResolveStringFromCode
702    /*
703     * Entry from managed code to resolve a string, this stub will allocate a String and deliver an
704     * exception on error. On success the String is returned. R0 holds the referring method,
705     * R1 holds the string index. The fast path check for hit in strings cache has already been
706     * performed.
707     */
708    ALIGN_FUNCTION_ENTRY
709art_resolve_string_from_code:
710    .cpload $25
711    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case of GC
712    move    $a2, rSELF                # pass Thread::Current
713    # artResolveStringFromCode(Method* referrer, uint32_t string_idx, Thread*, $sp)
714    jal     artResolveStringFromCode
715    move    $a3, $sp                  # pass $sp
716    RETURN_IF_NONZERO
717
718    .global art_alloc_object_from_code
719    .extern artAllocObjectFromCode
720    /*
721     * Called by managed code to allocate an object.
722     */
723    ALIGN_FUNCTION_ENTRY
724art_alloc_object_from_code:
725    .cpload $25
726    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case of GC
727    move    $a2, rSELF                # pass Thread::Current
728    jal     artAllocObjectFromCode    # (uint32_t type_idx, Method* method, Thread*, $sp)
729    move    $a3, $sp                  # pass $sp
730    RETURN_IF_NONZERO
731
732    .global art_alloc_object_from_code_with_access_check
733    .extern artAllocObjectFromCodeWithAccessCheck
734    /*
735     * Called by managed code to allocate an object when the caller doesn't know whether it has
736     * access to the created type.
737     */
738    ALIGN_FUNCTION_ENTRY
739art_alloc_object_from_code_with_access_check:
740    .cpload $25
741    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case of GC
742    move    $a2, rSELF                # pass Thread::Current
743    jal     artAllocObjectFromCodeWithAccessCheck  # (uint32_t type_idx, Method* method, Thread*, $sp)
744    move    $a3, $sp                  # pass $sp
745    RETURN_IF_NONZERO
746
747    .global art_alloc_array_from_code
748    .extern artAllocArrayFromCode
749    /*
750     * Called by managed code to allocate an array.
751     */
752    ALIGN_FUNCTION_ENTRY
753art_alloc_array_from_code:
754    .cpload $25
755    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case of GC
756    move    $a3, rSELF                # pass Thread::Current
757    # artAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count, Thread*, $sp)
758    jal     artAllocArrayFromCode
759    sw      $sp, 16($sp)              # pass $sp
760    RETURN_IF_NONZERO
761
762    .global art_alloc_array_from_code_with_access_check
763    .extern artAllocArrayFromCodeWithAccessCheck
764    /*
765     * Called by managed code to allocate an array when the caller doesn't know whether it has
766     * access to the created type.
767     */
768    ALIGN_FUNCTION_ENTRY
769art_alloc_array_from_code_with_access_check:
770    .cpload $25
771    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case of GC
772    move    $a3, rSELF                # pass Thread::Current
773    # artAllocArrayFromCodeWithAccessCheck(type_idx, method, component_count, Thread*, $sp)
774    jal     artAllocArrayFromCodeWithAccessCheck
775    sw      $sp, 16($sp)              # pass $sp
776    RETURN_IF_NONZERO
777
778    .global art_check_and_alloc_array_from_code
779    .extern artCheckAndAllocArrayFromCode
780    /*
781     * Called by managed code to allocate an array in a special case for FILLED_NEW_ARRAY.
782     */
783    ALIGN_FUNCTION_ENTRY
784art_check_and_alloc_array_from_code:
785    .cpload $25
786    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case of GC
787    move    $a3, rSELF                # pass Thread::Current
788    # artCheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t count, Thread* , $sp)
789    jal     artCheckAndAllocArrayFromCode
790    sw      $sp, 16($sp)              # pass $sp
791    RETURN_IF_NONZERO
792
793    .global art_check_and_alloc_array_from_code_with_access_check
794    .extern artCheckAndAllocArrayFromCodeWithAccessCheck
795    /*
796     * Called by managed code to allocate an array in a special case for FILLED_NEW_ARRAY.
797     */
798    ALIGN_FUNCTION_ENTRY
799art_check_and_alloc_array_from_code_with_access_check:
800    .cpload $25
801    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case of GC
802    move    $a3, rSELF                # pass Thread::Current
803    # artCheckAndAllocArrayFromCodeWithAccessCheck(type_idx, method, count, Thread* , $sp)
804    jal     artCheckAndAllocArrayFromCodeWithAccessCheck
805    sw      $sp, 16($sp)              # pass $sp
806    RETURN_IF_NONZERO
807
808    .global art_test_suspend
809    .extern artTestSuspendFromCode
810    /*
811     * Called by managed code when the value in rSUSPEND has been decremented to 0.
812     */
813    ALIGN_FUNCTION_ENTRY
814art_test_suspend:
815    .cpload $25
816    lh     $a0, THREAD_FLAGS_OFFSET(rSELF)
817    bnez   $a0, 1f
818    addi  rSUSPEND, $zero, SUSPEND_CHECK_INTERVAL   # reset rSUSPEND to SUSPEND_CHECK_INTERVAL
819    jr     $ra
820    nop
8211:
822    move   $a0, rSELF
823    SETUP_REF_ONLY_CALLEE_SAVE_FRAME          # save callee saves for stack crawl
824    jal    artTestSuspendFromCode             # (Thread*, $sp)
825    move   $a1, $sp
826    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
827
828    .global art_proxy_invoke_handler
829    .extern artProxyInvokeHandler
830    /*
831     * Called by managed code that is attempting to call a method on a proxy class. On entry
832     * r0 holds the proxy method; r1, r2 and r3 may contain arguments.
833     */
834    ALIGN_FUNCTION_ENTRY
835art_proxy_invoke_handler:
836    .cpload $25
837    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
838    sw      $a0, 0($sp)            # place proxy method at bottom of frame
839    move    $a2, rSELF             # pass Thread::Current
840    jal     artProxyInvokeHandler  # (Method* proxy method, receiver, Thread*, args...)
841    addiu   $a3, $sp, 8            # pointer to a2/a3/ra/caller's Method**/out-args as second arg
842    lw      $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
843    lw      $ra, 44($sp)           # restore $ra
844    lw      $v0, 8($sp)
845    lw      $v1, 12($sp)
846    bnez    $t0, 1f
847    addiu   $sp, $sp, 48           # pop frame
848    jr      $ra
849    nop
8501:
851    DELIVER_PENDING_EXCEPTION
852
853    .global art_trace_entry_from_code
854    .extern artTraceMethodEntryFromCode
855    /*
856     * Routine that intercepts method calls
857     */
858    ALIGN_FUNCTION_ENTRY
859art_trace_entry_from_code:
860    .cpload $25
861    addiu    $sp, $sp, -16
862    sw       $a0, 0($sp)
863    sw       $a1, 4($sp)
864    sw       $a2, 8($sp)
865    sw       $a3, 12($sp)
866    move     $a2, $ra       # pass $ra
867    jal      artTraceMethodEntryFromCode  # (Method*, Thread*, LR)
868    move     $a1, rSELF     # pass Thread::Current
869    move     $t0, $v0       # $t0 holds reference to code
870    lw       $a0, 0($sp)
871    lw       $a1, 4($sp)
872    lw       $a2, 8($sp)
873    lw       $a3, 12($sp)
874    jalr     $t0            # call method
875    addiu    $sp, $sp, 16
876    /* intentional fallthrough */
877
878    .global art_trace_exit_from_code
879    .extern artTraceMethodExitFromCode
880    /*
881     * Routine that intercepts method returns
882     */
883    ALIGN_FUNCTION_ENTRY
884art_trace_exit_from_code:
885    .cpload $25
886    addiu    $sp, $sp, -16
887    sw       $v0, 0($sp)
888    jal      artTraceMethodExitFromCode  # ()
889    sw       $v1, 4($sp)
890    move     $ra, $v0         # restore link register
891    lw       $v0, 0($sp)
892    lw       $v1, 4($sp)
893    jr       $ra              # return
894    addiu    $sp, $sp, 16
895
896    .global art_shl_long
897    /*
898     * Long integer shift.  This is different from the generic 32/64-bit
899     * binary operations because vAA/vBB are 64-bit but vCC (the shift
900     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
901     * 6 bits.
902     * On entry:
903     *   $a0: low word
904     *   $a1: high word
905     *   $a2: shift count
906     */
907    ALIGN_FUNCTION_ENTRY
908art_shl_long:
909    /* shl-long vAA, vBB, vCC */
910    sll     $v0, $a0, $a2                    #  rlo<- alo << (shift&31)
911    not     $v1, $a2                         #  rhi<- 31-shift  (shift is 5b)
912    srl     $a0, 1
913    srl     $a0, $v1                         #  alo<- alo >> (32-(shift&31))
914    sll     $v1, $a1, $a2                    #  rhi<- ahi << (shift&31)
915    or      $v1, $a0                         #  rhi<- rhi | alo
916    andi    $a2, 0x20                        #  shift< shift & 0x20
917    movn    $v1, $v0, $a2                    #  rhi<- rlo (if shift&0x20)
918    jr      $ra
919    movn    $v0, $zero, $a2                  #  rlo<- 0  (if shift&0x20)
920
921    .global art_shr_long
922    /*
923     * Long integer shift.  This is different from the generic 32/64-bit
924     * binary operations because vAA/vBB are 64-bit but vCC (the shift
925     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
926     * 6 bits.
927     * On entry:
928     *   $a0: low word
929     *   $a1: high word
930     *   $a2: shift count
931     */
932    ALIGN_FUNCTION_ENTRY
933art_shr_long:
934    sra     $v1, $a1, $a2                    #  rhi<- ahi >> (shift&31)
935    srl     $v0, $a0, $a2                    #  rlo<- alo >> (shift&31)
936    sra     $a3, $a1, 31                     #  $a3<- sign(ah)
937    not     $a0, $a2                         #  alo<- 31-shift (shift is 5b)
938    sll     $a1, 1
939    sll     $a1, $a0                         #  ahi<- ahi << (32-(shift&31))
940    or      $v0, $a1                         #  rlo<- rlo | ahi
941    andi    $a2, 0x20                        #  shift & 0x20
942    movn    $v0, $v1, $a2                    #  rlo<- rhi (if shift&0x20)
943    jr      $ra
944    movn    $v1, $a3, $a2                    #  rhi<- sign(ahi) (if shift&0x20)
945
946    .global art_ushr_long
947    /*
948     * Long integer shift.  This is different from the generic 32/64-bit
949     * binary operations because vAA/vBB are 64-bit but vCC (the shift
950     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
951     * 6 bits.
952     * On entry:
953     *   r0: low word
954     *   r1: high word
955     *   r2: shift count
956     */
957    /* ushr-long vAA, vBB, vCC */
958    ALIGN_FUNCTION_ENTRY
959art_ushr_long:
960    srl     $v1, $a1, $a2                    #  rhi<- ahi >> (shift&31)
961    srl     $v0, $a0, $a2                    #  rlo<- alo >> (shift&31)
962    not     $a0, $a2                         #  alo<- 31-shift (shift is 5b)
963    sll     $a1, 1
964    sll     $a1, $a0                         #  ahi<- ahi << (32-(shift&31))
965    or      $v0, $a1                         #  rlo<- rlo | ahi
966    andi    $a2, 0x20                        #  shift & 0x20
967    movn    $v0, $v1, $a2                    #  rlo<- rhi (if shift&0x20)
968    jr      $ra
969    movn    $v1, $zero, $a2                  #  rhi<- 0 (if shift&0x20)
970
971    .global art_indexof
972    ALIGN_FUNCTION_ENTRY
973art_indexof:
974    jr $ra
975    nop
976
977    .global art_string_compareto
978    ALIGN_FUNCTION_ENTRY
979art_string_compareto:
980    jr $ra
981    nop
982