quick_entrypoints_mips.S revision 4147fcc43c2ee019a06e55384985e3eaf82dcb8c
10f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes/*
20f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * Copyright (C) 2012 The Android Open Source Project
30f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes *
40f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
50f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * you may not use this file except in compliance with the License.
60f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * You may obtain a copy of the License at
70f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes *
80f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
90f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes *
100f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * Unless required by applicable law or agreed to in writing, software
110f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
120f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * See the License for the specific language governing permissions and
140f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * limitations under the License.
150f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes */
160f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes
177655f29fabc0a12765de828914a18314382e5a35Ian Rogers#include "asm_support_mips.S"
185bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
197410f29b4dae223befac036ea567d7f33351dad1Mathieu Chartier#include "arch/quick_alloc_entrypoints.S"
207410f29b4dae223befac036ea567d7f33351dad1Mathieu Chartier
210703060875166106af3d490c6c264611aea67ec8jeffhao    .set noreorder
225bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    .balign 4
235bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
245bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /* Deliver the given exception */
255bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    .extern artDeliverExceptionFromCode
265bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /* Deliver an exception pending on a thread */
278161c0336b97e11e02c000af357f8f40de2e23e4jeffhao    .extern artDeliverPendingExceptionFromCode
285bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
29735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung#define ARG_SLOT_SIZE   32    // space for a0-a3 plus 4 more words
30735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung
315bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
325bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * Macro that sets up the callee save frame to conform with
33fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko     * Runtime::CreateCalleeSaveMethod(kSaveAllCalleeSaves)
34735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung     * Callee-save: $s0-$s8 + $gp + $ra, 11 total + 1 word for Method*
35735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung     * Clobbers $t0 and $sp
36735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung     * Allocates ARG_SLOT_SIZE bytes at the bottom of the stack for arg slots.
37fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko     * Reserves FRAME_SIZE_SAVE_ALL_CALLEE_SAVES + ARG_SLOT_SIZE bytes on the stack
385bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
39fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko.macro SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
40a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    addiu  $sp, $sp, -96
41a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    .cfi_adjust_cfa_offset 96
425c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
435c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe     // Ugly compile-time check, but we only have the preprocessor.
44fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVES != 96)
45fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko#error "FRAME_SIZE_SAVE_ALL_CALLEE_SAVES(MIPS) size not as expected."
465c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe#endif
475c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
48a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    sw     $ra, 92($sp)
49a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    .cfi_rel_offset 31, 92
50a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    sw     $s8, 88($sp)
51a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    .cfi_rel_offset 30, 88
52a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    sw     $gp, 84($sp)
53a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    .cfi_rel_offset 28, 84
54a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    sw     $s7, 80($sp)
55a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    .cfi_rel_offset 23, 80
56a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    sw     $s6, 76($sp)
57a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    .cfi_rel_offset 22, 76
58a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    sw     $s5, 72($sp)
59a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    .cfi_rel_offset 21, 72
60a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    sw     $s4, 68($sp)
61a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    .cfi_rel_offset 20, 68
62a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    sw     $s3, 64($sp)
63a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    .cfi_rel_offset 19, 64
64a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    sw     $s2, 60($sp)
65a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    .cfi_rel_offset 18, 60
66a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    sw     $s1, 56($sp)
67a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    .cfi_rel_offset 17, 56
68a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    sw     $s0, 52($sp)
69a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    .cfi_rel_offset 16, 52
70a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe
71a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    SDu $f30, $f31, 44, $sp, $t1
72a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    SDu $f28, $f29, 36, $sp, $t1
73a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    SDu $f26, $f27, 28, $sp, $t1
74a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    SDu $f24, $f25, 20, $sp, $t1
75a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    SDu $f22, $f23, 12, $sp, $t1
76a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe    SDu $f20, $f21, 4,  $sp, $t1
77a4e0e67611f54180694e0807d6599c1132269b6cAndreas Gampe
78735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    # 1 word for holding Method*
791d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers
804af77b7636fe98aae443b46a241fd9a29f16e291Douglas Leung    lw $t0, %got(_ZN3art7Runtime9instance_E)($gp)
814af77b7636fe98aae443b46a241fd9a29f16e291Douglas Leung    lw $t0, 0($t0)
82fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    lw $t0, RUNTIME_SAVE_ALL_CALLEE_SAVES_METHOD_OFFSET($t0)
831d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    sw $t0, 0($sp)                                # Place Method* at bottom of stack.
841d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    sw $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF)  # Place sp in Thread::Current()->top_quick_frame.
85735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    addiu  $sp, $sp, -ARG_SLOT_SIZE               # reserve argument slots on the stack
86735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .cfi_adjust_cfa_offset ARG_SLOT_SIZE
875bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee.endm
885bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
895bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
905bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * Macro that sets up the callee save frame to conform with
91fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko     * Runtime::CreateCalleeSaveMethod(kSaveRefsOnly). Restoration assumes non-moving GC.
925bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * Does not include rSUSPEND or rSELF
93735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung     * callee-save: $s2-$s8 + $gp + $ra, 9 total + 2 words padding + 1 word to hold Method*
94735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung     * Clobbers $t0 and $sp
95735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung     * Allocates ARG_SLOT_SIZE bytes at the bottom of the stack for arg slots.
96fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko     * Reserves FRAME_SIZE_SAVE_REFS_ONLY + ARG_SLOT_SIZE bytes on the stack
975bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
98fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko.macro SETUP_SAVE_REFS_ONLY_FRAME
99735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    addiu  $sp, $sp, -48
100735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .cfi_adjust_cfa_offset 48
1015c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
1025c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe    // Ugly compile-time check, but we only have the preprocessor.
103fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko#if (FRAME_SIZE_SAVE_REFS_ONLY != 48)
104fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko#error "FRAME_SIZE_SAVE_REFS_ONLY(MIPS) size not as expected."
1055c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe#endif
1065c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
107735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    sw     $ra, 44($sp)
108735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .cfi_rel_offset 31, 44
109735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    sw     $s8, 40($sp)
110735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .cfi_rel_offset 30, 40
111735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    sw     $gp, 36($sp)
112735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .cfi_rel_offset 28, 36
113735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    sw     $s7, 32($sp)
114735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .cfi_rel_offset 23, 32
115735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    sw     $s6, 28($sp)
116735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .cfi_rel_offset 22, 28
117735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    sw     $s5, 24($sp)
118735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .cfi_rel_offset 21, 24
119735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    sw     $s4, 20($sp)
120735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .cfi_rel_offset 20, 20
121735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    sw     $s3, 16($sp)
122735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .cfi_rel_offset 19, 16
123735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    sw     $s2, 12($sp)
124735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .cfi_rel_offset 18, 12
125735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    # 2 words for alignment and bottom word will hold Method*
1261d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers
1274af77b7636fe98aae443b46a241fd9a29f16e291Douglas Leung    lw $t0, %got(_ZN3art7Runtime9instance_E)($gp)
1284af77b7636fe98aae443b46a241fd9a29f16e291Douglas Leung    lw $t0, 0($t0)
129fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    lw $t0, RUNTIME_SAVE_REFS_ONLY_METHOD_OFFSET($t0)
1301d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    sw $t0, 0($sp)                                # Place Method* at bottom of stack.
1311d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    sw $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF)  # Place sp in Thread::Current()->top_quick_frame.
132735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    addiu  $sp, $sp, -ARG_SLOT_SIZE               # reserve argument slots on the stack
133735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .cfi_adjust_cfa_offset ARG_SLOT_SIZE
1345bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee.endm
1355bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
136fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko.macro RESTORE_SAVE_REFS_ONLY_FRAME
137735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    addiu  $sp, $sp, ARG_SLOT_SIZE                # remove argument slots on the stack
138735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .cfi_adjust_cfa_offset -ARG_SLOT_SIZE
139735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    lw     $ra, 44($sp)
140bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 31
141735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    lw     $s8, 40($sp)
142bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 30
143735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    lw     $gp, 36($sp)
144bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 28
145735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    lw     $s7, 32($sp)
146bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 23
147735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    lw     $s6, 28($sp)
148bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 22
149735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    lw     $s5, 24($sp)
150bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 21
151735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    lw     $s4, 20($sp)
152bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 20
153735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    lw     $s3, 16($sp)
154bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 19
155735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    lw     $s2, 12($sp)
156bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 18
157735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    addiu  $sp, $sp, 48
158735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .cfi_adjust_cfa_offset -48
1595bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee.endm
1605bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
161fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko.macro RESTORE_SAVE_REFS_ONLY_FRAME_AND_RETURN
162fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    RESTORE_SAVE_REFS_ONLY_FRAME
1638d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr   $zero, $ra
164735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    nop
1655bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee.endm
1665bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
1675bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
1685bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * Macro that sets up the callee save frame to conform with
169fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko     * Runtime::CreateCalleeSaveMethod(kSaveRefsAndArgs).
1701b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze     * callee-save: $a1-$a3, $t0-$t1, $s2-$s8, $gp, $ra, $f8-$f19
1711b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze     *              (26 total + 1 word padding + method*)
1725bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
173fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko.macro SETUP_SAVE_REFS_AND_ARGS_FRAME_REGISTERS_ONLY
1741b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu  $sp, $sp, -112
1751b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .cfi_adjust_cfa_offset 112
1765c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
1775c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe    // Ugly compile-time check, but we only have the preprocessor.
1781b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze#if (FRAME_SIZE_SAVE_REFS_AND_ARGS != 112)
179fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko#error "FRAME_SIZE_SAVE_REFS_AND_ARGS(MIPS) size not as expected."
1805c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe#endif
1815c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
1821b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    sw     $ra, 108($sp)
1831b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .cfi_rel_offset 31, 108
1841b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    sw     $s8, 104($sp)
1851b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .cfi_rel_offset 30, 104
1861b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    sw     $gp, 100($sp)
1871b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .cfi_rel_offset 28, 100
1881b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    sw     $s7, 96($sp)
1891b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .cfi_rel_offset 23, 96
1901b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    sw     $s6, 92($sp)
1911b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .cfi_rel_offset 22, 92
1921b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    sw     $s5, 88($sp)
1931b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .cfi_rel_offset 21, 88
1941b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    sw     $s4, 84($sp)
1951b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .cfi_rel_offset 20, 84
1961b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    sw     $s3, 80($sp)
1971b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .cfi_rel_offset 19, 80
1981b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    sw     $s2, 76($sp)
1991b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .cfi_rel_offset 18, 76
2001b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    sw     $t1, 72($sp)
2011b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .cfi_rel_offset 9, 72
2021b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    sw     $t0, 68($sp)
2031b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .cfi_rel_offset 8, 68
2041b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    sw     $a3, 64($sp)
2051b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .cfi_rel_offset 7, 64
2061b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    sw     $a2, 60($sp)
2071b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .cfi_rel_offset 6, 60
2081b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    sw     $a1, 56($sp)
2091b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .cfi_rel_offset 5, 56
2101b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    SDu $f18, $f19, 48, $sp, $t8
2111b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    SDu $f16, $f17, 40, $sp, $t8
2121b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    SDu $f14, $f15, 32, $sp, $t8
2131b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    SDu $f12, $f13, 24, $sp, $t8
2141b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    SDu $f10, $f11, 16, $sp, $t8
2151b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    SDu $f8, $f9, 8, $sp, $t8
216fa147e22a73c6df166b08a2f71f9c9b52b09d17cjeffhao    # bottom will hold Method*
217735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung.endm
2181d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers
219735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    /*
220735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung     * Macro that sets up the callee save frame to conform with
221fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko     * Runtime::CreateCalleeSaveMethod(kSaveRefsAndArgs). Restoration assumes non-moving GC.
2221b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze     * callee-save: $a1-$a3, $t0-$t1, $s2-$s8, $gp, $ra, $f8-$f19
2231b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze     *              (26 total + 1 word padding + method*)
224735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung     * Clobbers $t0 and $sp
225735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung     * Allocates ARG_SLOT_SIZE bytes at the bottom of the stack for arg slots.
226fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko     * Reserves FRAME_SIZE_SAVE_REFS_AND_ARGS + ARG_SLOT_SIZE bytes on the stack
227735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung     */
228fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko.macro SETUP_SAVE_REFS_AND_ARGS_FRAME
229fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_REFS_AND_ARGS_FRAME_REGISTERS_ONLY
2304af77b7636fe98aae443b46a241fd9a29f16e291Douglas Leung    lw $t0, %got(_ZN3art7Runtime9instance_E)($gp)
2314af77b7636fe98aae443b46a241fd9a29f16e291Douglas Leung    lw $t0, 0($t0)
232fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    lw $t0, RUNTIME_SAVE_REFS_AND_ARGS_METHOD_OFFSET($t0)
2331d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    sw $t0, 0($sp)                                # Place Method* at bottom of stack.
2341d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    sw $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF)  # Place sp in Thread::Current()->top_quick_frame.
235735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    addiu  $sp, $sp, -ARG_SLOT_SIZE               # reserve argument slots on the stack
236735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .cfi_adjust_cfa_offset ARG_SLOT_SIZE
237735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung.endm
238735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung
239735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    /*
240735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung     * Macro that sets up the callee save frame to conform with
241fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko     * Runtime::CreateCalleeSaveMethod(kSaveRefsAndArgs). Restoration assumes non-moving GC.
2421b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze     * callee-save: $a1-$a3, $t0-$t1, $s2-$s8, $gp, $ra, $f8-$f19
2431b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze     *              (26 total + 1 word padding + method*)
244735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung     * Clobbers $sp
245735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung     * Use $a0 as the Method* and loads it into bottom of stack.
246735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung     * Allocates ARG_SLOT_SIZE bytes at the bottom of the stack for arg slots.
247fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko     * Reserves FRAME_SIZE_SAVE_REFS_AND_ARGS + ARG_SLOT_SIZE bytes on the stack
248735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung     */
249fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko.macro SETUP_SAVE_REFS_AND_ARGS_FRAME_WITH_METHOD_IN_A0
250fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_REFS_AND_ARGS_FRAME_REGISTERS_ONLY
251735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    sw $a0, 0($sp)                                # Place Method* at bottom of stack.
252735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    sw $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF)  # Place sp in Thread::Current()->top_quick_frame.
253735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    addiu  $sp, $sp, -ARG_SLOT_SIZE               # reserve argument slots on the stack
254735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .cfi_adjust_cfa_offset ARG_SLOT_SIZE
2555bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee.endm
2565bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
257fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko.macro RESTORE_SAVE_REFS_AND_ARGS_FRAME
258735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    addiu  $sp, $sp, ARG_SLOT_SIZE                # remove argument slots on the stack
259735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .cfi_adjust_cfa_offset -ARG_SLOT_SIZE
2601b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw     $ra, 108($sp)
261bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 31
2621b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw     $s8, 104($sp)
263bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 30
2641b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw     $gp, 100($sp)
265bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 28
2661b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw     $s7, 96($sp)
267bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 23
2681b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw     $s6, 92($sp)
269bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 22
2701b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw     $s5, 88($sp)
271bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 21
2721b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw     $s4, 84($sp)
273bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 20
2741b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw     $s3, 80($sp)
275bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 19
2761b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw     $s2, 76($sp)
277bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 18
2781b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw     $t1, 72($sp)
2791b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .cfi_restore 9
2801b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw     $t0, 68($sp)
2811b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .cfi_restore 8
2821b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw     $a3, 64($sp)
283bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 7
2841b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw     $a2, 60($sp)
285bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 6
2861b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw     $a1, 56($sp)
287bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 5
2881b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LDu $f18, $f19, 48, $sp, $t8
2891b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LDu $f16, $f17, 40, $sp, $t8
2901b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LDu $f14, $f15, 32, $sp, $t8
2911b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LDu $f12, $f13, 24, $sp, $t8
2921b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LDu $f10, $f11, 16, $sp, $t8
2931b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LDu $f8, $f9, 8, $sp, $t8
2941b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu  $sp, $sp, 112          # pop frame
2951b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .cfi_adjust_cfa_offset -112
2965bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee.endm
2975bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
2985bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
299952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko     * Macro that sets up the callee save frame to conform with
300952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko     * Runtime::CreateCalleeSaveMethod(kSaveEverything).
3013b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko     * when the $sp has already been decremented by FRAME_SIZE_SAVE_EVERYTHING.
302952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko     * Callee-save: $at, $v0-$v1, $a0-$a3, $t0-$t7, $s0-$s7, $t8-$t9, $gp, $fp $ra, $f0-$f31;
303952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko     *              28(GPR)+ 32(FPR) + 3 words for padding and 1 word for Method*
304952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko     * Clobbers $t0 and $t1.
305952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko     * Allocates ARG_SLOT_SIZE bytes at the bottom of the stack for arg slots.
306fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko     * Reserves FRAME_SIZE_SAVE_EVERYTHING + ARG_SLOT_SIZE bytes on the stack.
307952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko     * This macro sets up $gp; entrypoints using it should start with ENTRY_NO_GP.
308952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko     */
3093b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko.macro SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP
310952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko     // Ugly compile-time check, but we only have the preprocessor.
311fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko#if (FRAME_SIZE_SAVE_EVERYTHING != 256)
312fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko#error "FRAME_SIZE_SAVE_EVERYTHING(MIPS) size not as expected."
313952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko#endif
314952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko
315952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $ra, 252($sp)
316952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 31, 252
317952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $fp, 248($sp)
318952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 30, 248
319952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $gp, 244($sp)
320952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 28, 244
321952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $t9, 240($sp)
322952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 25, 240
323952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $t8, 236($sp)
324952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 24, 236
325952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $s7, 232($sp)
326952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 23, 232
327952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $s6, 228($sp)
328952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 22, 228
329952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $s5, 224($sp)
330952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 21, 224
331952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $s4, 220($sp)
332952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 20, 220
333952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $s3, 216($sp)
334952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 19, 216
335952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $s2, 212($sp)
336952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 18, 212
337952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $s1, 208($sp)
338952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 17, 208
339952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $s0, 204($sp)
340952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 16, 204
341952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $t7, 200($sp)
342952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 15, 200
343952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $t6, 196($sp)
344952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 14, 196
345952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $t5, 192($sp)
346952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 13, 192
347952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $t4, 188($sp)
348952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 12, 188
349952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $t3, 184($sp)
350952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 11, 184
351952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $t2, 180($sp)
352952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 10, 180
353952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $t1, 176($sp)
354952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 9, 176
355952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $t0, 172($sp)
356952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 8, 172
357952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $a3, 168($sp)
358952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 7, 168
359952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $a2, 164($sp)
360952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 6, 164
361952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $a1, 160($sp)
362952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 5, 160
363952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $a0, 156($sp)
364952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 4, 156
365952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $v1, 152($sp)
366952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 3, 152
367952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $v0, 148($sp)
368952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 2, 148
369952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko
370952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    // Set up $gp, clobbering $ra and using the branch delay slot for a useful instruction.
371952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    bal 1f
3722e42cf12e7bd62c5455a9c5ac0fc072de0f31884Goran Jakovljevic    .set push
3732e42cf12e7bd62c5455a9c5ac0fc072de0f31884Goran Jakovljevic    .set noat
374952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw     $at, 144($sp)
375952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_rel_offset 1, 144
3762e42cf12e7bd62c5455a9c5ac0fc072de0f31884Goran Jakovljevic    .set pop
377952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko1:
378952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cpload $ra
379952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko
380952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    SDu $f30, $f31, 136, $sp, $t1
381952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    SDu $f28, $f29, 128, $sp, $t1
382952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    SDu $f26, $f27, 120, $sp, $t1
383952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    SDu $f24, $f25, 112, $sp, $t1
384952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    SDu $f22, $f23, 104, $sp, $t1
385952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    SDu $f20, $f21, 96,  $sp, $t1
386952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    SDu $f18, $f19, 88,  $sp, $t1
387952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    SDu $f16, $f17, 80,  $sp, $t1
388952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    SDu $f14, $f15, 72,  $sp, $t1
389952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    SDu $f12, $f13, 64,  $sp, $t1
390952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    SDu $f10, $f11, 56,  $sp, $t1
391952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    SDu $f8, $f9, 48,  $sp, $t1
392952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    SDu $f6, $f7, 40,  $sp, $t1
393952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    SDu $f4, $f5, 32,  $sp, $t1
394952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    SDu $f2, $f3, 24,  $sp, $t1
395952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    SDu $f0, $f1, 16,  $sp, $t1
396952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko
397952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    # 3 words padding and 1 word for holding Method*
398952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko
399952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw $t0, %got(_ZN3art7Runtime9instance_E)($gp)
400952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw $t0, 0($t0)
401fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    lw $t0, RUNTIME_SAVE_EVERYTHING_METHOD_OFFSET($t0)
402952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw $t0, 0($sp)                                # Place Method* at bottom of stack.
403952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    sw $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF)  # Place sp in Thread::Current()->top_quick_frame.
404952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    addiu  $sp, $sp, -ARG_SLOT_SIZE               # reserve argument slots on the stack
405952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_adjust_cfa_offset ARG_SLOT_SIZE
406952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko.endm
407952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko
4083b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko    /*
4093b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko     * Macro that sets up the callee save frame to conform with
4103b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko     * Runtime::CreateCalleeSaveMethod(kSaveEverything).
4113b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko     * Callee-save: $at, $v0-$v1, $a0-$a3, $t0-$t7, $s0-$s7, $t8-$t9, $gp, $fp $ra, $f0-$f31;
4123b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko     *              28(GPR)+ 32(FPR) + 3 words for padding and 1 word for Method*
4133b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko     * Clobbers $t0 and $t1.
4143b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko     * Allocates ARG_SLOT_SIZE bytes at the bottom of the stack for arg slots.
4153b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko     * Reserves FRAME_SIZE_SAVE_EVERYTHING + ARG_SLOT_SIZE bytes on the stack.
4163b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko     * This macro sets up $gp; entrypoints using it should start with ENTRY_NO_GP.
4173b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko     */
4183b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko.macro SETUP_SAVE_EVERYTHING_FRAME
4193b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko    addiu  $sp, $sp, -(FRAME_SIZE_SAVE_EVERYTHING)
4203b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko    .cfi_adjust_cfa_offset (FRAME_SIZE_SAVE_EVERYTHING)
4213b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko    SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP
4223b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko.endm
4233b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko
424c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze.macro RESTORE_SAVE_EVERYTHING_FRAME restore_a0=1
425952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    addiu  $sp, $sp, ARG_SLOT_SIZE                # remove argument slots on the stack
426952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_adjust_cfa_offset -ARG_SLOT_SIZE
427952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko
428952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    LDu $f30, $f31, 136, $sp, $t1
429952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    LDu $f28, $f29, 128, $sp, $t1
430952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    LDu $f26, $f27, 120, $sp, $t1
431952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    LDu $f24, $f25, 112, $sp, $t1
432952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    LDu $f22, $f23, 104, $sp, $t1
433952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    LDu $f20, $f21, 96,  $sp, $t1
434952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    LDu $f18, $f19, 88,  $sp, $t1
435952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    LDu $f16, $f17, 80,  $sp, $t1
436952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    LDu $f14, $f15, 72,  $sp, $t1
437952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    LDu $f12, $f13, 64,  $sp, $t1
438952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    LDu $f10, $f11, 56,  $sp, $t1
439952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    LDu $f8, $f9, 48,  $sp, $t1
440952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    LDu $f6, $f7, 40,  $sp, $t1
441952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    LDu $f4, $f5, 32,  $sp, $t1
442952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    LDu $f2, $f3, 24,  $sp, $t1
443952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    LDu $f0, $f1, 16,  $sp, $t1
444952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko
445952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $ra, 252($sp)
446952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 31
447952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $fp, 248($sp)
448952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 30
449952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $gp, 244($sp)
450952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 28
451952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $t9, 240($sp)
452952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 25
453952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $t8, 236($sp)
454952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 24
455952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $s7, 232($sp)
456952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 23
457952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $s6, 228($sp)
458952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 22
459952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $s5, 224($sp)
460952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 21
461952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $s4, 220($sp)
462952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 20
463952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $s3, 216($sp)
464952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 19
465952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $s2, 212($sp)
466952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 18
467952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $s1, 208($sp)
468952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 17
469952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $s0, 204($sp)
470952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 16
471952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $t7, 200($sp)
472952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 15
473952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $t6, 196($sp)
474952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 14
475952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $t5, 192($sp)
476952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 13
477952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $t4, 188($sp)
478952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 12
479952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $t3, 184($sp)
480952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 11
481952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $t2, 180($sp)
482952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 10
483952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $t1, 176($sp)
484952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 9
485952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $t0, 172($sp)
486952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 8
487952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $a3, 168($sp)
488952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 7
489952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $a2, 164($sp)
490952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 6
491952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $a1, 160($sp)
492952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 5
493c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    .if \restore_a0
494952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $a0, 156($sp)
495952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 4
496c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    .endif
497952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $v1, 152($sp)
498952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 3
499952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $v0, 148($sp)
500952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 2
5012e42cf12e7bd62c5455a9c5ac0fc072de0f31884Goran Jakovljevic    .set push
5022e42cf12e7bd62c5455a9c5ac0fc072de0f31884Goran Jakovljevic    .set noat
503952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lw     $at, 144($sp)
504952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_restore 1
5052e42cf12e7bd62c5455a9c5ac0fc072de0f31884Goran Jakovljevic    .set pop
506952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko
507952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    addiu  $sp, $sp, 256            # pop frame
508952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    .cfi_adjust_cfa_offset -256
509952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko.endm
510952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko
511952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    /*
512c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze     * Macro that calls through to artDeliverPendingExceptionFromCode, where the pending
513c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze     * exception is Thread::Current()->exception_ when the runtime method frame is ready.
514c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze     * Requires $gp properly set up.
5155bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
516c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze.macro DELIVER_PENDING_EXCEPTION_FRAME_READY
5178161c0336b97e11e02c000af357f8f40de2e23e4jeffhao    la      $t9, artDeliverPendingExceptionFromCode
5188d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr    $zero, $t9                   # artDeliverPendingExceptionFromCode(Thread*)
5191d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    move    $a0, rSELF                   # pass Thread::Current
5205bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee.endm
5215bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
522c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    /*
523c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze     * Macro that calls through to artDeliverPendingExceptionFromCode, where the pending
524c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze     * exception is Thread::Current()->exception_.
525c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze     * Requires $gp properly set up.
526c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze     */
527c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze.macro DELIVER_PENDING_EXCEPTION
528c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    SETUP_SAVE_ALL_CALLEE_SAVES_FRAME    # save callee saves for throw
529c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    DELIVER_PENDING_EXCEPTION_FRAME_READY
530c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze.endm
531c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze
5325bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee.macro RETURN_IF_NO_EXCEPTION
5337fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw     $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
534fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    RESTORE_SAVE_REFS_ONLY_FRAME
5358161c0336b97e11e02c000af357f8f40de2e23e4jeffhao    bnez   $t0, 1f                       # success if no exception is pending
5365bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    nop
5378d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr   $zero, $ra
5385bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    nop
5395bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee1:
5405bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    DELIVER_PENDING_EXCEPTION
5415bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee.endm
5425bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
5435bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee.macro RETURN_IF_ZERO
544fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    RESTORE_SAVE_REFS_ONLY_FRAME
5457fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    bnez   $v0, 1f                       # success?
5465bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    nop
5478d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr   $zero, $ra                    # return on success
5485bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    nop
5495bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee1:
5505bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    DELIVER_PENDING_EXCEPTION
5515bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee.endm
5525bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
5531cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe.macro RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
554fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    RESTORE_SAVE_REFS_ONLY_FRAME
5557fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    beqz   $v0, 1f                       # success?
5565bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    nop
5578d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr   $zero, $ra                    # return on success
5585bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    nop
5595bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee1:
5605bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    DELIVER_PENDING_EXCEPTION
5615bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee.endm
5625bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
5635bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
5643bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic     * On stack replacement stub.
5653bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic     * On entry:
5663bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic     *   a0 = stack to copy
5673bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic     *   a1 = size of stack
5683bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic     *   a2 = pc to call
5693bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic     *   a3 = JValue* result
5703bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic     *   [sp + 16] = shorty
5713bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic     *   [sp + 20] = thread
5723bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic     */
5733bc13817a19e36f3833bb44624ef86800892eaadGoran JakovljevicENTRY art_quick_osr_stub
5743bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    // Save callee general purpose registers, RA and GP.
5753bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    addiu  $sp, $sp, -48
5763bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_adjust_cfa_offset 48
5773bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    sw     $ra, 44($sp)
5783bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_rel_offset 31, 44
5793bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    sw     $s8, 40($sp)
5803bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_rel_offset 30, 40
5813bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    sw     $gp, 36($sp)
5823bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_rel_offset 28, 36
5833bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    sw     $s7, 32($sp)
5843bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_rel_offset 23, 32
5853bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    sw     $s6, 28($sp)
5863bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_rel_offset 22, 28
5873bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    sw     $s5, 24($sp)
5883bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_rel_offset 21, 24
5893bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    sw     $s4, 20($sp)
5903bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_rel_offset 20, 20
5913bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    sw     $s3, 16($sp)
5923bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_rel_offset 19, 16
5933bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    sw     $s2, 12($sp)
5943bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_rel_offset 18, 12
5953bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    sw     $s1, 8($sp)
5963bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_rel_offset 17, 8
5973bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    sw     $s0, 4($sp)
5983bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_rel_offset 16, 4
5993bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic
6003bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    move   $s8, $sp                        # Save the stack pointer
6013bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    move   $s7, $a1                        # Save size of stack
6023bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    move   $s6, $a2                        # Save the pc to call
6033bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    lw     rSELF, 48+20($sp)               # Save managed thread pointer into rSELF
6043bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    addiu  $t0, $sp, -12                   # Reserve space for stack pointer,
6053bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic                                           #    JValue* result, and ArtMethod* slot.
6063bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    srl    $t0, $t0, 4                     # Align stack pointer to 16 bytes
6073bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    sll    $sp, $t0, 4                     # Update stack pointer
6083bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    sw     $s8, 4($sp)                     # Save old stack pointer
6093bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    sw     $a3, 8($sp)                     # Save JValue* result
6103bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    sw     $zero, 0($sp)                   # Store null for ArtMethod* at bottom of frame
6113bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    subu   $sp, $a1                        # Reserve space for callee stack
6123bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    move   $a2, $a1
6133bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    move   $a1, $a0
6143bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    move   $a0, $sp
6153bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    la     $t9, memcpy
6163bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    jalr   $t9                             # memcpy (dest a0, src a1, bytes a2)
6173bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    addiu  $sp, $sp, -16                   # make space for argument slots for memcpy
6183bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    bal    .Losr_entry                     # Call the method
6193bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    addiu  $sp, $sp, 16                    # restore stack after memcpy
6203bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    lw     $a2, 8($sp)                     # Restore JValue* result
6213bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    lw     $sp, 4($sp)                     # Restore saved stack pointer
6223bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    lw     $a0, 48+16($sp)                 # load shorty
6233bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    lbu    $a0, 0($a0)                     # load return type
6243bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    li     $a1, 'D'                        # put char 'D' into a1
6253bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    beq    $a0, $a1, .Losr_fp_result       # Test if result type char == 'D'
6263bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    li     $a1, 'F'                        # put char 'F' into a1
6273bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    beq    $a0, $a1, .Losr_fp_result       # Test if result type char == 'F'
6283bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    nop
6293bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    sw     $v0, 0($a2)
6303bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    b      .Losr_exit
6313bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    sw     $v1, 4($a2)                     # store v0/v1 into result
6323bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic.Losr_fp_result:
6333bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    SDu    $f0, $f1, 0, $a2, $t0           # store f0/f1 into result
6343bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic.Losr_exit:
6353bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    lw     $ra, 44($sp)
6363bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_restore 31
6373bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    lw     $s8, 40($sp)
6383bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_restore 30
6393bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    lw     $gp, 36($sp)
6403bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_restore 28
6413bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    lw     $s7, 32($sp)
6423bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_restore 23
6433bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    lw     $s6, 28($sp)
6443bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_restore 22
6453bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    lw     $s5, 24($sp)
6463bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_restore 21
6473bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    lw     $s4, 20($sp)
6483bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_restore 20
6493bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    lw     $s3, 16($sp)
6503bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_restore 19
6513bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    lw     $s2, 12($sp)
6523bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_restore 18
6533bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    lw     $s1, 8($sp)
6543bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_restore 17
6553bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    lw     $s0, 4($sp)
6563bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_restore 16
6573bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    jalr   $zero, $ra
6583bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    addiu  $sp, $sp, 48
6593bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    .cfi_adjust_cfa_offset -48
6603bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic.Losr_entry:
6613bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    addiu  $s7, $s7, -4
6623bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    addu   $t0, $s7, $sp
6633bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    move   $t9, $s6
6643bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    jalr   $zero, $t9
6653bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    sw     $ra, 0($t0)                     # Store RA per the compiler ABI
6663bc13817a19e36f3833bb44624ef86800892eaadGoran JakovljevicEND art_quick_osr_stub
6673bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic
6683bc13817a19e36f3833bb44624ef86800892eaadGoran Jakovljevic    /*
6697fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao     * On entry $a0 is uint32_t* gprs_ and $a1 is uint32_t* fprs_
6705bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * FIXME: just guessing about the shape of the jmpbuf.  Where will pc be?
6715bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
672d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff HaoENTRY art_quick_do_long_jump
673e34652f15f32666323052a6718a63248244f1e66Duane Sand    LDu  $f0,  $f1,   0*8, $a1, $t1
674e34652f15f32666323052a6718a63248244f1e66Duane Sand    LDu  $f2,  $f3,   1*8, $a1, $t1
675e34652f15f32666323052a6718a63248244f1e66Duane Sand    LDu  $f4,  $f5,   2*8, $a1, $t1
676e34652f15f32666323052a6718a63248244f1e66Duane Sand    LDu  $f6,  $f7,   3*8, $a1, $t1
677e34652f15f32666323052a6718a63248244f1e66Duane Sand    LDu  $f8,  $f9,   4*8, $a1, $t1
678e34652f15f32666323052a6718a63248244f1e66Duane Sand    LDu  $f10, $f11,  5*8, $a1, $t1
679e34652f15f32666323052a6718a63248244f1e66Duane Sand    LDu  $f12, $f13,  6*8, $a1, $t1
680e34652f15f32666323052a6718a63248244f1e66Duane Sand    LDu  $f14, $f15,  7*8, $a1, $t1
681e34652f15f32666323052a6718a63248244f1e66Duane Sand    LDu  $f16, $f17,  8*8, $a1, $t1
682e34652f15f32666323052a6718a63248244f1e66Duane Sand    LDu  $f18, $f19,  9*8, $a1, $t1
683e34652f15f32666323052a6718a63248244f1e66Duane Sand    LDu  $f20, $f21, 10*8, $a1, $t1
684e34652f15f32666323052a6718a63248244f1e66Duane Sand    LDu  $f22, $f23, 11*8, $a1, $t1
685e34652f15f32666323052a6718a63248244f1e66Duane Sand    LDu  $f24, $f25, 12*8, $a1, $t1
686e34652f15f32666323052a6718a63248244f1e66Duane Sand    LDu  $f26, $f27, 13*8, $a1, $t1
687e34652f15f32666323052a6718a63248244f1e66Duane Sand    LDu  $f28, $f29, 14*8, $a1, $t1
688e34652f15f32666323052a6718a63248244f1e66Duane Sand    LDu  $f30, $f31, 15*8, $a1, $t1
689e34652f15f32666323052a6718a63248244f1e66Duane Sand
690748dd957eecbce2f379a3182ce95c19be308a54eChris Dearman    .set push
691748dd957eecbce2f379a3182ce95c19be308a54eChris Dearman    .set nomacro
692748dd957eecbce2f379a3182ce95c19be308a54eChris Dearman    .set noat
6937fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $at, 4($a0)
694748dd957eecbce2f379a3182ce95c19be308a54eChris Dearman    .set pop
6957fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $v0, 8($a0)
6967fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $v1, 12($a0)
6977fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $a1, 20($a0)
6987fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $a2, 24($a0)
6997fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $a3, 28($a0)
7007fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $t0, 32($a0)
7017fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $t1, 36($a0)
7027fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $t2, 40($a0)
7037fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $t3, 44($a0)
7047fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $t4, 48($a0)
7057fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $t5, 52($a0)
7067fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $t6, 56($a0)
7077fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $t7, 60($a0)
7087fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $s0, 64($a0)
7097fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $s1, 68($a0)
7107fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $s2, 72($a0)
7117fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $s3, 76($a0)
7127fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $s4, 80($a0)
7137fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $s5, 84($a0)
7147fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $s6, 88($a0)
7157fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $s7, 92($a0)
7167fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $t8, 96($a0)
7177fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $t9, 100($a0)
7187fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $gp, 112($a0)
7197fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $sp, 116($a0)
7207fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $fp, 120($a0)
7217fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $ra, 124($a0)
7227fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    lw      $a0, 16($a0)
723590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    move    $v0, $zero          # clear result registers v0 and v1 (in branch delay slot)
72475969963213c39a029e01c3b9440fb388d793afbGoran Jakovljevic    jalr    $zero, $t9          # do long jump
7257fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    move    $v1, $zero
726d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff HaoEND art_quick_do_long_jump
7275bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
7285bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
7295bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * Called by managed code, saves most registers (forms basis of long jump context) and passes
7305bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * the bottom of the stack. artDeliverExceptionFromCode will place the callee save Method* at
73184bc06e30ba12c3ff07e577c52b63b9df162af7eLazar Trsic     * the bottom of the thread. On entry a0 holds Throwable*
7325bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
733468532ea115657709bc32ee498e701a4c71762d4Ian RogersENTRY art_quick_deliver_exception
734fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
7358161c0336b97e11e02c000af357f8f40de2e23e4jeffhao    la   $t9, artDeliverExceptionFromCode
7368d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr $zero, $t9                 # artDeliverExceptionFromCode(Throwable*, Thread*)
7371d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    move $a1, rSELF                 # pass Thread::Current
738468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND art_quick_deliver_exception
7395bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
7405bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
7415bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * Called by managed code to create and deliver a NullPointerException
7425bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
743d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff Hao    .extern artThrowNullPointerExceptionFromCode
744804b03ffb9b9dc6cc3153e004c2cd38667508b13Vladimir MarkoENTRY_NO_GP art_quick_throw_null_pointer_exception
745804b03ffb9b9dc6cc3153e004c2cd38667508b13Vladimir Marko    // Note that setting up $gp does not rely on $t9 here, so branching here directly is OK,
746804b03ffb9b9dc6cc3153e004c2cd38667508b13Vladimir Marko    // even after clobbering any registers we don't need to preserve, such as $gp or $t0.
747804b03ffb9b9dc6cc3153e004c2cd38667508b13Vladimir Marko    SETUP_SAVE_EVERYTHING_FRAME
7488161c0336b97e11e02c000af357f8f40de2e23e4jeffhao    la   $t9, artThrowNullPointerExceptionFromCode
7498d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr $zero, $t9                 # artThrowNullPointerExceptionFromCode(Thread*)
7501d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    move $a0, rSELF                 # pass Thread::Current
751468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND art_quick_throw_null_pointer_exception
7525bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
753e8e1127da3f154fae8d2eb16a94203544a182159Nicolas Geoffray
754e8e1127da3f154fae8d2eb16a94203544a182159Nicolas Geoffray    /*
755e8e1127da3f154fae8d2eb16a94203544a182159Nicolas Geoffray     * Call installed by a signal handler to create and deliver a NullPointerException.
756e8e1127da3f154fae8d2eb16a94203544a182159Nicolas Geoffray     */
757e8e1127da3f154fae8d2eb16a94203544a182159Nicolas Geoffray    .extern artThrowNullPointerExceptionFromSignal
7583b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir MarkoENTRY_NO_GP_CUSTOM_CFA art_quick_throw_null_pointer_exception_from_signal, FRAME_SIZE_SAVE_EVERYTHING
7593b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko    SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP
7603b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko    # Retrieve the fault address from the padding where the signal handler stores it.
7613b7537bfc5a6b7ccb18b3970d8edf14b72464af7Vladimir Marko    lw   $a0, (ARG_SLOT_SIZE + __SIZEOF_POINTER__)($sp)
762e8e1127da3f154fae8d2eb16a94203544a182159Nicolas Geoffray    la   $t9, artThrowNullPointerExceptionFromSignal
763e8e1127da3f154fae8d2eb16a94203544a182159Nicolas Geoffray    jalr $zero, $t9                 # artThrowNullPointerExceptionFromSignal(uintptr_t, Thread*)
764e8e1127da3f154fae8d2eb16a94203544a182159Nicolas Geoffray    move $a1, rSELF                 # pass Thread::Current
765e8e1127da3f154fae8d2eb16a94203544a182159Nicolas GeoffrayEND art_quick_throw_null_pointer_exception_from_signal
766e8e1127da3f154fae8d2eb16a94203544a182159Nicolas Geoffray
7675bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
7685bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * Called by managed code to create and deliver an ArithmeticException
7695bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
770d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff Hao    .extern artThrowDivZeroFromCode
771804b03ffb9b9dc6cc3153e004c2cd38667508b13Vladimir MarkoENTRY_NO_GP art_quick_throw_div_zero
772804b03ffb9b9dc6cc3153e004c2cd38667508b13Vladimir Marko    SETUP_SAVE_EVERYTHING_FRAME
7738161c0336b97e11e02c000af357f8f40de2e23e4jeffhao    la   $t9, artThrowDivZeroFromCode
7748d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr $zero, $t9                 # artThrowDivZeroFromCode(Thread*)
7751d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    move $a0, rSELF                 # pass Thread::Current
776468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND art_quick_throw_div_zero
7775bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
7785bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
7795bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException
7805bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
781d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff Hao    .extern artThrowArrayBoundsFromCode
782804b03ffb9b9dc6cc3153e004c2cd38667508b13Vladimir MarkoENTRY_NO_GP art_quick_throw_array_bounds
783804b03ffb9b9dc6cc3153e004c2cd38667508b13Vladimir Marko    // Note that setting up $gp does not rely on $t9 here, so branching here directly is OK,
784804b03ffb9b9dc6cc3153e004c2cd38667508b13Vladimir Marko    // even after clobbering any registers we don't need to preserve, such as $gp or $t0.
785804b03ffb9b9dc6cc3153e004c2cd38667508b13Vladimir Marko    SETUP_SAVE_EVERYTHING_FRAME
7868161c0336b97e11e02c000af357f8f40de2e23e4jeffhao    la   $t9, artThrowArrayBoundsFromCode
7878d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr $zero, $t9                 # artThrowArrayBoundsFromCode(index, limit, Thread*)
7881d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    move $a2, rSELF                 # pass Thread::Current
789468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND art_quick_throw_array_bounds
7905bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
79157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    /*
79287f3fcbd0db352157fc59148e94647ef21b73bceVladimir Marko     * Called by managed code to create and deliver a StringIndexOutOfBoundsException
79387f3fcbd0db352157fc59148e94647ef21b73bceVladimir Marko     * as if thrown from a call to String.charAt().
79487f3fcbd0db352157fc59148e94647ef21b73bceVladimir Marko     */
79587f3fcbd0db352157fc59148e94647ef21b73bceVladimir Marko    .extern artThrowStringBoundsFromCode
796804b03ffb9b9dc6cc3153e004c2cd38667508b13Vladimir MarkoENTRY_NO_GP art_quick_throw_string_bounds
797804b03ffb9b9dc6cc3153e004c2cd38667508b13Vladimir Marko    SETUP_SAVE_EVERYTHING_FRAME
79887f3fcbd0db352157fc59148e94647ef21b73bceVladimir Marko    la   $t9, artThrowStringBoundsFromCode
79987f3fcbd0db352157fc59148e94647ef21b73bceVladimir Marko    jalr $zero, $t9                 # artThrowStringBoundsFromCode(index, limit, Thread*)
80087f3fcbd0db352157fc59148e94647ef21b73bceVladimir Marko    move $a2, rSELF                 # pass Thread::Current
80187f3fcbd0db352157fc59148e94647ef21b73bceVladimir MarkoEND art_quick_throw_string_bounds
80287f3fcbd0db352157fc59148e94647ef21b73bceVladimir Marko
80387f3fcbd0db352157fc59148e94647ef21b73bceVladimir Marko    /*
80457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     * Called by managed code to create and deliver a StackOverflowError.
80557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     */
806d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff Hao    .extern artThrowStackOverflowFromCode
807468532ea115657709bc32ee498e701a4c71762d4Ian RogersENTRY art_quick_throw_stack_overflow
808fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
8098161c0336b97e11e02c000af357f8f40de2e23e4jeffhao    la   $t9, artThrowStackOverflowFromCode
8108d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr $zero, $t9                 # artThrowStackOverflowFromCode(Thread*)
8111d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    move $a0, rSELF                 # pass Thread::Current
812468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND art_quick_throw_stack_overflow
8135bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
81457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    /*
8155bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * All generated callsites for interface invokes and invocation slow paths will load arguments
8167fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao     * as usual - except instead of loading arg0/$a0 with the target Method*, arg0/$a0 will contain
8177ea6a170486d81b127e69673cd1020c4db628c93Nicolas Geoffray     * the method_idx.  This wrapper will save arg1-arg3, and call the appropriate C helper.
8187fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao     * NOTE: "this" is first visable argument of the target, and so can be found in arg1/$a1.
8195bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     *
8207fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao     * The helper will attempt to locate the target and return a 64-bit result in $v0/$v1 consisting
8217fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao     * of the target Method* in $v0 and method->code_ in $v1.
8225bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     *
8232cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier     * If unsuccessful, the helper will return null/null. There will be a pending exception in the
8245bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * thread and we branch to another stub to deliver it.
8255bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     *
8265bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * On success this wrapper will restore arguments and *jump* to the target, leaving the lr
8275bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * pointing back to the original caller.
8285bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
8293031c8da0c5009183f770b005c245f9bf2a4d01bAndreas Gampe.macro INVOKE_TRAMPOLINE_BODY cxx_name
8305bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    .extern \cxx_name
831fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_REFS_AND_ARGS_FRAME         # save callee saves in case allocation triggers GC
8327ea6a170486d81b127e69673cd1020c4db628c93Nicolas Geoffray    move  $a2, rSELF                       # pass Thread::Current
833590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la    $t9, \cxx_name
834590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    jalr  $t9                              # (method_idx, this, Thread*, $sp)
8357ea6a170486d81b127e69673cd1020c4db628c93Nicolas Geoffray    addiu $a3, $sp, ARG_SLOT_SIZE          # pass $sp (remove arg slots)
8367ea6a170486d81b127e69673cd1020c4db628c93Nicolas Geoffray    move  $a0, $v0                         # save target Method*
837fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    RESTORE_SAVE_REFS_AND_ARGS_FRAME
838fa147e22a73c6df166b08a2f71f9c9b52b09d17cjeffhao    beqz  $v0, 1f
8397ea6a170486d81b127e69673cd1020c4db628c93Nicolas Geoffray    move  $t9, $v1                         # save $v0->code_
8408d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr  $zero, $t9
8415bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    nop
8425bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee1:
8435bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    DELIVER_PENDING_EXCEPTION
8443031c8da0c5009183f770b005c245f9bf2a4d01bAndreas Gampe.endm
8453031c8da0c5009183f770b005c245f9bf2a4d01bAndreas Gampe.macro INVOKE_TRAMPOLINE c_name, cxx_name
8463031c8da0c5009183f770b005c245f9bf2a4d01bAndreas GampeENTRY \c_name
8473031c8da0c5009183f770b005c245f9bf2a4d01bAndreas Gampe    INVOKE_TRAMPOLINE_BODY \cxx_name
848d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff HaoEND \c_name
8495bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee.endm
8505bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
8518dbb708c7dc05c786329eb5c3fff3194ab6472acLogan ChienINVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck
8525bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
8538dbb708c7dc05c786329eb5c3fff3194ab6472acLogan ChienINVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck
8548dbb708c7dc05c786329eb5c3fff3194ab6472acLogan ChienINVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck
8558dbb708c7dc05c786329eb5c3fff3194ab6472acLogan ChienINVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
8568dbb708c7dc05c786329eb5c3fff3194ab6472acLogan ChienINVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
8575bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
8581b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze// Each of the following macros expands into four instructions or 16 bytes.
8591b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze// They are used to build indexable "tables" of code.
8601b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze
8611b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze.macro LOAD_WORD_TO_REG reg, next_arg, index_reg, label
862ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    lw    $\reg, -4($\next_arg)   # next_arg points to argument after the current one (offset is 4)
863ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    b     \label
8641b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $\index_reg, 16
8651b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .balign 16
866ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic.endm
867ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic
8681b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze.macro LOAD_LONG_TO_REG reg1, reg2, next_arg, index_reg, next_index, label
869ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    lw    $\reg1, -8($\next_arg)  # next_arg points to argument after the current one (offset is 8)
870ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    lw    $\reg2, -4($\next_arg)
871ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    b     \label
8721b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    li    $\index_reg, \next_index
8731b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .balign 16
874ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic.endm
875ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic
8761b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze.macro LOAD_FLOAT_TO_REG reg, next_arg, index_reg, label
877ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    lwc1  $\reg, -4($\next_arg)   # next_arg points to argument after the current one (offset is 4)
878ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    b     \label
8791b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $\index_reg, 16
8801b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .balign 16
881ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic.endm
882ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic
8831b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze#if defined(__mips_isa_rev) && __mips_isa_rev > 2
8841b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze// LDu expands into 3 instructions for 64-bit FPU, so index_reg cannot be updated here.
8851b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze.macro LOAD_DOUBLE_TO_REG reg1, reg2, next_arg, index_reg, tmp, label
8861b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .set reorder                                # force use of the branch delay slot
887ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    LDu  $\reg1, $\reg2, -8, $\next_arg, $\tmp  # next_arg points to argument after the current one
888ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic                                                # (offset is 8)
889ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    b     \label
8901b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .set noreorder
8911b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .balign 16
8921b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze.endm
8931b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze#else
8941b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze// LDu expands into 2 instructions for 32-bit FPU, so index_reg is updated here.
8951b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze.macro LOAD_DOUBLE_TO_REG reg1, reg2, next_arg, index_reg, tmp, label
8961b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LDu  $\reg1, $\reg2, -8, $\next_arg, $\tmp  # next_arg points to argument after the current one
8971b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze                                                # (offset is 8)
8981b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    b     \label
8991b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $\index_reg, 16
9001b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .balign 16
9011b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze.endm
9021b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze#endif
9031b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze
9041b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze.macro LOAD_END index_reg, next_index, label
9051b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    b     \label
9061b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    li    $\index_reg, \next_index
9071b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .balign 16
908ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic.endm
909ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic
910590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic#define SPILL_SIZE    32
911590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic
91279fe539587d4c09244172d0168eeed0ec9770466Jeff Hao    /*
913ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers     * Invocation stub for quick code.
9145d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao     * On entry:
9155d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao     *   a0 = method pointer
9162cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier     *   a1 = argument array or null for no argument methods
9175d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao     *   a2 = size of argument array in bytes
9185d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao     *   a3 = (managed) thread pointer
9196474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao     *   [sp + 16] = JValue* result
9200177e53ea521ad58b70c305700dab32f1ac773b7Ian Rogers     *   [sp + 20] = shorty
9215d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao     */
9225d9173014c1ca09f7249a6b07629aa37778b5f8fJeff HaoENTRY art_quick_invoke_stub
9235d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    sw    $a0, 0($sp)           # save out a0
924590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    addiu $sp, $sp, -SPILL_SIZE # spill s0, s1, fp, ra and gp
925590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    .cfi_adjust_cfa_offset SPILL_SIZE
926590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    sw    $gp, 16($sp)
9275d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    sw    $ra, 12($sp)
9285d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    .cfi_rel_offset 31, 12
9295d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    sw    $fp, 8($sp)
9305d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    .cfi_rel_offset 30, 8
9315d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    sw    $s1, 4($sp)
9325d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    .cfi_rel_offset 17, 4
9335d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    sw    $s0, 0($sp)
9345d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    .cfi_rel_offset 16, 0
9355d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    move  $fp, $sp              # save sp in fp
9365d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    .cfi_def_cfa_register 30
9375d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    move  $s1, $a3              # move managed thread pointer into s1
9385d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    addiu $s0, $zero, SUSPEND_CHECK_INTERVAL  # reset s0 to suspend check interval
939ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    addiu $t0, $a2, 4           # create space for ArtMethod* in frame.
940735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    subu  $t0, $sp, $t0         # reserve & align *stack* to 16 bytes:
941ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    srl   $t0, $t0, 4           #   native calling convention only aligns to 8B,
942ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    sll   $sp, $t0, 4           #   so we have to ensure ART 16B alignment ourselves.
943ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    addiu $a0, $sp, 4           # pass stack pointer + ArtMethod* as dest for memcpy
944590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la    $t9, memcpy
945590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    jalr  $t9                   # (dest, src, bytes)
9465d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    addiu $sp, $sp, -16         # make space for argument slots for memcpy
9475d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    addiu $sp, $sp, 16          # restore stack after memcpy
948590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    lw    $gp, 16($fp)          # restore $gp
949590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    lw    $a0, SPILL_SIZE($fp)  # restore ArtMethod*
950ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    lw    $a1, 4($sp)           # a1 = this*
9511b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t8, $sp, 8           # t8 = pointer to the current argument (skip ArtMethod* and this*)
9521b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    li    $t6, 0                # t6 = gpr_index = 0 (corresponds to A2; A0 and A1 are skipped)
9531b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    li    $t7, 0                # t7 = fp_index = 0
9541b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw    $t9, 20 + SPILL_SIZE($fp)  # get shorty (20 is offset from the $sp on entry + SPILL_SIZE
955590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic                                # as the $fp is SPILL_SIZE bytes below the $sp on entry)
9561b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t9, 1                # t9 = shorty + 1 (skip 1 for return type)
9571b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze
9581b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    // Load the base addresses of tabInt ... tabDouble.
9591b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    // We will use the register indices (gpr_index, fp_index) to branch.
9601b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    // Note that the indices are scaled by 16, so they can be added to the bases directly.
9611b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze#if defined(__mips_isa_rev) && __mips_isa_rev >= 6
9621b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lapc  $t2, tabInt
9631b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lapc  $t3, tabLong
9641b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lapc  $t4, tabSingle
9651b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lapc  $t5, tabDouble
9661b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze#else
9671b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    bltzal $zero, tabBase       # nal
9681b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t2, $ra, %lo(tabInt - tabBase)
9691b8464d17c2266763714ae18be7c4dc26e28bf61Alexey FrunzetabBase:
9701b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t3, $ra, %lo(tabLong - tabBase)
9711b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t4, $ra, %lo(tabSingle - tabBase)
9721b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t5, $ra, %lo(tabDouble - tabBase)
9731b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze#endif
9741b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze
975ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevicloop:
9761b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lbu   $ra, 0($t9)           # ra = shorty[i]
9771b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    beqz  $ra, loopEnd          # finish getting args when shorty[i] == '\0'
9781b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t9, 1
9791b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze
9801b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $ra, -'J'
9811b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    beqz  $ra, isLong           # branch if result type char == 'J'
9821b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $ra, 'J' - 'D'
9831b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    beqz  $ra, isDouble         # branch if result type char == 'D'
9841b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $ra, 'D' - 'F'
9851b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    beqz  $ra, isSingle         # branch if result type char == 'F'
9861b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze
9871b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addu  $ra, $t2, $t6
9881b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    jalr  $zero, $ra
9891b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t8, 4                # next_arg = curr_arg + 4
990ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic
991ff73498a5539d87424a964265e43765e788aec44Goran JakovljevicisLong:
9921b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addu  $ra, $t3, $t6
9931b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    jalr  $zero, $ra
9941b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t8, 8                # next_arg = curr_arg + 8
995ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic
996ff73498a5539d87424a964265e43765e788aec44Goran JakovljevicisSingle:
9971b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addu  $ra, $t4, $t7
9981b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    jalr  $zero, $ra
9991b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t8, 4                # next_arg = curr_arg + 4
10001b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze
10011b8464d17c2266763714ae18be7c4dc26e28bf61Alexey FrunzeisDouble:
10021b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addu  $ra, $t5, $t7
10031b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze#if defined(__mips_isa_rev) && __mips_isa_rev > 2
10041b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t7, 16               # fp_index += 16 didn't fit into LOAD_DOUBLE_TO_REG
10051b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze#endif
10061b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    jalr  $zero, $ra
10071b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t8, 8                # next_arg = curr_arg + 8
1008ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic
1009ff73498a5539d87424a964265e43765e788aec44Goran JakovljevicloopEnd:
1010e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    lw    $t9, ART_METHOD_QUICK_CODE_OFFSET_32($a0)  # get pointer to the code
10115d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    jalr  $t9                   # call the method
1012ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    sw    $zero, 0($sp)         # store null for ArtMethod* at bottom of frame
10135d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    move  $sp, $fp              # restore the stack
10145d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    lw    $s0, 0($sp)
1015bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 16
10165d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    lw    $s1, 4($sp)
1017bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 17
10185d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    lw    $fp, 8($sp)
1019bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 30
10205d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    lw    $ra, 12($sp)
1021bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    .cfi_restore 31
1022590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    addiu $sp, $sp, SPILL_SIZE
1023590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    .cfi_adjust_cfa_offset -SPILL_SIZE
10245d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    lw    $t0, 16($sp)          # get result pointer
10250177e53ea521ad58b70c305700dab32f1ac773b7Ian Rogers    lw    $t1, 20($sp)          # get shorty
10260177e53ea521ad58b70c305700dab32f1ac773b7Ian Rogers    lb    $t1, 0($t1)           # get result type char
1027ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    li    $t2, 'D'              # put char 'D' into t2
1028ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    beq   $t1, $t2, 5f          # branch if result type char == 'D'
1029ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    li    $t3, 'F'              # put char 'F' into t3
1030ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    beq   $t1, $t3, 5f          # branch if result type char == 'F'
10315d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    sw    $v0, 0($t0)           # store the result
10328d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr  $zero, $ra
10335d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    sw    $v1, 4($t0)           # store the other half of the result
1034ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic5:
1035e34652f15f32666323052a6718a63248244f1e66Duane Sand    SDu   $f0, $f1, 0, $t0, $t1 # store floating point result
10368d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr  $zero, $ra
1037e34652f15f32666323052a6718a63248244f1e66Duane Sand    nop
10381b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze
10391b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    // Note that gpr_index is kept within the range of tabInt and tabLong
10401b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    // and fp_index is kept within the range of tabSingle and tabDouble.
10411b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .balign 16
10421b8464d17c2266763714ae18be7c4dc26e28bf61Alexey FrunzetabInt:
10431b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_WORD_TO_REG a2, t8, t6, loop             # a2 = current argument, gpr_index += 16
10441b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_WORD_TO_REG a3, t8, t6, loop             # a3 = current argument, gpr_index += 16
10451b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_WORD_TO_REG t0, t8, t6, loop             # t0 = current argument, gpr_index += 16
10461b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_WORD_TO_REG t1, t8, t6, loop             # t1 = current argument, gpr_index += 16
10471b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_END t6, 4*16, loop                       # no more GPR args, gpr_index = 4*16
10481b8464d17c2266763714ae18be7c4dc26e28bf61Alexey FrunzetabLong:
10491b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_LONG_TO_REG a2, a3, t8, t6, 2*16, loop   # a2_a3 = curr_arg, gpr_index = 2*16
10501b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_LONG_TO_REG t0, t1, t8, t6, 4*16, loop   # t0_t1 = curr_arg, gpr_index = 4*16
10511b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_LONG_TO_REG t0, t1, t8, t6, 4*16, loop   # t0_t1 = curr_arg, gpr_index = 4*16
10521b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_END t6, 4*16, loop                       # no more GPR args, gpr_index = 4*16
10531b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_END t6, 4*16, loop                       # no more GPR args, gpr_index = 4*16
10541b8464d17c2266763714ae18be7c4dc26e28bf61Alexey FrunzetabSingle:
10551b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_FLOAT_TO_REG f8, t8, t7, loop            # f8 = curr_arg, fp_index += 16
10561b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_FLOAT_TO_REG f10, t8, t7, loop           # f10 = curr_arg, fp_index += 16
10571b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_FLOAT_TO_REG f12, t8, t7, loop           # f12 = curr_arg, fp_index += 16
10581b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_FLOAT_TO_REG f14, t8, t7, loop           # f14 = curr_arg, fp_index += 16
10591b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_FLOAT_TO_REG f16, t8, t7, loop           # f16 = curr_arg, fp_index += 16
10601b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_FLOAT_TO_REG f18, t8, t7, loop           # f18 = curr_arg, fp_index += 16
10611b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_END t7, 6*16, loop                       # no more FPR args, fp_index = 6*16
10621b8464d17c2266763714ae18be7c4dc26e28bf61Alexey FrunzetabDouble:
10631b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_DOUBLE_TO_REG f8, f9, t8, t7, ra, loop   # f8_f9 = curr_arg; if FPU32, fp_index += 16
10641b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_DOUBLE_TO_REG f10, f11, t8, t7, ra, loop # f10_f11 = curr_arg; if FPU32, fp_index += 16
10651b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_DOUBLE_TO_REG f12, f13, t8, t7, ra, loop # f12_f13 = curr_arg; if FPU32, fp_index += 16
10661b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_DOUBLE_TO_REG f14, f15, t8, t7, ra, loop # f14_f15 = curr_arg; if FPU32, fp_index += 16
10671b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_DOUBLE_TO_REG f16, f17, t8, t7, ra, loop # f16_f17 = curr_arg; if FPU32, fp_index += 16
10681b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_DOUBLE_TO_REG f18, f19, t8, t7, ra, loop # f18_f19 = curr_arg; if FPU32, fp_index += 16
10691b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_END t7, 6*16, loop                       # no more FPR args, fp_index = 6*16
10705d9173014c1ca09f7249a6b07629aa37778b5f8fJeff HaoEND art_quick_invoke_stub
10715d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao
10725d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    /*
1073ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic     * Invocation static stub for quick code.
1074ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic     * On entry:
1075ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic     *   a0 = method pointer
1076ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic     *   a1 = argument array or null for no argument methods
1077ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic     *   a2 = size of argument array in bytes
1078ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic     *   a3 = (managed) thread pointer
1079ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic     *   [sp + 16] = JValue* result
1080ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic     *   [sp + 20] = shorty
1081ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic     */
1082ff73498a5539d87424a964265e43765e788aec44Goran JakovljevicENTRY art_quick_invoke_static_stub
1083ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    sw    $a0, 0($sp)           # save out a0
1084590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    addiu $sp, $sp, -SPILL_SIZE # spill s0, s1, fp, ra and gp
1085590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    .cfi_adjust_cfa_offset SPILL_SIZE
1086590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    sw    $gp, 16($sp)
1087ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    sw    $ra, 12($sp)
1088ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    .cfi_rel_offset 31, 12
1089ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    sw    $fp, 8($sp)
1090ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    .cfi_rel_offset 30, 8
1091ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    sw    $s1, 4($sp)
1092ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    .cfi_rel_offset 17, 4
1093ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    sw    $s0, 0($sp)
1094ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    .cfi_rel_offset 16, 0
1095ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    move  $fp, $sp              # save sp in fp
1096ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    .cfi_def_cfa_register 30
1097ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    move  $s1, $a3              # move managed thread pointer into s1
1098ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    addiu $s0, $zero, SUSPEND_CHECK_INTERVAL  # reset s0 to suspend check interval
1099ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    addiu $t0, $a2, 4           # create space for ArtMethod* in frame.
1100ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    subu  $t0, $sp, $t0         # reserve & align *stack* to 16 bytes:
1101ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    srl   $t0, $t0, 4           #   native calling convention only aligns to 8B,
1102ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    sll   $sp, $t0, 4           #   so we have to ensure ART 16B alignment ourselves.
1103ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    addiu $a0, $sp, 4           # pass stack pointer + ArtMethod* as dest for memcpy
1104590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la    $t9, memcpy
1105590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    jalr  $t9                   # (dest, src, bytes)
1106ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    addiu $sp, $sp, -16         # make space for argument slots for memcpy
1107ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    addiu $sp, $sp, 16          # restore stack after memcpy
1108590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    lw    $gp, 16($fp)          # restore $gp
1109590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    lw    $a0, SPILL_SIZE($fp)  # restore ArtMethod*
11101b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t8, $sp, 4           # t8 = pointer to the current argument (skip ArtMethod*)
11111b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    li    $t6, 0                # t6 = gpr_index = 0 (corresponds to A1; A0 is skipped)
11121b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    li    $t7, 0                # t7 = fp_index = 0
11131b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw    $t9, 20 + SPILL_SIZE($fp)  # get shorty (20 is offset from the $sp on entry + SPILL_SIZE
1114590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic                                # as the $fp is SPILL_SIZE bytes below the $sp on entry)
11151b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t9, 1                # t9 = shorty + 1 (skip 1 for return type)
11161b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze
11171b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    // Load the base addresses of tabIntS ... tabDoubleS.
11181b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    // We will use the register indices (gpr_index, fp_index) to branch.
11191b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    // Note that the indices are scaled by 16, so they can be added to the bases directly.
11201b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze#if defined(__mips_isa_rev) && __mips_isa_rev >= 6
11211b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lapc  $t2, tabIntS
11221b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lapc  $t3, tabLongS
11231b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lapc  $t4, tabSingleS
11241b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lapc  $t5, tabDoubleS
11251b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze#else
11261b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    bltzal $zero, tabBaseS      # nal
11271b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t2, $ra, %lo(tabIntS - tabBaseS)
11281b8464d17c2266763714ae18be7c4dc26e28bf61Alexey FrunzetabBaseS:
11291b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t3, $ra, %lo(tabLongS - tabBaseS)
11301b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t4, $ra, %lo(tabSingleS - tabBaseS)
11311b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t5, $ra, %lo(tabDoubleS - tabBaseS)
11321b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze#endif
11331b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze
1134ff73498a5539d87424a964265e43765e788aec44Goran JakovljevicloopS:
11351b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lbu   $ra, 0($t9)           # ra = shorty[i]
11361b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    beqz  $ra, loopEndS         # finish getting args when shorty[i] == '\0'
11371b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t9, 1
11381b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze
11391b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $ra, -'J'
11401b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    beqz  $ra, isLongS          # branch if result type char == 'J'
11411b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $ra, 'J' - 'D'
11421b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    beqz  $ra, isDoubleS        # branch if result type char == 'D'
11431b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $ra, 'D' - 'F'
11441b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    beqz  $ra, isSingleS        # branch if result type char == 'F'
11451b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze
11461b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addu  $ra, $t2, $t6
11471b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    jalr  $zero, $ra
11481b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t8, 4                # next_arg = curr_arg + 4
1149ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic
1150ff73498a5539d87424a964265e43765e788aec44Goran JakovljevicisLongS:
11511b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addu  $ra, $t3, $t6
11521b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    jalr  $zero, $ra
11531b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t8, 8                # next_arg = curr_arg + 8
1154ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic
1155ff73498a5539d87424a964265e43765e788aec44Goran JakovljevicisSingleS:
11561b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addu  $ra, $t4, $t7
11571b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    jalr  $zero, $ra
11581b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t8, 4                # next_arg = curr_arg + 4
11591b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze
11601b8464d17c2266763714ae18be7c4dc26e28bf61Alexey FrunzeisDoubleS:
11611b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addu  $ra, $t5, $t7
11621b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze#if defined(__mips_isa_rev) && __mips_isa_rev > 2
11631b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t7, 16               # fp_index += 16 didn't fit into LOAD_DOUBLE_TO_REG
11641b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze#endif
11651b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    jalr  $zero, $ra
11661b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addiu $t8, 8                # next_arg = curr_arg + 8
1167ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic
1168ff73498a5539d87424a964265e43765e788aec44Goran JakovljevicloopEndS:
1169ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    lw    $t9, ART_METHOD_QUICK_CODE_OFFSET_32($a0)  # get pointer to the code
1170ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    jalr  $t9                   # call the method
1171ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    sw    $zero, 0($sp)         # store null for ArtMethod* at bottom of frame
1172ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    move  $sp, $fp              # restore the stack
1173ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    lw    $s0, 0($sp)
1174ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    .cfi_restore 16
1175ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    lw    $s1, 4($sp)
1176ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    .cfi_restore 17
1177ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    lw    $fp, 8($sp)
1178ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    .cfi_restore 30
1179ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    lw    $ra, 12($sp)
1180ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    .cfi_restore 31
1181590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    addiu $sp, $sp, SPILL_SIZE
1182590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    .cfi_adjust_cfa_offset -SPILL_SIZE
1183ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    lw    $t0, 16($sp)          # get result pointer
1184ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    lw    $t1, 20($sp)          # get shorty
1185ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    lb    $t1, 0($t1)           # get result type char
1186ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    li    $t2, 'D'              # put char 'D' into t2
1187ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    beq   $t1, $t2, 6f          # branch if result type char == 'D'
1188ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    li    $t3, 'F'              # put char 'F' into t3
1189ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    beq   $t1, $t3, 6f          # branch if result type char == 'F'
1190ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    sw    $v0, 0($t0)           # store the result
1191ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    jalr  $zero, $ra
1192ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    sw    $v1, 4($t0)           # store the other half of the result
1193ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic6:
1194ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    SDu   $f0, $f1, 0, $t0, $t1 # store floating point result
1195ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    jalr  $zero, $ra
1196ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    nop
11971b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze
11981b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    // Note that gpr_index is kept within the range of tabIntS and tabLongS
11991b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    // and fp_index is kept within the range of tabSingleS and tabDoubleS.
12001b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    .balign 16
12011b8464d17c2266763714ae18be7c4dc26e28bf61Alexey FrunzetabIntS:
12021b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_WORD_TO_REG a1, t8, t6, loopS             # a1 = current argument, gpr_index += 16
12031b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_WORD_TO_REG a2, t8, t6, loopS             # a2 = current argument, gpr_index += 16
12041b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_WORD_TO_REG a3, t8, t6, loopS             # a3 = current argument, gpr_index += 16
12051b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_WORD_TO_REG t0, t8, t6, loopS             # t0 = current argument, gpr_index += 16
12061b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_WORD_TO_REG t1, t8, t6, loopS             # t1 = current argument, gpr_index += 16
12071b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_END t6, 5*16, loopS                       # no more GPR args, gpr_index = 5*16
12081b8464d17c2266763714ae18be7c4dc26e28bf61Alexey FrunzetabLongS:
12091b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_LONG_TO_REG a2, a3, t8, t6, 3*16, loopS   # a2_a3 = curr_arg, gpr_index = 3*16
12101b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_LONG_TO_REG a2, a3, t8, t6, 3*16, loopS   # a2_a3 = curr_arg, gpr_index = 3*16
12111b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_LONG_TO_REG t0, t1, t8, t6, 5*16, loopS   # t0_t1 = curr_arg, gpr_index = 5*16
12121b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_LONG_TO_REG t0, t1, t8, t6, 5*16, loopS   # t0_t1 = curr_arg, gpr_index = 5*16
12131b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_END t6, 5*16, loopS                       # no more GPR args, gpr_index = 5*16
12141b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_END t6, 5*16, loopS                       # no more GPR args, gpr_index = 5*16
12151b8464d17c2266763714ae18be7c4dc26e28bf61Alexey FrunzetabSingleS:
12161b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_FLOAT_TO_REG f8, t8, t7, loopS            # f8 = curr_arg, fp_index += 16
12171b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_FLOAT_TO_REG f10, t8, t7, loopS           # f10 = curr_arg, fp_index += 16
12181b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_FLOAT_TO_REG f12, t8, t7, loopS           # f12 = curr_arg, fp_index += 16
12191b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_FLOAT_TO_REG f14, t8, t7, loopS           # f14 = curr_arg, fp_index += 16
12201b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_FLOAT_TO_REG f16, t8, t7, loopS           # f16 = curr_arg, fp_index += 16
12211b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_FLOAT_TO_REG f18, t8, t7, loopS           # f18 = curr_arg, fp_index += 16
12221b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_END t7, 6*16, loopS                       # no more FPR args, fp_index = 6*16
12231b8464d17c2266763714ae18be7c4dc26e28bf61Alexey FrunzetabDoubleS:
12241b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_DOUBLE_TO_REG f8, f9, t8, t7, ra, loopS   # f8_f9 = curr_arg; if FPU32, fp_index += 16
12251b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_DOUBLE_TO_REG f10, f11, t8, t7, ra, loopS # f10_f11 = curr_arg; if FPU32, fp_index += 16
12261b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_DOUBLE_TO_REG f12, f13, t8, t7, ra, loopS # f12_f13 = curr_arg; if FPU32, fp_index += 16
12271b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_DOUBLE_TO_REG f14, f15, t8, t7, ra, loopS # f14_f15 = curr_arg; if FPU32, fp_index += 16
12281b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_DOUBLE_TO_REG f16, f17, t8, t7, ra, loopS # f16_f17 = curr_arg; if FPU32, fp_index += 16
12291b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_DOUBLE_TO_REG f18, f19, t8, t7, ra, loopS # f18_f19 = curr_arg; if FPU32, fp_index += 16
12301b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    LOAD_END t7, 6*16, loopS                       # no more FPR args, fp_index = 6*16
1231ff73498a5539d87424a964265e43765e788aec44Goran JakovljevicEND art_quick_invoke_static_stub
1232ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic
1233590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic#undef SPILL_SIZE
1234590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic
1235ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic    /*
12365bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * Entry from managed code that calls artHandleFillArrayDataFromCode and delivers exception on
12375bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * failure.
12385bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
1239d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff Hao    .extern artHandleFillArrayDataFromCode
1240468532ea115657709bc32ee498e701a4c71762d4Ian RogersENTRY art_quick_handle_fill_data
1241fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    lw     $a2, 0($sp)                # pass referrer's Method*
1242fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_REFS_ONLY_FRAME        # save callee saves in case exception allocation triggers GC
1243590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la     $t9, artHandleFillArrayDataFromCode
1244fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    jalr   $t9                        # (payload offset, Array*, method, Thread*)
1245fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    move   $a3, rSELF                 # pass Thread::Current
1246fc6a30e2fa8f0d44e6c95bbeb5deca4b499f67cejeffhao    RETURN_IF_ZERO
1247468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND art_quick_handle_fill_data
12485bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
12495bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
125057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     * Entry from managed code that calls artLockObjectFromCode, may block for GC.
12515bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
1252d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff Hao    .extern artLockObjectFromCode
1253468532ea115657709bc32ee498e701a4c71762d4Ian RogersENTRY art_quick_lock_object
1254804b03ffb9b9dc6cc3153e004c2cd38667508b13Vladimir Marko    beqz    $a0, art_quick_throw_null_pointer_exception
1255ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    li      $t8, LOCK_WORD_THIN_LOCK_COUNT_ONE
1256ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    li      $t3, LOCK_WORD_GC_STATE_MASK_SHIFTED_TOGGLED
1257ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze.Lretry_lock:
1258ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    lw      $t0, THREAD_ID_OFFSET(rSELF)  # TODO: Can the thread ID really change during the loop?
1259ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    ll      $t1, MIRROR_OBJECT_LOCK_WORD_OFFSET($a0)
1260ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    and     $t2, $t1, $t3                 # zero the gc bits
1261ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    bnez    $t2, .Lnot_unlocked           # already thin locked
1262ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    # Unlocked case - $t1: original lock word that's zero except for the read barrier bits.
1263ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    or      $t2, $t1, $t0                 # $t2 holds thread id with count of 0 with preserved read barrier bits
1264ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    sc      $t2, MIRROR_OBJECT_LOCK_WORD_OFFSET($a0)
1265ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    beqz    $t2, .Lretry_lock             # store failed, retry
1266a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    nop
1267ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    jalr    $zero, $ra
1268ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    sync                                  # full (LoadLoad|LoadStore) memory barrier
1269ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze.Lnot_unlocked:
1270ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    # $t1: original lock word, $t0: thread_id with count of 0 and zero read barrier bits
1271ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    srl     $t2, $t1, LOCK_WORD_STATE_SHIFT
1272ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    bnez    $t2, .Lslow_lock              # if either of the top two bits are set, go slow path
1273ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    xor     $t2, $t1, $t0                 # lock_word.ThreadId() ^ self->ThreadId()
1274ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    andi    $t2, $t2, 0xFFFF              # zero top 16 bits
1275ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    bnez    $t2, .Lslow_lock              # lock word and self thread id's match -> recursive lock
1276ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze                                          # otherwise contention, go to slow path
1277ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    and     $t2, $t1, $t3                 # zero the gc bits
1278ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    addu    $t2, $t2, $t8                 # increment count in lock word
1279ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    srl     $t2, $t2, LOCK_WORD_STATE_SHIFT  # if the first gc state bit is set, we overflowed.
1280ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    bnez    $t2, .Lslow_lock              # if we overflow the count go slow path
1281ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    addu    $t2, $t1, $t8                 # increment count for real
1282ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    sc      $t2, MIRROR_OBJECT_LOCK_WORD_OFFSET($a0)
1283ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    beqz    $t2, .Lretry_lock             # store failed, retry
1284ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    nop
1285ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    jalr    $zero, $ra
1286ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    nop
1287ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze.Lslow_lock:
1288fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_REFS_ONLY_FRAME            # save callee saves in case we block
1289590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la      $t9, artLockObjectFromCode
1290590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    jalr    $t9                           # (Object* obj, Thread*)
12917fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    move    $a1, rSELF                    # pass Thread::Current
12926bcd163d322b867578fbcfe60e4e3b247c42974bIan Rogers    RETURN_IF_ZERO
1293468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND art_quick_lock_object
12945bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
1295c7ed09bd5d6f2c7af3bcba1c39b3f9185af68796Andreas GampeENTRY art_quick_lock_object_no_inline
1296804b03ffb9b9dc6cc3153e004c2cd38667508b13Vladimir Marko    beqz    $a0, art_quick_throw_null_pointer_exception
1297c7ed09bd5d6f2c7af3bcba1c39b3f9185af68796Andreas Gampe    nop
1298fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_REFS_ONLY_FRAME            # save callee saves in case we block
1299c7ed09bd5d6f2c7af3bcba1c39b3f9185af68796Andreas Gampe    la      $t9, artLockObjectFromCode
1300c7ed09bd5d6f2c7af3bcba1c39b3f9185af68796Andreas Gampe    jalr    $t9                           # (Object* obj, Thread*)
1301c7ed09bd5d6f2c7af3bcba1c39b3f9185af68796Andreas Gampe    move    $a1, rSELF                    # pass Thread::Current
1302c7ed09bd5d6f2c7af3bcba1c39b3f9185af68796Andreas Gampe    RETURN_IF_ZERO
1303c7ed09bd5d6f2c7af3bcba1c39b3f9185af68796Andreas GampeEND art_quick_lock_object_no_inline
1304c7ed09bd5d6f2c7af3bcba1c39b3f9185af68796Andreas Gampe
13055bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
13065bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * Entry from managed code that calls artUnlockObjectFromCode and delivers exception on failure.
13075bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
1308d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff Hao    .extern artUnlockObjectFromCode
1309468532ea115657709bc32ee498e701a4c71762d4Ian RogersENTRY art_quick_unlock_object
1310804b03ffb9b9dc6cc3153e004c2cd38667508b13Vladimir Marko    beqz    $a0, art_quick_throw_null_pointer_exception
1311ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    li      $t8, LOCK_WORD_THIN_LOCK_COUNT_ONE
1312ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    li      $t3, LOCK_WORD_GC_STATE_MASK_SHIFTED_TOGGLED
1313ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze.Lretry_unlock:
1314ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze#ifndef USE_READ_BARRIER
1315ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    lw      $t1, MIRROR_OBJECT_LOCK_WORD_OFFSET($a0)
1316ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze#else
1317ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    ll      $t1, MIRROR_OBJECT_LOCK_WORD_OFFSET($a0)  # Need to use atomic read-modify-write for read barrier
1318ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze#endif
1319ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    srl     $t2, $t1, LOCK_WORD_STATE_SHIFT
1320ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    bnez    $t2, .Lslow_unlock         # if either of the top two bits are set, go slow path
1321ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    lw      $t0, THREAD_ID_OFFSET(rSELF)
1322ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    and     $t2, $t1, $t3              # zero the gc bits
1323ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    xor     $t2, $t2, $t0              # lock_word.ThreadId() ^ self->ThreadId()
1324ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    andi    $t2, $t2, 0xFFFF           # zero top 16 bits
1325ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    bnez    $t2, .Lslow_unlock         # do lock word and self thread id's match?
1326ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    and     $t2, $t1, $t3              # zero the gc bits
1327ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    bgeu    $t2, $t8, .Lrecursive_thin_unlock
1328ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    # transition to unlocked
1329ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    nor     $t2, $zero, $t3            # $t2 = LOCK_WORD_GC_STATE_MASK_SHIFTED
1330ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    and     $t2, $t1, $t2              # $t2: zero except for the preserved gc bits
1331ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    sync                               # full (LoadStore|StoreStore) memory barrier
1332ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze#ifndef USE_READ_BARRIER
1333ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    jalr    $zero, $ra
1334ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    sw      $t2, MIRROR_OBJECT_LOCK_WORD_OFFSET($a0)
1335ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze#else
1336ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    sc      $t2, MIRROR_OBJECT_LOCK_WORD_OFFSET($a0)
1337ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    beqz    $t2, .Lretry_unlock        # store failed, retry
1338a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    nop
1339ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    jalr    $zero, $ra
1340ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    nop
1341ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze#endif
1342ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze.Lrecursive_thin_unlock:
1343ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    # t1: original lock word
1344ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    subu    $t2, $t1, $t8              # decrement count
1345ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze#ifndef USE_READ_BARRIER
1346ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    jalr    $zero, $ra
1347ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    sw      $t2, MIRROR_OBJECT_LOCK_WORD_OFFSET($a0)
1348ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze#else
1349ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    sc      $t2, MIRROR_OBJECT_LOCK_WORD_OFFSET($a0)
1350ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    beqz    $t2, .Lretry_unlock        # store failed, retry
1351ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    nop
1352ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    jalr    $zero, $ra
1353ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    nop
1354ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze#endif
1355ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze.Lslow_unlock:
1356ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    SETUP_SAVE_REFS_ONLY_FRAME         # save callee saves in case exception allocation triggers GC
1357590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la      $t9, artUnlockObjectFromCode
1358ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    jalr    $t9                        # (Object* obj, Thread*)
1359ad63fe5f330d10e08467e0c7c6f4c199b62fa3abAlexey Frunze    move    $a1, rSELF                 # pass Thread::Current
13605bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    RETURN_IF_ZERO
1361468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND art_quick_unlock_object
13625bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
1363c7ed09bd5d6f2c7af3bcba1c39b3f9185af68796Andreas GampeENTRY art_quick_unlock_object_no_inline
1364804b03ffb9b9dc6cc3153e004c2cd38667508b13Vladimir Marko    beqz    $a0, art_quick_throw_null_pointer_exception
1365c7ed09bd5d6f2c7af3bcba1c39b3f9185af68796Andreas Gampe    nop
1366fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_REFS_ONLY_FRAME        # save callee saves in case exception allocation triggers GC
1367c7ed09bd5d6f2c7af3bcba1c39b3f9185af68796Andreas Gampe    la      $t9, artUnlockObjectFromCode
1368c7ed09bd5d6f2c7af3bcba1c39b3f9185af68796Andreas Gampe    jalr    $t9                       # (Object* obj, Thread*)
1369c7ed09bd5d6f2c7af3bcba1c39b3f9185af68796Andreas Gampe    move    $a1, rSELF                # pass Thread::Current
1370c7ed09bd5d6f2c7af3bcba1c39b3f9185af68796Andreas Gampe    RETURN_IF_ZERO
1371c7ed09bd5d6f2c7af3bcba1c39b3f9185af68796Andreas GampeEND art_quick_unlock_object_no_inline
1372c7ed09bd5d6f2c7af3bcba1c39b3f9185af68796Andreas Gampe
13735bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
1374b99f4d6463e7cb5654af3893ed7b3113665df658Mathieu Chartier     * Entry from managed code that calls artInstanceOfFromCode and delivers exception on failure.
13755bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
1376b99f4d6463e7cb5654af3893ed7b3113665df658Mathieu Chartier    .extern artInstanceOfFromCode
1377b99f4d6463e7cb5654af3893ed7b3113665df658Mathieu Chartier    .extern artThrowClassCastExceptionForObject
1378b99f4d6463e7cb5654af3893ed7b3113665df658Mathieu ChartierENTRY art_quick_check_instance_of
1379590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    addiu  $sp, $sp, -32
1380590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    .cfi_adjust_cfa_offset 32
1381590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    sw     $gp, 16($sp)
1382a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    sw     $ra, 12($sp)
1383a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    .cfi_rel_offset 31, 12
1384a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    sw     $t9, 8($sp)
1385a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    sw     $a1, 4($sp)
1386a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    sw     $a0, 0($sp)
1387b99f4d6463e7cb5654af3893ed7b3113665df658Mathieu Chartier    la     $t9, artInstanceOfFromCode
1388590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    jalr   $t9
1389735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    addiu  $sp, $sp, -16             # reserve argument slots on the stack
1390735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    addiu  $sp, $sp, 16
1391590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    lw     $gp, 16($sp)
139286bcdc251f5ae22fcedd18c096ea538b7dbfa8cbIan Rogers    beqz   $v0, .Lthrow_class_cast_exception
1393a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    lw     $ra, 12($sp)
13948d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr   $zero, $ra
1395590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    addiu  $sp, $sp, 32
1396590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    .cfi_adjust_cfa_offset -32
139786bcdc251f5ae22fcedd18c096ea538b7dbfa8cbIan Rogers.Lthrow_class_cast_exception:
1398a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    lw     $t9, 8($sp)
1399a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    lw     $a1, 4($sp)
1400a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    lw     $a0, 0($sp)
1401590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    addiu  $sp, $sp, 32
1402590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    .cfi_adjust_cfa_offset -32
1403fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
1404b99f4d6463e7cb5654af3893ed7b3113665df658Mathieu Chartier    la   $t9, artThrowClassCastExceptionForObject
1405b99f4d6463e7cb5654af3893ed7b3113665df658Mathieu Chartier    jalr $zero, $t9                 # artThrowClassCastException (Object*, Class*, Thread*)
14061d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    move $a2, rSELF                 # pass Thread::Current
1407b99f4d6463e7cb5654af3893ed7b3113665df658Mathieu ChartierEND art_quick_check_instance_of
14085bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
14095bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
14101aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao     * Restore rReg's value from offset($sp) if rReg is not the same as rExclude.
14111aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao     * nReg is the register number for rReg.
14121aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao     */
14131aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao.macro POP_REG_NE rReg, nReg, offset, rExclude
14141aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .ifnc \rReg, \rExclude
14151aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao        lw \rReg, \offset($sp)      # restore rReg
14161aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao        .cfi_restore \nReg
14171aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .endif
14181aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao.endm
14191aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao
14201aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    /*
14211aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao     * Macro to insert read barrier, only used in art_quick_aput_obj.
14221aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao     * rObj and rDest are registers, offset is a defined literal such as MIRROR_OBJECT_CLASS_OFFSET.
14231aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao     * TODO: When read barrier has a fast path, add heap unpoisoning support for the fast path.
14241aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao     */
14251aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao.macro READ_BARRIER rDest, rObj, offset
14261aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao#ifdef USE_READ_BARRIER
14271aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    # saved registers used in art_quick_aput_obj: a0-a2, t0-t1, t9, ra. 8 words for 16B alignment.
14281aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    addiu  $sp, $sp, -32
14291aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .cfi_adjust_cfa_offset 32
14301aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    sw     $ra, 28($sp)
14311aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .cfi_rel_offset 31, 28
14321aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    sw     $t9, 24($sp)
14331aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .cfi_rel_offset 25, 24
14341aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    sw     $t1, 20($sp)
14351aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .cfi_rel_offset 9, 20
14361aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    sw     $t0, 16($sp)
14371aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .cfi_rel_offset 8, 16
14381aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    sw     $a2, 8($sp)              # padding slot at offset 12 (padding can be any slot in the 32B)
14391aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .cfi_rel_offset 6, 8
14401aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    sw     $a1, 4($sp)
14411aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .cfi_rel_offset 5, 4
14421aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    sw     $a0, 0($sp)
14431aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .cfi_rel_offset 4, 0
14441aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao
14456306921722283d2b0f8aac01883ad83215d6e864Man Cao    # move $a0, \rRef               # pass ref in a0 (no-op for now since parameter ref is unused)
14461aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .ifnc \rObj, $a1
14471aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao        move $a1, \rObj             # pass rObj
14481aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .endif
1449590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    addiu  $a2, $zero, \offset      # pass offset
1450590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la     $t9, artReadBarrierSlow
1451590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    jalr   $t9                      # artReadBarrierSlow(ref, rObj, offset)
14521aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    addiu  $sp, $sp, -16            # Use branch delay slot to reserve argument slots on the stack
14531aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao                                    # before the call to artReadBarrierSlow.
14541aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    addiu  $sp, $sp, 16             # restore stack after call to artReadBarrierSlow
14551aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    # No need to unpoison return value in v0, artReadBarrierSlow() would do the unpoisoning.
14561aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    move \rDest, $v0                # save return value in rDest
14571aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao                                    # (rDest cannot be v0 in art_quick_aput_obj)
14581aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao
14591aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    lw     $a0, 0($sp)              # restore registers except rDest
14601aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao                                    # (rDest can only be t0 or t1 in art_quick_aput_obj)
14611aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .cfi_restore 4
14621aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    lw     $a1, 4($sp)
14631aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .cfi_restore 5
14641aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    lw     $a2, 8($sp)
14651aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .cfi_restore 6
14661aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    POP_REG_NE $t0, 8, 16, \rDest
14671aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    POP_REG_NE $t1, 9, 20, \rDest
14681aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    lw     $t9, 24($sp)
14691aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .cfi_restore 25
14701aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    lw     $ra, 28($sp)             # restore $ra
14711aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .cfi_restore 31
14721aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    addiu  $sp, $sp, 32
14731aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .cfi_adjust_cfa_offset -32
14741aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao#else
14751aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    lw     \rDest, \offset(\rObj)
14761aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    UNPOISON_HEAP_REF \rDest
14771aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao#endif  // USE_READ_BARRIER
14781aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao.endm
14791aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao
14801aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao#ifdef USE_READ_BARRIER
14811aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .extern artReadBarrierSlow
14821aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao#endif
1483a9a8254c920ce8e22210abfc16c9842ce0aea28fIan RogersENTRY art_quick_aput_obj
148486bcdc251f5ae22fcedd18c096ea538b7dbfa8cbIan Rogers    beqz $a2, .Ldo_aput_null
1485a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    nop
14861aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    READ_BARRIER $t0, $a0, MIRROR_OBJECT_CLASS_OFFSET
14871aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    READ_BARRIER $t1, $a2, MIRROR_OBJECT_CLASS_OFFSET
14881aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    READ_BARRIER $t0, $t0, MIRROR_CLASS_COMPONENT_TYPE_OFFSET
148986bcdc251f5ae22fcedd18c096ea538b7dbfa8cbIan Rogers    bne $t1, $t0, .Lcheck_assignability  # value's type == array's component type - trivial assignability
1490a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    nop
149186bcdc251f5ae22fcedd18c096ea538b7dbfa8cbIan Rogers.Ldo_aput:
1492a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    sll $a1, $a1, 2
1493a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    add $t0, $a0, $a1
1494bfa5eb6e8d15ea73a36f8df449630f285a91e995Hiroshi Yamauchi    POISON_HEAP_REF $a2
14951d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    sw  $a2, MIRROR_OBJECT_ARRAY_DATA_OFFSET($t0)
1496a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    lw  $t0, THREAD_CARD_TABLE_OFFSET(rSELF)
1497afdcbcb56d0c2f985d0291c369bbc493eedb05b0Mathieu Chartier    srl $t1, $a0, CARD_TABLE_CARD_SHIFT
1498a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    add $t1, $t1, $t0
1499a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    sb  $t0, ($t1)
15008d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr $zero, $ra
1501a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    nop
150286bcdc251f5ae22fcedd18c096ea538b7dbfa8cbIan Rogers.Ldo_aput_null:
1503a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    sll $a1, $a1, 2
1504a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    add $t0, $a0, $a1
15051d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    sw  $a2, MIRROR_OBJECT_ARRAY_DATA_OFFSET($t0)
15068d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr $zero, $ra
1507a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    nop
150886bcdc251f5ae22fcedd18c096ea538b7dbfa8cbIan Rogers.Lcheck_assignability:
1509a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    addiu  $sp, $sp, -32
1510a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    .cfi_adjust_cfa_offset 32
1511a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    sw     $ra, 28($sp)
1512a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    .cfi_rel_offset 31, 28
1513590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    sw     $gp, 16($sp)
1514a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    sw     $t9, 12($sp)
1515a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    sw     $a2, 8($sp)
1516a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    sw     $a1, 4($sp)
1517a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    sw     $a0, 0($sp)
1518a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    move   $a1, $t1
1519a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    move   $a0, $t0
1520590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la     $t9, artIsAssignableFromCode
1521590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    jalr   $t9               # (Class*, Class*)
1522590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    addiu  $sp, $sp, -16     # reserve argument slots on the stack
1523590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    addiu  $sp, $sp, 16
1524a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    lw     $ra, 28($sp)
1525590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    lw     $gp, 16($sp)
1526a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    lw     $t9, 12($sp)
1527a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    lw     $a2, 8($sp)
1528a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    lw     $a1, 4($sp)
1529a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    lw     $a0, 0($sp)
1530e34652f15f32666323052a6718a63248244f1e66Duane Sand    addiu  $sp, 32
1531a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    .cfi_adjust_cfa_offset -32
153286bcdc251f5ae22fcedd18c096ea538b7dbfa8cbIan Rogers    bnez   $v0, .Ldo_aput
1533a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    nop
1534fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
1535a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    move $a1, $a2
1536a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    la   $t9, artThrowArrayStoreException
15378d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr $zero, $t9                 # artThrowArrayStoreException(Class*, Class*, Thread*)
15381d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    move $a2, rSELF                 # pass Thread::Current
1539a9a8254c920ce8e22210abfc16c9842ce0aea28fIan RogersEND art_quick_aput_obj
15405bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
15410cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze// Macros taking opportunity of code similarities for downcalls.
15420cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze.macro ONE_ARG_REF_DOWNCALL name, entrypoint, return
15430cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    .extern \entrypoint
15440cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeENTRY \name
15450cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    SETUP_SAVE_REFS_ONLY_FRAME        # save callee saves in case of GC
15460cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    la      $t9, \entrypoint
15470cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    jalr    $t9                       # (field_idx, Thread*)
15480cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    move    $a1, rSELF                # pass Thread::Current
15490cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    \return                           # RETURN_IF_NO_EXCEPTION or RETURN_IF_ZERO
15500cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeEND \name
15510cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze.endm
155237f05ef45e0393de812d51261dc293240c17294dFred Shih
15530cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze.macro TWO_ARG_REF_DOWNCALL name, entrypoint, return
15540cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    .extern \entrypoint
15550cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeENTRY \name
15560cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    SETUP_SAVE_REFS_ONLY_FRAME        # save callee saves in case of GC
15570cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    la      $t9, \entrypoint
15580cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    jalr    $t9                       # (field_idx, Object*, Thread*) or
15590cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze                                      # (field_idx, new_val, Thread*)
15600cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    move    $a2, rSELF                # pass Thread::Current
15610cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    \return                           # RETURN_IF_NO_EXCEPTION or RETURN_IF_ZERO
15620cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeEND \name
15630cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze.endm
156437f05ef45e0393de812d51261dc293240c17294dFred Shih
15650cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze.macro THREE_ARG_REF_DOWNCALL name, entrypoint, return
15660cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    .extern \entrypoint
15670cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeENTRY \name
15680cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    SETUP_SAVE_REFS_ONLY_FRAME        # save callee saves in case of GC
15690cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    la      $t9, \entrypoint
15700cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    jalr    $t9                       # (field_idx, Object*, new_val, Thread*)
15710cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    move    $a3, rSELF                # pass Thread::Current
15720cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    \return                           # RETURN_IF_NO_EXCEPTION or RETURN_IF_ZERO
15730cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeEND \name
15740cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze.endm
15755bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
15760cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze.macro FOUR_ARG_REF_DOWNCALL name, entrypoint, return
15770cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    .extern \entrypoint
15780cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeENTRY \name
15790cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    SETUP_SAVE_REFS_ONLY_FRAME        # save callee saves in case of GC
15800cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    la      $t9, \entrypoint
15810cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    jalr    $t9                       # (field_idx, Object*, 64-bit new_val, Thread*) or
15820cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze                                      # (field_idx, 64-bit new_val, Thread*)
15830cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze                                      # Note that a 64-bit new_val needs to be aligned with
15840cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze                                      # an even-numbered register, hence A1 may be skipped
15850cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze                                      # for new_val to reside in A2-A3.
15860cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    sw      rSELF, 16($sp)            # pass Thread::Current
15870cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze    \return                           # RETURN_IF_NO_EXCEPTION or RETURN_IF_ZERO
15880cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeEND \name
15890cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze.endm
15905bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
15915bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
15920cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey Frunze     * Called by managed code to resolve a static/instance field and load/store a value.
15935bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
15940cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeONE_ARG_REF_DOWNCALL art_quick_get_byte_static, artGetByteStaticFromCompiledCode, RETURN_IF_NO_EXCEPTION
15950cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeONE_ARG_REF_DOWNCALL art_quick_get_boolean_static, artGetBooleanStaticFromCompiledCode, RETURN_IF_NO_EXCEPTION
15960cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeONE_ARG_REF_DOWNCALL art_quick_get_short_static, artGetShortStaticFromCompiledCode, RETURN_IF_NO_EXCEPTION
15970cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeONE_ARG_REF_DOWNCALL art_quick_get_char_static, artGetCharStaticFromCompiledCode, RETURN_IF_NO_EXCEPTION
15980cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeONE_ARG_REF_DOWNCALL art_quick_get32_static, artGet32StaticFromCompiledCode, RETURN_IF_NO_EXCEPTION
15990cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeONE_ARG_REF_DOWNCALL art_quick_get_obj_static, artGetObjStaticFromCompiledCode, RETURN_IF_NO_EXCEPTION
16000cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeONE_ARG_REF_DOWNCALL art_quick_get64_static, artGet64StaticFromCompiledCode, RETURN_IF_NO_EXCEPTION
16010cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeTWO_ARG_REF_DOWNCALL art_quick_get_byte_instance, artGetByteInstanceFromCompiledCode, RETURN_IF_NO_EXCEPTION
16020cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeTWO_ARG_REF_DOWNCALL art_quick_get_boolean_instance, artGetBooleanInstanceFromCompiledCode, RETURN_IF_NO_EXCEPTION
16030cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeTWO_ARG_REF_DOWNCALL art_quick_get_short_instance, artGetShortInstanceFromCompiledCode, RETURN_IF_NO_EXCEPTION
16040cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeTWO_ARG_REF_DOWNCALL art_quick_get_char_instance, artGetCharInstanceFromCompiledCode, RETURN_IF_NO_EXCEPTION
16050cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeTWO_ARG_REF_DOWNCALL art_quick_get32_instance, artGet32InstanceFromCompiledCode, RETURN_IF_NO_EXCEPTION
16060cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeTWO_ARG_REF_DOWNCALL art_quick_get_obj_instance, artGetObjInstanceFromCompiledCode, RETURN_IF_NO_EXCEPTION
16070cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeTWO_ARG_REF_DOWNCALL art_quick_get64_instance, artGet64InstanceFromCompiledCode, RETURN_IF_NO_EXCEPTION
16080cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeTWO_ARG_REF_DOWNCALL art_quick_set8_static, artSet8StaticFromCompiledCode, RETURN_IF_ZERO
16090cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeTWO_ARG_REF_DOWNCALL art_quick_set16_static, artSet16StaticFromCompiledCode, RETURN_IF_ZERO
16100cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeTWO_ARG_REF_DOWNCALL art_quick_set32_static, artSet32StaticFromCompiledCode, RETURN_IF_ZERO
16110cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeTWO_ARG_REF_DOWNCALL art_quick_set_obj_static, artSetObjStaticFromCompiledCode, RETURN_IF_ZERO
16120cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeFOUR_ARG_REF_DOWNCALL art_quick_set64_static, artSet64StaticFromCompiledCode, RETURN_IF_ZERO
16130cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeTHREE_ARG_REF_DOWNCALL art_quick_set8_instance, artSet8InstanceFromCompiledCode, RETURN_IF_ZERO
16140cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeTHREE_ARG_REF_DOWNCALL art_quick_set16_instance, artSet16InstanceFromCompiledCode, RETURN_IF_ZERO
16150cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeTHREE_ARG_REF_DOWNCALL art_quick_set32_instance, artSet32InstanceFromCompiledCode, RETURN_IF_ZERO
16160cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeTHREE_ARG_REF_DOWNCALL art_quick_set_obj_instance, artSetObjInstanceFromCompiledCode, RETURN_IF_ZERO
16170cb124219e986a27c40001a1b22ea7ebd833a2d8Alexey FrunzeFOUR_ARG_REF_DOWNCALL art_quick_set64_instance, artSet64InstanceFromCompiledCode, RETURN_IF_ZERO
16185bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
1619a3c382738bc54f464a57e2b51b51ad305eb03dd2Vladimir Marko// Macro to facilitate adding new allocation entrypoints.
16205ea536aa4a6414db01beaf6f8bd8cb9adc5cfc92Vladimir Marko.macro ONE_ARG_DOWNCALL name, entrypoint, return
16215ea536aa4a6414db01beaf6f8bd8cb9adc5cfc92Vladimir Marko    .extern \entrypoint
16225ea536aa4a6414db01beaf6f8bd8cb9adc5cfc92Vladimir MarkoENTRY \name
1623fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_REFS_ONLY_FRAME        # save callee saves in case of GC
1624590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la      $t9, \entrypoint
1625590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    jalr    $t9
16265ea536aa4a6414db01beaf6f8bd8cb9adc5cfc92Vladimir Marko    move    $a1, rSELF                # pass Thread::Current
16275ea536aa4a6414db01beaf6f8bd8cb9adc5cfc92Vladimir Marko    \return
16285ea536aa4a6414db01beaf6f8bd8cb9adc5cfc92Vladimir MarkoEND \name
16295ea536aa4a6414db01beaf6f8bd8cb9adc5cfc92Vladimir Marko.endm
16305ea536aa4a6414db01beaf6f8bd8cb9adc5cfc92Vladimir Marko
1631cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier.macro TWO_ARG_DOWNCALL name, entrypoint, return
1632cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier    .extern \entrypoint
1633cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu ChartierENTRY \name
1634fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_REFS_ONLY_FRAME        # save callee saves in case of GC
1635590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la      $t9, \entrypoint
1636590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    jalr    $t9
16371d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    move    $a2, rSELF                # pass Thread::Current
1638cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier    \return
1639cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu ChartierEND \name
1640cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier.endm
16415bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
1642cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier.macro THREE_ARG_DOWNCALL name, entrypoint, return
1643cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier    .extern \entrypoint
1644cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu ChartierENTRY \name
1645fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_REFS_ONLY_FRAME        # save callee saves in case of GC
1646590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la      $t9, \entrypoint
1647590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    jalr    $t9
16481d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    move    $a3, rSELF                # pass Thread::Current
1649cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier    \return
1650cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu ChartierEND \name
1651cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier.endm
16525bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
1653848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao.macro FOUR_ARG_DOWNCALL name, entrypoint, return
1654848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    .extern \entrypoint
1655848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff HaoENTRY \name
1656fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_REFS_ONLY_FRAME        # save callee saves in case of GC
1657590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la      $t9, \entrypoint
1658590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    jalr    $t9
1659a3c382738bc54f464a57e2b51b51ad305eb03dd2Vladimir Marko    sw      rSELF, 16($sp)            # pass Thread::Current
1660848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    \return
1661848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff HaoEND \name
1662848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao.endm
1663848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao
16647410f29b4dae223befac036ea567d7f33351dad1Mathieu Chartier// Generate the allocation entrypoints for each allocator.
1665854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_ENTRYPOINTS_FOR_NON_TLAB_ALLOCATORS
1666854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// Comment out allocators that have mips specific asm.
1667854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_region_tlab, RegionTLAB)
1668854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_region_tlab, RegionTLAB)
1669854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_region_tlab, RegionTLAB)
1670854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_region_tlab, RegionTLAB)
1671854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED8(_region_tlab, RegionTLAB)
1672854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED16(_region_tlab, RegionTLAB)
1673854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED32(_region_tlab, RegionTLAB)
1674854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED64(_region_tlab, RegionTLAB)
1675854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_BYTES(_region_tlab, RegionTLAB)
1676854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_CHARS(_region_tlab, RegionTLAB)
1677854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_STRING(_region_tlab, RegionTLAB)
1678854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic
1679854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_tlab, TLAB)
1680854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_tlab, TLAB)
1681854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_tlab, TLAB)
1682854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_tlab, TLAB)
1683854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED8(_tlab, TLAB)
1684854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED16(_tlab, TLAB)
1685854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED32(_tlab, TLAB)
1686854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED64(_tlab, TLAB)
1687854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_BYTES(_tlab, TLAB)
1688854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_CHARS(_tlab, TLAB)
1689854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_STRING(_tlab, TLAB)
169010d4c08c0ea9df0a85a11e1c77974df24078c0ecHiroshi Yamauchi
16912449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic// A hand-written override for:
16922449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic//   GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_rosalloc, RosAlloc)
16932449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic//   GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_rosalloc, RosAlloc)
1694854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.macro ART_QUICK_ALLOC_OBJECT_ROSALLOC c_name, cxx_name, isInitialized
1695854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicENTRY_NO_GP \c_name
16962449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # Fast path rosalloc allocation
16972449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # a0: type
16982449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # s1: Thread::Current
16992449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # -----------------------------
17002449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # t1: object size
17012449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # t2: rosalloc run
17022449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # t3: thread stack top offset
17032449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # t4: thread stack bottom offset
17042449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # v0: free list head
17052449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    #
17062449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # t5, t6 : temps
17072449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    lw    $t3, THREAD_LOCAL_ALLOC_STACK_TOP_OFFSET($s1)        # Check if thread local allocation
17082449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    lw    $t4, THREAD_LOCAL_ALLOC_STACK_END_OFFSET($s1)        # stack has any room left.
17092449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    bgeu  $t3, $t4, .Lslow_path_\c_name
17102449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic
17112449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    lw    $t1, MIRROR_CLASS_OBJECT_SIZE_ALLOC_FAST_PATH_OFFSET($a0)  # Load object size (t1).
17122449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    li    $t5, ROSALLOC_MAX_THREAD_LOCAL_BRACKET_SIZE          # Check if size is for a thread local
17132449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic                                                               # allocation. Also does the
17142449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic                                                               # initialized and finalizable checks.
1715854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # When isInitialized == 0, then the class is potentially not yet initialized.
1716854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # If the class is not yet initialized, the object size will be very large to force the branch
1717854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # below to be taken.
1718854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    #
1719854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # See InitializeClassVisitors in class-inl.h for more details.
17202449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    bgtu  $t1, $t5, .Lslow_path_\c_name
17212449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic
17222449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # Compute the rosalloc bracket index from the size. Since the size is already aligned we can
17232449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # combine the two shifts together.
17242449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    srl   $t1, $t1, (ROSALLOC_BRACKET_QUANTUM_SIZE_SHIFT - POINTER_SIZE_SHIFT)
17252449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic
17262449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    addu  $t2, $t1, $s1
17272449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    lw    $t2, (THREAD_ROSALLOC_RUNS_OFFSET - __SIZEOF_POINTER__)($t2)  # Load rosalloc run (t2).
17282449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic
17292449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # Load the free list head (v0).
17302449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # NOTE: this will be the return val.
17312449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    lw    $v0, (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_HEAD_OFFSET)($t2)
17322449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    beqz  $v0, .Lslow_path_\c_name
17332449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    nop
17342449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic
17352449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # Load the next pointer of the head and update the list head with the next pointer.
17362449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    lw    $t5, ROSALLOC_SLOT_NEXT_OFFSET($v0)
17372449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    sw    $t5, (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_HEAD_OFFSET)($t2)
17382449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic
17392449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # Store the class pointer in the header. This also overwrites the first pointer. The offsets are
17402449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # asserted to match.
17412449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic
17422449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic#if ROSALLOC_SLOT_NEXT_OFFSET != MIRROR_OBJECT_CLASS_OFFSET
17432449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic#error "Class pointer needs to overwrite next pointer."
17442449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic#endif
17452449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic
17462449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    POISON_HEAP_REF $a0
17472449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    sw    $a0, MIRROR_OBJECT_CLASS_OFFSET($v0)
17482449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic
17492449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # Push the new object onto the thread local allocation stack and increment the thread local
17502449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # allocation stack top.
17512449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    sw    $v0, 0($t3)
17522449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    addiu $t3, $t3, COMPRESSED_REFERENCE_SIZE
17532449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    sw    $t3, THREAD_LOCAL_ALLOC_STACK_TOP_OFFSET($s1)
17542449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic
17552449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    # Decrement the size of the free list.
17562449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    lw    $t5, (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_SIZE_OFFSET)($t2)
17572449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    addiu $t5, $t5, -1
17582449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    sw    $t5, (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_SIZE_OFFSET)($t2)
17592449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic
1760854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.if \isInitialized == 0
1761854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # This barrier is only necessary when the allocation also requires a class initialization check.
1762854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    #
1763854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # If the class is already observably initialized, then new-instance allocations are protected
1764854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # from publishing by the compiler which inserts its own StoreStore barrier.
17652449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    sync                                                          # Fence.
1766854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.endif
17672449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    jalr  $zero, $ra
17682449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    nop
17692449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic
17702449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic  .Lslow_path_\c_name:
1771854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    addiu $t9, $t9, (.Lslow_path_\c_name - \c_name) + 4
1772854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    .cpload $t9
17732449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    SETUP_SAVE_REFS_ONLY_FRAME
17742449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    la    $t9, \cxx_name
17752449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    jalr  $t9
17762449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    move  $a1, $s1                                                # Pass self as argument.
17772449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic    RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
17782449e5c95b536791fc11344530365b36ae18e0dfGoran JakovljevicEND \c_name
17792449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic.endm
17802449e5c95b536791fc11344530365b36ae18e0dfGoran Jakovljevic
1781854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicART_QUICK_ALLOC_OBJECT_ROSALLOC art_quick_alloc_object_resolved_rosalloc, artAllocObjectFromCodeResolvedRosAlloc, /* isInitialized */ 0
1782854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicART_QUICK_ALLOC_OBJECT_ROSALLOC art_quick_alloc_object_initialized_rosalloc, artAllocObjectFromCodeInitializedRosAlloc, /* isInitialized */ 1
1783854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic
1784854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// The common fast path code for art_quick_alloc_object_resolved/initialized_tlab
1785854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// and art_quick_alloc_object_resolved/initialized_region_tlab.
1786854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic//
1787854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// a0: type, s1(rSELF): Thread::Current.
1788854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// Need to preserve a0 to the slow path.
1789854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic//
1790854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// If isInitialized=1 then the compiler assumes the object's class has already been initialized.
1791854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// If isInitialized=0 the compiler can only assume it's been at least resolved.
1792854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.macro ALLOC_OBJECT_RESOLVED_TLAB_FAST_PATH slowPathLabel isInitialized
1793854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    lw    $v0, THREAD_LOCAL_POS_OFFSET(rSELF)          # Load thread_local_pos.
1794854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    lw    $a2, THREAD_LOCAL_END_OFFSET(rSELF)          # Load thread_local_end.
1795854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    subu  $a3, $a2, $v0                                # Compute the remaining buffer size.
1796854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    lw    $t0, MIRROR_CLASS_OBJECT_SIZE_ALLOC_FAST_PATH_OFFSET($a0)  # Load the object size.
1797854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic
1798854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # When isInitialized == 0, then the class is potentially not yet initialized.
1799854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # If the class is not yet initialized, the object size will be very large to force the branch
1800854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # below to be taken.
1801854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    #
1802854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # See InitializeClassVisitors in class-inl.h for more details.
1803854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    bgtu  $t0, $a3, \slowPathLabel                     # Check if it fits.
1804854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    addu  $t1, $v0, $t0                                # Add object size to tlab pos (in branch
1805854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic                                                       # delay slot).
1806854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # "Point of no slow path". Won't go to the slow path from here on.
1807854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    sw    $t1, THREAD_LOCAL_POS_OFFSET(rSELF)          # Store new thread_local_pos.
1808854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    lw    $a2, THREAD_LOCAL_OBJECTS_OFFSET(rSELF)      # Increment thread_local_objects.
1809854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    addiu $a2, $a2, 1
1810854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    sw    $a2, THREAD_LOCAL_OBJECTS_OFFSET(rSELF)
1811854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    POISON_HEAP_REF $a0
1812854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    sw    $a0, MIRROR_OBJECT_CLASS_OFFSET($v0)         # Store the class pointer.
1813854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic
1814854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.if \isInitialized == 0
1815854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # This barrier is only necessary when the allocation also requires a class initialization check.
1816854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    #
1817854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # If the class is already observably initialized, then new-instance allocations are protected
1818854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # from publishing by the compiler which inserts its own StoreStore barrier.
1819854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    sync                                               # Fence.
1820854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.endif
1821854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    jalr  $zero, $ra
1822854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    nop
1823854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.endm
1824854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic
1825854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// The common code for art_quick_alloc_object_resolved/initialized_tlab
1826854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// and art_quick_alloc_object_resolved/initialized_region_tlab.
1827854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.macro GENERATE_ALLOC_OBJECT_TLAB name, entrypoint, isInitialized
1828854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicENTRY_NO_GP \name
1829854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # Fast path tlab allocation.
1830854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # a0: type, s1(rSELF): Thread::Current.
1831854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    ALLOC_OBJECT_RESOLVED_TLAB_FAST_PATH .Lslow_path_\name, \isInitialized
1832854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.Lslow_path_\name:
1833854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    addiu $t9, $t9, (.Lslow_path_\name - \name) + 4
1834854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    .cpload $t9
1835854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    SETUP_SAVE_REFS_ONLY_FRAME                         # Save callee saves in case of GC.
1836854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    la    $t9, \entrypoint
1837854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    jalr  $t9                                          # (mirror::Class*, Thread*)
1838854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    move  $a1, rSELF                                   # Pass Thread::Current.
1839854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
1840854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicEND \name
1841854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.endm
1842854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic
1843854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_OBJECT_TLAB art_quick_alloc_object_resolved_region_tlab, artAllocObjectFromCodeResolvedRegionTLAB, /* isInitialized */ 0
1844854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_OBJECT_TLAB art_quick_alloc_object_initialized_region_tlab, artAllocObjectFromCodeInitializedRegionTLAB, /* isInitialized */ 1
1845854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_OBJECT_TLAB art_quick_alloc_object_resolved_tlab, artAllocObjectFromCodeResolvedTLAB, /* isInitialized */ 0
1846854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_OBJECT_TLAB art_quick_alloc_object_initialized_tlab, artAllocObjectFromCodeInitializedTLAB, /* isInitialized */ 1
1847854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic
1848854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// The common fast path code for art_quick_alloc_array_resolved/initialized_tlab
1849854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// and art_quick_alloc_array_resolved/initialized_region_tlab.
1850854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic//
1851854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// a0: type, a1: component_count, a2: total_size, s1(rSELF): Thread::Current.
1852854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic// Need to preserve a0 and a1 to the slow path.
1853854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.macro ALLOC_ARRAY_TLAB_FAST_PATH_RESOLVED_WITH_SIZE slowPathLabel
1854854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    li    $a3, OBJECT_ALIGNMENT_MASK_TOGGLED           # Apply alignemnt mask
1855854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    and   $a2, $a2, $a3                                # (addr + 7) & ~7.
1856854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic
1857854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    lw    $v0, THREAD_LOCAL_POS_OFFSET(rSELF)          # Load thread_local_pos.
1858854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    lw    $t1, THREAD_LOCAL_END_OFFSET(rSELF)          # Load thread_local_end.
1859854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    subu  $t2, $t1, $v0                                # Compute the remaining buffer size.
1860854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    bgtu  $a2, $t2, \slowPathLabel                     # Check if it fits.
1861854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    addu  $a2, $v0, $a2                                # Add object size to tlab pos (in branch
1862854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic                                                       # delay slot).
1863854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic
1864854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # "Point of no slow path". Won't go to the slow path from here on.
1865854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    sw    $a2, THREAD_LOCAL_POS_OFFSET(rSELF)          # Store new thread_local_pos.
1866854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    lw    $a2, THREAD_LOCAL_OBJECTS_OFFSET(rSELF)      # Increment thread_local_objects.
1867854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    addiu $a2, $a2, 1
1868854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    sw    $a2, THREAD_LOCAL_OBJECTS_OFFSET(rSELF)
1869854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    POISON_HEAP_REF $a0
1870854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    sw    $a0, MIRROR_OBJECT_CLASS_OFFSET($v0)         # Store the class pointer.
1871854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    jalr  $zero, $ra
1872854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    sw    $a1, MIRROR_ARRAY_LENGTH_OFFSET($v0)         # Store the array length.
1873854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.endm
1874854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic
1875854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.macro GENERATE_ALLOC_ARRAY_TLAB name, entrypoint, size_setup
1876854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicENTRY_NO_GP \name
1877854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # Fast path array allocation for region tlab allocation.
1878854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # a0: mirror::Class* type
1879854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # a1: int32_t component_count
1880854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # s1(rSELF): Thread::Current
1881854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    \size_setup .Lslow_path_\name
1882854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    ALLOC_ARRAY_TLAB_FAST_PATH_RESOLVED_WITH_SIZE .Lslow_path_\name
1883854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.Lslow_path_\name:
1884854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # a0: mirror::Class* type
1885854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # a1: int32_t component_count
1886854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # a2: Thread* self
1887854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    addiu $t9, $t9, (.Lslow_path_\name - \name) + 4
1888854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    .cpload $t9
1889854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    SETUP_SAVE_REFS_ONLY_FRAME                         # Save callee saves in case of GC.
1890854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    la    $t9, \entrypoint
1891854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    jalr  $t9
1892854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    move  $a2, rSELF                                   # Pass Thread::Current.
1893854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
1894854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicEND \name
1895854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.endm
1896854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic
1897854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.macro COMPUTE_ARRAY_SIZE_UNKNOWN slow_path
1898854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    break                                              # We should never enter here.
1899854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic                                                       # Code below is for reference.
1900854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic                                                       # Possibly a large object, go slow.
1901854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic                                                       # Also does negative array size check.
1902854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    li    $a2, ((MIN_LARGE_OBJECT_THRESHOLD - MIRROR_WIDE_ARRAY_DATA_OFFSET) / 8)
1903854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    bgtu  $a1, $a2, \slow_path
1904854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic                                                       # Array classes are never finalizable
1905854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic                                                       # or uninitialized, no need to check.
1906854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    lw    $a3, MIRROR_CLASS_COMPONENT_TYPE_OFFSET($a0) # Load component type.
1907854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    UNPOISON_HEAP_REF $a3
1908854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    lw    $a3, MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET($a3)
1909854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    srl   $a3, $a3, PRIMITIVE_TYPE_SIZE_SHIFT_SHIFT    # Component size shift is in high 16 bits.
1910854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    sllv  $a2, $a1, $a3                                # Calculate data size.
1911854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic                                                       # Add array data offset and alignment.
1912854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    addiu $a2, $a2, (MIRROR_INT_ARRAY_DATA_OFFSET + OBJECT_ALIGNMENT_MASK)
1913854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic#if MIRROR_WIDE_ARRAY_DATA_OFFSET != MIRROR_INT_ARRAY_DATA_OFFSET + 4
1914854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic#error Long array data offset must be 4 greater than int array data offset.
1915854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic#endif
1916854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic
1917854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    addiu $a3, $a3, 1                                  # Add 4 to the length only if the component
1918854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    andi  $a3, $a3, 4                                  # size shift is 3 (for 64 bit alignment).
1919854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    addu  $a2, $a2, $a3
1920854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.endm
1921854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic
1922854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.macro COMPUTE_ARRAY_SIZE_8 slow_path
1923854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # Possibly a large object, go slow.
1924854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # Also does negative array size check.
1925854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    li    $a2, (MIN_LARGE_OBJECT_THRESHOLD - MIRROR_INT_ARRAY_DATA_OFFSET)
1926854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    bgtu  $a1, $a2, \slow_path
1927854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # Add array data offset and alignment (in branch delay slot).
1928854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    addiu $a2, $a1, (MIRROR_INT_ARRAY_DATA_OFFSET + OBJECT_ALIGNMENT_MASK)
1929854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.endm
1930854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic
1931854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.macro COMPUTE_ARRAY_SIZE_16 slow_path
1932854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # Possibly a large object, go slow.
1933854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # Also does negative array size check.
1934854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    li    $a2, ((MIN_LARGE_OBJECT_THRESHOLD - MIRROR_INT_ARRAY_DATA_OFFSET) / 2)
1935854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    bgtu  $a1, $a2, \slow_path
1936854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    sll   $a2, $a1, 1
1937854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # Add array data offset and alignment.
1938854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    addiu $a2, $a2, (MIRROR_INT_ARRAY_DATA_OFFSET + OBJECT_ALIGNMENT_MASK)
1939854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.endm
1940854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic
1941854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.macro COMPUTE_ARRAY_SIZE_32 slow_path
1942854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # Possibly a large object, go slow.
1943854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # Also does negative array size check.
1944854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    li    $a2, ((MIN_LARGE_OBJECT_THRESHOLD - MIRROR_INT_ARRAY_DATA_OFFSET) / 4)
1945854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    bgtu  $a1, $a2, \slow_path
1946854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    sll   $a2, $a1, 2
1947854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # Add array data offset and alignment.
1948854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    addiu $a2, $a2, (MIRROR_INT_ARRAY_DATA_OFFSET + OBJECT_ALIGNMENT_MASK)
1949854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.endm
1950854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic
1951854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.macro COMPUTE_ARRAY_SIZE_64 slow_path
1952854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # Possibly a large object, go slow.
1953854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # Also does negative array size check.
1954854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    li    $a2, ((MIN_LARGE_OBJECT_THRESHOLD - MIRROR_LONG_ARRAY_DATA_OFFSET) / 8)
1955854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    bgtu  $a1, $a2, \slow_path
1956854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    sll   $a2, $a1, 3
1957854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    # Add array data offset and alignment.
1958854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic    addiu $a2, $a2, (MIRROR_WIDE_ARRAY_DATA_OFFSET + OBJECT_ALIGNMENT_MASK)
1959854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic.endm
19603b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi
1961854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved_region_tlab, artAllocArrayFromCodeResolvedRegionTLAB, COMPUTE_ARRAY_SIZE_UNKNOWN
1962854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved8_region_tlab, artAllocArrayFromCodeResolvedRegionTLAB, COMPUTE_ARRAY_SIZE_8
1963854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved16_region_tlab, artAllocArrayFromCodeResolvedRegionTLAB, COMPUTE_ARRAY_SIZE_16
1964854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved32_region_tlab, artAllocArrayFromCodeResolvedRegionTLAB, COMPUTE_ARRAY_SIZE_32
1965854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved64_region_tlab, artAllocArrayFromCodeResolvedRegionTLAB, COMPUTE_ARRAY_SIZE_64
1966854df416f12c48b52239fe163ab8a7fcac4cddd3Goran Jakovljevic
1967854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved_tlab, artAllocArrayFromCodeResolvedTLAB, COMPUTE_ARRAY_SIZE_UNKNOWN
1968854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved8_tlab, artAllocArrayFromCodeResolvedTLAB, COMPUTE_ARRAY_SIZE_8
1969854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved16_tlab, artAllocArrayFromCodeResolvedTLAB, COMPUTE_ARRAY_SIZE_16
1970854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved32_tlab, artAllocArrayFromCodeResolvedTLAB, COMPUTE_ARRAY_SIZE_32
1971854df416f12c48b52239fe163ab8a7fcac4cddd3Goran JakovljevicGENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved64_tlab, artAllocArrayFromCodeResolvedTLAB, COMPUTE_ARRAY_SIZE_64
197210d4c08c0ea9df0a85a11e1c77974df24078c0ecHiroshi Yamauchi
1973c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze// Macro for string and type resolution and initialization.
1974c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze// $a0 is both input and output.
1975c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze.macro ONE_ARG_SAVE_EVERYTHING_DOWNCALL name, entrypoint
1976c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    .extern \entrypoint
1977c61c0761150340263160b568d8a952e9a3d80d56Alexey FrunzeENTRY_NO_GP \name
1978c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    SETUP_SAVE_EVERYTHING_FRAME       # Save everything in case of GC.
1979c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    move    $s2, $gp                  # Preserve $gp across the call for exception delivery.
1980c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    la      $t9, \entrypoint
1981c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    jalr    $t9                       # (uint32_t index, Thread*)
1982c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    move    $a1, rSELF                # Pass Thread::Current (in delay slot).
1983c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    beqz    $v0, 1f                   # Success?
1984c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    move    $a0, $v0                  # Move result to $a0 (in delay slot).
1985c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    RESTORE_SAVE_EVERYTHING_FRAME 0   # Restore everything except $a0.
1986c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    jalr    $zero, $ra                # Return on success.
1987c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    nop
1988c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze1:
1989c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    move    $gp, $s2
1990c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    DELIVER_PENDING_EXCEPTION_FRAME_READY
1991c61c0761150340263160b568d8a952e9a3d80d56Alexey FrunzeEND \name
1992c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze.endm
1993c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze
19945bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
19951cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe     * Entry from managed code to resolve a string, this stub will allocate a String and deliver an
19965ea536aa4a6414db01beaf6f8bd8cb9adc5cfc92Vladimir Marko     * exception on error. On success the String is returned. A0 holds the string index. The fast
19975ea536aa4a6414db01beaf6f8bd8cb9adc5cfc92Vladimir Marko     * path check for hit in strings cache has already been performed.
19981cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe     */
1999c61c0761150340263160b568d8a952e9a3d80d56Alexey FrunzeONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_string, artResolveStringFromCode
20001cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe
20011cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe    /*
20021cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe     * Entry from managed code when uninitialized static storage, this stub will run the class
20031cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe     * initializer and deliver the exception on error. On success the static storage base is
20041cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe     * returned.
20051cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe     */
2006c61c0761150340263160b568d8a952e9a3d80d56Alexey FrunzeONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode
20071cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe
20081cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe    /*
20091cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe     * Entry from managed code when dex cache misses for a type_idx.
20101cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe     */
2011c61c0761150340263160b568d8a952e9a3d80d56Alexey FrunzeONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode
20121cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe
20131cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe    /*
20141cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe     * Entry from managed code when type_idx needs to be checked for access and dex cache may also
20151cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe     * miss.
20161cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe     */
2017c61c0761150340263160b568d8a952e9a3d80d56Alexey FrunzeONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode
20181cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe
20191cc7dbabd03e0a6c09d68161417a21bd6f9df371Andreas Gampe    /*
202057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     * Called by managed code when the value in rSUSPEND has been decremented to 0.
20215bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
2022d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff Hao    .extern artTestSuspendFromCode
2023952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir MarkoENTRY_NO_GP art_quick_test_suspend
2024952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    lh     rSUSPEND, THREAD_FLAGS_OFFSET(rSELF)
2025952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    bnez   rSUSPEND, 1f
2026e34652f15f32666323052a6718a63248244f1e66Duane Sand    addiu  rSUSPEND, $zero, SUSPEND_CHECK_INTERVAL   # reset rSUSPEND to SUSPEND_CHECK_INTERVAL
20278d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr   $zero, $ra
20285bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    nop
20295bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee1:
2030fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_EVERYTHING_FRAME                      # save everything for stack crawl
2031590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la     $t9, artTestSuspendFromCode
2032952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    jalr   $t9                                       # (Thread*)
20337fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    move   $a0, rSELF
2034fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    RESTORE_SAVE_EVERYTHING_FRAME
2035952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    jalr   $zero, $ra
2036952dbb19cd094b8bfb01dbb33e0878db429e499aVladimir Marko    nop
2037d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff HaoEND art_quick_test_suspend
20385bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
20395bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
20405bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * Called by managed code that is attempting to call a method on a proxy class. On entry
2041590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic     * a0 holds the proxy method; a1, a2 and a3 may contain arguments.
20425bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
20435fa60c3db4208df407113b5a69d295a9c93d53b1Jeff Hao    .extern artQuickProxyInvokeHandler
2044d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff HaoENTRY art_quick_proxy_invoke_handler
2045fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_REFS_AND_ARGS_FRAME_WITH_METHOD_IN_A0
2046735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    move    $a2, rSELF                  # pass Thread::Current
2047590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la      $t9, artQuickProxyInvokeHandler
2048590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    jalr    $t9                         # (Method* proxy method, receiver, Thread*, SP)
2049735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    addiu   $a3, $sp, ARG_SLOT_SIZE     # pass $sp (remove arg slots)
20501b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw      $t7, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
2051fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    RESTORE_SAVE_REFS_AND_ARGS_FRAME
20521b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    bnez    $t7, 1f
2053e34652f15f32666323052a6718a63248244f1e66Duane Sand    # don't care if $v0 and/or $v1 are modified, when exception branch taken
2054e34652f15f32666323052a6718a63248244f1e66Duane Sand    MTD     $v0, $v1, $f0, $f1          # move float value to return value
20558d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr    $zero, $ra
2056e34652f15f32666323052a6718a63248244f1e66Duane Sand    nop
20575bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee1:
20585bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    DELIVER_PENDING_EXCEPTION
2059d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff HaoEND art_quick_proxy_invoke_handler
20605bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
206188474b416eb257078e590bf9bc7957cee604a186Jeff Hao    /*
206259028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic     * Called to resolve an imt conflict.
206359028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic     * a0 is the conflict ArtMethod.
20641b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze     * t7 is a hidden argument that holds the target interface method's dex method index.
206559028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic     *
20661b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze     * Note that this stub writes to a0, t7 and t8.
206788474b416eb257078e590bf9bc7957cee604a186Jeff Hao     */
206813738bf7c769638b7922cb2477471ad382632bc2Douglas LeungENTRY art_quick_imt_conflict_trampoline
20691b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw      $t8, 0($sp)                                      # Load referrer.
20701b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw      $t8, ART_METHOD_DEX_CACHE_METHODS_OFFSET_32($t8) # Load dex cache methods array.
20711b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    sll     $t7, $t7, POINTER_SIZE_SHIFT                     # Calculate offset.
20721b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    addu    $t7, $t8, $t7                                    # Add offset to base.
20731b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw      $t7, 0($t7)                                      # Load interface method.
207459028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic    lw      $a0, ART_METHOD_JNI_OFFSET_32($a0)               # Load ImtConflictTable.
207559028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic
207659028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic.Limt_table_iterate:
20771b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw      $t8, 0($a0)                                      # Load next entry in ImtConflictTable.
207859028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic    # Branch if found.
20791b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    beq     $t8, $t7, .Limt_table_found
208059028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic    nop
208159028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic    # If the entry is null, the interface method is not in the ImtConflictTable.
20821b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    beqz    $t8, .Lconflict_trampoline
208359028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic    nop
208459028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic    # Iterate over the entries of the ImtConflictTable.
208559028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic    b       .Limt_table_iterate
208659028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic    addiu   $a0, $a0, 2 * __SIZEOF_POINTER__                 # Iterate to the next entry.
208759028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic
208859028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic.Limt_table_found:
208959028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic    # We successfully hit an entry in the table. Load the target method and jump to it.
209059028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic    lw      $a0, __SIZEOF_POINTER__($a0)
209159028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic    lw      $t9, ART_METHOD_QUICK_CODE_OFFSET_32($a0)
20921b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    jalr    $zero, $t9
209359028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic    nop
209459028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic
209559028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic.Lconflict_trampoline:
209659028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic    # Call the runtime stub to populate the ImtConflictTable and jump to the resolved method.
20975667f56867383fc4113aa4a6551efdf9f48ee5e7Jeff Hao    move    $a0, $t7                                         # Load interface method.
20983031c8da0c5009183f770b005c245f9bf2a4d01bAndreas Gampe    INVOKE_TRAMPOLINE_BODY artInvokeInterfaceTrampoline
209988474b416eb257078e590bf9bc7957cee604a186Jeff HaoEND art_quick_imt_conflict_trampoline
210088474b416eb257078e590bf9bc7957cee604a186Jeff Hao
2101468532ea115657709bc32ee498e701a4c71762d4Ian Rogers    .extern artQuickResolutionTrampoline
2102468532ea115657709bc32ee498e701a4c71762d4Ian RogersENTRY art_quick_resolution_trampoline
2103fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_REFS_AND_ARGS_FRAME
2104735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    move    $a2, rSELF                    # pass Thread::Current
2105590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la      $t9, artQuickResolutionTrampoline
2106590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    jalr    $t9                           # (Method* called, receiver, Thread*, SP)
2107735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    addiu   $a3, $sp, ARG_SLOT_SIZE       # pass $sp (remove arg slots)
2108468532ea115657709bc32ee498e701a4c71762d4Ian Rogers    beqz    $v0, 1f
2109735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    lw      $a0, ARG_SLOT_SIZE($sp)       # load resolved method to $a0
2110fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    RESTORE_SAVE_REFS_AND_ARGS_FRAME
211165d1b22d0b02fb0111f69013163c8170e68392f1Ian Rogers    move    $t9, $v0               # code pointer must be in $t9 to generate the global pointer
2112f96e8bdf47cfcbecd8ad8ebceb765e5a257ca143Douglas Leung    jalr    $zero, $t9             # tail call to method
21131984152ac92aad244ae15184d12f9ceade686b7bMathieu Chartier    nop
2114468532ea115657709bc32ee498e701a4c71762d4Ian Rogers1:
2115fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    RESTORE_SAVE_REFS_AND_ARGS_FRAME
2116468532ea115657709bc32ee498e701a4c71762d4Ian Rogers    DELIVER_PENDING_EXCEPTION
2117468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND art_quick_resolution_trampoline
2118468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
2119735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .extern artQuickGenericJniTrampoline
2120735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .extern artQuickGenericJniEndTrampoline
2121735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas LeungENTRY art_quick_generic_jni_trampoline
2122fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_REFS_AND_ARGS_FRAME_WITH_METHOD_IN_A0
2123735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    move    $s8, $sp               # save $sp to $s8
2124735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    move    $s3, $gp               # save $gp to $s3
2125735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung
2126735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    # prepare for call to artQuickGenericJniTrampoline(Thread*, SP)
2127735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    move    $a0, rSELF                     # pass Thread::Current
2128735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    addiu   $a1, $sp, ARG_SLOT_SIZE        # save $sp (remove arg slots)
2129590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la      $t9, artQuickGenericJniTrampoline
2130590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    jalr    $t9                            # (Thread*, SP)
2131735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    addiu   $sp, $sp, -5120                # reserve space on the stack
2132735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung
2133735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    # The C call will have registered the complete save-frame on success.
2134735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    # The result of the call is:
2135735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    # v0: ptr to native code, 0 on error.
2136735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    # v1: ptr to the bottom of the used area of the alloca, can restore stack till here.
21371b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    beq     $v0, $zero, 2f         # check entry error
2138735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    move    $t9, $v0               # save the code ptr
2139735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    move    $sp, $v1               # release part of the alloca
2140735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung
2141735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    # Load parameters from stack into registers
2142735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    lw      $a0,   0($sp)
2143735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    lw      $a1,   4($sp)
2144735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    lw      $a2,   8($sp)
21451b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw      $a3,  12($sp)
21461b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze
21471b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    # artQuickGenericJniTrampoline sets bit 0 of the native code address to 1
21481b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    # when the first two arguments are both single precision floats. This lets
21491b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    # us extract them properly from the stack and load into floating point
21501b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    # registers.
21511b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    MTD     $a0, $a1, $f12, $f13
21521b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    andi    $t0, $t9, 1
21531b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    xor     $t9, $t9, $t0
21541b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    bnez    $t0, 1f
21551b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    mtc1    $a1, $f14
21561b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    MTD     $a2, $a3, $f14, $f15
2157735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung
21581b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze1:
2159735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    jalr    $t9                    # native call
21601b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    nop
2161735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    addiu   $sp, $sp, 16           # remove arg slots
2162735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung
2163735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    move    $gp, $s3               # restore $gp from $s3
2164735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung
2165735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    # result sign extension is handled in C code
2166735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    # prepare for call to artQuickGenericJniEndTrampoline(Thread*, result, result_f)
2167735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    move    $a0, rSELF             # pass Thread::Current
2168735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    move    $a2, $v0               # pass result
2169735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    move    $a3, $v1
2170735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    addiu   $sp, $sp, -24          # reserve arg slots
2171590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la      $t9, artQuickGenericJniEndTrampoline
2172590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    jalr    $t9
2173735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    s.d     $f0, 16($sp)           # pass result_f
2174735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung
2175735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    lw      $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
21761b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    bne     $t0, $zero, 2f         # check for pending exceptions
2177126d65952a03b3e44d5021208673c01920a982a4Nicolas Geoffray
2178735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    move    $sp, $s8               # tear down the alloca
2179735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung
21801b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    # tear down the callee-save frame
2181fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    RESTORE_SAVE_REFS_AND_ARGS_FRAME
2182735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung
2183e34652f15f32666323052a6718a63248244f1e66Duane Sand    MTD     $v0, $v1, $f0, $f1     # move float value to return value
21848d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr    $zero, $ra
2185e34652f15f32666323052a6718a63248244f1e66Duane Sand    nop
2186735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung
21871b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze2:
2188c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    lw      $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF)
2189c61c0761150340263160b568d8a952e9a3d80d56Alexey Frunze    move    $gp, $s3               # restore $gp from $s3
2190126d65952a03b3e44d5021208673c01920a982a4Nicolas Geoffray    # This will create a new save-all frame, required by the runtime.
2191735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    DELIVER_PENDING_EXCEPTION
2192735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas LeungEND art_quick_generic_jni_trampoline
21932da882315a61072664f7ce3c212307342e907207Andreas Gampe
2194468532ea115657709bc32ee498e701a4c71762d4Ian Rogers    .extern artQuickToInterpreterBridge
2195468532ea115657709bc32ee498e701a4c71762d4Ian RogersENTRY art_quick_to_interpreter_bridge
2196fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_REFS_AND_ARGS_FRAME
2197735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    move    $a1, rSELF                          # pass Thread::Current
2198590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la      $t9, artQuickToInterpreterBridge
2199590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    jalr    $t9                                 # (Method* method, Thread*, SP)
2200735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    addiu   $a2, $sp, ARG_SLOT_SIZE             # pass $sp (remove arg slots)
22011b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    lw      $t7, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
2202fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    RESTORE_SAVE_REFS_AND_ARGS_FRAME
22031b8464d17c2266763714ae18be7c4dc26e28bf61Alexey Frunze    bnez    $t7, 1f
2204e34652f15f32666323052a6718a63248244f1e66Duane Sand    # don't care if $v0 and/or $v1 are modified, when exception branch taken
2205e34652f15f32666323052a6718a63248244f1e66Duane Sand    MTD     $v0, $v1, $f0, $f1                  # move float value to return value
22068d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe    jalr    $zero, $ra
2207e34652f15f32666323052a6718a63248244f1e66Duane Sand    nop
22087db619bb2a4e01e8532a04b613745d4926b205d7Ian Rogers1:
22097db619bb2a4e01e8532a04b613745d4926b205d7Ian Rogers    DELIVER_PENDING_EXCEPTION
2210468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND art_quick_to_interpreter_bridge
22117db619bb2a4e01e8532a04b613745d4926b205d7Ian Rogers
2212db01a091aefbd78b56777f4c2e8c5e3f2d8c2712Alex Light    .extern artInvokeObsoleteMethod
2213db01a091aefbd78b56777f4c2e8c5e3f2d8c2712Alex LightENTRY art_invoke_obsolete_method_stub
2214db01a091aefbd78b56777f4c2e8c5e3f2d8c2712Alex Light    SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
2215db01a091aefbd78b56777f4c2e8c5e3f2d8c2712Alex Light    la      $t9, artInvokeObsoleteMethod
2216db01a091aefbd78b56777f4c2e8c5e3f2d8c2712Alex Light    jalr    $t9                                 # (Method* method, Thread* self)
2217db01a091aefbd78b56777f4c2e8c5e3f2d8c2712Alex Light    move    $a1, rSELF                          # pass Thread::Current
2218db01a091aefbd78b56777f4c2e8c5e3f2d8c2712Alex LightEND art_invoke_obsolete_method_stub
2219db01a091aefbd78b56777f4c2e8c5e3f2d8c2712Alex Light
22205bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
2221725a957985171d712d5c048cc3d00ff14968784bjeffhao     * Routine that intercepts method calls and returns.
22225bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
2223d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff Hao    .extern artInstrumentationMethodEntryFromCode
2224d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff Hao    .extern artInstrumentationMethodExitFromCode
2225468532ea115657709bc32ee498e701a4c71762d4Ian RogersENTRY art_quick_instrumentation_entry
2226fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_REFS_AND_ARGS_FRAME
2227735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    sw       $a0, 28($sp)   # save arg0 in free arg slot
222825e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    addiu    $a3, $sp, ARG_SLOT_SIZE      # Pass $sp.
2229590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la       $t9, artInstrumentationMethodEntryFromCode
223025e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    jalr     $t9            # (Method*, Object*, Thread*, SP)
223162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    move     $a2, rSELF     # pass Thread::Current
223225e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    beqz     $v0, .Ldeliver_instrumentation_entry_exception
22338161c0336b97e11e02c000af357f8f40de2e23e4jeffhao    move     $t9, $v0       # $t9 holds reference to code
2234735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    lw       $a0, 28($sp)   # restore arg0 from free arg slot
2235fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    RESTORE_SAVE_REFS_AND_ARGS_FRAME
22368161c0336b97e11e02c000af357f8f40de2e23e4jeffhao    jalr     $t9            # call method
223762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    nop
2238468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND art_quick_instrumentation_entry
22395bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /* intentional fallthrough */
2240468532ea115657709bc32ee498e701a4c71762d4Ian Rogers    .global art_quick_instrumentation_exit
2241468532ea115657709bc32ee498e701a4c71762d4Ian Rogersart_quick_instrumentation_exit:
2242d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff Hao    .cfi_startproc
224312051ea86ec27703b07b3d5c2cd4604b20f71810jeffhao    addiu    $t9, $ra, 4    # put current address into $t9 to rebuild $gp
22441d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    .cpload  $t9
2245c3d131e1ec030b4ff5c44fe2a45d5fb45b3295afDouglas Leung    move     $ra, $zero     # link register is to here, so clobber with 0 for later checks
2246735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung
2247fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_REFS_ONLY_FRAME
2248735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    addiu    $sp, $sp, -16  # allocate temp storage on the stack
2249735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung    .cfi_adjust_cfa_offset 16
225025e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    sw       $v0, ARG_SLOT_SIZE+8($sp)
225125e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    .cfi_rel_offset 2, ARG_SLOT_SIZE+8
225225e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    sw       $v1, ARG_SLOT_SIZE+12($sp)
225325e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    .cfi_rel_offset 3, ARG_SLOT_SIZE+12
2254f96e8bdf47cfcbecd8ad8ebceb765e5a257ca143Douglas Leung    s.d      $f0, ARG_SLOT_SIZE($sp)
225525e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    addiu    $a3, $sp, ARG_SLOT_SIZE      # Pass fpr_res pointer.
225625e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    addiu    $a2, $sp, ARG_SLOT_SIZE+8    # Pass gpr_res pointer.
225725e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    addiu    $a1, $sp, ARG_SLOT_SIZE+16   # Pass $sp (remove arg slots and temp storage).
2258590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la       $t9, artInstrumentationMethodExitFromCode
225925e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    jalr     $t9                          # (Thread*, SP, gpr_res*, fpr_res*)
226025e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    move     $a0, rSELF                   # Pass Thread::Current.
226125e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    move     $t9, $v0                     # Set aside returned link register.
226225e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    move     $ra, $v1                     # Set link register for deoptimization.
226325e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    lw       $v0, ARG_SLOT_SIZE+8($sp)    # Restore return values.
226425e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    lw       $v1, ARG_SLOT_SIZE+12($sp)
2265f96e8bdf47cfcbecd8ad8ebceb765e5a257ca143Douglas Leung    l.d      $f0, ARG_SLOT_SIZE($sp)
226625e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    addiu    $sp, $sp, 16
226725e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    .cfi_adjust_cfa_offset -16
226825e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    RESTORE_SAVE_REFS_ONLY_FRAME
226925e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    beqz     $t9, .Ldo_deliver_instrumentation_exception
227025e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    nop                     # Deliver exception if we got nullptr as function.
227125e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    jalr     $zero, $t9     # Otherwise, return.
227225e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    nop
227325e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic.Ldeliver_instrumentation_entry_exception:
227425e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    # Deliver exception for art_quick_instrumentation_entry placed after
227525e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    # art_quick_instrumentation_exit so that the fallthrough works.
227625e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    RESTORE_SAVE_REFS_AND_ARGS_FRAME
227725e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic.Ldo_deliver_instrumentation_exception:
227825e4d1ea98fedebf49ceee40ea67ec93e2407c53Goran Jakovljevic    DELIVER_PENDING_EXCEPTION
2279468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND art_quick_instrumentation_exit
22805bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
228112051ea86ec27703b07b3d5c2cd4604b20f71810jeffhao    /*
228262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers     * Instrumentation has requested that we deoptimize into the interpreter. The deoptimization
228362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers     * will long jump to the upcall with a special exception of -1.
228412051ea86ec27703b07b3d5c2cd4604b20f71810jeffhao     */
2285d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff Hao    .extern artDeoptimize
2286d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff HaoENTRY art_quick_deoptimize
2287fd36f1f927c138575184a1f4c7ea4e7abb3e2dbfVladimir Marko    SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
2288590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la       $t9, artDeoptimize
22894e92c3ce7ef354620a785553bbada554fca83a67Nicolas Geoffray    jalr     $t9            # (Thread*)
22901d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    move     $a0, rSELF     # pass Thread::current
2291d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff HaoEND art_quick_deoptimize
229212051ea86ec27703b07b3d5c2cd4604b20f71810jeffhao
22935bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
22940747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz     * Compiled code has requested that we deoptimize into the interpreter. The deoptimization
22950747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz     * will long jump to the upcall with a special exception of -1.
22960747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz     */
22970747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz    .extern artDeoptimizeFromCompiledCode
22980747466fca310eedea5fc49e37d54f240a0b3c0fSebastien HertzENTRY art_quick_deoptimize_from_compiled_code
2299239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    SETUP_SAVE_EVERYTHING_FRAME
2300590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic    la       $t9, artDeoptimizeFromCompiledCode
23014e92c3ce7ef354620a785553bbada554fca83a67Nicolas Geoffray    jalr     $t9                            # (DeoptimizationKind, Thread*)
23024e92c3ce7ef354620a785553bbada554fca83a67Nicolas Geoffray    move     $a1, rSELF                     # pass Thread::current
23030747466fca310eedea5fc49e37d54f240a0b3c0fSebastien HertzEND art_quick_deoptimize_from_compiled_code
23040747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz
23050747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz    /*
23065bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * Long integer shift.  This is different from the generic 32/64-bit
23075bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * binary operations because vAA/vBB are 64-bit but vCC (the shift
23085bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
23095bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * 6 bits.
23105bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * On entry:
23117fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao     *   $a0: low word
23127fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao     *   $a1: high word
23137fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao     *   $a2: shift count
23145bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
23151d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersENTRY_NO_GP art_quick_shl_long
23165bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /* shl-long vAA, vBB, vCC */
23177fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    sll     $v0, $a0, $a2                    #  rlo<- alo << (shift&31)
23187fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    not     $v1, $a2                         #  rhi<- 31-shift  (shift is 5b)
23197fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    srl     $a0, 1
23207fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    srl     $a0, $v1                         #  alo<- alo >> (32-(shift&31))
23217fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    sll     $v1, $a1, $a2                    #  rhi<- ahi << (shift&31)
23227fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    andi    $a2, 0x20                        #  shift< shift & 0x20
2323e34652f15f32666323052a6718a63248244f1e66Duane Sand    beqz    $a2, 1f
2324e34652f15f32666323052a6718a63248244f1e66Duane Sand    or      $v1, $a0                         #  rhi<- rhi | alo
2325e34652f15f32666323052a6718a63248244f1e66Duane Sand
2326e34652f15f32666323052a6718a63248244f1e66Duane Sand    move    $v1, $v0                         #  rhi<- rlo (if shift&0x20)
2327e34652f15f32666323052a6718a63248244f1e66Duane Sand    move    $v0, $zero                       #  rlo<- 0 (if shift&0x20)
2328e34652f15f32666323052a6718a63248244f1e66Duane Sand
23298d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe1:  jalr    $zero, $ra
2330e34652f15f32666323052a6718a63248244f1e66Duane Sand    nop
2331d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff HaoEND art_quick_shl_long
23325bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
23335bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
23345bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * Long integer shift.  This is different from the generic 32/64-bit
23355bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * binary operations because vAA/vBB are 64-bit but vCC (the shift
23365bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
23375bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * 6 bits.
23385bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * On entry:
23397fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao     *   $a0: low word
23407fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao     *   $a1: high word
23417fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao     *   $a2: shift count
23425bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
23431d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersENTRY_NO_GP art_quick_shr_long
23447fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    sra     $v1, $a1, $a2                    #  rhi<- ahi >> (shift&31)
23457fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    srl     $v0, $a0, $a2                    #  rlo<- alo >> (shift&31)
23467fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    sra     $a3, $a1, 31                     #  $a3<- sign(ah)
23477fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    not     $a0, $a2                         #  alo<- 31-shift (shift is 5b)
23487fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    sll     $a1, 1
23497fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    sll     $a1, $a0                         #  ahi<- ahi << (32-(shift&31))
23507fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    andi    $a2, 0x20                        #  shift & 0x20
2351475cfd8ff9dcc73d1a7502c9310efe0f1a30337fDouglas Leung    beqz    $a2, 1f
2352e34652f15f32666323052a6718a63248244f1e66Duane Sand    or      $v0, $a1                         #  rlo<- rlo | ahi
2353e34652f15f32666323052a6718a63248244f1e66Duane Sand
2354e34652f15f32666323052a6718a63248244f1e66Duane Sand    move    $v0, $v1                         #  rlo<- rhi (if shift&0x20)
2355e34652f15f32666323052a6718a63248244f1e66Duane Sand    move    $v1, $a3                         #  rhi<- sign(ahi) (if shift&0x20)
2356e34652f15f32666323052a6718a63248244f1e66Duane Sand
23578d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe1:  jalr    $zero, $ra
2358e34652f15f32666323052a6718a63248244f1e66Duane Sand    nop
2359d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff HaoEND art_quick_shr_long
23605bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee
23615bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /*
23625bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * Long integer shift.  This is different from the generic 32/64-bit
23635bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * binary operations because vAA/vBB are 64-bit but vCC (the shift
23645bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
23655bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * 6 bits.
23665bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     * On entry:
2367590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic     *   $a0: low word
2368590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic     *   $a1: high word
2369590b1362b64d7feeb688d787c1d140d9b7ca78b1Goran Jakovljevic     *   $a2: shift count
23705bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee     */
23715bc5a7b9d9adcfb50e18bd3776d3875ad7a4ae8cbuzbee    /* ushr-long vAA, vBB, vCC */
23721d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersENTRY_NO_GP art_quick_ushr_long
2373fc6a30e2fa8f0d44e6c95bbeb5deca4b499f67cejeffhao    srl     $v1, $a1, $a2                    #  rhi<- ahi >> (shift&31)
23747fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    srl     $v0, $a0, $a2                    #  rlo<- alo >> (shift&31)
23757fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    not     $a0, $a2                         #  alo<- 31-shift (shift is 5b)
23767fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    sll     $a1, 1
23777fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    sll     $a1, $a0                         #  ahi<- ahi << (32-(shift&31))
23787fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    andi    $a2, 0x20                        #  shift & 0x20
2379e34652f15f32666323052a6718a63248244f1e66Duane Sand    beqz    $a2, 1f
2380e34652f15f32666323052a6718a63248244f1e66Duane Sand    or      $v0, $a1                         #  rlo<- rlo | ahi
2381e34652f15f32666323052a6718a63248244f1e66Duane Sand
2382e34652f15f32666323052a6718a63248244f1e66Duane Sand    move    $v0, $v1                         #  rlo<- rhi (if shift&0x20)
2383e34652f15f32666323052a6718a63248244f1e66Duane Sand    move    $v1, $zero                       #  rhi<- 0 (if shift&0x20)
2384e34652f15f32666323052a6718a63248244f1e66Duane Sand
23858d36591d93920e7b7830c3ffee3759b561f5339eAndreas Gampe1:  jalr    $zero, $ra
2386e34652f15f32666323052a6718a63248244f1e66Duane Sand    nop
2387d4c3f7d4e850049b3c1019e451b18b05443b0f28Jeff HaoEND art_quick_ushr_long
23887fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao
2389cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen/* java.lang.String.indexOf(int ch, int fromIndex=0) */
2390cf283daf579e9eda586f312c3fc89444601e2525Chris LarsenENTRY_NO_GP art_quick_indexof
2391cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen/* $a0 holds address of "this" */
2392cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen/* $a1 holds "ch" */
2393cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen/* $a2 holds "fromIndex" */
2394f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic#if (STRING_COMPRESSION_FEATURE)
2395f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    lw    $a3, MIRROR_STRING_COUNT_OFFSET($a0)    # 'count' field of this
2396f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic#else
2397f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    lw    $t0, MIRROR_STRING_COUNT_OFFSET($a0)    # this.length()
2398f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic#endif
2399f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    slt   $t1, $a2, $zero # if fromIndex < 0
2400cdb23d6f4d4049f6f26b0ed629fcc5018bfe3a57Goran Jakovljevic#if defined(_MIPS_ARCH_MIPS32R6)
2401f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    seleqz $a2, $a2, $t1  #     fromIndex = 0;
2402cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen#else
2403f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    movn   $a2, $zero, $t1 #    fromIndex = 0;
2404cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen#endif
2405cdb23d6f4d4049f6f26b0ed629fcc5018bfe3a57Goran Jakovljevic
2406f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic#if (STRING_COMPRESSION_FEATURE)
2407f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    srl   $t0, $a3, 1     # $a3 holds count (with flag) and $t0 holds actual length
2408f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic#endif
2409f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    subu  $t0, $t0, $a2   # this.length() - fromIndex
2410f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    blez  $t0, 6f         # if this.length()-fromIndex <= 0
2411f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    li    $v0, -1         #     return -1;
2412f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic
2413f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic#if (STRING_COMPRESSION_FEATURE)
2414f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    sll   $a3, $a3, 31    # Extract compression flag.
2415f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    beqz  $a3, .Lstring_indexof_compressed
2416f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    move  $t2, $a0        # Save a copy in $t2 to later compute result (in branch delay slot).
2417f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic#endif
2418f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    sll   $v0, $a2, 1     # $a0 += $a2 * 2
2419f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    addu  $a0, $a0, $v0   #  "  ditto  "
2420f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    move  $v0, $a2        # Set i to fromIndex.
2421cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen
2422cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen1:
2423f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    lhu   $t3, MIRROR_STRING_VALUE_OFFSET($a0)    # if this.charAt(i) == ch
2424f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    beq   $t3, $a1, 6f                            #     return i;
2425f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    addu  $a0, $a0, 2     # i++
2426f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    subu  $t0, $t0, 1     # this.length() - i
2427f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    bnez  $t0, 1b         # while this.length() - i > 0
2428f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    addu  $v0, $v0, 1     # i++
2429cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen
2430f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    li    $v0, -1         # if this.length() - i <= 0
2431f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic                          #     return -1;
2432cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen
2433cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen6:
2434f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    j     $ra
2435f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    nop
2436f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic
2437f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic#if (STRING_COMPRESSION_FEATURE)
2438f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic.Lstring_indexof_compressed:
2439f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    addu  $a0, $a0, $a2   # $a0 += $a2
2440f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic
2441f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic.Lstring_indexof_compressed_loop:
2442f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    lbu   $t3, MIRROR_STRING_VALUE_OFFSET($a0)
2443f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    beq   $t3, $a1, .Lstring_indexof_compressed_matched
2444f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    subu  $t0, $t0, 1
2445f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    bgtz  $t0, .Lstring_indexof_compressed_loop
2446f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    addu  $a0, $a0, 1
2447f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic
2448f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic.Lstring_indexof_nomatch:
2449f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    jalr  $zero, $ra
2450f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    li    $v0, -1         # return -1;
2451f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic
2452f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic.Lstring_indexof_compressed_matched:
2453f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    jalr  $zero, $ra
2454f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    subu  $v0, $a0, $t2   # return (current - start);
2455f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic#endif
2456cf283daf579e9eda586f312c3fc89444601e2525Chris LarsenEND art_quick_indexof
2457cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen
2458cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen/* java.lang.String.compareTo(String anotherString) */
2459cf283daf579e9eda586f312c3fc89444601e2525Chris LarsenENTRY_NO_GP art_quick_string_compareto
2460cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen/* $a0 holds address of "this" */
2461cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen/* $a1 holds address of "anotherString" */
2462f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    beq    $a0, $a1, .Lstring_compareto_length_diff   # this and anotherString are the same object
2463f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    move   $a3, $a2                                   # trick to return 0 (it returns a2 - a3)
2464f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic
2465f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic#if (STRING_COMPRESSION_FEATURE)
2466f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    lw     $t0, MIRROR_STRING_COUNT_OFFSET($a0)   # 'count' field of this
2467f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    lw     $t1, MIRROR_STRING_COUNT_OFFSET($a1)   # 'count' field of anotherString
2468f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    sra    $a2, $t0, 1                            # this.length()
2469f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    sra    $a3, $t1, 1                            # anotherString.length()
2470f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic#else
2471f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    lw     $a2, MIRROR_STRING_COUNT_OFFSET($a0)   # this.length()
2472f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    lw     $a3, MIRROR_STRING_COUNT_OFFSET($a1)   # anotherString.length()
2473f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic#endif
2474cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen
2475f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    MINu   $t2, $a2, $a3
2476f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    # $t2 now holds min(this.length(),anotherString.length())
2477cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen
2478f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    # while min(this.length(),anotherString.length())-i != 0
2479f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    beqz   $t2, .Lstring_compareto_length_diff # if $t2==0
2480f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    nop                                        #     return (this.length() - anotherString.length())
2481f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic
2482f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic#if (STRING_COMPRESSION_FEATURE)
2483f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    # Differ cases:
2484f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    sll    $t3, $t0, 31
2485f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    beqz   $t3, .Lstring_compareto_this_is_compressed
2486f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    sll    $t3, $t1, 31                           # In branch delay slot.
2487f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    beqz   $t3, .Lstring_compareto_that_is_compressed
2488f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    nop
2489f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    b      .Lstring_compareto_both_not_compressed
2490f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    nop
2491f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic
2492f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic.Lstring_compareto_this_is_compressed:
2493f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    beqz   $t3, .Lstring_compareto_both_compressed
2494f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    nop
2495f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    /* If (this->IsCompressed() && that->IsCompressed() == false) */
2496f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic.Lstring_compareto_loop_comparison_this_compressed:
2497f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    lbu    $t0, MIRROR_STRING_VALUE_OFFSET($a0)
2498f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    lhu    $t1, MIRROR_STRING_VALUE_OFFSET($a1)
2499f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    bne    $t0, $t1, .Lstring_compareto_char_diff
2500f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    addiu  $a0, $a0, 1    # point at this.charAt(i++) - compressed
2501f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    subu   $t2, $t2, 1    # new value of min(this.length(),anotherString.length())-i
2502f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    bnez   $t2, .Lstring_compareto_loop_comparison_this_compressed
2503f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    addiu  $a1, $a1, 2    # point at anotherString.charAt(i++) - uncompressed
2504f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    jalr   $zero, $ra
2505f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    subu   $v0, $a2, $a3  # return (this.length() - anotherString.length())
2506f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic
2507f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic.Lstring_compareto_that_is_compressed:
2508f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    lhu    $t0, MIRROR_STRING_VALUE_OFFSET($a0)
2509f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    lbu    $t1, MIRROR_STRING_VALUE_OFFSET($a1)
2510f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    bne    $t0, $t1, .Lstring_compareto_char_diff
2511f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    addiu  $a0, $a0, 2    # point at this.charAt(i++) - uncompressed
2512f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    subu   $t2, $t2, 1    # new value of min(this.length(),anotherString.length())-i
2513f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    bnez   $t2, .Lstring_compareto_that_is_compressed
2514f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    addiu  $a1, $a1, 1    # point at anotherString.charAt(i++) - compressed
2515f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    jalr   $zero, $ra
2516f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    subu   $v0, $a2, $a3  # return (this.length() - anotherString.length())
2517f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic
2518f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic.Lstring_compareto_both_compressed:
2519f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    lbu    $t0, MIRROR_STRING_VALUE_OFFSET($a0)
2520f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    lbu    $t1, MIRROR_STRING_VALUE_OFFSET($a1)
2521f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    bne    $t0, $t1, .Lstring_compareto_char_diff
2522f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    addiu  $a0, $a0, 1    # point at this.charAt(i++) - compressed
2523f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    subu   $t2, $t2, 1    # new value of min(this.length(),anotherString.length())-i
2524f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    bnez   $t2, .Lstring_compareto_both_compressed
2525f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    addiu  $a1, $a1, 1    # point at anotherString.charAt(i++) - compressed
2526f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    jalr   $zero, $ra
2527f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    subu   $v0, $a2, $a3  # return (this.length() - anotherString.length())
2528f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic#endif
2529f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic
2530f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic.Lstring_compareto_both_not_compressed:
2531f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    lhu    $t0, MIRROR_STRING_VALUE_OFFSET($a0)   # while this.charAt(i) == anotherString.charAt(i)
2532f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    lhu    $t1, MIRROR_STRING_VALUE_OFFSET($a1)
2533f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    bne    $t0, $t1, .Lstring_compareto_char_diff # if this.charAt(i) != anotherString.charAt(i)
2534f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic                          #     return (this.charAt(i) - anotherString.charAt(i))
2535f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    addiu  $a0, $a0, 2    # point at this.charAt(i++)
2536f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    subu   $t2, $t2, 1    # new value of min(this.length(),anotherString.length())-i
2537f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    bnez   $t2, .Lstring_compareto_both_not_compressed
2538f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    addiu  $a1, $a1, 2    # point at anotherString.charAt(i++)
2539f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic
2540f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic.Lstring_compareto_length_diff:
2541f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    jalr   $zero, $ra
2542f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    subu   $v0, $a2, $a3  # return (this.length() - anotherString.length())
2543f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic
2544f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic.Lstring_compareto_char_diff:
2545f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    jalr   $zero, $ra
2546f94fa81e20d00929ef52707cd577353b95d40284Goran Jakovljevic    subu   $v0, $t0, $t1  # return (this.charAt(i) - anotherString.charAt(i))
2547cf283daf579e9eda586f312c3fc89444601e2525Chris LarsenEND art_quick_string_compareto
2548ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson
25491595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    /*
25501595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze     * Create a function `name` calling the ReadBarrier::Mark routine,
25511595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze     * getting its argument and returning its result through register
25521595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze     * `reg`, saving and restoring all caller-save registers.
25531595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze     */
25541595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze.macro READ_BARRIER_MARK_REG name, reg
25551595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeENTRY \name
2556a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    // Null check so that we can load the lock word.
2557a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    bnez    \reg, .Lnot_null_\name
2558a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    nop
2559a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze.Lret_rb_\name:
2560a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    jalr    $zero, $ra
2561a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    nop
2562a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze.Lnot_null_\name:
2563a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    // Check lock word for mark bit, if marked return.
2564a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    lw      $t9, MIRROR_OBJECT_LOCK_WORD_OFFSET(\reg)
2565a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    .set push
2566a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    .set noat
2567a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    sll     $at, $t9, 31 - LOCK_WORD_MARK_BIT_SHIFT     # Move mark bit to sign bit.
2568a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    bltz    $at, .Lret_rb_\name
2569a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze#if (LOCK_WORD_STATE_SHIFT != 30) || (LOCK_WORD_STATE_FORWARDING_ADDRESS != 3)
2570a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    // The below code depends on the lock word state being in the highest bits
2571a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    // and the "forwarding address" state having all bits set.
2572a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze#error "Unexpected lock word state shift or forwarding address state value."
2573a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze#endif
2574a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    // Test that both the forwarding state bits are 1.
2575a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    sll     $at, $t9, 1
2576a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    and     $at, $at, $t9                               # Sign bit = 1 IFF both bits are 1.
2577a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    bltz    $at, .Lret_forwarding_address\name
2578a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    nop
2579a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    .set pop
2580a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze
2581a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    addiu   $sp, $sp, -160      # Includes 16 bytes of space for argument registers a0-a3.
25821595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_adjust_cfa_offset 160
25831595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze
25841595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sw      $ra, 156($sp)
25851595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_rel_offset 31, 156
25861595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sw      $t8, 152($sp)
25871595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_rel_offset 24, 152
25881595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sw      $t7, 148($sp)
25891595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_rel_offset 15, 148
25901595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sw      $t6, 144($sp)
25911595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_rel_offset 14, 144
25921595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sw      $t5, 140($sp)
25931595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_rel_offset 13, 140
25941595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sw      $t4, 136($sp)
25951595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_rel_offset 12, 136
25961595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sw      $t3, 132($sp)
25971595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_rel_offset 11, 132
25981595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sw      $t2, 128($sp)
25991595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_rel_offset 10, 128
26001595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sw      $t1, 124($sp)
26011595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_rel_offset 9, 124
26021595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sw      $t0, 120($sp)
26031595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_rel_offset 8, 120
26041595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sw      $a3, 116($sp)
26051595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_rel_offset 7, 116
26061595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sw      $a2, 112($sp)
26071595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_rel_offset 6, 112
26081595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sw      $a1, 108($sp)
26091595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_rel_offset 5, 108
26101595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sw      $a0, 104($sp)
26111595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_rel_offset 4, 104
26121595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sw      $v1, 100($sp)
26131595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_rel_offset 3, 100
26141595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sw      $v0, 96($sp)
26151595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_rel_offset 2, 96
26161595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze
26171595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    la      $t9, artReadBarrierMark
26181595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze
26191595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sdc1    $f18, 88($sp)
26201595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sdc1    $f16, 80($sp)
26211595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sdc1    $f14, 72($sp)
26221595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sdc1    $f12, 64($sp)
26231595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sdc1    $f10, 56($sp)
26241595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sdc1    $f8,  48($sp)
26251595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sdc1    $f6,  40($sp)
26261595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sdc1    $f4,  32($sp)
26271595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sdc1    $f2,  24($sp)
26281595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze
26291595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .ifnc \reg, $a0
26301595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze      move  $a0, \reg           # pass obj from `reg` in a0
26311595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .endif
26321595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    jalr    $t9                 # v0 <- artReadBarrierMark(obj)
26331595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    sdc1    $f0,  16($sp)       # in delay slot
26341595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze
26351595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    lw      $ra, 156($sp)
26361595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_restore 31
26371595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    lw      $t8, 152($sp)
26381595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_restore 24
26391595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    lw      $t7, 148($sp)
26401595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_restore 15
26411595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    lw      $t6, 144($sp)
26421595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_restore 14
26431595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    lw      $t5, 140($sp)
26441595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_restore 13
26451595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    lw      $t4, 136($sp)
26461595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_restore 12
26471595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    lw      $t3, 132($sp)
26481595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_restore 11
26491595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    lw      $t2, 128($sp)
26501595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_restore 10
26511595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    lw      $t1, 124($sp)
26521595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_restore 9
26531595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    lw      $t0, 120($sp)
26541595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_restore 8
26551595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    lw      $a3, 116($sp)
26561595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_restore 7
26571595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    lw      $a2, 112($sp)
26581595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_restore 6
26591595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    lw      $a1, 108($sp)
26601595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_restore 5
26611595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    lw      $a0, 104($sp)
26621595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_restore 4
26631595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    lw      $v1, 100($sp)
26641595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_restore 3
26651595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze
26661595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .ifnc \reg, $v0
26671595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze      move  \reg, $v0           # `reg` <- v0
26681595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze      lw    $v0, 96($sp)
26691595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze      .cfi_restore 2
26701595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .endif
26711595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze
26721595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    ldc1    $f18, 88($sp)
26731595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    ldc1    $f16, 80($sp)
26741595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    ldc1    $f14, 72($sp)
26751595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    ldc1    $f12, 64($sp)
26761595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    ldc1    $f10, 56($sp)
26771595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    ldc1    $f8,  48($sp)
26781595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    ldc1    $f6,  40($sp)
26791595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    ldc1    $f4,  32($sp)
26801595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    ldc1    $f2,  24($sp)
26811595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    ldc1    $f0,  16($sp)
26821595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze
26831595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    jalr    $zero, $ra
26841595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    addiu   $sp, $sp, 160
26851595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze    .cfi_adjust_cfa_offset -160
2686a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze
2687a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze.Lret_forwarding_address\name:
2688a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    jalr    $zero, $ra
2689a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    // Shift left by the forwarding address shift. This clears out the state bits since they are
2690a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    // in the top 2 bits of the lock word.
2691a3cb132792e998d64b917d36052b715f0076820bAlexey Frunze    sll     \reg, $t9, LOCK_WORD_STATE_FORWARDING_ADDRESS_SHIFT
26921595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeEND \name
26931595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze.endm
26941595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze
26951595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze// Note that art_quick_read_barrier_mark_regXX corresponds to register XX+1.
26961595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze// ZERO (register 0) is reserved.
26971595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze// AT (register 1) is reserved as a temporary/scratch register.
26981595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg01, $v0
26991595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg02, $v1
27001595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg03, $a0
27011595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg04, $a1
27021595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg05, $a2
27031595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg06, $a3
27041595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg07, $t0
27051595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg08, $t1
27061595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg09, $t2
27071595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg10, $t3
27081595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg11, $t4
27091595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg12, $t5
27101595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg13, $t6
27111595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg14, $t7
27121595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze// S0 and S1 (registers 16 and 17) are reserved as suspended and thread registers.
27131595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg17, $s2
27141595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg18, $s3
27151595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg19, $s4
27161595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg20, $s5
27171595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg21, $s6
27181595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg22, $s7
27191595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze// T8 and T9 (registers 24 and 25) are reserved as temporary/scratch registers.
27201595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze// K0, K1, GP, SP (registers 26 - 29) are reserved.
27211595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey FrunzeREAD_BARRIER_MARK_REG art_quick_read_barrier_mark_reg29, $s8
27221595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze// RA (register 31) is reserved.
27231595815c2a914a78df7dfb6f0082f47d4e82bb36Alexey Frunze
27244147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze// Caller code:
27254147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze// Short constant offset/index:
27264147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze// R2:                           | R6:
27274147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze//  lw      $t9, pReadBarrierMarkReg00
27284147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze//  beqz    $t9, skip_call       |  beqzc   $t9, skip_call
27294147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze//  addiu   $t9, $t9, thunk_disp |  nop
27304147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze//  jalr    $t9                  |  jialc   $t9, thunk_disp
27314147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze//  nop                          |
27324147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze// skip_call:                    | skip_call:
27334147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze//  lw      `out`, ofs(`obj`)    |  lw      `out`, ofs(`obj`)
27344147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze// [subu    `out`, $zero, `out`] | [subu    `out`, $zero, `out`]  # Unpoison reference.
27354147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze.macro BRB_FIELD_SHORT_OFFSET_ENTRY obj
27364147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze1:
27374147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    # Explicit null check. May be redundant (for array elements or when the field
27384147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    # offset is larger than the page size, 4KB).
27394147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    # $ra will be adjusted to point to lw's stack map when throwing NPE.
27404147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    beqz    \obj, .Lintrospection_throw_npe
27414147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze#if defined(_MIPS_ARCH_MIPS32R6)
27424147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lapc    $gp, .Lintrospection_exits                  # $gp = address of .Lintrospection_exits.
27434147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze#else
27444147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    addiu   $gp, $t9, (.Lintrospection_exits - 1b)      # $gp = address of .Lintrospection_exits.
27454147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze#endif
27464147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .set push
27474147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .set noat
27484147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $at, MIRROR_OBJECT_LOCK_WORD_OFFSET(\obj)
27494147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sll     $at, $at, 31 - LOCK_WORD_READ_BARRIER_STATE_SHIFT   # Move barrier state bit
27504147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze                                                                # to sign bit.
27514147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    bltz    $at, .Lintrospection_field_array            # If gray, load reference, mark.
27524147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    move    $t8, \obj                                   # Move `obj` to $t8 for common code.
27534147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .set pop
27544147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    jalr    $zero, $ra                                  # Otherwise, load-load barrier and return.
27554147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sync
27564147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze.endm
27574147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
27584147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze// Caller code (R2):
27594147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze// Long constant offset/index:   | Variable index:
27604147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze//  lw      $t9, pReadBarrierMarkReg00
27614147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze//  lui     $t8, ofs_hi          |  sll     $t8, `index`, 2
27624147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze//  beqz    $t9, skip_call       |  beqz    $t9, skip_call
27634147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze//  addiu   $t9, $t9, thunk_disp |  addiu   $t9, $t9, thunk_disp
27644147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze//  jalr    $t9                  |  jalr    $t9
27654147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze// skip_call:                    | skip_call:
27664147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze//  addu    $t8, $t8, `obj`      |  addu    $t8, $t8, `obj`
27674147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze//  lw      `out`, ofs_lo($t8)   |  lw      `out`, ofs($t8)
27684147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze// [subu    `out`, $zero, `out`] | [subu    `out`, $zero, `out`]  # Unpoison reference.
27694147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze//
27704147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze// Caller code (R6):
27714147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze// Long constant offset/index:   | Variable index:
27724147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze//  lw      $t9, pReadBarrierMarkReg00
27734147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze//  beqz    $t9, skip_call       |  beqz    $t9, skip_call
27744147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze//  aui     $t8, `obj`, ofs_hi   |  lsa     $t8, `index`, `obj`, 2
27754147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze//  jialc   $t9, thunk_disp      |  jialc   $t9, thunk_disp
27764147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze// skip_call:                    | skip_call:
27774147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze//  lw      `out`, ofs_lo($t8)   |  lw      `out`, ofs($t8)
27784147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze// [subu    `out`, $zero, `out`] | [subu    `out`, $zero, `out`]  # Unpoison reference.
27794147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze.macro BRB_FIELD_LONG_OFFSET_ENTRY obj
27804147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze1:
27814147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    # No explicit null check for variable indices or large constant indices/offsets
27824147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    # as it must have been done earlier.
27834147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze#if defined(_MIPS_ARCH_MIPS32R6)
27844147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lapc    $gp, .Lintrospection_exits                  # $gp = address of .Lintrospection_exits.
27854147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze#else
27864147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    addiu   $gp, $t9, (.Lintrospection_exits - 1b)      # $gp = address of .Lintrospection_exits.
27874147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze#endif
27884147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .set push
27894147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .set noat
27904147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $at, MIRROR_OBJECT_LOCK_WORD_OFFSET(\obj)
27914147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sll     $at, $at, 31 - LOCK_WORD_READ_BARRIER_STATE_SHIFT   # Move barrier state bit
27924147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze                                                                # to sign bit.
27934147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    bltz    $at, .Lintrospection_field_array            # If gray, load reference, mark.
27944147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    nop
27954147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .set pop
27964147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    jalr    $zero, $ra                                  # Otherwise, load-load barrier and return.
27974147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sync
27984147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    break                                               # Padding to 8 instructions.
27994147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze.endm
28004147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
28014147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze.macro BRB_GC_ROOT_ENTRY root
28024147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze1:
28034147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze#if defined(_MIPS_ARCH_MIPS32R6)
28044147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lapc    $gp, .Lintrospection_exit_\root             # $gp = exit point address.
28054147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze#else
28064147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    addiu   $gp, $t9, (.Lintrospection_exit_\root - 1b)  # $gp = exit point address.
28074147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze#endif
28084147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    bnez    \root, .Lintrospection_common
28094147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    move    $t8, \root                                  # Move reference to $t8 for common code.
28104147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    jalr    $zero, $ra                                  # Return if null.
28114147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    # The next instruction (from the following BRB_GC_ROOT_ENTRY) fills the delay slot.
28124147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    # This instruction has no effect (actual NOP for the last entry; otherwise changes $gp,
28134147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    # which is unused after that anyway).
28144147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze.endm
28154147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
28164147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze.macro BRB_FIELD_EXIT out
28174147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze.Lintrospection_exit_\out:
28184147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    jalr    $zero, $ra
28194147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    move    \out, $t8                                   # Return reference in expected register.
28204147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze.endm
28214147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
28224147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze.macro BRB_FIELD_EXIT_BREAK
28234147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    break
28244147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    break
28254147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze.endm
28264147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
28274147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey FrunzeENTRY_NO_GP art_quick_read_barrier_mark_introspection
28284147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    # Entry points for offsets/indices not fitting into int16_t and for variable indices.
28294147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $v0
28304147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $v1
28314147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $a0
28324147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $a1
28334147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $a2
28344147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $a3
28354147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $t0
28364147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $t1
28374147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $t2
28384147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $t3
28394147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $t4
28404147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $t5
28414147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $t6
28424147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $t7
28434147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $s2
28444147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $s3
28454147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $s4
28464147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $s5
28474147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $s6
28484147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $s7
28494147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_LONG_OFFSET_ENTRY $s8
28504147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
28514147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    # Entry points for offsets/indices fitting into int16_t.
28524147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $v0
28534147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $v1
28544147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $a0
28554147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $a1
28564147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $a2
28574147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $a3
28584147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $t0
28594147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $t1
28604147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $t2
28614147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $t3
28624147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $t4
28634147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $t5
28644147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $t6
28654147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $t7
28664147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $s2
28674147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $s3
28684147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $s4
28694147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $s5
28704147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $s6
28714147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $s7
28724147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_SHORT_OFFSET_ENTRY $s8
28734147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
28744147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .global art_quick_read_barrier_mark_introspection_gc_roots
28754147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunzeart_quick_read_barrier_mark_introspection_gc_roots:
28764147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    # Entry points for GC roots.
28774147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $v0
28784147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $v1
28794147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $a0
28804147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $a1
28814147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $a2
28824147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $a3
28834147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $t0
28844147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $t1
28854147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $t2
28864147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $t3
28874147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $t4
28884147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $t5
28894147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $t6
28904147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $t7
28914147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $s2
28924147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $s3
28934147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $s4
28944147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $s5
28954147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $s6
28964147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $s7
28974147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_GC_ROOT_ENTRY $s8
28984147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .global art_quick_read_barrier_mark_introspection_end_of_entries
28994147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunzeart_quick_read_barrier_mark_introspection_end_of_entries:
29004147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    nop                         # Fill the delay slot of the last BRB_GC_ROOT_ENTRY.
29014147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
29024147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze.Lintrospection_throw_npe:
29034147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    b       art_quick_throw_null_pointer_exception
29044147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    addiu   $ra, $ra, 4         # Skip lw, make $ra point to lw's stack map.
29054147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
29064147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .set push
29074147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .set noat
29084147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
29094147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    // Fields and array elements.
29104147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
29114147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze.Lintrospection_field_array:
29124147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    // Get the field/element address using $t8 and the offset from the lw instruction.
29134147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lh      $at, 0($ra)         # $ra points to lw: $at = field/element offset.
29144147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    addiu   $ra, $ra, 4 + HEAP_POISON_INSTR_SIZE  # Skip lw(+subu).
29154147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    addu    $t8, $t8, $at       # $t8 = field/element address.
29164147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
29174147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    // Calculate the address of the exit point, store it in $gp and load the reference into $t8.
29184147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lb      $at, (-HEAP_POISON_INSTR_SIZE - 2)($ra)   # $ra-HEAP_POISON_INSTR_SIZE-4 points to
29194147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze                                                      # "lw `out`, ...".
29204147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    andi    $at, $at, 31        # Extract `out` from lw.
29214147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sll     $at, $at, 3         # Multiply `out` by the exit point size (BRB_FIELD_EXIT* macros).
29224147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
29234147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $t8, 0($t8)         # $t8 = reference.
29244147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    UNPOISON_HEAP_REF $t8
29254147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
29264147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    // Return if null reference.
29274147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    bnez    $t8, .Lintrospection_common
29284147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    addu    $gp, $gp, $at       # $gp = address of the exit point.
29294147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
29304147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    // Early return through the exit point.
29314147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze.Lintrospection_return_early:
29324147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    jalr    $zero, $gp          # Move $t8 to `out` and return.
29334147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    nop
29344147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
29354147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    // Code common for GC roots, fields and array elements.
29364147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
29374147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze.Lintrospection_common:
29384147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    // Check lock word for mark bit, if marked return.
29394147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $t9, MIRROR_OBJECT_LOCK_WORD_OFFSET($t8)
29404147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sll     $at, $t9, 31 - LOCK_WORD_MARK_BIT_SHIFT     # Move mark bit to sign bit.
29414147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    bltz    $at, .Lintrospection_return_early
29424147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze#if (LOCK_WORD_STATE_SHIFT != 30) || (LOCK_WORD_STATE_FORWARDING_ADDRESS != 3)
29434147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    // The below code depends on the lock word state being in the highest bits
29444147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    // and the "forwarding address" state having all bits set.
29454147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze#error "Unexpected lock word state shift or forwarding address state value."
29464147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze#endif
29474147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    // Test that both the forwarding state bits are 1.
29484147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sll     $at, $t9, 1
29494147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    and     $at, $at, $t9                               # Sign bit = 1 IFF both bits are 1.
29504147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    bgez    $at, .Lintrospection_mark
29514147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    nop
29524147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
29534147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .set pop
29544147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
29554147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    // Shift left by the forwarding address shift. This clears out the state bits since they are
29564147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    // in the top 2 bits of the lock word.
29574147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    jalr    $zero, $gp          # Move $t8 to `out` and return.
29584147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sll     $t8, $t9, LOCK_WORD_STATE_FORWARDING_ADDRESS_SHIFT
29594147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
29604147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze.Lintrospection_mark:
29614147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    // Partially set up the stack frame preserving only $ra.
29624147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    addiu   $sp, $sp, -160      # Includes 16 bytes of space for argument registers $a0-$a3.
29634147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_adjust_cfa_offset 160
29644147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sw      $ra, 156($sp)
29654147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_rel_offset 31, 156
29664147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
29674147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    // Set up $gp, clobbering $ra and using the branch delay slot for a useful instruction.
29684147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    bal     1f
29694147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sw      $gp, 152($sp)       # Preserve the exit point address.
29704147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze1:
29714147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cpload $ra
29724147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
29734147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    // Finalize the stack frame and call.
29744147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sw      $t7, 148($sp)
29754147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_rel_offset 15, 148
29764147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sw      $t6, 144($sp)
29774147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_rel_offset 14, 144
29784147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sw      $t5, 140($sp)
29794147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_rel_offset 13, 140
29804147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sw      $t4, 136($sp)
29814147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_rel_offset 12, 136
29824147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sw      $t3, 132($sp)
29834147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_rel_offset 11, 132
29844147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sw      $t2, 128($sp)
29854147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_rel_offset 10, 128
29864147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sw      $t1, 124($sp)
29874147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_rel_offset 9, 124
29884147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sw      $t0, 120($sp)
29894147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_rel_offset 8, 120
29904147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sw      $a3, 116($sp)
29914147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_rel_offset 7, 116
29924147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sw      $a2, 112($sp)
29934147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_rel_offset 6, 112
29944147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sw      $a1, 108($sp)
29954147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_rel_offset 5, 108
29964147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sw      $a0, 104($sp)
29974147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_rel_offset 4, 104
29984147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sw      $v1, 100($sp)
29994147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_rel_offset 3, 100
30004147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sw      $v0, 96($sp)
30014147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_rel_offset 2, 96
30024147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
30034147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    la      $t9, artReadBarrierMark
30044147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
30054147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sdc1    $f18, 88($sp)
30064147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sdc1    $f16, 80($sp)
30074147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sdc1    $f14, 72($sp)
30084147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sdc1    $f12, 64($sp)
30094147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sdc1    $f10, 56($sp)
30104147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sdc1    $f8,  48($sp)
30114147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sdc1    $f6,  40($sp)
30124147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sdc1    $f4,  32($sp)
30134147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sdc1    $f2,  24($sp)
30144147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    sdc1    $f0,  16($sp)
30154147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
30164147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    jalr    $t9                 # $v0 <- artReadBarrierMark(reference)
30174147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    move    $a0, $t8            # Pass reference in $a0.
30184147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    move    $t8, $v0
30194147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
30204147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $ra, 156($sp)
30214147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_restore 31
30224147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $gp, 152($sp)       # $gp = address of the exit point.
30234147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $t7, 148($sp)
30244147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_restore 15
30254147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $t6, 144($sp)
30264147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_restore 14
30274147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $t5, 140($sp)
30284147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_restore 13
30294147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $t4, 136($sp)
30304147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_restore 12
30314147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $t3, 132($sp)
30324147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_restore 11
30334147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $t2, 128($sp)
30344147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_restore 10
30354147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $t1, 124($sp)
30364147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_restore 9
30374147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $t0, 120($sp)
30384147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_restore 8
30394147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $a3, 116($sp)
30404147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_restore 7
30414147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $a2, 112($sp)
30424147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_restore 6
30434147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $a1, 108($sp)
30444147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_restore 5
30454147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $a0, 104($sp)
30464147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_restore 4
30474147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $v1, 100($sp)
30484147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_restore 3
30494147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    lw      $v0, 96($sp)
30504147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_restore 2
30514147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
30524147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    ldc1    $f18, 88($sp)
30534147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    ldc1    $f16, 80($sp)
30544147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    ldc1    $f14, 72($sp)
30554147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    ldc1    $f12, 64($sp)
30564147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    ldc1    $f10, 56($sp)
30574147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    ldc1    $f8,  48($sp)
30584147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    ldc1    $f6,  40($sp)
30594147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    ldc1    $f4,  32($sp)
30604147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    ldc1    $f2,  24($sp)
30614147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    ldc1    $f0,  16($sp)
30624147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
30634147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    // Return through the exit point.
30644147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    jalr    $zero, $gp          # Move $t8 to `out` and return.
30654147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    addiu   $sp, $sp, 160
30664147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    .cfi_adjust_cfa_offset -160
30674147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
30684147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze.Lintrospection_exits:
30694147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT_BREAK
30704147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT_BREAK
30714147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $v0
30724147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $v1
30734147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $a0
30744147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $a1
30754147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $a2
30764147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $a3
30774147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $t0
30784147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $t1
30794147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $t2
30804147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $t3
30814147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $t4
30824147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $t5
30834147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $t6
30844147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $t7
30854147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT_BREAK
30864147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT_BREAK
30874147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $s2
30884147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $s3
30894147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $s4
30904147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $s5
30914147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $s6
30924147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $s7
30934147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT_BREAK
30944147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT_BREAK
30954147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT_BREAK
30964147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT_BREAK
30974147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT_BREAK
30984147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT_BREAK
30994147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT $s8
31004147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze    BRB_FIELD_EXIT_BREAK
31014147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey FrunzeEND art_quick_read_barrier_mark_introspection
31024147fcc43c2ee019a06e55384985e3eaf82dcb8cAlexey Frunze
3103ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson.extern artInvokePolymorphic
3104ac141397dc29189ad2b2df41f8d4312246beec60Orion HodsonENTRY art_quick_invoke_polymorphic
3105ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    SETUP_SAVE_REFS_AND_ARGS_FRAME
3106ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    move  $a2, rSELF                          # Make $a2 an alias for the current Thread.
3107c480b9853ac7be67581cd26c49c2ed7426ae68a4Alexey Frunze    addiu $a3, $sp, ARG_SLOT_SIZE             # Make $a3 a pointer to the saved frame context.
3108ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    sw    $zero, 20($sp)                      # Initialize JValue result.
3109ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    sw    $zero, 16($sp)
3110ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    la    $t9, artInvokePolymorphic
3111ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    jalr  $t9                                 # (result, receiver, Thread*, context)
3112c480b9853ac7be67581cd26c49c2ed7426ae68a4Alexey Frunze    addiu $a0, $sp, 16                        # Make $a0 a pointer to the JValue result
3113ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson.macro MATCH_RETURN_TYPE c, handler
3114ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    li    $t0, \c
3115ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    beq   $v0, $t0, \handler
3116ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson.endm
3117ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    MATCH_RETURN_TYPE 'V', .Lcleanup_and_return
3118ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    MATCH_RETURN_TYPE 'L', .Lstore_int_result
3119ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    MATCH_RETURN_TYPE 'I', .Lstore_int_result
3120ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    MATCH_RETURN_TYPE 'J', .Lstore_long_result
3121ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    MATCH_RETURN_TYPE 'B', .Lstore_int_result
3122ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    MATCH_RETURN_TYPE 'C', .Lstore_char_result
3123ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    MATCH_RETURN_TYPE 'D', .Lstore_double_result
3124ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    MATCH_RETURN_TYPE 'F', .Lstore_float_result
3125ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    MATCH_RETURN_TYPE 'S', .Lstore_int_result
3126c480b9853ac7be67581cd26c49c2ed7426ae68a4Alexey Frunze    MATCH_RETURN_TYPE 'Z', .Lstore_boolean_result
3127ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson.purgem MATCH_RETURN_TYPE
3128ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    nop
3129ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    b .Lcleanup_and_return
3130ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    nop
3131ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson.Lstore_boolean_result:
3132ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    b .Lcleanup_and_return
3133c480b9853ac7be67581cd26c49c2ed7426ae68a4Alexey Frunze    lbu   $v0, 16($sp)                        # Move byte from JValue result to return value register.
3134ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson.Lstore_char_result:
3135ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    b .Lcleanup_and_return
3136c480b9853ac7be67581cd26c49c2ed7426ae68a4Alexey Frunze    lhu   $v0, 16($sp)                        # Move char from JValue result to return value register.
3137ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson.Lstore_double_result:
3138ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson.Lstore_float_result:
3139ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    LDu   $f0, $f1, 16, $sp, $t0              # Move double/float from JValue result to return value register.
3140ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    b .Lcleanup_and_return
3141ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    nop
3142ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson.Lstore_long_result:
3143ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    lw    $v1, 20($sp)                        # Move upper bits from JValue result to return value register.
3144ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    // Fall-through for lower bits.
3145ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson.Lstore_int_result:
3146ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    lw    $v0, 16($sp)                        # Move lower bits from JValue result to return value register.
3147ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    // Fall-through to clean up and return.
3148ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson.Lcleanup_and_return:
3149ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    lw    $t7, THREAD_EXCEPTION_OFFSET(rSELF) # Load Thread::Current()->exception_
3150ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    RESTORE_SAVE_REFS_AND_ARGS_FRAME
3151ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    bnez  $t7, 1f                             # Success if no exception is pending.
3152ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    nop
3153ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    jalr  $zero, $ra
3154ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    nop
3155ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson1:
3156ac141397dc29189ad2b2df41f8d4312246beec60Orion Hodson    DELIVER_PENDING_EXCEPTION
3157ac141397dc29189ad2b2df41f8d4312246beec60Orion HodsonEND art_quick_invoke_polymorphic
3158