blob: e628a9f40dc5e9b935aabacefcd228d005ac5a67 [file] [log] [blame]
Elliott Hughes0f3c5532012-03-30 14:51:51 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Ian Rogers7655f292013-07-29 11:07:13 -070017#include "asm_support_mips.S"
buzbee5bc5a7b2012-03-07 15:52:59 -080018
Mathieu Chartier7410f292013-11-24 13:17:35 -080019#include "arch/quick_alloc_entrypoints.S"
20
jeffhao07030602012-09-26 14:33:14 -070021 .set noreorder
buzbee5bc5a7b2012-03-07 15:52:59 -080022 .balign 4
23
24 /* Deliver the given exception */
25 .extern artDeliverExceptionFromCode
26 /* Deliver an exception pending on a thread */
jeffhao8161c032012-10-31 15:50:00 -070027 .extern artDeliverPendingExceptionFromCode
buzbee5bc5a7b2012-03-07 15:52:59 -080028
Douglas Leung735b8552014-10-31 12:21:40 -070029#define ARG_SLOT_SIZE 32 // space for a0-a3 plus 4 more words
30
buzbee5bc5a7b2012-03-07 15:52:59 -080031 /*
32 * Macro that sets up the callee save frame to conform with
Vladimir Markofd36f1f2016-08-03 18:49:58 +010033 * Runtime::CreateCalleeSaveMethod(kSaveAllCalleeSaves)
Douglas Leung735b8552014-10-31 12:21:40 -070034 * Callee-save: $s0-$s8 + $gp + $ra, 11 total + 1 word for Method*
35 * Clobbers $t0 and $sp
36 * Allocates ARG_SLOT_SIZE bytes at the bottom of the stack for arg slots.
Vladimir Markofd36f1f2016-08-03 18:49:58 +010037 * Reserves FRAME_SIZE_SAVE_ALL_CALLEE_SAVES + ARG_SLOT_SIZE bytes on the stack
buzbee5bc5a7b2012-03-07 15:52:59 -080038 */
Vladimir Markofd36f1f2016-08-03 18:49:58 +010039.macro SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
Andreas Gampea4e0e672015-05-27 18:31:42 -070040 addiu $sp, $sp, -96
41 .cfi_adjust_cfa_offset 96
Andreas Gampe5c1e4352014-04-21 19:28:24 -070042
43 // Ugly compile-time check, but we only have the preprocessor.
Vladimir Markofd36f1f2016-08-03 18:49:58 +010044#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVES != 96)
45#error "FRAME_SIZE_SAVE_ALL_CALLEE_SAVES(MIPS) size not as expected."
Andreas Gampe5c1e4352014-04-21 19:28:24 -070046#endif
47
Andreas Gampea4e0e672015-05-27 18:31:42 -070048 sw $ra, 92($sp)
49 .cfi_rel_offset 31, 92
50 sw $s8, 88($sp)
51 .cfi_rel_offset 30, 88
52 sw $gp, 84($sp)
53 .cfi_rel_offset 28, 84
54 sw $s7, 80($sp)
55 .cfi_rel_offset 23, 80
56 sw $s6, 76($sp)
57 .cfi_rel_offset 22, 76
58 sw $s5, 72($sp)
59 .cfi_rel_offset 21, 72
60 sw $s4, 68($sp)
61 .cfi_rel_offset 20, 68
62 sw $s3, 64($sp)
63 .cfi_rel_offset 19, 64
64 sw $s2, 60($sp)
65 .cfi_rel_offset 18, 60
66 sw $s1, 56($sp)
67 .cfi_rel_offset 17, 56
68 sw $s0, 52($sp)
69 .cfi_rel_offset 16, 52
70
71 SDu $f30, $f31, 44, $sp, $t1
72 SDu $f28, $f29, 36, $sp, $t1
73 SDu $f26, $f27, 28, $sp, $t1
74 SDu $f24, $f25, 20, $sp, $t1
75 SDu $f22, $f23, 12, $sp, $t1
76 SDu $f20, $f21, 4, $sp, $t1
77
Douglas Leung735b8552014-10-31 12:21:40 -070078 # 1 word for holding Method*
Ian Rogers1d8cdbc2014-09-22 22:51:09 -070079
Douglas Leung4af77b72014-10-22 16:32:28 -070080 lw $t0, %got(_ZN3art7Runtime9instance_E)($gp)
81 lw $t0, 0($t0)
Vladimir Markofd36f1f2016-08-03 18:49:58 +010082 lw $t0, RUNTIME_SAVE_ALL_CALLEE_SAVES_METHOD_OFFSET($t0)
Ian Rogers1d8cdbc2014-09-22 22:51:09 -070083 sw $t0, 0($sp) # Place Method* at bottom of stack.
84 sw $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF) # Place sp in Thread::Current()->top_quick_frame.
Douglas Leung735b8552014-10-31 12:21:40 -070085 addiu $sp, $sp, -ARG_SLOT_SIZE # reserve argument slots on the stack
86 .cfi_adjust_cfa_offset ARG_SLOT_SIZE
buzbee5bc5a7b2012-03-07 15:52:59 -080087.endm
88
89 /*
90 * Macro that sets up the callee save frame to conform with
Vladimir Markofd36f1f2016-08-03 18:49:58 +010091 * Runtime::CreateCalleeSaveMethod(kSaveRefsOnly). Restoration assumes non-moving GC.
buzbee5bc5a7b2012-03-07 15:52:59 -080092 * Does not include rSUSPEND or rSELF
Douglas Leung735b8552014-10-31 12:21:40 -070093 * callee-save: $s2-$s8 + $gp + $ra, 9 total + 2 words padding + 1 word to hold Method*
94 * Clobbers $t0 and $sp
95 * Allocates ARG_SLOT_SIZE bytes at the bottom of the stack for arg slots.
Vladimir Markofd36f1f2016-08-03 18:49:58 +010096 * Reserves FRAME_SIZE_SAVE_REFS_ONLY + ARG_SLOT_SIZE bytes on the stack
buzbee5bc5a7b2012-03-07 15:52:59 -080097 */
Vladimir Markofd36f1f2016-08-03 18:49:58 +010098.macro SETUP_SAVE_REFS_ONLY_FRAME
Douglas Leung735b8552014-10-31 12:21:40 -070099 addiu $sp, $sp, -48
100 .cfi_adjust_cfa_offset 48
Andreas Gampe5c1e4352014-04-21 19:28:24 -0700101
102 // Ugly compile-time check, but we only have the preprocessor.
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100103#if (FRAME_SIZE_SAVE_REFS_ONLY != 48)
104#error "FRAME_SIZE_SAVE_REFS_ONLY(MIPS) size not as expected."
Andreas Gampe5c1e4352014-04-21 19:28:24 -0700105#endif
106
Douglas Leung735b8552014-10-31 12:21:40 -0700107 sw $ra, 44($sp)
108 .cfi_rel_offset 31, 44
109 sw $s8, 40($sp)
110 .cfi_rel_offset 30, 40
111 sw $gp, 36($sp)
112 .cfi_rel_offset 28, 36
113 sw $s7, 32($sp)
114 .cfi_rel_offset 23, 32
115 sw $s6, 28($sp)
116 .cfi_rel_offset 22, 28
117 sw $s5, 24($sp)
118 .cfi_rel_offset 21, 24
119 sw $s4, 20($sp)
120 .cfi_rel_offset 20, 20
121 sw $s3, 16($sp)
122 .cfi_rel_offset 19, 16
123 sw $s2, 12($sp)
124 .cfi_rel_offset 18, 12
125 # 2 words for alignment and bottom word will hold Method*
Ian Rogers1d8cdbc2014-09-22 22:51:09 -0700126
Douglas Leung4af77b72014-10-22 16:32:28 -0700127 lw $t0, %got(_ZN3art7Runtime9instance_E)($gp)
128 lw $t0, 0($t0)
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100129 lw $t0, RUNTIME_SAVE_REFS_ONLY_METHOD_OFFSET($t0)
Ian Rogers1d8cdbc2014-09-22 22:51:09 -0700130 sw $t0, 0($sp) # Place Method* at bottom of stack.
131 sw $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF) # Place sp in Thread::Current()->top_quick_frame.
Douglas Leung735b8552014-10-31 12:21:40 -0700132 addiu $sp, $sp, -ARG_SLOT_SIZE # reserve argument slots on the stack
133 .cfi_adjust_cfa_offset ARG_SLOT_SIZE
buzbee5bc5a7b2012-03-07 15:52:59 -0800134.endm
135
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100136.macro RESTORE_SAVE_REFS_ONLY_FRAME
Douglas Leung735b8552014-10-31 12:21:40 -0700137 addiu $sp, $sp, ARG_SLOT_SIZE # remove argument slots on the stack
138 .cfi_adjust_cfa_offset -ARG_SLOT_SIZE
139 lw $ra, 44($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800140 .cfi_restore 31
Douglas Leung735b8552014-10-31 12:21:40 -0700141 lw $s8, 40($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800142 .cfi_restore 30
Douglas Leung735b8552014-10-31 12:21:40 -0700143 lw $gp, 36($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800144 .cfi_restore 28
Douglas Leung735b8552014-10-31 12:21:40 -0700145 lw $s7, 32($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800146 .cfi_restore 23
Douglas Leung735b8552014-10-31 12:21:40 -0700147 lw $s6, 28($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800148 .cfi_restore 22
Douglas Leung735b8552014-10-31 12:21:40 -0700149 lw $s5, 24($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800150 .cfi_restore 21
Douglas Leung735b8552014-10-31 12:21:40 -0700151 lw $s4, 20($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800152 .cfi_restore 20
Douglas Leung735b8552014-10-31 12:21:40 -0700153 lw $s3, 16($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800154 .cfi_restore 19
Douglas Leung735b8552014-10-31 12:21:40 -0700155 lw $s2, 12($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800156 .cfi_restore 18
Douglas Leung735b8552014-10-31 12:21:40 -0700157 addiu $sp, $sp, 48
158 .cfi_adjust_cfa_offset -48
buzbee5bc5a7b2012-03-07 15:52:59 -0800159.endm
160
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100161.macro RESTORE_SAVE_REFS_ONLY_FRAME_AND_RETURN
162 RESTORE_SAVE_REFS_ONLY_FRAME
Andreas Gampe8d365912015-01-13 11:32:32 -0800163 jalr $zero, $ra
Douglas Leung735b8552014-10-31 12:21:40 -0700164 nop
buzbee5bc5a7b2012-03-07 15:52:59 -0800165.endm
166
167 /*
168 * Macro that sets up the callee save frame to conform with
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100169 * Runtime::CreateCalleeSaveMethod(kSaveRefsAndArgs).
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800170 * callee-save: $a1-$a3, $t0-$t1, $s2-$s8, $gp, $ra, $f8-$f19
171 * (26 total + 1 word padding + method*)
buzbee5bc5a7b2012-03-07 15:52:59 -0800172 */
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100173.macro SETUP_SAVE_REFS_AND_ARGS_FRAME_REGISTERS_ONLY
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800174 addiu $sp, $sp, -112
175 .cfi_adjust_cfa_offset 112
Andreas Gampe5c1e4352014-04-21 19:28:24 -0700176
177 // Ugly compile-time check, but we only have the preprocessor.
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800178#if (FRAME_SIZE_SAVE_REFS_AND_ARGS != 112)
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100179#error "FRAME_SIZE_SAVE_REFS_AND_ARGS(MIPS) size not as expected."
Andreas Gampe5c1e4352014-04-21 19:28:24 -0700180#endif
181
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800182 sw $ra, 108($sp)
183 .cfi_rel_offset 31, 108
184 sw $s8, 104($sp)
185 .cfi_rel_offset 30, 104
186 sw $gp, 100($sp)
187 .cfi_rel_offset 28, 100
188 sw $s7, 96($sp)
189 .cfi_rel_offset 23, 96
190 sw $s6, 92($sp)
191 .cfi_rel_offset 22, 92
192 sw $s5, 88($sp)
193 .cfi_rel_offset 21, 88
194 sw $s4, 84($sp)
195 .cfi_rel_offset 20, 84
196 sw $s3, 80($sp)
197 .cfi_rel_offset 19, 80
198 sw $s2, 76($sp)
199 .cfi_rel_offset 18, 76
200 sw $t1, 72($sp)
201 .cfi_rel_offset 9, 72
202 sw $t0, 68($sp)
203 .cfi_rel_offset 8, 68
204 sw $a3, 64($sp)
205 .cfi_rel_offset 7, 64
206 sw $a2, 60($sp)
207 .cfi_rel_offset 6, 60
208 sw $a1, 56($sp)
209 .cfi_rel_offset 5, 56
210 SDu $f18, $f19, 48, $sp, $t8
211 SDu $f16, $f17, 40, $sp, $t8
212 SDu $f14, $f15, 32, $sp, $t8
213 SDu $f12, $f13, 24, $sp, $t8
214 SDu $f10, $f11, 16, $sp, $t8
215 SDu $f8, $f9, 8, $sp, $t8
jeffhaofa147e22012-10-12 17:03:32 -0700216 # bottom will hold Method*
Douglas Leung735b8552014-10-31 12:21:40 -0700217.endm
Ian Rogers1d8cdbc2014-09-22 22:51:09 -0700218
Douglas Leung735b8552014-10-31 12:21:40 -0700219 /*
220 * Macro that sets up the callee save frame to conform with
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100221 * Runtime::CreateCalleeSaveMethod(kSaveRefsAndArgs). Restoration assumes non-moving GC.
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800222 * callee-save: $a1-$a3, $t0-$t1, $s2-$s8, $gp, $ra, $f8-$f19
223 * (26 total + 1 word padding + method*)
Douglas Leung735b8552014-10-31 12:21:40 -0700224 * Clobbers $t0 and $sp
225 * Allocates ARG_SLOT_SIZE bytes at the bottom of the stack for arg slots.
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100226 * Reserves FRAME_SIZE_SAVE_REFS_AND_ARGS + ARG_SLOT_SIZE bytes on the stack
Douglas Leung735b8552014-10-31 12:21:40 -0700227 */
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100228.macro SETUP_SAVE_REFS_AND_ARGS_FRAME
229 SETUP_SAVE_REFS_AND_ARGS_FRAME_REGISTERS_ONLY
Douglas Leung4af77b72014-10-22 16:32:28 -0700230 lw $t0, %got(_ZN3art7Runtime9instance_E)($gp)
231 lw $t0, 0($t0)
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100232 lw $t0, RUNTIME_SAVE_REFS_AND_ARGS_METHOD_OFFSET($t0)
Ian Rogers1d8cdbc2014-09-22 22:51:09 -0700233 sw $t0, 0($sp) # Place Method* at bottom of stack.
234 sw $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF) # Place sp in Thread::Current()->top_quick_frame.
Douglas Leung735b8552014-10-31 12:21:40 -0700235 addiu $sp, $sp, -ARG_SLOT_SIZE # reserve argument slots on the stack
236 .cfi_adjust_cfa_offset ARG_SLOT_SIZE
237.endm
238
239 /*
240 * Macro that sets up the callee save frame to conform with
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100241 * Runtime::CreateCalleeSaveMethod(kSaveRefsAndArgs). Restoration assumes non-moving GC.
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800242 * callee-save: $a1-$a3, $t0-$t1, $s2-$s8, $gp, $ra, $f8-$f19
243 * (26 total + 1 word padding + method*)
Douglas Leung735b8552014-10-31 12:21:40 -0700244 * Clobbers $sp
245 * Use $a0 as the Method* and loads it into bottom of stack.
246 * Allocates ARG_SLOT_SIZE bytes at the bottom of the stack for arg slots.
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100247 * Reserves FRAME_SIZE_SAVE_REFS_AND_ARGS + ARG_SLOT_SIZE bytes on the stack
Douglas Leung735b8552014-10-31 12:21:40 -0700248 */
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100249.macro SETUP_SAVE_REFS_AND_ARGS_FRAME_WITH_METHOD_IN_A0
250 SETUP_SAVE_REFS_AND_ARGS_FRAME_REGISTERS_ONLY
Douglas Leung735b8552014-10-31 12:21:40 -0700251 sw $a0, 0($sp) # Place Method* at bottom of stack.
252 sw $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF) # Place sp in Thread::Current()->top_quick_frame.
253 addiu $sp, $sp, -ARG_SLOT_SIZE # reserve argument slots on the stack
254 .cfi_adjust_cfa_offset ARG_SLOT_SIZE
buzbee5bc5a7b2012-03-07 15:52:59 -0800255.endm
256
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100257.macro RESTORE_SAVE_REFS_AND_ARGS_FRAME
Douglas Leung735b8552014-10-31 12:21:40 -0700258 addiu $sp, $sp, ARG_SLOT_SIZE # remove argument slots on the stack
259 .cfi_adjust_cfa_offset -ARG_SLOT_SIZE
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800260 lw $ra, 108($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800261 .cfi_restore 31
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800262 lw $s8, 104($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800263 .cfi_restore 30
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800264 lw $gp, 100($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800265 .cfi_restore 28
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800266 lw $s7, 96($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800267 .cfi_restore 23
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800268 lw $s6, 92($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800269 .cfi_restore 22
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800270 lw $s5, 88($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800271 .cfi_restore 21
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800272 lw $s4, 84($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800273 .cfi_restore 20
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800274 lw $s3, 80($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800275 .cfi_restore 19
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800276 lw $s2, 76($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800277 .cfi_restore 18
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800278 lw $t1, 72($sp)
279 .cfi_restore 9
280 lw $t0, 68($sp)
281 .cfi_restore 8
282 lw $a3, 64($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800283 .cfi_restore 7
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800284 lw $a2, 60($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800285 .cfi_restore 6
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800286 lw $a1, 56($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -0800287 .cfi_restore 5
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800288 LDu $f18, $f19, 48, $sp, $t8
289 LDu $f16, $f17, 40, $sp, $t8
290 LDu $f14, $f15, 32, $sp, $t8
291 LDu $f12, $f13, 24, $sp, $t8
292 LDu $f10, $f11, 16, $sp, $t8
293 LDu $f8, $f9, 8, $sp, $t8
294 addiu $sp, $sp, 112 # pop frame
295 .cfi_adjust_cfa_offset -112
buzbee5bc5a7b2012-03-07 15:52:59 -0800296.endm
297
298 /*
Vladimir Marko952dbb12016-07-28 12:01:51 +0100299 * Macro that sets up the callee save frame to conform with
300 * Runtime::CreateCalleeSaveMethod(kSaveEverything).
Vladimir Marko3b7537b2016-09-13 11:56:01 +0000301 * when the $sp has already been decremented by FRAME_SIZE_SAVE_EVERYTHING.
Vladimir Marko952dbb12016-07-28 12:01:51 +0100302 * Callee-save: $at, $v0-$v1, $a0-$a3, $t0-$t7, $s0-$s7, $t8-$t9, $gp, $fp $ra, $f0-$f31;
303 * 28(GPR)+ 32(FPR) + 3 words for padding and 1 word for Method*
304 * Clobbers $t0 and $t1.
305 * Allocates ARG_SLOT_SIZE bytes at the bottom of the stack for arg slots.
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100306 * Reserves FRAME_SIZE_SAVE_EVERYTHING + ARG_SLOT_SIZE bytes on the stack.
Vladimir Marko952dbb12016-07-28 12:01:51 +0100307 * This macro sets up $gp; entrypoints using it should start with ENTRY_NO_GP.
308 */
Vladimir Marko3b7537b2016-09-13 11:56:01 +0000309.macro SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP
Vladimir Marko952dbb12016-07-28 12:01:51 +0100310 // Ugly compile-time check, but we only have the preprocessor.
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100311#if (FRAME_SIZE_SAVE_EVERYTHING != 256)
312#error "FRAME_SIZE_SAVE_EVERYTHING(MIPS) size not as expected."
Vladimir Marko952dbb12016-07-28 12:01:51 +0100313#endif
314
315 sw $ra, 252($sp)
316 .cfi_rel_offset 31, 252
317 sw $fp, 248($sp)
318 .cfi_rel_offset 30, 248
319 sw $gp, 244($sp)
320 .cfi_rel_offset 28, 244
321 sw $t9, 240($sp)
322 .cfi_rel_offset 25, 240
323 sw $t8, 236($sp)
324 .cfi_rel_offset 24, 236
325 sw $s7, 232($sp)
326 .cfi_rel_offset 23, 232
327 sw $s6, 228($sp)
328 .cfi_rel_offset 22, 228
329 sw $s5, 224($sp)
330 .cfi_rel_offset 21, 224
331 sw $s4, 220($sp)
332 .cfi_rel_offset 20, 220
333 sw $s3, 216($sp)
334 .cfi_rel_offset 19, 216
335 sw $s2, 212($sp)
336 .cfi_rel_offset 18, 212
337 sw $s1, 208($sp)
338 .cfi_rel_offset 17, 208
339 sw $s0, 204($sp)
340 .cfi_rel_offset 16, 204
341 sw $t7, 200($sp)
342 .cfi_rel_offset 15, 200
343 sw $t6, 196($sp)
344 .cfi_rel_offset 14, 196
345 sw $t5, 192($sp)
346 .cfi_rel_offset 13, 192
347 sw $t4, 188($sp)
348 .cfi_rel_offset 12, 188
349 sw $t3, 184($sp)
350 .cfi_rel_offset 11, 184
351 sw $t2, 180($sp)
352 .cfi_rel_offset 10, 180
353 sw $t1, 176($sp)
354 .cfi_rel_offset 9, 176
355 sw $t0, 172($sp)
356 .cfi_rel_offset 8, 172
357 sw $a3, 168($sp)
358 .cfi_rel_offset 7, 168
359 sw $a2, 164($sp)
360 .cfi_rel_offset 6, 164
361 sw $a1, 160($sp)
362 .cfi_rel_offset 5, 160
363 sw $a0, 156($sp)
364 .cfi_rel_offset 4, 156
365 sw $v1, 152($sp)
366 .cfi_rel_offset 3, 152
367 sw $v0, 148($sp)
368 .cfi_rel_offset 2, 148
369
370 // Set up $gp, clobbering $ra and using the branch delay slot for a useful instruction.
371 bal 1f
Goran Jakovljevic2e42cf12016-08-09 15:15:39 +0200372 .set push
373 .set noat
Vladimir Marko952dbb12016-07-28 12:01:51 +0100374 sw $at, 144($sp)
375 .cfi_rel_offset 1, 144
Goran Jakovljevic2e42cf12016-08-09 15:15:39 +0200376 .set pop
Vladimir Marko952dbb12016-07-28 12:01:51 +01003771:
378 .cpload $ra
379
380 SDu $f30, $f31, 136, $sp, $t1
381 SDu $f28, $f29, 128, $sp, $t1
382 SDu $f26, $f27, 120, $sp, $t1
383 SDu $f24, $f25, 112, $sp, $t1
384 SDu $f22, $f23, 104, $sp, $t1
385 SDu $f20, $f21, 96, $sp, $t1
386 SDu $f18, $f19, 88, $sp, $t1
387 SDu $f16, $f17, 80, $sp, $t1
388 SDu $f14, $f15, 72, $sp, $t1
389 SDu $f12, $f13, 64, $sp, $t1
390 SDu $f10, $f11, 56, $sp, $t1
391 SDu $f8, $f9, 48, $sp, $t1
392 SDu $f6, $f7, 40, $sp, $t1
393 SDu $f4, $f5, 32, $sp, $t1
394 SDu $f2, $f3, 24, $sp, $t1
395 SDu $f0, $f1, 16, $sp, $t1
396
397 # 3 words padding and 1 word for holding Method*
398
399 lw $t0, %got(_ZN3art7Runtime9instance_E)($gp)
400 lw $t0, 0($t0)
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100401 lw $t0, RUNTIME_SAVE_EVERYTHING_METHOD_OFFSET($t0)
Vladimir Marko952dbb12016-07-28 12:01:51 +0100402 sw $t0, 0($sp) # Place Method* at bottom of stack.
403 sw $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF) # Place sp in Thread::Current()->top_quick_frame.
404 addiu $sp, $sp, -ARG_SLOT_SIZE # reserve argument slots on the stack
405 .cfi_adjust_cfa_offset ARG_SLOT_SIZE
406.endm
407
Vladimir Marko3b7537b2016-09-13 11:56:01 +0000408 /*
409 * Macro that sets up the callee save frame to conform with
410 * Runtime::CreateCalleeSaveMethod(kSaveEverything).
411 * Callee-save: $at, $v0-$v1, $a0-$a3, $t0-$t7, $s0-$s7, $t8-$t9, $gp, $fp $ra, $f0-$f31;
412 * 28(GPR)+ 32(FPR) + 3 words for padding and 1 word for Method*
413 * Clobbers $t0 and $t1.
414 * Allocates ARG_SLOT_SIZE bytes at the bottom of the stack for arg slots.
415 * Reserves FRAME_SIZE_SAVE_EVERYTHING + ARG_SLOT_SIZE bytes on the stack.
416 * This macro sets up $gp; entrypoints using it should start with ENTRY_NO_GP.
417 */
418.macro SETUP_SAVE_EVERYTHING_FRAME
419 addiu $sp, $sp, -(FRAME_SIZE_SAVE_EVERYTHING)
420 .cfi_adjust_cfa_offset (FRAME_SIZE_SAVE_EVERYTHING)
421 SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP
422.endm
423
Alexey Frunzec61c0762017-04-10 13:54:23 -0700424.macro RESTORE_SAVE_EVERYTHING_FRAME restore_a0=1
Vladimir Marko952dbb12016-07-28 12:01:51 +0100425 addiu $sp, $sp, ARG_SLOT_SIZE # remove argument slots on the stack
426 .cfi_adjust_cfa_offset -ARG_SLOT_SIZE
427
428 LDu $f30, $f31, 136, $sp, $t1
429 LDu $f28, $f29, 128, $sp, $t1
430 LDu $f26, $f27, 120, $sp, $t1
431 LDu $f24, $f25, 112, $sp, $t1
432 LDu $f22, $f23, 104, $sp, $t1
433 LDu $f20, $f21, 96, $sp, $t1
434 LDu $f18, $f19, 88, $sp, $t1
435 LDu $f16, $f17, 80, $sp, $t1
436 LDu $f14, $f15, 72, $sp, $t1
437 LDu $f12, $f13, 64, $sp, $t1
438 LDu $f10, $f11, 56, $sp, $t1
439 LDu $f8, $f9, 48, $sp, $t1
440 LDu $f6, $f7, 40, $sp, $t1
441 LDu $f4, $f5, 32, $sp, $t1
442 LDu $f2, $f3, 24, $sp, $t1
443 LDu $f0, $f1, 16, $sp, $t1
444
445 lw $ra, 252($sp)
446 .cfi_restore 31
447 lw $fp, 248($sp)
448 .cfi_restore 30
449 lw $gp, 244($sp)
450 .cfi_restore 28
451 lw $t9, 240($sp)
452 .cfi_restore 25
453 lw $t8, 236($sp)
454 .cfi_restore 24
455 lw $s7, 232($sp)
456 .cfi_restore 23
457 lw $s6, 228($sp)
458 .cfi_restore 22
459 lw $s5, 224($sp)
460 .cfi_restore 21
461 lw $s4, 220($sp)
462 .cfi_restore 20
463 lw $s3, 216($sp)
464 .cfi_restore 19
465 lw $s2, 212($sp)
466 .cfi_restore 18
467 lw $s1, 208($sp)
468 .cfi_restore 17
469 lw $s0, 204($sp)
470 .cfi_restore 16
471 lw $t7, 200($sp)
472 .cfi_restore 15
473 lw $t6, 196($sp)
474 .cfi_restore 14
475 lw $t5, 192($sp)
476 .cfi_restore 13
477 lw $t4, 188($sp)
478 .cfi_restore 12
479 lw $t3, 184($sp)
480 .cfi_restore 11
481 lw $t2, 180($sp)
482 .cfi_restore 10
483 lw $t1, 176($sp)
484 .cfi_restore 9
485 lw $t0, 172($sp)
486 .cfi_restore 8
487 lw $a3, 168($sp)
488 .cfi_restore 7
489 lw $a2, 164($sp)
490 .cfi_restore 6
491 lw $a1, 160($sp)
492 .cfi_restore 5
Alexey Frunzec61c0762017-04-10 13:54:23 -0700493 .if \restore_a0
Vladimir Marko952dbb12016-07-28 12:01:51 +0100494 lw $a0, 156($sp)
495 .cfi_restore 4
Alexey Frunzec61c0762017-04-10 13:54:23 -0700496 .endif
Vladimir Marko952dbb12016-07-28 12:01:51 +0100497 lw $v1, 152($sp)
498 .cfi_restore 3
499 lw $v0, 148($sp)
500 .cfi_restore 2
Goran Jakovljevic2e42cf12016-08-09 15:15:39 +0200501 .set push
502 .set noat
Vladimir Marko952dbb12016-07-28 12:01:51 +0100503 lw $at, 144($sp)
504 .cfi_restore 1
Goran Jakovljevic2e42cf12016-08-09 15:15:39 +0200505 .set pop
Vladimir Marko952dbb12016-07-28 12:01:51 +0100506
507 addiu $sp, $sp, 256 # pop frame
508 .cfi_adjust_cfa_offset -256
509.endm
510
511 /*
Alexey Frunzec61c0762017-04-10 13:54:23 -0700512 * Macro that calls through to artDeliverPendingExceptionFromCode, where the pending
513 * exception is Thread::Current()->exception_ when the runtime method frame is ready.
514 * Requires $gp properly set up.
buzbee5bc5a7b2012-03-07 15:52:59 -0800515 */
Alexey Frunzec61c0762017-04-10 13:54:23 -0700516.macro DELIVER_PENDING_EXCEPTION_FRAME_READY
jeffhao8161c032012-10-31 15:50:00 -0700517 la $t9, artDeliverPendingExceptionFromCode
Andreas Gampe8d365912015-01-13 11:32:32 -0800518 jalr $zero, $t9 # artDeliverPendingExceptionFromCode(Thread*)
Ian Rogers1d8cdbc2014-09-22 22:51:09 -0700519 move $a0, rSELF # pass Thread::Current
buzbee5bc5a7b2012-03-07 15:52:59 -0800520.endm
521
Alexey Frunzec61c0762017-04-10 13:54:23 -0700522 /*
523 * Macro that calls through to artDeliverPendingExceptionFromCode, where the pending
524 * exception is Thread::Current()->exception_.
525 * Requires $gp properly set up.
526 */
527.macro DELIVER_PENDING_EXCEPTION
528 SETUP_SAVE_ALL_CALLEE_SAVES_FRAME # save callee saves for throw
529 DELIVER_PENDING_EXCEPTION_FRAME_READY
530.endm
531
buzbee5bc5a7b2012-03-07 15:52:59 -0800532.macro RETURN_IF_NO_EXCEPTION
jeffhao7fbee072012-08-24 17:56:54 -0700533 lw $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100534 RESTORE_SAVE_REFS_ONLY_FRAME
jeffhao8161c032012-10-31 15:50:00 -0700535 bnez $t0, 1f # success if no exception is pending
buzbee5bc5a7b2012-03-07 15:52:59 -0800536 nop
Andreas Gampe8d365912015-01-13 11:32:32 -0800537 jalr $zero, $ra
buzbee5bc5a7b2012-03-07 15:52:59 -0800538 nop
5391:
540 DELIVER_PENDING_EXCEPTION
541.endm
542
543.macro RETURN_IF_ZERO
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100544 RESTORE_SAVE_REFS_ONLY_FRAME
jeffhao7fbee072012-08-24 17:56:54 -0700545 bnez $v0, 1f # success?
buzbee5bc5a7b2012-03-07 15:52:59 -0800546 nop
Andreas Gampe8d365912015-01-13 11:32:32 -0800547 jalr $zero, $ra # return on success
buzbee5bc5a7b2012-03-07 15:52:59 -0800548 nop
5491:
550 DELIVER_PENDING_EXCEPTION
551.endm
552
Andreas Gampe1cc7dba2014-12-17 18:43:01 -0800553.macro RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100554 RESTORE_SAVE_REFS_ONLY_FRAME
jeffhao7fbee072012-08-24 17:56:54 -0700555 beqz $v0, 1f # success?
buzbee5bc5a7b2012-03-07 15:52:59 -0800556 nop
Andreas Gampe8d365912015-01-13 11:32:32 -0800557 jalr $zero, $ra # return on success
buzbee5bc5a7b2012-03-07 15:52:59 -0800558 nop
5591:
560 DELIVER_PENDING_EXCEPTION
561.endm
562
buzbee5bc5a7b2012-03-07 15:52:59 -0800563 /*
Goran Jakovljevic3bc13812016-03-22 17:16:05 +0100564 * On stack replacement stub.
565 * On entry:
566 * a0 = stack to copy
567 * a1 = size of stack
568 * a2 = pc to call
569 * a3 = JValue* result
570 * [sp + 16] = shorty
571 * [sp + 20] = thread
572 */
573ENTRY art_quick_osr_stub
574 // Save callee general purpose registers, RA and GP.
575 addiu $sp, $sp, -48
576 .cfi_adjust_cfa_offset 48
577 sw $ra, 44($sp)
578 .cfi_rel_offset 31, 44
579 sw $s8, 40($sp)
580 .cfi_rel_offset 30, 40
581 sw $gp, 36($sp)
582 .cfi_rel_offset 28, 36
583 sw $s7, 32($sp)
584 .cfi_rel_offset 23, 32
585 sw $s6, 28($sp)
586 .cfi_rel_offset 22, 28
587 sw $s5, 24($sp)
588 .cfi_rel_offset 21, 24
589 sw $s4, 20($sp)
590 .cfi_rel_offset 20, 20
591 sw $s3, 16($sp)
592 .cfi_rel_offset 19, 16
593 sw $s2, 12($sp)
594 .cfi_rel_offset 18, 12
595 sw $s1, 8($sp)
596 .cfi_rel_offset 17, 8
597 sw $s0, 4($sp)
598 .cfi_rel_offset 16, 4
599
600 move $s8, $sp # Save the stack pointer
601 move $s7, $a1 # Save size of stack
602 move $s6, $a2 # Save the pc to call
603 lw rSELF, 48+20($sp) # Save managed thread pointer into rSELF
604 addiu $t0, $sp, -12 # Reserve space for stack pointer,
605 # JValue* result, and ArtMethod* slot.
606 srl $t0, $t0, 4 # Align stack pointer to 16 bytes
607 sll $sp, $t0, 4 # Update stack pointer
608 sw $s8, 4($sp) # Save old stack pointer
609 sw $a3, 8($sp) # Save JValue* result
610 sw $zero, 0($sp) # Store null for ArtMethod* at bottom of frame
611 subu $sp, $a1 # Reserve space for callee stack
612 move $a2, $a1
613 move $a1, $a0
614 move $a0, $sp
615 la $t9, memcpy
616 jalr $t9 # memcpy (dest a0, src a1, bytes a2)
617 addiu $sp, $sp, -16 # make space for argument slots for memcpy
618 bal .Losr_entry # Call the method
619 addiu $sp, $sp, 16 # restore stack after memcpy
620 lw $a2, 8($sp) # Restore JValue* result
621 lw $sp, 4($sp) # Restore saved stack pointer
622 lw $a0, 48+16($sp) # load shorty
623 lbu $a0, 0($a0) # load return type
624 li $a1, 'D' # put char 'D' into a1
625 beq $a0, $a1, .Losr_fp_result # Test if result type char == 'D'
626 li $a1, 'F' # put char 'F' into a1
627 beq $a0, $a1, .Losr_fp_result # Test if result type char == 'F'
628 nop
629 sw $v0, 0($a2)
630 b .Losr_exit
631 sw $v1, 4($a2) # store v0/v1 into result
632.Losr_fp_result:
633 SDu $f0, $f1, 0, $a2, $t0 # store f0/f1 into result
634.Losr_exit:
635 lw $ra, 44($sp)
636 .cfi_restore 31
637 lw $s8, 40($sp)
638 .cfi_restore 30
639 lw $gp, 36($sp)
640 .cfi_restore 28
641 lw $s7, 32($sp)
642 .cfi_restore 23
643 lw $s6, 28($sp)
644 .cfi_restore 22
645 lw $s5, 24($sp)
646 .cfi_restore 21
647 lw $s4, 20($sp)
648 .cfi_restore 20
649 lw $s3, 16($sp)
650 .cfi_restore 19
651 lw $s2, 12($sp)
652 .cfi_restore 18
653 lw $s1, 8($sp)
654 .cfi_restore 17
655 lw $s0, 4($sp)
656 .cfi_restore 16
657 jalr $zero, $ra
658 addiu $sp, $sp, 48
659 .cfi_adjust_cfa_offset -48
660.Losr_entry:
661 addiu $s7, $s7, -4
662 addu $t0, $s7, $sp
663 move $t9, $s6
664 jalr $zero, $t9
665 sw $ra, 0($t0) # Store RA per the compiler ABI
666END art_quick_osr_stub
667
668 /*
jeffhao7fbee072012-08-24 17:56:54 -0700669 * On entry $a0 is uint32_t* gprs_ and $a1 is uint32_t* fprs_
buzbee5bc5a7b2012-03-07 15:52:59 -0800670 * FIXME: just guessing about the shape of the jmpbuf. Where will pc be?
671 */
Jeff Haod4c3f7d2013-02-14 14:14:44 -0800672ENTRY art_quick_do_long_jump
Duane Sande34652f2014-11-04 11:09:36 -0800673 LDu $f0, $f1, 0*8, $a1, $t1
674 LDu $f2, $f3, 1*8, $a1, $t1
675 LDu $f4, $f5, 2*8, $a1, $t1
676 LDu $f6, $f7, 3*8, $a1, $t1
677 LDu $f8, $f9, 4*8, $a1, $t1
678 LDu $f10, $f11, 5*8, $a1, $t1
679 LDu $f12, $f13, 6*8, $a1, $t1
680 LDu $f14, $f15, 7*8, $a1, $t1
681 LDu $f16, $f17, 8*8, $a1, $t1
682 LDu $f18, $f19, 9*8, $a1, $t1
683 LDu $f20, $f21, 10*8, $a1, $t1
684 LDu $f22, $f23, 11*8, $a1, $t1
685 LDu $f24, $f25, 12*8, $a1, $t1
686 LDu $f26, $f27, 13*8, $a1, $t1
687 LDu $f28, $f29, 14*8, $a1, $t1
688 LDu $f30, $f31, 15*8, $a1, $t1
689
Chris Dearman748dd952014-05-23 10:47:01 -0700690 .set push
691 .set nomacro
692 .set noat
jeffhao7fbee072012-08-24 17:56:54 -0700693 lw $at, 4($a0)
Chris Dearman748dd952014-05-23 10:47:01 -0700694 .set pop
jeffhao7fbee072012-08-24 17:56:54 -0700695 lw $v0, 8($a0)
696 lw $v1, 12($a0)
697 lw $a1, 20($a0)
698 lw $a2, 24($a0)
699 lw $a3, 28($a0)
700 lw $t0, 32($a0)
701 lw $t1, 36($a0)
702 lw $t2, 40($a0)
703 lw $t3, 44($a0)
704 lw $t4, 48($a0)
705 lw $t5, 52($a0)
706 lw $t6, 56($a0)
707 lw $t7, 60($a0)
708 lw $s0, 64($a0)
709 lw $s1, 68($a0)
710 lw $s2, 72($a0)
711 lw $s3, 76($a0)
712 lw $s4, 80($a0)
713 lw $s5, 84($a0)
714 lw $s6, 88($a0)
715 lw $s7, 92($a0)
716 lw $t8, 96($a0)
717 lw $t9, 100($a0)
jeffhao7fbee072012-08-24 17:56:54 -0700718 lw $gp, 112($a0)
719 lw $sp, 116($a0)
720 lw $fp, 120($a0)
721 lw $ra, 124($a0)
722 lw $a0, 16($a0)
Goran Jakovljevic590b1362016-03-21 14:24:43 +0100723 move $v0, $zero # clear result registers v0 and v1 (in branch delay slot)
Goran Jakovljevic75969962015-10-27 12:29:07 +0100724 jalr $zero, $t9 # do long jump
jeffhao7fbee072012-08-24 17:56:54 -0700725 move $v1, $zero
Jeff Haod4c3f7d2013-02-14 14:14:44 -0800726END art_quick_do_long_jump
buzbee5bc5a7b2012-03-07 15:52:59 -0800727
buzbee5bc5a7b2012-03-07 15:52:59 -0800728 /*
729 * Called by managed code, saves most registers (forms basis of long jump context) and passes
730 * the bottom of the stack. artDeliverExceptionFromCode will place the callee save Method* at
Lazar Trsic84bc06e2015-06-10 16:05:46 +0200731 * the bottom of the thread. On entry a0 holds Throwable*
buzbee5bc5a7b2012-03-07 15:52:59 -0800732 */
Ian Rogers468532e2013-08-05 10:56:33 -0700733ENTRY art_quick_deliver_exception
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100734 SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
jeffhao8161c032012-10-31 15:50:00 -0700735 la $t9, artDeliverExceptionFromCode
Andreas Gampe8d365912015-01-13 11:32:32 -0800736 jalr $zero, $t9 # artDeliverExceptionFromCode(Throwable*, Thread*)
Ian Rogers1d8cdbc2014-09-22 22:51:09 -0700737 move $a1, rSELF # pass Thread::Current
Ian Rogers468532e2013-08-05 10:56:33 -0700738END art_quick_deliver_exception
buzbee5bc5a7b2012-03-07 15:52:59 -0800739
buzbee5bc5a7b2012-03-07 15:52:59 -0800740 /*
741 * Called by managed code to create and deliver a NullPointerException
742 */
Jeff Haod4c3f7d2013-02-14 14:14:44 -0800743 .extern artThrowNullPointerExceptionFromCode
Vladimir Marko804b03f2016-09-14 16:26:36 +0100744ENTRY_NO_GP art_quick_throw_null_pointer_exception
745 // Note that setting up $gp does not rely on $t9 here, so branching here directly is OK,
746 // even after clobbering any registers we don't need to preserve, such as $gp or $t0.
747 SETUP_SAVE_EVERYTHING_FRAME
jeffhao8161c032012-10-31 15:50:00 -0700748 la $t9, artThrowNullPointerExceptionFromCode
Andreas Gampe8d365912015-01-13 11:32:32 -0800749 jalr $zero, $t9 # artThrowNullPointerExceptionFromCode(Thread*)
Ian Rogers1d8cdbc2014-09-22 22:51:09 -0700750 move $a0, rSELF # pass Thread::Current
Ian Rogers468532e2013-08-05 10:56:33 -0700751END art_quick_throw_null_pointer_exception
buzbee5bc5a7b2012-03-07 15:52:59 -0800752
Nicolas Geoffraye8e11272016-06-28 18:08:46 +0100753
754 /*
755 * Call installed by a signal handler to create and deliver a NullPointerException.
756 */
757 .extern artThrowNullPointerExceptionFromSignal
Vladimir Marko3b7537b2016-09-13 11:56:01 +0000758ENTRY_NO_GP_CUSTOM_CFA art_quick_throw_null_pointer_exception_from_signal, FRAME_SIZE_SAVE_EVERYTHING
759 SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP
760 # Retrieve the fault address from the padding where the signal handler stores it.
761 lw $a0, (ARG_SLOT_SIZE + __SIZEOF_POINTER__)($sp)
Nicolas Geoffraye8e11272016-06-28 18:08:46 +0100762 la $t9, artThrowNullPointerExceptionFromSignal
763 jalr $zero, $t9 # artThrowNullPointerExceptionFromSignal(uintptr_t, Thread*)
764 move $a1, rSELF # pass Thread::Current
765END art_quick_throw_null_pointer_exception_from_signal
766
buzbee5bc5a7b2012-03-07 15:52:59 -0800767 /*
768 * Called by managed code to create and deliver an ArithmeticException
769 */
Jeff Haod4c3f7d2013-02-14 14:14:44 -0800770 .extern artThrowDivZeroFromCode
Vladimir Marko804b03f2016-09-14 16:26:36 +0100771ENTRY_NO_GP art_quick_throw_div_zero
772 SETUP_SAVE_EVERYTHING_FRAME
jeffhao8161c032012-10-31 15:50:00 -0700773 la $t9, artThrowDivZeroFromCode
Andreas Gampe8d365912015-01-13 11:32:32 -0800774 jalr $zero, $t9 # artThrowDivZeroFromCode(Thread*)
Ian Rogers1d8cdbc2014-09-22 22:51:09 -0700775 move $a0, rSELF # pass Thread::Current
Ian Rogers468532e2013-08-05 10:56:33 -0700776END art_quick_throw_div_zero
buzbee5bc5a7b2012-03-07 15:52:59 -0800777
buzbee5bc5a7b2012-03-07 15:52:59 -0800778 /*
779 * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException
780 */
Jeff Haod4c3f7d2013-02-14 14:14:44 -0800781 .extern artThrowArrayBoundsFromCode
Vladimir Marko804b03f2016-09-14 16:26:36 +0100782ENTRY_NO_GP art_quick_throw_array_bounds
783 // Note that setting up $gp does not rely on $t9 here, so branching here directly is OK,
784 // even after clobbering any registers we don't need to preserve, such as $gp or $t0.
785 SETUP_SAVE_EVERYTHING_FRAME
jeffhao8161c032012-10-31 15:50:00 -0700786 la $t9, artThrowArrayBoundsFromCode
Andreas Gampe8d365912015-01-13 11:32:32 -0800787 jalr $zero, $t9 # artThrowArrayBoundsFromCode(index, limit, Thread*)
Ian Rogers1d8cdbc2014-09-22 22:51:09 -0700788 move $a2, rSELF # pass Thread::Current
Ian Rogers468532e2013-08-05 10:56:33 -0700789END art_quick_throw_array_bounds
buzbee5bc5a7b2012-03-07 15:52:59 -0800790
Ian Rogers57b86d42012-03-27 16:05:41 -0700791 /*
Vladimir Marko87f3fcb2016-04-28 15:52:11 +0100792 * Called by managed code to create and deliver a StringIndexOutOfBoundsException
793 * as if thrown from a call to String.charAt().
794 */
795 .extern artThrowStringBoundsFromCode
Vladimir Marko804b03f2016-09-14 16:26:36 +0100796ENTRY_NO_GP art_quick_throw_string_bounds
797 SETUP_SAVE_EVERYTHING_FRAME
Vladimir Marko87f3fcb2016-04-28 15:52:11 +0100798 la $t9, artThrowStringBoundsFromCode
799 jalr $zero, $t9 # artThrowStringBoundsFromCode(index, limit, Thread*)
800 move $a2, rSELF # pass Thread::Current
801END art_quick_throw_string_bounds
802
803 /*
Ian Rogers57b86d42012-03-27 16:05:41 -0700804 * Called by managed code to create and deliver a StackOverflowError.
805 */
Jeff Haod4c3f7d2013-02-14 14:14:44 -0800806 .extern artThrowStackOverflowFromCode
Ian Rogers468532e2013-08-05 10:56:33 -0700807ENTRY art_quick_throw_stack_overflow
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100808 SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
jeffhao8161c032012-10-31 15:50:00 -0700809 la $t9, artThrowStackOverflowFromCode
Andreas Gampe8d365912015-01-13 11:32:32 -0800810 jalr $zero, $t9 # artThrowStackOverflowFromCode(Thread*)
Ian Rogers1d8cdbc2014-09-22 22:51:09 -0700811 move $a0, rSELF # pass Thread::Current
Ian Rogers468532e2013-08-05 10:56:33 -0700812END art_quick_throw_stack_overflow
buzbee5bc5a7b2012-03-07 15:52:59 -0800813
Ian Rogers57b86d42012-03-27 16:05:41 -0700814 /*
buzbee5bc5a7b2012-03-07 15:52:59 -0800815 * All generated callsites for interface invokes and invocation slow paths will load arguments
jeffhao7fbee072012-08-24 17:56:54 -0700816 * as usual - except instead of loading arg0/$a0 with the target Method*, arg0/$a0 will contain
Nicolas Geoffray7ea6a172015-05-19 18:58:54 +0100817 * the method_idx. This wrapper will save arg1-arg3, and call the appropriate C helper.
jeffhao7fbee072012-08-24 17:56:54 -0700818 * NOTE: "this" is first visable argument of the target, and so can be found in arg1/$a1.
buzbee5bc5a7b2012-03-07 15:52:59 -0800819 *
jeffhao7fbee072012-08-24 17:56:54 -0700820 * The helper will attempt to locate the target and return a 64-bit result in $v0/$v1 consisting
821 * of the target Method* in $v0 and method->code_ in $v1.
buzbee5bc5a7b2012-03-07 15:52:59 -0800822 *
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700823 * If unsuccessful, the helper will return null/null. There will be a pending exception in the
buzbee5bc5a7b2012-03-07 15:52:59 -0800824 * thread and we branch to another stub to deliver it.
825 *
826 * On success this wrapper will restore arguments and *jump* to the target, leaving the lr
827 * pointing back to the original caller.
828 */
Andreas Gampe3031c8d2015-07-13 20:11:06 -0700829.macro INVOKE_TRAMPOLINE_BODY cxx_name
buzbee5bc5a7b2012-03-07 15:52:59 -0800830 .extern \cxx_name
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100831 SETUP_SAVE_REFS_AND_ARGS_FRAME # save callee saves in case allocation triggers GC
Nicolas Geoffray7ea6a172015-05-19 18:58:54 +0100832 move $a2, rSELF # pass Thread::Current
Goran Jakovljevic590b1362016-03-21 14:24:43 +0100833 la $t9, \cxx_name
834 jalr $t9 # (method_idx, this, Thread*, $sp)
Nicolas Geoffray7ea6a172015-05-19 18:58:54 +0100835 addiu $a3, $sp, ARG_SLOT_SIZE # pass $sp (remove arg slots)
836 move $a0, $v0 # save target Method*
Vladimir Markofd36f1f2016-08-03 18:49:58 +0100837 RESTORE_SAVE_REFS_AND_ARGS_FRAME
jeffhaofa147e22012-10-12 17:03:32 -0700838 beqz $v0, 1f
Nicolas Geoffray7ea6a172015-05-19 18:58:54 +0100839 move $t9, $v1 # save $v0->code_
Andreas Gampe8d365912015-01-13 11:32:32 -0800840 jalr $zero, $t9
buzbee5bc5a7b2012-03-07 15:52:59 -0800841 nop
8421:
843 DELIVER_PENDING_EXCEPTION
Andreas Gampe3031c8d2015-07-13 20:11:06 -0700844.endm
845.macro INVOKE_TRAMPOLINE c_name, cxx_name
846ENTRY \c_name
847 INVOKE_TRAMPOLINE_BODY \cxx_name
Jeff Haod4c3f7d2013-02-14 14:14:44 -0800848END \c_name
buzbee5bc5a7b2012-03-07 15:52:59 -0800849.endm
850
Logan Chien8dbb7082013-01-25 20:31:17 +0800851INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck
buzbee5bc5a7b2012-03-07 15:52:59 -0800852
Logan Chien8dbb7082013-01-25 20:31:17 +0800853INVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck
854INVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck
855INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
856INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
buzbee5bc5a7b2012-03-07 15:52:59 -0800857
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800858// Each of the following macros expands into four instructions or 16 bytes.
859// They are used to build indexable "tables" of code.
860
861.macro LOAD_WORD_TO_REG reg, next_arg, index_reg, label
Goran Jakovljevicff734982015-08-24 12:58:55 +0000862 lw $\reg, -4($\next_arg) # next_arg points to argument after the current one (offset is 4)
863 b \label
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800864 addiu $\index_reg, 16
865 .balign 16
Goran Jakovljevicff734982015-08-24 12:58:55 +0000866.endm
867
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800868.macro LOAD_LONG_TO_REG reg1, reg2, next_arg, index_reg, next_index, label
Goran Jakovljevicff734982015-08-24 12:58:55 +0000869 lw $\reg1, -8($\next_arg) # next_arg points to argument after the current one (offset is 8)
870 lw $\reg2, -4($\next_arg)
871 b \label
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800872 li $\index_reg, \next_index
873 .balign 16
Goran Jakovljevicff734982015-08-24 12:58:55 +0000874.endm
875
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800876.macro LOAD_FLOAT_TO_REG reg, next_arg, index_reg, label
Goran Jakovljevicff734982015-08-24 12:58:55 +0000877 lwc1 $\reg, -4($\next_arg) # next_arg points to argument after the current one (offset is 4)
878 b \label
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800879 addiu $\index_reg, 16
880 .balign 16
Goran Jakovljevicff734982015-08-24 12:58:55 +0000881.endm
882
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800883#if defined(__mips_isa_rev) && __mips_isa_rev > 2
884// LDu expands into 3 instructions for 64-bit FPU, so index_reg cannot be updated here.
885.macro LOAD_DOUBLE_TO_REG reg1, reg2, next_arg, index_reg, tmp, label
886 .set reorder # force use of the branch delay slot
Goran Jakovljevicff734982015-08-24 12:58:55 +0000887 LDu $\reg1, $\reg2, -8, $\next_arg, $\tmp # next_arg points to argument after the current one
888 # (offset is 8)
889 b \label
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800890 .set noreorder
891 .balign 16
892.endm
893#else
894// LDu expands into 2 instructions for 32-bit FPU, so index_reg is updated here.
895.macro LOAD_DOUBLE_TO_REG reg1, reg2, next_arg, index_reg, tmp, label
896 LDu $\reg1, $\reg2, -8, $\next_arg, $\tmp # next_arg points to argument after the current one
897 # (offset is 8)
898 b \label
899 addiu $\index_reg, 16
900 .balign 16
901.endm
902#endif
903
904.macro LOAD_END index_reg, next_index, label
905 b \label
906 li $\index_reg, \next_index
907 .balign 16
Goran Jakovljevicff734982015-08-24 12:58:55 +0000908.endm
909
Goran Jakovljevic590b1362016-03-21 14:24:43 +0100910#define SPILL_SIZE 32
911
Jeff Hao79fe5392013-04-24 18:41:58 -0700912 /*
Ian Rogersef7d42f2014-01-06 12:55:46 -0800913 * Invocation stub for quick code.
Jeff Hao5d917302013-02-27 17:57:33 -0800914 * On entry:
915 * a0 = method pointer
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700916 * a1 = argument array or null for no argument methods
Jeff Hao5d917302013-02-27 17:57:33 -0800917 * a2 = size of argument array in bytes
918 * a3 = (managed) thread pointer
Jeff Hao6474d192013-03-26 14:08:09 -0700919 * [sp + 16] = JValue* result
Ian Rogers0177e532014-02-11 16:30:46 -0800920 * [sp + 20] = shorty
Jeff Hao5d917302013-02-27 17:57:33 -0800921 */
922ENTRY art_quick_invoke_stub
Jeff Hao5d917302013-02-27 17:57:33 -0800923 sw $a0, 0($sp) # save out a0
Goran Jakovljevic590b1362016-03-21 14:24:43 +0100924 addiu $sp, $sp, -SPILL_SIZE # spill s0, s1, fp, ra and gp
925 .cfi_adjust_cfa_offset SPILL_SIZE
926 sw $gp, 16($sp)
Jeff Hao5d917302013-02-27 17:57:33 -0800927 sw $ra, 12($sp)
928 .cfi_rel_offset 31, 12
929 sw $fp, 8($sp)
930 .cfi_rel_offset 30, 8
931 sw $s1, 4($sp)
932 .cfi_rel_offset 17, 4
933 sw $s0, 0($sp)
934 .cfi_rel_offset 16, 0
935 move $fp, $sp # save sp in fp
936 .cfi_def_cfa_register 30
937 move $s1, $a3 # move managed thread pointer into s1
938 addiu $s0, $zero, SUSPEND_CHECK_INTERVAL # reset s0 to suspend check interval
Goran Jakovljevicff734982015-08-24 12:58:55 +0000939 addiu $t0, $a2, 4 # create space for ArtMethod* in frame.
Douglas Leung735b8552014-10-31 12:21:40 -0700940 subu $t0, $sp, $t0 # reserve & align *stack* to 16 bytes:
Goran Jakovljevicff734982015-08-24 12:58:55 +0000941 srl $t0, $t0, 4 # native calling convention only aligns to 8B,
942 sll $sp, $t0, 4 # so we have to ensure ART 16B alignment ourselves.
943 addiu $a0, $sp, 4 # pass stack pointer + ArtMethod* as dest for memcpy
Goran Jakovljevic590b1362016-03-21 14:24:43 +0100944 la $t9, memcpy
945 jalr $t9 # (dest, src, bytes)
Jeff Hao5d917302013-02-27 17:57:33 -0800946 addiu $sp, $sp, -16 # make space for argument slots for memcpy
947 addiu $sp, $sp, 16 # restore stack after memcpy
Goran Jakovljevic590b1362016-03-21 14:24:43 +0100948 lw $gp, 16($fp) # restore $gp
949 lw $a0, SPILL_SIZE($fp) # restore ArtMethod*
Goran Jakovljevicff734982015-08-24 12:58:55 +0000950 lw $a1, 4($sp) # a1 = this*
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800951 addiu $t8, $sp, 8 # t8 = pointer to the current argument (skip ArtMethod* and this*)
952 li $t6, 0 # t6 = gpr_index = 0 (corresponds to A2; A0 and A1 are skipped)
953 li $t7, 0 # t7 = fp_index = 0
954 lw $t9, 20 + SPILL_SIZE($fp) # get shorty (20 is offset from the $sp on entry + SPILL_SIZE
Goran Jakovljevic590b1362016-03-21 14:24:43 +0100955 # as the $fp is SPILL_SIZE bytes below the $sp on entry)
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800956 addiu $t9, 1 # t9 = shorty + 1 (skip 1 for return type)
957
958 // Load the base addresses of tabInt ... tabDouble.
959 // We will use the register indices (gpr_index, fp_index) to branch.
960 // Note that the indices are scaled by 16, so they can be added to the bases directly.
961#if defined(__mips_isa_rev) && __mips_isa_rev >= 6
962 lapc $t2, tabInt
963 lapc $t3, tabLong
964 lapc $t4, tabSingle
965 lapc $t5, tabDouble
966#else
967 bltzal $zero, tabBase # nal
968 addiu $t2, $ra, %lo(tabInt - tabBase)
969tabBase:
970 addiu $t3, $ra, %lo(tabLong - tabBase)
971 addiu $t4, $ra, %lo(tabSingle - tabBase)
972 addiu $t5, $ra, %lo(tabDouble - tabBase)
973#endif
974
Goran Jakovljevicff734982015-08-24 12:58:55 +0000975loop:
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800976 lbu $ra, 0($t9) # ra = shorty[i]
977 beqz $ra, loopEnd # finish getting args when shorty[i] == '\0'
978 addiu $t9, 1
Goran Jakovljevicff734982015-08-24 12:58:55 +0000979
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800980 addiu $ra, -'J'
981 beqz $ra, isLong # branch if result type char == 'J'
982 addiu $ra, 'J' - 'D'
983 beqz $ra, isDouble # branch if result type char == 'D'
984 addiu $ra, 'D' - 'F'
985 beqz $ra, isSingle # branch if result type char == 'F'
Goran Jakovljevicff734982015-08-24 12:58:55 +0000986
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800987 addu $ra, $t2, $t6
988 jalr $zero, $ra
989 addiu $t8, 4 # next_arg = curr_arg + 4
Goran Jakovljevicff734982015-08-24 12:58:55 +0000990
991isLong:
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800992 addu $ra, $t3, $t6
993 jalr $zero, $ra
994 addiu $t8, 8 # next_arg = curr_arg + 8
Goran Jakovljevicff734982015-08-24 12:58:55 +0000995
996isSingle:
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800997 addu $ra, $t4, $t7
998 jalr $zero, $ra
999 addiu $t8, 4 # next_arg = curr_arg + 4
1000
1001isDouble:
1002 addu $ra, $t5, $t7
1003#if defined(__mips_isa_rev) && __mips_isa_rev > 2
1004 addiu $t7, 16 # fp_index += 16 didn't fit into LOAD_DOUBLE_TO_REG
1005#endif
1006 jalr $zero, $ra
1007 addiu $t8, 8 # next_arg = curr_arg + 8
Goran Jakovljevicff734982015-08-24 12:58:55 +00001008
1009loopEnd:
Mathieu Chartiere401d142015-04-22 13:56:20 -07001010 lw $t9, ART_METHOD_QUICK_CODE_OFFSET_32($a0) # get pointer to the code
Jeff Hao5d917302013-02-27 17:57:33 -08001011 jalr $t9 # call the method
Goran Jakovljevicff734982015-08-24 12:58:55 +00001012 sw $zero, 0($sp) # store null for ArtMethod* at bottom of frame
Jeff Hao5d917302013-02-27 17:57:33 -08001013 move $sp, $fp # restore the stack
1014 lw $s0, 0($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -08001015 .cfi_restore 16
Jeff Hao5d917302013-02-27 17:57:33 -08001016 lw $s1, 4($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -08001017 .cfi_restore 17
Jeff Hao5d917302013-02-27 17:57:33 -08001018 lw $fp, 8($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -08001019 .cfi_restore 30
Jeff Hao5d917302013-02-27 17:57:33 -08001020 lw $ra, 12($sp)
Dave Allisonbbb32c22013-11-05 18:25:18 -08001021 .cfi_restore 31
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001022 addiu $sp, $sp, SPILL_SIZE
1023 .cfi_adjust_cfa_offset -SPILL_SIZE
Jeff Hao5d917302013-02-27 17:57:33 -08001024 lw $t0, 16($sp) # get result pointer
Ian Rogers0177e532014-02-11 16:30:46 -08001025 lw $t1, 20($sp) # get shorty
1026 lb $t1, 0($t1) # get result type char
Goran Jakovljevicff734982015-08-24 12:58:55 +00001027 li $t2, 'D' # put char 'D' into t2
1028 beq $t1, $t2, 5f # branch if result type char == 'D'
1029 li $t3, 'F' # put char 'F' into t3
1030 beq $t1, $t3, 5f # branch if result type char == 'F'
Jeff Hao5d917302013-02-27 17:57:33 -08001031 sw $v0, 0($t0) # store the result
Andreas Gampe8d365912015-01-13 11:32:32 -08001032 jalr $zero, $ra
Jeff Hao5d917302013-02-27 17:57:33 -08001033 sw $v1, 4($t0) # store the other half of the result
Goran Jakovljevicff734982015-08-24 12:58:55 +000010345:
Duane Sande34652f2014-11-04 11:09:36 -08001035 SDu $f0, $f1, 0, $t0, $t1 # store floating point result
Andreas Gampe8d365912015-01-13 11:32:32 -08001036 jalr $zero, $ra
Duane Sande34652f2014-11-04 11:09:36 -08001037 nop
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001038
1039 // Note that gpr_index is kept within the range of tabInt and tabLong
1040 // and fp_index is kept within the range of tabSingle and tabDouble.
1041 .balign 16
1042tabInt:
1043 LOAD_WORD_TO_REG a2, t8, t6, loop # a2 = current argument, gpr_index += 16
1044 LOAD_WORD_TO_REG a3, t8, t6, loop # a3 = current argument, gpr_index += 16
1045 LOAD_WORD_TO_REG t0, t8, t6, loop # t0 = current argument, gpr_index += 16
1046 LOAD_WORD_TO_REG t1, t8, t6, loop # t1 = current argument, gpr_index += 16
1047 LOAD_END t6, 4*16, loop # no more GPR args, gpr_index = 4*16
1048tabLong:
1049 LOAD_LONG_TO_REG a2, a3, t8, t6, 2*16, loop # a2_a3 = curr_arg, gpr_index = 2*16
1050 LOAD_LONG_TO_REG t0, t1, t8, t6, 4*16, loop # t0_t1 = curr_arg, gpr_index = 4*16
1051 LOAD_LONG_TO_REG t0, t1, t8, t6, 4*16, loop # t0_t1 = curr_arg, gpr_index = 4*16
1052 LOAD_END t6, 4*16, loop # no more GPR args, gpr_index = 4*16
1053 LOAD_END t6, 4*16, loop # no more GPR args, gpr_index = 4*16
1054tabSingle:
1055 LOAD_FLOAT_TO_REG f8, t8, t7, loop # f8 = curr_arg, fp_index += 16
1056 LOAD_FLOAT_TO_REG f10, t8, t7, loop # f10 = curr_arg, fp_index += 16
1057 LOAD_FLOAT_TO_REG f12, t8, t7, loop # f12 = curr_arg, fp_index += 16
1058 LOAD_FLOAT_TO_REG f14, t8, t7, loop # f14 = curr_arg, fp_index += 16
1059 LOAD_FLOAT_TO_REG f16, t8, t7, loop # f16 = curr_arg, fp_index += 16
1060 LOAD_FLOAT_TO_REG f18, t8, t7, loop # f18 = curr_arg, fp_index += 16
1061 LOAD_END t7, 6*16, loop # no more FPR args, fp_index = 6*16
1062tabDouble:
1063 LOAD_DOUBLE_TO_REG f8, f9, t8, t7, ra, loop # f8_f9 = curr_arg; if FPU32, fp_index += 16
1064 LOAD_DOUBLE_TO_REG f10, f11, t8, t7, ra, loop # f10_f11 = curr_arg; if FPU32, fp_index += 16
1065 LOAD_DOUBLE_TO_REG f12, f13, t8, t7, ra, loop # f12_f13 = curr_arg; if FPU32, fp_index += 16
1066 LOAD_DOUBLE_TO_REG f14, f15, t8, t7, ra, loop # f14_f15 = curr_arg; if FPU32, fp_index += 16
1067 LOAD_DOUBLE_TO_REG f16, f17, t8, t7, ra, loop # f16_f17 = curr_arg; if FPU32, fp_index += 16
1068 LOAD_DOUBLE_TO_REG f18, f19, t8, t7, ra, loop # f18_f19 = curr_arg; if FPU32, fp_index += 16
1069 LOAD_END t7, 6*16, loop # no more FPR args, fp_index = 6*16
Jeff Hao5d917302013-02-27 17:57:33 -08001070END art_quick_invoke_stub
1071
1072 /*
Goran Jakovljevicff734982015-08-24 12:58:55 +00001073 * Invocation static stub for quick code.
1074 * On entry:
1075 * a0 = method pointer
1076 * a1 = argument array or null for no argument methods
1077 * a2 = size of argument array in bytes
1078 * a3 = (managed) thread pointer
1079 * [sp + 16] = JValue* result
1080 * [sp + 20] = shorty
1081 */
1082ENTRY art_quick_invoke_static_stub
1083 sw $a0, 0($sp) # save out a0
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001084 addiu $sp, $sp, -SPILL_SIZE # spill s0, s1, fp, ra and gp
1085 .cfi_adjust_cfa_offset SPILL_SIZE
1086 sw $gp, 16($sp)
Goran Jakovljevicff734982015-08-24 12:58:55 +00001087 sw $ra, 12($sp)
1088 .cfi_rel_offset 31, 12
1089 sw $fp, 8($sp)
1090 .cfi_rel_offset 30, 8
1091 sw $s1, 4($sp)
1092 .cfi_rel_offset 17, 4
1093 sw $s0, 0($sp)
1094 .cfi_rel_offset 16, 0
1095 move $fp, $sp # save sp in fp
1096 .cfi_def_cfa_register 30
1097 move $s1, $a3 # move managed thread pointer into s1
1098 addiu $s0, $zero, SUSPEND_CHECK_INTERVAL # reset s0 to suspend check interval
1099 addiu $t0, $a2, 4 # create space for ArtMethod* in frame.
1100 subu $t0, $sp, $t0 # reserve & align *stack* to 16 bytes:
1101 srl $t0, $t0, 4 # native calling convention only aligns to 8B,
1102 sll $sp, $t0, 4 # so we have to ensure ART 16B alignment ourselves.
1103 addiu $a0, $sp, 4 # pass stack pointer + ArtMethod* as dest for memcpy
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001104 la $t9, memcpy
1105 jalr $t9 # (dest, src, bytes)
Goran Jakovljevicff734982015-08-24 12:58:55 +00001106 addiu $sp, $sp, -16 # make space for argument slots for memcpy
1107 addiu $sp, $sp, 16 # restore stack after memcpy
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001108 lw $gp, 16($fp) # restore $gp
1109 lw $a0, SPILL_SIZE($fp) # restore ArtMethod*
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001110 addiu $t8, $sp, 4 # t8 = pointer to the current argument (skip ArtMethod*)
1111 li $t6, 0 # t6 = gpr_index = 0 (corresponds to A1; A0 is skipped)
1112 li $t7, 0 # t7 = fp_index = 0
1113 lw $t9, 20 + SPILL_SIZE($fp) # get shorty (20 is offset from the $sp on entry + SPILL_SIZE
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001114 # as the $fp is SPILL_SIZE bytes below the $sp on entry)
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001115 addiu $t9, 1 # t9 = shorty + 1 (skip 1 for return type)
1116
1117 // Load the base addresses of tabIntS ... tabDoubleS.
1118 // We will use the register indices (gpr_index, fp_index) to branch.
1119 // Note that the indices are scaled by 16, so they can be added to the bases directly.
1120#if defined(__mips_isa_rev) && __mips_isa_rev >= 6
1121 lapc $t2, tabIntS
1122 lapc $t3, tabLongS
1123 lapc $t4, tabSingleS
1124 lapc $t5, tabDoubleS
1125#else
1126 bltzal $zero, tabBaseS # nal
1127 addiu $t2, $ra, %lo(tabIntS - tabBaseS)
1128tabBaseS:
1129 addiu $t3, $ra, %lo(tabLongS - tabBaseS)
1130 addiu $t4, $ra, %lo(tabSingleS - tabBaseS)
1131 addiu $t5, $ra, %lo(tabDoubleS - tabBaseS)
1132#endif
1133
Goran Jakovljevicff734982015-08-24 12:58:55 +00001134loopS:
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001135 lbu $ra, 0($t9) # ra = shorty[i]
1136 beqz $ra, loopEndS # finish getting args when shorty[i] == '\0'
1137 addiu $t9, 1
Goran Jakovljevicff734982015-08-24 12:58:55 +00001138
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001139 addiu $ra, -'J'
1140 beqz $ra, isLongS # branch if result type char == 'J'
1141 addiu $ra, 'J' - 'D'
1142 beqz $ra, isDoubleS # branch if result type char == 'D'
1143 addiu $ra, 'D' - 'F'
1144 beqz $ra, isSingleS # branch if result type char == 'F'
Goran Jakovljevicff734982015-08-24 12:58:55 +00001145
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001146 addu $ra, $t2, $t6
1147 jalr $zero, $ra
1148 addiu $t8, 4 # next_arg = curr_arg + 4
Goran Jakovljevicff734982015-08-24 12:58:55 +00001149
1150isLongS:
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001151 addu $ra, $t3, $t6
1152 jalr $zero, $ra
1153 addiu $t8, 8 # next_arg = curr_arg + 8
Goran Jakovljevicff734982015-08-24 12:58:55 +00001154
1155isSingleS:
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001156 addu $ra, $t4, $t7
1157 jalr $zero, $ra
1158 addiu $t8, 4 # next_arg = curr_arg + 4
1159
1160isDoubleS:
1161 addu $ra, $t5, $t7
1162#if defined(__mips_isa_rev) && __mips_isa_rev > 2
1163 addiu $t7, 16 # fp_index += 16 didn't fit into LOAD_DOUBLE_TO_REG
1164#endif
1165 jalr $zero, $ra
1166 addiu $t8, 8 # next_arg = curr_arg + 8
Goran Jakovljevicff734982015-08-24 12:58:55 +00001167
1168loopEndS:
1169 lw $t9, ART_METHOD_QUICK_CODE_OFFSET_32($a0) # get pointer to the code
1170 jalr $t9 # call the method
1171 sw $zero, 0($sp) # store null for ArtMethod* at bottom of frame
1172 move $sp, $fp # restore the stack
1173 lw $s0, 0($sp)
1174 .cfi_restore 16
1175 lw $s1, 4($sp)
1176 .cfi_restore 17
1177 lw $fp, 8($sp)
1178 .cfi_restore 30
1179 lw $ra, 12($sp)
1180 .cfi_restore 31
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001181 addiu $sp, $sp, SPILL_SIZE
1182 .cfi_adjust_cfa_offset -SPILL_SIZE
Goran Jakovljevicff734982015-08-24 12:58:55 +00001183 lw $t0, 16($sp) # get result pointer
1184 lw $t1, 20($sp) # get shorty
1185 lb $t1, 0($t1) # get result type char
1186 li $t2, 'D' # put char 'D' into t2
1187 beq $t1, $t2, 6f # branch if result type char == 'D'
1188 li $t3, 'F' # put char 'F' into t3
1189 beq $t1, $t3, 6f # branch if result type char == 'F'
1190 sw $v0, 0($t0) # store the result
1191 jalr $zero, $ra
1192 sw $v1, 4($t0) # store the other half of the result
11936:
1194 SDu $f0, $f1, 0, $t0, $t1 # store floating point result
1195 jalr $zero, $ra
1196 nop
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001197
1198 // Note that gpr_index is kept within the range of tabIntS and tabLongS
1199 // and fp_index is kept within the range of tabSingleS and tabDoubleS.
1200 .balign 16
1201tabIntS:
1202 LOAD_WORD_TO_REG a1, t8, t6, loopS # a1 = current argument, gpr_index += 16
1203 LOAD_WORD_TO_REG a2, t8, t6, loopS # a2 = current argument, gpr_index += 16
1204 LOAD_WORD_TO_REG a3, t8, t6, loopS # a3 = current argument, gpr_index += 16
1205 LOAD_WORD_TO_REG t0, t8, t6, loopS # t0 = current argument, gpr_index += 16
1206 LOAD_WORD_TO_REG t1, t8, t6, loopS # t1 = current argument, gpr_index += 16
1207 LOAD_END t6, 5*16, loopS # no more GPR args, gpr_index = 5*16
1208tabLongS:
1209 LOAD_LONG_TO_REG a2, a3, t8, t6, 3*16, loopS # a2_a3 = curr_arg, gpr_index = 3*16
1210 LOAD_LONG_TO_REG a2, a3, t8, t6, 3*16, loopS # a2_a3 = curr_arg, gpr_index = 3*16
1211 LOAD_LONG_TO_REG t0, t1, t8, t6, 5*16, loopS # t0_t1 = curr_arg, gpr_index = 5*16
1212 LOAD_LONG_TO_REG t0, t1, t8, t6, 5*16, loopS # t0_t1 = curr_arg, gpr_index = 5*16
1213 LOAD_END t6, 5*16, loopS # no more GPR args, gpr_index = 5*16
1214 LOAD_END t6, 5*16, loopS # no more GPR args, gpr_index = 5*16
1215tabSingleS:
1216 LOAD_FLOAT_TO_REG f8, t8, t7, loopS # f8 = curr_arg, fp_index += 16
1217 LOAD_FLOAT_TO_REG f10, t8, t7, loopS # f10 = curr_arg, fp_index += 16
1218 LOAD_FLOAT_TO_REG f12, t8, t7, loopS # f12 = curr_arg, fp_index += 16
1219 LOAD_FLOAT_TO_REG f14, t8, t7, loopS # f14 = curr_arg, fp_index += 16
1220 LOAD_FLOAT_TO_REG f16, t8, t7, loopS # f16 = curr_arg, fp_index += 16
1221 LOAD_FLOAT_TO_REG f18, t8, t7, loopS # f18 = curr_arg, fp_index += 16
1222 LOAD_END t7, 6*16, loopS # no more FPR args, fp_index = 6*16
1223tabDoubleS:
1224 LOAD_DOUBLE_TO_REG f8, f9, t8, t7, ra, loopS # f8_f9 = curr_arg; if FPU32, fp_index += 16
1225 LOAD_DOUBLE_TO_REG f10, f11, t8, t7, ra, loopS # f10_f11 = curr_arg; if FPU32, fp_index += 16
1226 LOAD_DOUBLE_TO_REG f12, f13, t8, t7, ra, loopS # f12_f13 = curr_arg; if FPU32, fp_index += 16
1227 LOAD_DOUBLE_TO_REG f14, f15, t8, t7, ra, loopS # f14_f15 = curr_arg; if FPU32, fp_index += 16
1228 LOAD_DOUBLE_TO_REG f16, f17, t8, t7, ra, loopS # f16_f17 = curr_arg; if FPU32, fp_index += 16
1229 LOAD_DOUBLE_TO_REG f18, f19, t8, t7, ra, loopS # f18_f19 = curr_arg; if FPU32, fp_index += 16
1230 LOAD_END t7, 6*16, loopS # no more FPR args, fp_index = 6*16
Goran Jakovljevicff734982015-08-24 12:58:55 +00001231END art_quick_invoke_static_stub
1232
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001233#undef SPILL_SIZE
1234
Goran Jakovljevicff734982015-08-24 12:58:55 +00001235 /*
buzbee5bc5a7b2012-03-07 15:52:59 -08001236 * Entry from managed code that calls artHandleFillArrayDataFromCode and delivers exception on
1237 * failure.
1238 */
Jeff Haod4c3f7d2013-02-14 14:14:44 -08001239 .extern artHandleFillArrayDataFromCode
Ian Rogers468532e2013-08-05 10:56:33 -07001240ENTRY art_quick_handle_fill_data
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001241 lw $a2, 0($sp) # pass referrer's Method*
1242 SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case exception allocation triggers GC
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001243 la $t9, artHandleFillArrayDataFromCode
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001244 jalr $t9 # (payload offset, Array*, method, Thread*)
1245 move $a3, rSELF # pass Thread::Current
jeffhaofc6a30e2012-10-18 18:24:15 -07001246 RETURN_IF_ZERO
Ian Rogers468532e2013-08-05 10:56:33 -07001247END art_quick_handle_fill_data
buzbee5bc5a7b2012-03-07 15:52:59 -08001248
buzbee5bc5a7b2012-03-07 15:52:59 -08001249 /*
Ian Rogers57b86d42012-03-27 16:05:41 -07001250 * Entry from managed code that calls artLockObjectFromCode, may block for GC.
buzbee5bc5a7b2012-03-07 15:52:59 -08001251 */
Jeff Haod4c3f7d2013-02-14 14:14:44 -08001252 .extern artLockObjectFromCode
Ian Rogers468532e2013-08-05 10:56:33 -07001253ENTRY art_quick_lock_object
Vladimir Marko804b03f2016-09-14 16:26:36 +01001254 beqz $a0, art_quick_throw_null_pointer_exception
Ian Rogersa9a82542013-10-04 11:17:26 -07001255 nop
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001256 SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case we block
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001257 la $t9, artLockObjectFromCode
1258 jalr $t9 # (Object* obj, Thread*)
jeffhao7fbee072012-08-24 17:56:54 -07001259 move $a1, rSELF # pass Thread::Current
Ian Rogers6bcd1632013-10-08 18:50:47 -07001260 RETURN_IF_ZERO
Ian Rogers468532e2013-08-05 10:56:33 -07001261END art_quick_lock_object
buzbee5bc5a7b2012-03-07 15:52:59 -08001262
Andreas Gampec7ed09b2016-04-25 20:08:55 -07001263ENTRY art_quick_lock_object_no_inline
Vladimir Marko804b03f2016-09-14 16:26:36 +01001264 beqz $a0, art_quick_throw_null_pointer_exception
Andreas Gampec7ed09b2016-04-25 20:08:55 -07001265 nop
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001266 SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case we block
Andreas Gampec7ed09b2016-04-25 20:08:55 -07001267 la $t9, artLockObjectFromCode
1268 jalr $t9 # (Object* obj, Thread*)
1269 move $a1, rSELF # pass Thread::Current
1270 RETURN_IF_ZERO
1271END art_quick_lock_object_no_inline
1272
buzbee5bc5a7b2012-03-07 15:52:59 -08001273 /*
1274 * Entry from managed code that calls artUnlockObjectFromCode and delivers exception on failure.
1275 */
Jeff Haod4c3f7d2013-02-14 14:14:44 -08001276 .extern artUnlockObjectFromCode
Ian Rogers468532e2013-08-05 10:56:33 -07001277ENTRY art_quick_unlock_object
Vladimir Marko804b03f2016-09-14 16:26:36 +01001278 beqz $a0, art_quick_throw_null_pointer_exception
Ian Rogersa9a82542013-10-04 11:17:26 -07001279 nop
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001280 SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case exception allocation triggers GC
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001281 la $t9, artUnlockObjectFromCode
1282 jalr $t9 # (Object* obj, Thread*)
jeffhao7fbee072012-08-24 17:56:54 -07001283 move $a1, rSELF # pass Thread::Current
buzbee5bc5a7b2012-03-07 15:52:59 -08001284 RETURN_IF_ZERO
Ian Rogers468532e2013-08-05 10:56:33 -07001285END art_quick_unlock_object
buzbee5bc5a7b2012-03-07 15:52:59 -08001286
Andreas Gampec7ed09b2016-04-25 20:08:55 -07001287ENTRY art_quick_unlock_object_no_inline
Vladimir Marko804b03f2016-09-14 16:26:36 +01001288 beqz $a0, art_quick_throw_null_pointer_exception
Andreas Gampec7ed09b2016-04-25 20:08:55 -07001289 nop
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001290 SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case exception allocation triggers GC
Andreas Gampec7ed09b2016-04-25 20:08:55 -07001291 la $t9, artUnlockObjectFromCode
1292 jalr $t9 # (Object* obj, Thread*)
1293 move $a1, rSELF # pass Thread::Current
1294 RETURN_IF_ZERO
1295END art_quick_unlock_object_no_inline
1296
buzbee5bc5a7b2012-03-07 15:52:59 -08001297 /*
Mathieu Chartierb99f4d62016-11-07 16:17:26 -08001298 * Entry from managed code that calls artInstanceOfFromCode and delivers exception on failure.
buzbee5bc5a7b2012-03-07 15:52:59 -08001299 */
Mathieu Chartierb99f4d62016-11-07 16:17:26 -08001300 .extern artInstanceOfFromCode
1301 .extern artThrowClassCastExceptionForObject
1302ENTRY art_quick_check_instance_of
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001303 addiu $sp, $sp, -32
1304 .cfi_adjust_cfa_offset 32
1305 sw $gp, 16($sp)
Ian Rogersa9a82542013-10-04 11:17:26 -07001306 sw $ra, 12($sp)
1307 .cfi_rel_offset 31, 12
1308 sw $t9, 8($sp)
1309 sw $a1, 4($sp)
1310 sw $a0, 0($sp)
Mathieu Chartierb99f4d62016-11-07 16:17:26 -08001311 la $t9, artInstanceOfFromCode
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001312 jalr $t9
Douglas Leung735b8552014-10-31 12:21:40 -07001313 addiu $sp, $sp, -16 # reserve argument slots on the stack
1314 addiu $sp, $sp, 16
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001315 lw $gp, 16($sp)
Ian Rogers86bcdc22014-02-21 22:06:38 -08001316 beqz $v0, .Lthrow_class_cast_exception
Ian Rogersa9a82542013-10-04 11:17:26 -07001317 lw $ra, 12($sp)
Andreas Gampe8d365912015-01-13 11:32:32 -08001318 jalr $zero, $ra
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001319 addiu $sp, $sp, 32
1320 .cfi_adjust_cfa_offset -32
Ian Rogers86bcdc22014-02-21 22:06:38 -08001321.Lthrow_class_cast_exception:
Ian Rogersa9a82542013-10-04 11:17:26 -07001322 lw $t9, 8($sp)
1323 lw $a1, 4($sp)
1324 lw $a0, 0($sp)
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001325 addiu $sp, $sp, 32
1326 .cfi_adjust_cfa_offset -32
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001327 SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
Mathieu Chartierb99f4d62016-11-07 16:17:26 -08001328 la $t9, artThrowClassCastExceptionForObject
1329 jalr $zero, $t9 # artThrowClassCastException (Object*, Class*, Thread*)
Ian Rogers1d8cdbc2014-09-22 22:51:09 -07001330 move $a2, rSELF # pass Thread::Current
Mathieu Chartierb99f4d62016-11-07 16:17:26 -08001331END art_quick_check_instance_of
buzbee5bc5a7b2012-03-07 15:52:59 -08001332
buzbee5bc5a7b2012-03-07 15:52:59 -08001333 /*
Man Cao1aee9002015-07-14 22:31:42 -07001334 * Restore rReg's value from offset($sp) if rReg is not the same as rExclude.
1335 * nReg is the register number for rReg.
1336 */
1337.macro POP_REG_NE rReg, nReg, offset, rExclude
1338 .ifnc \rReg, \rExclude
1339 lw \rReg, \offset($sp) # restore rReg
1340 .cfi_restore \nReg
1341 .endif
1342.endm
1343
1344 /*
1345 * Macro to insert read barrier, only used in art_quick_aput_obj.
1346 * rObj and rDest are registers, offset is a defined literal such as MIRROR_OBJECT_CLASS_OFFSET.
1347 * TODO: When read barrier has a fast path, add heap unpoisoning support for the fast path.
1348 */
1349.macro READ_BARRIER rDest, rObj, offset
1350#ifdef USE_READ_BARRIER
1351 # saved registers used in art_quick_aput_obj: a0-a2, t0-t1, t9, ra. 8 words for 16B alignment.
1352 addiu $sp, $sp, -32
1353 .cfi_adjust_cfa_offset 32
1354 sw $ra, 28($sp)
1355 .cfi_rel_offset 31, 28
1356 sw $t9, 24($sp)
1357 .cfi_rel_offset 25, 24
1358 sw $t1, 20($sp)
1359 .cfi_rel_offset 9, 20
1360 sw $t0, 16($sp)
1361 .cfi_rel_offset 8, 16
1362 sw $a2, 8($sp) # padding slot at offset 12 (padding can be any slot in the 32B)
1363 .cfi_rel_offset 6, 8
1364 sw $a1, 4($sp)
1365 .cfi_rel_offset 5, 4
1366 sw $a0, 0($sp)
1367 .cfi_rel_offset 4, 0
1368
Man Cao63069212015-08-21 15:51:39 -07001369 # move $a0, \rRef # pass ref in a0 (no-op for now since parameter ref is unused)
Man Cao1aee9002015-07-14 22:31:42 -07001370 .ifnc \rObj, $a1
1371 move $a1, \rObj # pass rObj
1372 .endif
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001373 addiu $a2, $zero, \offset # pass offset
1374 la $t9, artReadBarrierSlow
1375 jalr $t9 # artReadBarrierSlow(ref, rObj, offset)
Man Cao1aee9002015-07-14 22:31:42 -07001376 addiu $sp, $sp, -16 # Use branch delay slot to reserve argument slots on the stack
1377 # before the call to artReadBarrierSlow.
1378 addiu $sp, $sp, 16 # restore stack after call to artReadBarrierSlow
1379 # No need to unpoison return value in v0, artReadBarrierSlow() would do the unpoisoning.
1380 move \rDest, $v0 # save return value in rDest
1381 # (rDest cannot be v0 in art_quick_aput_obj)
1382
1383 lw $a0, 0($sp) # restore registers except rDest
1384 # (rDest can only be t0 or t1 in art_quick_aput_obj)
1385 .cfi_restore 4
1386 lw $a1, 4($sp)
1387 .cfi_restore 5
1388 lw $a2, 8($sp)
1389 .cfi_restore 6
1390 POP_REG_NE $t0, 8, 16, \rDest
1391 POP_REG_NE $t1, 9, 20, \rDest
1392 lw $t9, 24($sp)
1393 .cfi_restore 25
1394 lw $ra, 28($sp) # restore $ra
1395 .cfi_restore 31
1396 addiu $sp, $sp, 32
1397 .cfi_adjust_cfa_offset -32
1398#else
1399 lw \rDest, \offset(\rObj)
1400 UNPOISON_HEAP_REF \rDest
1401#endif // USE_READ_BARRIER
1402.endm
1403
Man Cao1aee9002015-07-14 22:31:42 -07001404#ifdef USE_READ_BARRIER
1405 .extern artReadBarrierSlow
1406#endif
Ian Rogersa9a82542013-10-04 11:17:26 -07001407ENTRY art_quick_aput_obj
Ian Rogers86bcdc22014-02-21 22:06:38 -08001408 beqz $a2, .Ldo_aput_null
Ian Rogersa9a82542013-10-04 11:17:26 -07001409 nop
Man Cao1aee9002015-07-14 22:31:42 -07001410 READ_BARRIER $t0, $a0, MIRROR_OBJECT_CLASS_OFFSET
1411 READ_BARRIER $t1, $a2, MIRROR_OBJECT_CLASS_OFFSET
1412 READ_BARRIER $t0, $t0, MIRROR_CLASS_COMPONENT_TYPE_OFFSET
Ian Rogers86bcdc22014-02-21 22:06:38 -08001413 bne $t1, $t0, .Lcheck_assignability # value's type == array's component type - trivial assignability
Ian Rogersa9a82542013-10-04 11:17:26 -07001414 nop
Ian Rogers86bcdc22014-02-21 22:06:38 -08001415.Ldo_aput:
Ian Rogersa9a82542013-10-04 11:17:26 -07001416 sll $a1, $a1, 2
1417 add $t0, $a0, $a1
Hiroshi Yamauchibfa5eb62015-05-29 15:04:41 -07001418 POISON_HEAP_REF $a2
Ian Rogers1d8cdbc2014-09-22 22:51:09 -07001419 sw $a2, MIRROR_OBJECT_ARRAY_DATA_OFFSET($t0)
Ian Rogersa9a82542013-10-04 11:17:26 -07001420 lw $t0, THREAD_CARD_TABLE_OFFSET(rSELF)
Mathieu Chartierafdcbcb2017-04-26 16:43:35 -07001421 srl $t1, $a0, CARD_TABLE_CARD_SHIFT
Ian Rogersa9a82542013-10-04 11:17:26 -07001422 add $t1, $t1, $t0
1423 sb $t0, ($t1)
Andreas Gampe8d365912015-01-13 11:32:32 -08001424 jalr $zero, $ra
Ian Rogersa9a82542013-10-04 11:17:26 -07001425 nop
Ian Rogers86bcdc22014-02-21 22:06:38 -08001426.Ldo_aput_null:
Ian Rogersa9a82542013-10-04 11:17:26 -07001427 sll $a1, $a1, 2
1428 add $t0, $a0, $a1
Ian Rogers1d8cdbc2014-09-22 22:51:09 -07001429 sw $a2, MIRROR_OBJECT_ARRAY_DATA_OFFSET($t0)
Andreas Gampe8d365912015-01-13 11:32:32 -08001430 jalr $zero, $ra
Ian Rogersa9a82542013-10-04 11:17:26 -07001431 nop
Ian Rogers86bcdc22014-02-21 22:06:38 -08001432.Lcheck_assignability:
Ian Rogersa9a82542013-10-04 11:17:26 -07001433 addiu $sp, $sp, -32
1434 .cfi_adjust_cfa_offset 32
1435 sw $ra, 28($sp)
1436 .cfi_rel_offset 31, 28
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001437 sw $gp, 16($sp)
Ian Rogersa9a82542013-10-04 11:17:26 -07001438 sw $t9, 12($sp)
1439 sw $a2, 8($sp)
1440 sw $a1, 4($sp)
1441 sw $a0, 0($sp)
1442 move $a1, $t1
1443 move $a0, $t0
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001444 la $t9, artIsAssignableFromCode
1445 jalr $t9 # (Class*, Class*)
1446 addiu $sp, $sp, -16 # reserve argument slots on the stack
1447 addiu $sp, $sp, 16
Ian Rogersa9a82542013-10-04 11:17:26 -07001448 lw $ra, 28($sp)
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001449 lw $gp, 16($sp)
Ian Rogersa9a82542013-10-04 11:17:26 -07001450 lw $t9, 12($sp)
1451 lw $a2, 8($sp)
1452 lw $a1, 4($sp)
1453 lw $a0, 0($sp)
Duane Sande34652f2014-11-04 11:09:36 -08001454 addiu $sp, 32
Ian Rogersa9a82542013-10-04 11:17:26 -07001455 .cfi_adjust_cfa_offset -32
Ian Rogers86bcdc22014-02-21 22:06:38 -08001456 bnez $v0, .Ldo_aput
Ian Rogersa9a82542013-10-04 11:17:26 -07001457 nop
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001458 SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
Ian Rogersa9a82542013-10-04 11:17:26 -07001459 move $a1, $a2
Ian Rogersa9a82542013-10-04 11:17:26 -07001460 la $t9, artThrowArrayStoreException
Andreas Gampe8d365912015-01-13 11:32:32 -08001461 jalr $zero, $t9 # artThrowArrayStoreException(Class*, Class*, Thread*)
Ian Rogers1d8cdbc2014-09-22 22:51:09 -07001462 move $a2, rSELF # pass Thread::Current
Ian Rogersa9a82542013-10-04 11:17:26 -07001463END art_quick_aput_obj
buzbee5bc5a7b2012-03-07 15:52:59 -08001464
Alexey Frunze0cb12422017-01-25 19:30:18 -08001465// Macros taking opportunity of code similarities for downcalls.
1466.macro ONE_ARG_REF_DOWNCALL name, entrypoint, return
1467 .extern \entrypoint
1468ENTRY \name
1469 SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case of GC
1470 la $t9, \entrypoint
1471 jalr $t9 # (field_idx, Thread*)
1472 move $a1, rSELF # pass Thread::Current
1473 \return # RETURN_IF_NO_EXCEPTION or RETURN_IF_ZERO
1474END \name
1475.endm
1476
1477.macro TWO_ARG_REF_DOWNCALL name, entrypoint, return
1478 .extern \entrypoint
1479ENTRY \name
1480 SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case of GC
1481 la $t9, \entrypoint
1482 jalr $t9 # (field_idx, Object*, Thread*) or
1483 # (field_idx, new_val, Thread*)
1484 move $a2, rSELF # pass Thread::Current
1485 \return # RETURN_IF_NO_EXCEPTION or RETURN_IF_ZERO
1486END \name
1487.endm
1488
1489.macro THREE_ARG_REF_DOWNCALL name, entrypoint, return
1490 .extern \entrypoint
1491ENTRY \name
1492 SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case of GC
1493 la $t9, \entrypoint
1494 jalr $t9 # (field_idx, Object*, new_val, Thread*)
1495 move $a3, rSELF # pass Thread::Current
1496 \return # RETURN_IF_NO_EXCEPTION or RETURN_IF_ZERO
1497END \name
1498.endm
1499
1500.macro FOUR_ARG_REF_DOWNCALL name, entrypoint, return
1501 .extern \entrypoint
1502ENTRY \name
1503 SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case of GC
1504 la $t9, \entrypoint
1505 jalr $t9 # (field_idx, Object*, 64-bit new_val, Thread*) or
1506 # (field_idx, 64-bit new_val, Thread*)
1507 # Note that a 64-bit new_val needs to be aligned with
1508 # an even-numbered register, hence A1 may be skipped
1509 # for new_val to reside in A2-A3.
1510 sw rSELF, 16($sp) # pass Thread::Current
1511 \return # RETURN_IF_NO_EXCEPTION or RETURN_IF_ZERO
1512END \name
1513.endm
Fred Shih37f05ef2014-07-16 18:38:08 -07001514
1515 /*
Alexey Frunze0cb12422017-01-25 19:30:18 -08001516 * Called by managed code to resolve a static/instance field and load/store a value.
Fred Shih37f05ef2014-07-16 18:38:08 -07001517 */
Alexey Frunze0cb12422017-01-25 19:30:18 -08001518ONE_ARG_REF_DOWNCALL art_quick_get_byte_static, artGetByteStaticFromCompiledCode, RETURN_IF_NO_EXCEPTION
1519ONE_ARG_REF_DOWNCALL art_quick_get_boolean_static, artGetBooleanStaticFromCompiledCode, RETURN_IF_NO_EXCEPTION
1520ONE_ARG_REF_DOWNCALL art_quick_get_short_static, artGetShortStaticFromCompiledCode, RETURN_IF_NO_EXCEPTION
1521ONE_ARG_REF_DOWNCALL art_quick_get_char_static, artGetCharStaticFromCompiledCode, RETURN_IF_NO_EXCEPTION
1522ONE_ARG_REF_DOWNCALL art_quick_get32_static, artGet32StaticFromCompiledCode, RETURN_IF_NO_EXCEPTION
1523ONE_ARG_REF_DOWNCALL art_quick_get_obj_static, artGetObjStaticFromCompiledCode, RETURN_IF_NO_EXCEPTION
1524ONE_ARG_REF_DOWNCALL art_quick_get64_static, artGet64StaticFromCompiledCode, RETURN_IF_NO_EXCEPTION
1525TWO_ARG_REF_DOWNCALL art_quick_get_byte_instance, artGetByteInstanceFromCompiledCode, RETURN_IF_NO_EXCEPTION
1526TWO_ARG_REF_DOWNCALL art_quick_get_boolean_instance, artGetBooleanInstanceFromCompiledCode, RETURN_IF_NO_EXCEPTION
1527TWO_ARG_REF_DOWNCALL art_quick_get_short_instance, artGetShortInstanceFromCompiledCode, RETURN_IF_NO_EXCEPTION
1528TWO_ARG_REF_DOWNCALL art_quick_get_char_instance, artGetCharInstanceFromCompiledCode, RETURN_IF_NO_EXCEPTION
1529TWO_ARG_REF_DOWNCALL art_quick_get32_instance, artGet32InstanceFromCompiledCode, RETURN_IF_NO_EXCEPTION
1530TWO_ARG_REF_DOWNCALL art_quick_get_obj_instance, artGetObjInstanceFromCompiledCode, RETURN_IF_NO_EXCEPTION
1531TWO_ARG_REF_DOWNCALL art_quick_get64_instance, artGet64InstanceFromCompiledCode, RETURN_IF_NO_EXCEPTION
1532TWO_ARG_REF_DOWNCALL art_quick_set8_static, artSet8StaticFromCompiledCode, RETURN_IF_ZERO
1533TWO_ARG_REF_DOWNCALL art_quick_set16_static, artSet16StaticFromCompiledCode, RETURN_IF_ZERO
1534TWO_ARG_REF_DOWNCALL art_quick_set32_static, artSet32StaticFromCompiledCode, RETURN_IF_ZERO
1535TWO_ARG_REF_DOWNCALL art_quick_set_obj_static, artSetObjStaticFromCompiledCode, RETURN_IF_ZERO
1536FOUR_ARG_REF_DOWNCALL art_quick_set64_static, artSet64StaticFromCompiledCode, RETURN_IF_ZERO
1537THREE_ARG_REF_DOWNCALL art_quick_set8_instance, artSet8InstanceFromCompiledCode, RETURN_IF_ZERO
1538THREE_ARG_REF_DOWNCALL art_quick_set16_instance, artSet16InstanceFromCompiledCode, RETURN_IF_ZERO
1539THREE_ARG_REF_DOWNCALL art_quick_set32_instance, artSet32InstanceFromCompiledCode, RETURN_IF_ZERO
1540THREE_ARG_REF_DOWNCALL art_quick_set_obj_instance, artSetObjInstanceFromCompiledCode, RETURN_IF_ZERO
1541FOUR_ARG_REF_DOWNCALL art_quick_set64_instance, artSet64InstanceFromCompiledCode, RETURN_IF_ZERO
buzbee5bc5a7b2012-03-07 15:52:59 -08001542
Vladimir Markoa3c38272015-04-28 12:37:09 +01001543// Macro to facilitate adding new allocation entrypoints.
Vladimir Marko5ea536a2015-04-20 20:11:30 +01001544.macro ONE_ARG_DOWNCALL name, entrypoint, return
1545 .extern \entrypoint
1546ENTRY \name
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001547 SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case of GC
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001548 la $t9, \entrypoint
1549 jalr $t9
Vladimir Marko5ea536a2015-04-20 20:11:30 +01001550 move $a1, rSELF # pass Thread::Current
1551 \return
1552END \name
1553.endm
1554
Mathieu Chartiercbb2d202013-11-14 17:45:16 -08001555.macro TWO_ARG_DOWNCALL name, entrypoint, return
1556 .extern \entrypoint
1557ENTRY \name
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001558 SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case of GC
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001559 la $t9, \entrypoint
1560 jalr $t9
Ian Rogers1d8cdbc2014-09-22 22:51:09 -07001561 move $a2, rSELF # pass Thread::Current
Mathieu Chartiercbb2d202013-11-14 17:45:16 -08001562 \return
1563END \name
1564.endm
buzbee5bc5a7b2012-03-07 15:52:59 -08001565
Mathieu Chartiercbb2d202013-11-14 17:45:16 -08001566.macro THREE_ARG_DOWNCALL name, entrypoint, return
1567 .extern \entrypoint
1568ENTRY \name
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001569 SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case of GC
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001570 la $t9, \entrypoint
1571 jalr $t9
Ian Rogers1d8cdbc2014-09-22 22:51:09 -07001572 move $a3, rSELF # pass Thread::Current
Mathieu Chartiercbb2d202013-11-14 17:45:16 -08001573 \return
1574END \name
1575.endm
buzbee5bc5a7b2012-03-07 15:52:59 -08001576
Jeff Hao848f70a2014-01-15 13:49:50 -08001577.macro FOUR_ARG_DOWNCALL name, entrypoint, return
1578 .extern \entrypoint
1579ENTRY \name
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001580 SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case of GC
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001581 la $t9, \entrypoint
1582 jalr $t9
Vladimir Markoa3c38272015-04-28 12:37:09 +01001583 sw rSELF, 16($sp) # pass Thread::Current
Jeff Hao848f70a2014-01-15 13:49:50 -08001584 \return
1585END \name
1586.endm
1587
Mathieu Chartier7410f292013-11-24 13:17:35 -08001588// Generate the allocation entrypoints for each allocator.
Pavle Batuta712c59d2015-12-02 18:39:01 +01001589GENERATE_ALLOC_ENTRYPOINTS_FOR_EACH_ALLOCATOR
Hiroshi Yamauchi10d4c082016-02-24 12:51:18 -08001590
Goran Jakovljevic2449e5c2017-01-19 11:39:18 +01001591// A hand-written override for:
1592// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_rosalloc, RosAlloc)
1593// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_rosalloc, RosAlloc)
1594.macro ART_QUICK_ALLOC_OBJECT_ROSALLOC c_name, cxx_name
1595ENTRY \c_name
1596 # Fast path rosalloc allocation
1597 # a0: type
1598 # s1: Thread::Current
1599 # -----------------------------
1600 # t1: object size
1601 # t2: rosalloc run
1602 # t3: thread stack top offset
1603 # t4: thread stack bottom offset
1604 # v0: free list head
1605 #
1606 # t5, t6 : temps
1607 lw $t3, THREAD_LOCAL_ALLOC_STACK_TOP_OFFSET($s1) # Check if thread local allocation
1608 lw $t4, THREAD_LOCAL_ALLOC_STACK_END_OFFSET($s1) # stack has any room left.
1609 bgeu $t3, $t4, .Lslow_path_\c_name
Pavle Batuta712c59d2015-12-02 18:39:01 +01001610
Goran Jakovljevic2449e5c2017-01-19 11:39:18 +01001611 lw $t1, MIRROR_CLASS_OBJECT_SIZE_ALLOC_FAST_PATH_OFFSET($a0) # Load object size (t1).
1612 li $t5, ROSALLOC_MAX_THREAD_LOCAL_BRACKET_SIZE # Check if size is for a thread local
1613 # allocation. Also does the
1614 # initialized and finalizable checks.
1615 bgtu $t1, $t5, .Lslow_path_\c_name
1616
1617 # Compute the rosalloc bracket index from the size. Since the size is already aligned we can
1618 # combine the two shifts together.
1619 srl $t1, $t1, (ROSALLOC_BRACKET_QUANTUM_SIZE_SHIFT - POINTER_SIZE_SHIFT)
1620
1621 addu $t2, $t1, $s1
1622 lw $t2, (THREAD_ROSALLOC_RUNS_OFFSET - __SIZEOF_POINTER__)($t2) # Load rosalloc run (t2).
1623
1624 # Load the free list head (v0).
1625 # NOTE: this will be the return val.
1626 lw $v0, (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_HEAD_OFFSET)($t2)
1627 beqz $v0, .Lslow_path_\c_name
1628 nop
1629
1630 # Load the next pointer of the head and update the list head with the next pointer.
1631 lw $t5, ROSALLOC_SLOT_NEXT_OFFSET($v0)
1632 sw $t5, (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_HEAD_OFFSET)($t2)
1633
1634 # Store the class pointer in the header. This also overwrites the first pointer. The offsets are
1635 # asserted to match.
1636
1637#if ROSALLOC_SLOT_NEXT_OFFSET != MIRROR_OBJECT_CLASS_OFFSET
1638#error "Class pointer needs to overwrite next pointer."
1639#endif
1640
1641 POISON_HEAP_REF $a0
1642 sw $a0, MIRROR_OBJECT_CLASS_OFFSET($v0)
1643
1644 # Push the new object onto the thread local allocation stack and increment the thread local
1645 # allocation stack top.
1646 sw $v0, 0($t3)
1647 addiu $t3, $t3, COMPRESSED_REFERENCE_SIZE
1648 sw $t3, THREAD_LOCAL_ALLOC_STACK_TOP_OFFSET($s1)
1649
1650 # Decrement the size of the free list.
1651 lw $t5, (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_SIZE_OFFSET)($t2)
1652 addiu $t5, $t5, -1
1653 sw $t5, (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_SIZE_OFFSET)($t2)
1654
1655 sync # Fence.
1656
1657 jalr $zero, $ra
1658 nop
1659
1660 .Lslow_path_\c_name:
1661 SETUP_SAVE_REFS_ONLY_FRAME
1662 la $t9, \cxx_name
1663 jalr $t9
1664 move $a1, $s1 # Pass self as argument.
1665 RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
1666END \c_name
1667.endm
1668
1669ART_QUICK_ALLOC_OBJECT_ROSALLOC art_quick_alloc_object_resolved_rosalloc, artAllocObjectFromCodeResolvedRosAlloc
1670ART_QUICK_ALLOC_OBJECT_ROSALLOC art_quick_alloc_object_initialized_rosalloc, artAllocObjectFromCodeInitializedRosAlloc
1671
Nicolas Geoffray0d3998b2017-01-12 15:35:12 +00001672GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_tlab, TLAB)
1673GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_region_tlab, RegionTLAB)
Hiroshi Yamauchi10d4c082016-02-24 12:51:18 -08001674
Alexey Frunzec61c0762017-04-10 13:54:23 -07001675// Macro for string and type resolution and initialization.
1676// $a0 is both input and output.
1677.macro ONE_ARG_SAVE_EVERYTHING_DOWNCALL name, entrypoint
1678 .extern \entrypoint
1679ENTRY_NO_GP \name
1680 SETUP_SAVE_EVERYTHING_FRAME # Save everything in case of GC.
1681 move $s2, $gp # Preserve $gp across the call for exception delivery.
1682 la $t9, \entrypoint
1683 jalr $t9 # (uint32_t index, Thread*)
1684 move $a1, rSELF # Pass Thread::Current (in delay slot).
1685 beqz $v0, 1f # Success?
1686 move $a0, $v0 # Move result to $a0 (in delay slot).
1687 RESTORE_SAVE_EVERYTHING_FRAME 0 # Restore everything except $a0.
1688 jalr $zero, $ra # Return on success.
1689 nop
16901:
1691 move $gp, $s2
1692 DELIVER_PENDING_EXCEPTION_FRAME_READY
1693END \name
1694.endm
1695
buzbee5bc5a7b2012-03-07 15:52:59 -08001696 /*
Andreas Gampe1cc7dba2014-12-17 18:43:01 -08001697 * Entry from managed code to resolve a string, this stub will allocate a String and deliver an
Vladimir Marko5ea536a2015-04-20 20:11:30 +01001698 * exception on error. On success the String is returned. A0 holds the string index. The fast
1699 * path check for hit in strings cache has already been performed.
Andreas Gampe1cc7dba2014-12-17 18:43:01 -08001700 */
Alexey Frunzec61c0762017-04-10 13:54:23 -07001701ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_string, artResolveStringFromCode
Andreas Gampe1cc7dba2014-12-17 18:43:01 -08001702
1703 /*
1704 * Entry from managed code when uninitialized static storage, this stub will run the class
1705 * initializer and deliver the exception on error. On success the static storage base is
1706 * returned.
1707 */
Alexey Frunzec61c0762017-04-10 13:54:23 -07001708ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode
Andreas Gampe1cc7dba2014-12-17 18:43:01 -08001709
1710 /*
1711 * Entry from managed code when dex cache misses for a type_idx.
1712 */
Alexey Frunzec61c0762017-04-10 13:54:23 -07001713ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode
Andreas Gampe1cc7dba2014-12-17 18:43:01 -08001714
1715 /*
1716 * Entry from managed code when type_idx needs to be checked for access and dex cache may also
1717 * miss.
1718 */
Alexey Frunzec61c0762017-04-10 13:54:23 -07001719ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode
Andreas Gampe1cc7dba2014-12-17 18:43:01 -08001720
1721 /*
Ian Rogers57b86d42012-03-27 16:05:41 -07001722 * Called by managed code when the value in rSUSPEND has been decremented to 0.
buzbee5bc5a7b2012-03-07 15:52:59 -08001723 */
Jeff Haod4c3f7d2013-02-14 14:14:44 -08001724 .extern artTestSuspendFromCode
Vladimir Marko952dbb12016-07-28 12:01:51 +01001725ENTRY_NO_GP art_quick_test_suspend
1726 lh rSUSPEND, THREAD_FLAGS_OFFSET(rSELF)
1727 bnez rSUSPEND, 1f
Duane Sande34652f2014-11-04 11:09:36 -08001728 addiu rSUSPEND, $zero, SUSPEND_CHECK_INTERVAL # reset rSUSPEND to SUSPEND_CHECK_INTERVAL
Andreas Gampe8d365912015-01-13 11:32:32 -08001729 jalr $zero, $ra
buzbee5bc5a7b2012-03-07 15:52:59 -08001730 nop
17311:
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001732 SETUP_SAVE_EVERYTHING_FRAME # save everything for stack crawl
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001733 la $t9, artTestSuspendFromCode
Vladimir Marko952dbb12016-07-28 12:01:51 +01001734 jalr $t9 # (Thread*)
jeffhao7fbee072012-08-24 17:56:54 -07001735 move $a0, rSELF
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001736 RESTORE_SAVE_EVERYTHING_FRAME
Vladimir Marko952dbb12016-07-28 12:01:51 +01001737 jalr $zero, $ra
1738 nop
Jeff Haod4c3f7d2013-02-14 14:14:44 -08001739END art_quick_test_suspend
buzbee5bc5a7b2012-03-07 15:52:59 -08001740
buzbee5bc5a7b2012-03-07 15:52:59 -08001741 /*
1742 * Called by managed code that is attempting to call a method on a proxy class. On entry
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001743 * a0 holds the proxy method; a1, a2 and a3 may contain arguments.
buzbee5bc5a7b2012-03-07 15:52:59 -08001744 */
Jeff Hao5fa60c32013-04-04 17:57:01 -07001745 .extern artQuickProxyInvokeHandler
Jeff Haod4c3f7d2013-02-14 14:14:44 -08001746ENTRY art_quick_proxy_invoke_handler
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001747 SETUP_SAVE_REFS_AND_ARGS_FRAME_WITH_METHOD_IN_A0
Douglas Leung735b8552014-10-31 12:21:40 -07001748 move $a2, rSELF # pass Thread::Current
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001749 la $t9, artQuickProxyInvokeHandler
1750 jalr $t9 # (Method* proxy method, receiver, Thread*, SP)
Douglas Leung735b8552014-10-31 12:21:40 -07001751 addiu $a3, $sp, ARG_SLOT_SIZE # pass $sp (remove arg slots)
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001752 lw $t7, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001753 RESTORE_SAVE_REFS_AND_ARGS_FRAME
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001754 bnez $t7, 1f
Duane Sande34652f2014-11-04 11:09:36 -08001755 # don't care if $v0 and/or $v1 are modified, when exception branch taken
1756 MTD $v0, $v1, $f0, $f1 # move float value to return value
Andreas Gampe8d365912015-01-13 11:32:32 -08001757 jalr $zero, $ra
Duane Sande34652f2014-11-04 11:09:36 -08001758 nop
buzbee5bc5a7b2012-03-07 15:52:59 -080017591:
1760 DELIVER_PENDING_EXCEPTION
Jeff Haod4c3f7d2013-02-14 14:14:44 -08001761END art_quick_proxy_invoke_handler
buzbee5bc5a7b2012-03-07 15:52:59 -08001762
Jeff Hao88474b42013-10-23 16:24:40 -07001763 /*
Goran Jakovljevic59028d92016-03-29 18:05:03 +02001764 * Called to resolve an imt conflict.
1765 * a0 is the conflict ArtMethod.
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001766 * t7 is a hidden argument that holds the target interface method's dex method index.
Goran Jakovljevic59028d92016-03-29 18:05:03 +02001767 *
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001768 * Note that this stub writes to a0, t7 and t8.
Jeff Hao88474b42013-10-23 16:24:40 -07001769 */
Douglas Leung13738bf2014-10-27 14:44:47 -07001770ENTRY art_quick_imt_conflict_trampoline
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001771 lw $t8, 0($sp) # Load referrer.
1772 lw $t8, ART_METHOD_DEX_CACHE_METHODS_OFFSET_32($t8) # Load dex cache methods array.
1773 sll $t7, $t7, POINTER_SIZE_SHIFT # Calculate offset.
1774 addu $t7, $t8, $t7 # Add offset to base.
1775 lw $t7, 0($t7) # Load interface method.
Goran Jakovljevic59028d92016-03-29 18:05:03 +02001776 lw $a0, ART_METHOD_JNI_OFFSET_32($a0) # Load ImtConflictTable.
1777
1778.Limt_table_iterate:
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001779 lw $t8, 0($a0) # Load next entry in ImtConflictTable.
Goran Jakovljevic59028d92016-03-29 18:05:03 +02001780 # Branch if found.
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001781 beq $t8, $t7, .Limt_table_found
Goran Jakovljevic59028d92016-03-29 18:05:03 +02001782 nop
1783 # If the entry is null, the interface method is not in the ImtConflictTable.
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001784 beqz $t8, .Lconflict_trampoline
Goran Jakovljevic59028d92016-03-29 18:05:03 +02001785 nop
1786 # Iterate over the entries of the ImtConflictTable.
1787 b .Limt_table_iterate
1788 addiu $a0, $a0, 2 * __SIZEOF_POINTER__ # Iterate to the next entry.
1789
1790.Limt_table_found:
1791 # We successfully hit an entry in the table. Load the target method and jump to it.
1792 lw $a0, __SIZEOF_POINTER__($a0)
1793 lw $t9, ART_METHOD_QUICK_CODE_OFFSET_32($a0)
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001794 jalr $zero, $t9
Goran Jakovljevic59028d92016-03-29 18:05:03 +02001795 nop
1796
1797.Lconflict_trampoline:
1798 # Call the runtime stub to populate the ImtConflictTable and jump to the resolved method.
Jeff Hao5667f562017-02-27 19:32:01 -08001799 move $a0, $t7 # Load interface method.
Andreas Gampe3031c8d2015-07-13 20:11:06 -07001800 INVOKE_TRAMPOLINE_BODY artInvokeInterfaceTrampoline
Jeff Hao88474b42013-10-23 16:24:40 -07001801END art_quick_imt_conflict_trampoline
1802
Ian Rogers468532e2013-08-05 10:56:33 -07001803 .extern artQuickResolutionTrampoline
1804ENTRY art_quick_resolution_trampoline
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001805 SETUP_SAVE_REFS_AND_ARGS_FRAME
Douglas Leung735b8552014-10-31 12:21:40 -07001806 move $a2, rSELF # pass Thread::Current
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001807 la $t9, artQuickResolutionTrampoline
1808 jalr $t9 # (Method* called, receiver, Thread*, SP)
Douglas Leung735b8552014-10-31 12:21:40 -07001809 addiu $a3, $sp, ARG_SLOT_SIZE # pass $sp (remove arg slots)
Ian Rogers468532e2013-08-05 10:56:33 -07001810 beqz $v0, 1f
Douglas Leung735b8552014-10-31 12:21:40 -07001811 lw $a0, ARG_SLOT_SIZE($sp) # load resolved method to $a0
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001812 RESTORE_SAVE_REFS_AND_ARGS_FRAME
Ian Rogers65d1b222013-09-27 10:59:41 -07001813 move $t9, $v0 # code pointer must be in $t9 to generate the global pointer
Douglas Leungf96e8bd2015-03-27 15:38:30 -07001814 jalr $zero, $t9 # tail call to method
Mathieu Chartier19841522013-10-22 11:29:00 -07001815 nop
Ian Rogers468532e2013-08-05 10:56:33 -070018161:
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001817 RESTORE_SAVE_REFS_AND_ARGS_FRAME
Ian Rogers468532e2013-08-05 10:56:33 -07001818 DELIVER_PENDING_EXCEPTION
1819END art_quick_resolution_trampoline
1820
Douglas Leung735b8552014-10-31 12:21:40 -07001821 .extern artQuickGenericJniTrampoline
1822 .extern artQuickGenericJniEndTrampoline
1823ENTRY art_quick_generic_jni_trampoline
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001824 SETUP_SAVE_REFS_AND_ARGS_FRAME_WITH_METHOD_IN_A0
Douglas Leung735b8552014-10-31 12:21:40 -07001825 move $s8, $sp # save $sp to $s8
1826 move $s3, $gp # save $gp to $s3
1827
1828 # prepare for call to artQuickGenericJniTrampoline(Thread*, SP)
1829 move $a0, rSELF # pass Thread::Current
1830 addiu $a1, $sp, ARG_SLOT_SIZE # save $sp (remove arg slots)
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001831 la $t9, artQuickGenericJniTrampoline
1832 jalr $t9 # (Thread*, SP)
Douglas Leung735b8552014-10-31 12:21:40 -07001833 addiu $sp, $sp, -5120 # reserve space on the stack
1834
1835 # The C call will have registered the complete save-frame on success.
1836 # The result of the call is:
1837 # v0: ptr to native code, 0 on error.
1838 # v1: ptr to the bottom of the used area of the alloca, can restore stack till here.
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001839 beq $v0, $zero, 2f # check entry error
Douglas Leung735b8552014-10-31 12:21:40 -07001840 move $t9, $v0 # save the code ptr
1841 move $sp, $v1 # release part of the alloca
1842
1843 # Load parameters from stack into registers
1844 lw $a0, 0($sp)
1845 lw $a1, 4($sp)
1846 lw $a2, 8($sp)
Douglas Leung735b8552014-10-31 12:21:40 -07001847 lw $a3, 12($sp)
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001848
1849 # artQuickGenericJniTrampoline sets bit 0 of the native code address to 1
1850 # when the first two arguments are both single precision floats. This lets
1851 # us extract them properly from the stack and load into floating point
1852 # registers.
1853 MTD $a0, $a1, $f12, $f13
1854 andi $t0, $t9, 1
1855 xor $t9, $t9, $t0
1856 bnez $t0, 1f
1857 mtc1 $a1, $f14
1858 MTD $a2, $a3, $f14, $f15
1859
18601:
1861 jalr $t9 # native call
1862 nop
Douglas Leung735b8552014-10-31 12:21:40 -07001863 addiu $sp, $sp, 16 # remove arg slots
1864
1865 move $gp, $s3 # restore $gp from $s3
1866
1867 # result sign extension is handled in C code
1868 # prepare for call to artQuickGenericJniEndTrampoline(Thread*, result, result_f)
1869 move $a0, rSELF # pass Thread::Current
1870 move $a2, $v0 # pass result
1871 move $a3, $v1
1872 addiu $sp, $sp, -24 # reserve arg slots
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001873 la $t9, artQuickGenericJniEndTrampoline
1874 jalr $t9
Douglas Leung735b8552014-10-31 12:21:40 -07001875 s.d $f0, 16($sp) # pass result_f
Douglas Leung735b8552014-10-31 12:21:40 -07001876
1877 lw $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001878 bne $t0, $zero, 2f # check for pending exceptions
Nicolas Geoffray126d6592015-03-03 14:28:35 +00001879
Douglas Leung735b8552014-10-31 12:21:40 -07001880 move $sp, $s8 # tear down the alloca
1881
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001882 # tear down the callee-save frame
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001883 RESTORE_SAVE_REFS_AND_ARGS_FRAME
Douglas Leung735b8552014-10-31 12:21:40 -07001884
Duane Sande34652f2014-11-04 11:09:36 -08001885 MTD $v0, $v1, $f0, $f1 # move float value to return value
Andreas Gampe8d365912015-01-13 11:32:32 -08001886 jalr $zero, $ra
Duane Sande34652f2014-11-04 11:09:36 -08001887 nop
Douglas Leung735b8552014-10-31 12:21:40 -07001888
Alexey Frunze1b8464d2016-11-12 17:22:05 -080018892:
Alexey Frunzec61c0762017-04-10 13:54:23 -07001890 lw $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF)
1891 move $gp, $s3 # restore $gp from $s3
Nicolas Geoffray126d6592015-03-03 14:28:35 +00001892 # This will create a new save-all frame, required by the runtime.
Douglas Leung735b8552014-10-31 12:21:40 -07001893 DELIVER_PENDING_EXCEPTION
1894END art_quick_generic_jni_trampoline
Andreas Gampe2da88232014-02-27 12:26:20 -08001895
Ian Rogers468532e2013-08-05 10:56:33 -07001896 .extern artQuickToInterpreterBridge
1897ENTRY art_quick_to_interpreter_bridge
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001898 SETUP_SAVE_REFS_AND_ARGS_FRAME
Douglas Leung735b8552014-10-31 12:21:40 -07001899 move $a1, rSELF # pass Thread::Current
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001900 la $t9, artQuickToInterpreterBridge
1901 jalr $t9 # (Method* method, Thread*, SP)
Douglas Leung735b8552014-10-31 12:21:40 -07001902 addiu $a2, $sp, ARG_SLOT_SIZE # pass $sp (remove arg slots)
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001903 lw $t7, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001904 RESTORE_SAVE_REFS_AND_ARGS_FRAME
Alexey Frunze1b8464d2016-11-12 17:22:05 -08001905 bnez $t7, 1f
Duane Sande34652f2014-11-04 11:09:36 -08001906 # don't care if $v0 and/or $v1 are modified, when exception branch taken
1907 MTD $v0, $v1, $f0, $f1 # move float value to return value
Andreas Gampe8d365912015-01-13 11:32:32 -08001908 jalr $zero, $ra
Duane Sande34652f2014-11-04 11:09:36 -08001909 nop
Ian Rogers7db619b2013-01-16 18:35:48 -080019101:
1911 DELIVER_PENDING_EXCEPTION
Ian Rogers468532e2013-08-05 10:56:33 -07001912END art_quick_to_interpreter_bridge
Ian Rogers7db619b2013-01-16 18:35:48 -08001913
Alex Lightdb01a092017-04-03 15:39:55 -07001914 .extern artInvokeObsoleteMethod
1915ENTRY art_invoke_obsolete_method_stub
1916 SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
1917 la $t9, artInvokeObsoleteMethod
1918 jalr $t9 # (Method* method, Thread* self)
1919 move $a1, rSELF # pass Thread::Current
1920END art_invoke_obsolete_method_stub
1921
buzbee5bc5a7b2012-03-07 15:52:59 -08001922 /*
jeffhao725a9572012-11-13 18:20:12 -08001923 * Routine that intercepts method calls and returns.
buzbee5bc5a7b2012-03-07 15:52:59 -08001924 */
Jeff Haod4c3f7d2013-02-14 14:14:44 -08001925 .extern artInstrumentationMethodEntryFromCode
1926 .extern artInstrumentationMethodExitFromCode
Ian Rogers468532e2013-08-05 10:56:33 -07001927ENTRY art_quick_instrumentation_entry
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001928 SETUP_SAVE_REFS_AND_ARGS_FRAME
Douglas Leung735b8552014-10-31 12:21:40 -07001929 sw $a0, 28($sp) # save arg0 in free arg slot
Ian Rogers1d8cdbc2014-09-22 22:51:09 -07001930 move $a3, $ra # pass $ra
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001931 la $t9, artInstrumentationMethodEntryFromCode
1932 jalr $t9 # (Method*, Object*, Thread*, LR)
Ian Rogers62d6c772013-02-27 08:32:07 -08001933 move $a2, rSELF # pass Thread::Current
jeffhao8161c032012-10-31 15:50:00 -07001934 move $t9, $v0 # $t9 holds reference to code
Douglas Leung735b8552014-10-31 12:21:40 -07001935 lw $a0, 28($sp) # restore arg0 from free arg slot
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001936 RESTORE_SAVE_REFS_AND_ARGS_FRAME
jeffhao8161c032012-10-31 15:50:00 -07001937 jalr $t9 # call method
Ian Rogers62d6c772013-02-27 08:32:07 -08001938 nop
Ian Rogers468532e2013-08-05 10:56:33 -07001939END art_quick_instrumentation_entry
buzbee5bc5a7b2012-03-07 15:52:59 -08001940 /* intentional fallthrough */
Ian Rogers468532e2013-08-05 10:56:33 -07001941 .global art_quick_instrumentation_exit
1942art_quick_instrumentation_exit:
Jeff Haod4c3f7d2013-02-14 14:14:44 -08001943 .cfi_startproc
jeffhao12051ea2013-01-10 11:24:31 -08001944 addiu $t9, $ra, 4 # put current address into $t9 to rebuild $gp
Ian Rogers1d8cdbc2014-09-22 22:51:09 -07001945 .cpload $t9
Douglas Leungc3d131e2014-07-16 17:32:41 -07001946 move $ra, $zero # link register is to here, so clobber with 0 for later checks
Douglas Leung735b8552014-10-31 12:21:40 -07001947
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001948 SETUP_SAVE_REFS_ONLY_FRAME
Douglas Leung735b8552014-10-31 12:21:40 -07001949 addiu $sp, $sp, -16 # allocate temp storage on the stack
1950 .cfi_adjust_cfa_offset 16
Douglas Leungf96e8bd2015-03-27 15:38:30 -07001951 sw $v0, ARG_SLOT_SIZE+12($sp)
1952 .cfi_rel_offset 2, ARG_SLOT_SIZE+12
1953 sw $v1, ARG_SLOT_SIZE+8($sp)
1954 .cfi_rel_offset 3, ARG_SLOT_SIZE+8
1955 s.d $f0, ARG_SLOT_SIZE($sp)
Duane Sande34652f2014-11-04 11:09:36 -08001956 s.d $f0, 16($sp) # pass fpr result
Ian Rogers62d6c772013-02-27 08:32:07 -08001957 move $a2, $v0 # pass gpr result
1958 move $a3, $v1
Douglas Leungf96e8bd2015-03-27 15:38:30 -07001959 addiu $a1, $sp, ARG_SLOT_SIZE+16 # pass $sp (remove arg slots and temp storage)
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001960 la $t9, artInstrumentationMethodExitFromCode
1961 jalr $t9 # (Thread*, SP, gpr_res, fpr_res)
jeffhao12051ea2013-01-10 11:24:31 -08001962 move $a0, rSELF # pass Thread::Current
Douglas Leungf96e8bd2015-03-27 15:38:30 -07001963 move $t9, $v0 # set aside returned link register
jeffhao12051ea2013-01-10 11:24:31 -08001964 move $ra, $v1 # set link register for deoptimization
Douglas Leungf96e8bd2015-03-27 15:38:30 -07001965 lw $v0, ARG_SLOT_SIZE+12($sp) # restore return values
1966 lw $v1, ARG_SLOT_SIZE+8($sp)
1967 l.d $f0, ARG_SLOT_SIZE($sp)
1968 jalr $zero, $t9 # return
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001969 addiu $sp, $sp, ARG_SLOT_SIZE+FRAME_SIZE_SAVE_REFS_ONLY+16 # restore stack
1970 .cfi_adjust_cfa_offset -(ARG_SLOT_SIZE+FRAME_SIZE_SAVE_REFS_ONLY+16)
Ian Rogers468532e2013-08-05 10:56:33 -07001971END art_quick_instrumentation_exit
buzbee5bc5a7b2012-03-07 15:52:59 -08001972
jeffhao12051ea2013-01-10 11:24:31 -08001973 /*
Ian Rogers62d6c772013-02-27 08:32:07 -08001974 * Instrumentation has requested that we deoptimize into the interpreter. The deoptimization
1975 * will long jump to the upcall with a special exception of -1.
jeffhao12051ea2013-01-10 11:24:31 -08001976 */
Jeff Haod4c3f7d2013-02-14 14:14:44 -08001977 .extern artDeoptimize
Jeff Haod4c3f7d2013-02-14 14:14:44 -08001978ENTRY art_quick_deoptimize
Vladimir Markofd36f1f2016-08-03 18:49:58 +01001979 SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001980 la $t9, artDeoptimize
Nicolas Geoffray4e92c3c2017-05-08 09:34:26 +01001981 jalr $t9 # (Thread*)
Ian Rogers1d8cdbc2014-09-22 22:51:09 -07001982 move $a0, rSELF # pass Thread::current
Jeff Haod4c3f7d2013-02-14 14:14:44 -08001983END art_quick_deoptimize
jeffhao12051ea2013-01-10 11:24:31 -08001984
buzbee5bc5a7b2012-03-07 15:52:59 -08001985 /*
Sebastien Hertz07474662015-08-25 15:12:33 +00001986 * Compiled code has requested that we deoptimize into the interpreter. The deoptimization
1987 * will long jump to the upcall with a special exception of -1.
1988 */
1989 .extern artDeoptimizeFromCompiledCode
1990ENTRY art_quick_deoptimize_from_compiled_code
Vladimir Marko239d6ea2016-09-05 10:44:04 +01001991 SETUP_SAVE_EVERYTHING_FRAME
Goran Jakovljevic590b1362016-03-21 14:24:43 +01001992 la $t9, artDeoptimizeFromCompiledCode
Nicolas Geoffray4e92c3c2017-05-08 09:34:26 +01001993 jalr $t9 # (DeoptimizationKind, Thread*)
1994 move $a1, rSELF # pass Thread::current
Sebastien Hertz07474662015-08-25 15:12:33 +00001995END art_quick_deoptimize_from_compiled_code
1996
1997 /*
buzbee5bc5a7b2012-03-07 15:52:59 -08001998 * Long integer shift. This is different from the generic 32/64-bit
1999 * binary operations because vAA/vBB are 64-bit but vCC (the shift
2000 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low
2001 * 6 bits.
2002 * On entry:
jeffhao7fbee072012-08-24 17:56:54 -07002003 * $a0: low word
2004 * $a1: high word
2005 * $a2: shift count
buzbee5bc5a7b2012-03-07 15:52:59 -08002006 */
Ian Rogers1d8cdbc2014-09-22 22:51:09 -07002007ENTRY_NO_GP art_quick_shl_long
buzbee5bc5a7b2012-03-07 15:52:59 -08002008 /* shl-long vAA, vBB, vCC */
jeffhao7fbee072012-08-24 17:56:54 -07002009 sll $v0, $a0, $a2 # rlo<- alo << (shift&31)
2010 not $v1, $a2 # rhi<- 31-shift (shift is 5b)
2011 srl $a0, 1
2012 srl $a0, $v1 # alo<- alo >> (32-(shift&31))
2013 sll $v1, $a1, $a2 # rhi<- ahi << (shift&31)
jeffhao7fbee072012-08-24 17:56:54 -07002014 andi $a2, 0x20 # shift< shift & 0x20
Duane Sande34652f2014-11-04 11:09:36 -08002015 beqz $a2, 1f
2016 or $v1, $a0 # rhi<- rhi | alo
2017
2018 move $v1, $v0 # rhi<- rlo (if shift&0x20)
2019 move $v0, $zero # rlo<- 0 (if shift&0x20)
2020
Andreas Gampe8d365912015-01-13 11:32:32 -080020211: jalr $zero, $ra
Duane Sande34652f2014-11-04 11:09:36 -08002022 nop
Jeff Haod4c3f7d2013-02-14 14:14:44 -08002023END art_quick_shl_long
buzbee5bc5a7b2012-03-07 15:52:59 -08002024
buzbee5bc5a7b2012-03-07 15:52:59 -08002025 /*
2026 * Long integer shift. This is different from the generic 32/64-bit
2027 * binary operations because vAA/vBB are 64-bit but vCC (the shift
2028 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low
2029 * 6 bits.
2030 * On entry:
jeffhao7fbee072012-08-24 17:56:54 -07002031 * $a0: low word
2032 * $a1: high word
2033 * $a2: shift count
buzbee5bc5a7b2012-03-07 15:52:59 -08002034 */
Ian Rogers1d8cdbc2014-09-22 22:51:09 -07002035ENTRY_NO_GP art_quick_shr_long
jeffhao7fbee072012-08-24 17:56:54 -07002036 sra $v1, $a1, $a2 # rhi<- ahi >> (shift&31)
2037 srl $v0, $a0, $a2 # rlo<- alo >> (shift&31)
2038 sra $a3, $a1, 31 # $a3<- sign(ah)
2039 not $a0, $a2 # alo<- 31-shift (shift is 5b)
2040 sll $a1, 1
2041 sll $a1, $a0 # ahi<- ahi << (32-(shift&31))
jeffhao7fbee072012-08-24 17:56:54 -07002042 andi $a2, 0x20 # shift & 0x20
Douglas Leung475cfd82014-12-16 20:15:41 -08002043 beqz $a2, 1f
Duane Sande34652f2014-11-04 11:09:36 -08002044 or $v0, $a1 # rlo<- rlo | ahi
2045
2046 move $v0, $v1 # rlo<- rhi (if shift&0x20)
2047 move $v1, $a3 # rhi<- sign(ahi) (if shift&0x20)
2048
Andreas Gampe8d365912015-01-13 11:32:32 -080020491: jalr $zero, $ra
Duane Sande34652f2014-11-04 11:09:36 -08002050 nop
Jeff Haod4c3f7d2013-02-14 14:14:44 -08002051END art_quick_shr_long
buzbee5bc5a7b2012-03-07 15:52:59 -08002052
buzbee5bc5a7b2012-03-07 15:52:59 -08002053 /*
2054 * Long integer shift. This is different from the generic 32/64-bit
2055 * binary operations because vAA/vBB are 64-bit but vCC (the shift
2056 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low
2057 * 6 bits.
2058 * On entry:
Goran Jakovljevic590b1362016-03-21 14:24:43 +01002059 * $a0: low word
2060 * $a1: high word
2061 * $a2: shift count
buzbee5bc5a7b2012-03-07 15:52:59 -08002062 */
2063 /* ushr-long vAA, vBB, vCC */
Ian Rogers1d8cdbc2014-09-22 22:51:09 -07002064ENTRY_NO_GP art_quick_ushr_long
jeffhaofc6a30e2012-10-18 18:24:15 -07002065 srl $v1, $a1, $a2 # rhi<- ahi >> (shift&31)
jeffhao7fbee072012-08-24 17:56:54 -07002066 srl $v0, $a0, $a2 # rlo<- alo >> (shift&31)
jeffhao7fbee072012-08-24 17:56:54 -07002067 not $a0, $a2 # alo<- 31-shift (shift is 5b)
2068 sll $a1, 1
2069 sll $a1, $a0 # ahi<- ahi << (32-(shift&31))
jeffhao7fbee072012-08-24 17:56:54 -07002070 andi $a2, 0x20 # shift & 0x20
Duane Sande34652f2014-11-04 11:09:36 -08002071 beqz $a2, 1f
2072 or $v0, $a1 # rlo<- rlo | ahi
2073
2074 move $v0, $v1 # rlo<- rhi (if shift&0x20)
2075 move $v1, $zero # rhi<- 0 (if shift&0x20)
2076
Andreas Gampe8d365912015-01-13 11:32:32 -080020771: jalr $zero, $ra
Duane Sande34652f2014-11-04 11:09:36 -08002078 nop
Jeff Haod4c3f7d2013-02-14 14:14:44 -08002079END art_quick_ushr_long
jeffhao7fbee072012-08-24 17:56:54 -07002080
Chris Larsencf283da2016-01-19 16:45:35 -08002081/* java.lang.String.indexOf(int ch, int fromIndex=0) */
2082ENTRY_NO_GP art_quick_indexof
2083/* $a0 holds address of "this" */
2084/* $a1 holds "ch" */
2085/* $a2 holds "fromIndex" */
Goran Jakovljevicf94fa812017-02-10 17:48:52 +01002086#if (STRING_COMPRESSION_FEATURE)
2087 lw $a3, MIRROR_STRING_COUNT_OFFSET($a0) # 'count' field of this
Chris Larsencf283da2016-01-19 16:45:35 -08002088#else
Goran Jakovljevicf94fa812017-02-10 17:48:52 +01002089 lw $t0, MIRROR_STRING_COUNT_OFFSET($a0) # this.length()
Chris Larsencf283da2016-01-19 16:45:35 -08002090#endif
Goran Jakovljevicf94fa812017-02-10 17:48:52 +01002091 slt $t1, $a2, $zero # if fromIndex < 0
Goran Jakovljeviccdb23d62017-02-28 14:58:01 +01002092#if defined(_MIPS_ARCH_MIPS32R6)
Goran Jakovljevicf94fa812017-02-10 17:48:52 +01002093 seleqz $a2, $a2, $t1 # fromIndex = 0;
2094#else
2095 movn $a2, $zero, $t1 # fromIndex = 0;
2096#endif
Goran Jakovljeviccdb23d62017-02-28 14:58:01 +01002097
Goran Jakovljevicf94fa812017-02-10 17:48:52 +01002098#if (STRING_COMPRESSION_FEATURE)
2099 srl $t0, $a3, 1 # $a3 holds count (with flag) and $t0 holds actual length
2100#endif
2101 subu $t0, $t0, $a2 # this.length() - fromIndex
2102 blez $t0, 6f # if this.length()-fromIndex <= 0
2103 li $v0, -1 # return -1;
Chris Larsencf283da2016-01-19 16:45:35 -08002104
Goran Jakovljevicf94fa812017-02-10 17:48:52 +01002105#if (STRING_COMPRESSION_FEATURE)
2106 sll $a3, $a3, 31 # Extract compression flag.
2107 beqz $a3, .Lstring_indexof_compressed
2108 move $t2, $a0 # Save a copy in $t2 to later compute result (in branch delay slot).
2109#endif
2110 sll $v0, $a2, 1 # $a0 += $a2 * 2
2111 addu $a0, $a0, $v0 # " ditto "
2112 move $v0, $a2 # Set i to fromIndex.
Chris Larsencf283da2016-01-19 16:45:35 -08002113
21141:
Goran Jakovljevicf94fa812017-02-10 17:48:52 +01002115 lhu $t3, MIRROR_STRING_VALUE_OFFSET($a0) # if this.charAt(i) == ch
2116 beq $t3, $a1, 6f # return i;
2117 addu $a0, $a0, 2 # i++
2118 subu $t0, $t0, 1 # this.length() - i
2119 bnez $t0, 1b # while this.length() - i > 0
2120 addu $v0, $v0, 1 # i++
Chris Larsencf283da2016-01-19 16:45:35 -08002121
Goran Jakovljevicf94fa812017-02-10 17:48:52 +01002122 li $v0, -1 # if this.length() - i <= 0
2123 # return -1;
Chris Larsencf283da2016-01-19 16:45:35 -08002124
21256:
Goran Jakovljevicf94fa812017-02-10 17:48:52 +01002126 j $ra
2127 nop
2128
2129#if (STRING_COMPRESSION_FEATURE)
2130.Lstring_indexof_compressed:
2131 addu $a0, $a0, $a2 # $a0 += $a2
2132
2133.Lstring_indexof_compressed_loop:
2134 lbu $t3, MIRROR_STRING_VALUE_OFFSET($a0)
2135 beq $t3, $a1, .Lstring_indexof_compressed_matched
2136 subu $t0, $t0, 1
2137 bgtz $t0, .Lstring_indexof_compressed_loop
2138 addu $a0, $a0, 1
2139
2140.Lstring_indexof_nomatch:
2141 jalr $zero, $ra
2142 li $v0, -1 # return -1;
2143
2144.Lstring_indexof_compressed_matched:
2145 jalr $zero, $ra
2146 subu $v0, $a0, $t2 # return (current - start);
2147#endif
Chris Larsencf283da2016-01-19 16:45:35 -08002148END art_quick_indexof
2149
Chris Larsencf283da2016-01-19 16:45:35 -08002150/* java.lang.String.compareTo(String anotherString) */
2151ENTRY_NO_GP art_quick_string_compareto
2152/* $a0 holds address of "this" */
2153/* $a1 holds address of "anotherString" */
Goran Jakovljevicf94fa812017-02-10 17:48:52 +01002154 beq $a0, $a1, .Lstring_compareto_length_diff # this and anotherString are the same object
2155 move $a3, $a2 # trick to return 0 (it returns a2 - a3)
Chris Larsencf283da2016-01-19 16:45:35 -08002156
Goran Jakovljevicf94fa812017-02-10 17:48:52 +01002157#if (STRING_COMPRESSION_FEATURE)
2158 lw $t0, MIRROR_STRING_COUNT_OFFSET($a0) # 'count' field of this
2159 lw $t1, MIRROR_STRING_COUNT_OFFSET($a1) # 'count' field of anotherString
2160 sra $a2, $t0, 1 # this.length()
2161 sra $a3, $t1, 1 # anotherString.length()
2162#else
2163 lw $a2, MIRROR_STRING_COUNT_OFFSET($a0) # this.length()
2164 lw $a3, MIRROR_STRING_COUNT_OFFSET($a1) # anotherString.length()
2165#endif
Chris Larsencf283da2016-01-19 16:45:35 -08002166
Goran Jakovljevicf94fa812017-02-10 17:48:52 +01002167 MINu $t2, $a2, $a3
2168 # $t2 now holds min(this.length(),anotherString.length())
Chris Larsencf283da2016-01-19 16:45:35 -08002169
Goran Jakovljevicf94fa812017-02-10 17:48:52 +01002170 # while min(this.length(),anotherString.length())-i != 0
2171 beqz $t2, .Lstring_compareto_length_diff # if $t2==0
2172 nop # return (this.length() - anotherString.length())
2173
2174#if (STRING_COMPRESSION_FEATURE)
2175 # Differ cases:
2176 sll $t3, $t0, 31
2177 beqz $t3, .Lstring_compareto_this_is_compressed
2178 sll $t3, $t1, 31 # In branch delay slot.
2179 beqz $t3, .Lstring_compareto_that_is_compressed
2180 nop
2181 b .Lstring_compareto_both_not_compressed
2182 nop
2183
2184.Lstring_compareto_this_is_compressed:
2185 beqz $t3, .Lstring_compareto_both_compressed
2186 nop
2187 /* If (this->IsCompressed() && that->IsCompressed() == false) */
2188.Lstring_compareto_loop_comparison_this_compressed:
2189 lbu $t0, MIRROR_STRING_VALUE_OFFSET($a0)
2190 lhu $t1, MIRROR_STRING_VALUE_OFFSET($a1)
2191 bne $t0, $t1, .Lstring_compareto_char_diff
2192 addiu $a0, $a0, 1 # point at this.charAt(i++) - compressed
2193 subu $t2, $t2, 1 # new value of min(this.length(),anotherString.length())-i
2194 bnez $t2, .Lstring_compareto_loop_comparison_this_compressed
2195 addiu $a1, $a1, 2 # point at anotherString.charAt(i++) - uncompressed
2196 jalr $zero, $ra
2197 subu $v0, $a2, $a3 # return (this.length() - anotherString.length())
2198
2199.Lstring_compareto_that_is_compressed:
2200 lhu $t0, MIRROR_STRING_VALUE_OFFSET($a0)
2201 lbu $t1, MIRROR_STRING_VALUE_OFFSET($a1)
2202 bne $t0, $t1, .Lstring_compareto_char_diff
2203 addiu $a0, $a0, 2 # point at this.charAt(i++) - uncompressed
2204 subu $t2, $t2, 1 # new value of min(this.length(),anotherString.length())-i
2205 bnez $t2, .Lstring_compareto_that_is_compressed
2206 addiu $a1, $a1, 1 # point at anotherString.charAt(i++) - compressed
2207 jalr $zero, $ra
2208 subu $v0, $a2, $a3 # return (this.length() - anotherString.length())
2209
2210.Lstring_compareto_both_compressed:
2211 lbu $t0, MIRROR_STRING_VALUE_OFFSET($a0)
2212 lbu $t1, MIRROR_STRING_VALUE_OFFSET($a1)
2213 bne $t0, $t1, .Lstring_compareto_char_diff
2214 addiu $a0, $a0, 1 # point at this.charAt(i++) - compressed
2215 subu $t2, $t2, 1 # new value of min(this.length(),anotherString.length())-i
2216 bnez $t2, .Lstring_compareto_both_compressed
2217 addiu $a1, $a1, 1 # point at anotherString.charAt(i++) - compressed
2218 jalr $zero, $ra
2219 subu $v0, $a2, $a3 # return (this.length() - anotherString.length())
2220#endif
2221
2222.Lstring_compareto_both_not_compressed:
2223 lhu $t0, MIRROR_STRING_VALUE_OFFSET($a0) # while this.charAt(i) == anotherString.charAt(i)
2224 lhu $t1, MIRROR_STRING_VALUE_OFFSET($a1)
2225 bne $t0, $t1, .Lstring_compareto_char_diff # if this.charAt(i) != anotherString.charAt(i)
2226 # return (this.charAt(i) - anotherString.charAt(i))
2227 addiu $a0, $a0, 2 # point at this.charAt(i++)
2228 subu $t2, $t2, 1 # new value of min(this.length(),anotherString.length())-i
2229 bnez $t2, .Lstring_compareto_both_not_compressed
2230 addiu $a1, $a1, 2 # point at anotherString.charAt(i++)
2231
2232.Lstring_compareto_length_diff:
2233 jalr $zero, $ra
2234 subu $v0, $a2, $a3 # return (this.length() - anotherString.length())
2235
2236.Lstring_compareto_char_diff:
2237 jalr $zero, $ra
2238 subu $v0, $t0, $t1 # return (this.charAt(i) - anotherString.charAt(i))
Chris Larsencf283da2016-01-19 16:45:35 -08002239END art_quick_string_compareto
Orion Hodsonac141392017-01-13 11:53:47 +00002240
Alexey Frunze15958152017-02-09 19:08:30 -08002241 /*
2242 * Create a function `name` calling the ReadBarrier::Mark routine,
2243 * getting its argument and returning its result through register
2244 * `reg`, saving and restoring all caller-save registers.
2245 */
2246.macro READ_BARRIER_MARK_REG name, reg
2247ENTRY \name
Alexey Frunzea3cb1322017-05-01 18:49:46 -07002248 // Null check so that we can load the lock word.
2249 bnez \reg, .Lnot_null_\name
2250 nop
2251.Lret_rb_\name:
2252 jalr $zero, $ra
2253 nop
2254.Lnot_null_\name:
2255 // Check lock word for mark bit, if marked return.
2256 lw $t9, MIRROR_OBJECT_LOCK_WORD_OFFSET(\reg)
2257 .set push
2258 .set noat
2259 sll $at, $t9, 31 - LOCK_WORD_MARK_BIT_SHIFT # Move mark bit to sign bit.
2260 bltz $at, .Lret_rb_\name
2261#if (LOCK_WORD_STATE_SHIFT != 30) || (LOCK_WORD_STATE_FORWARDING_ADDRESS != 3)
2262 // The below code depends on the lock word state being in the highest bits
2263 // and the "forwarding address" state having all bits set.
2264#error "Unexpected lock word state shift or forwarding address state value."
2265#endif
2266 // Test that both the forwarding state bits are 1.
2267 sll $at, $t9, 1
2268 and $at, $at, $t9 # Sign bit = 1 IFF both bits are 1.
2269 bltz $at, .Lret_forwarding_address\name
2270 nop
2271 .set pop
2272
2273 addiu $sp, $sp, -160 # Includes 16 bytes of space for argument registers a0-a3.
Alexey Frunze15958152017-02-09 19:08:30 -08002274 .cfi_adjust_cfa_offset 160
2275
2276 sw $ra, 156($sp)
2277 .cfi_rel_offset 31, 156
2278 sw $t8, 152($sp)
2279 .cfi_rel_offset 24, 152
2280 sw $t7, 148($sp)
2281 .cfi_rel_offset 15, 148
2282 sw $t6, 144($sp)
2283 .cfi_rel_offset 14, 144
2284 sw $t5, 140($sp)
2285 .cfi_rel_offset 13, 140
2286 sw $t4, 136($sp)
2287 .cfi_rel_offset 12, 136
2288 sw $t3, 132($sp)
2289 .cfi_rel_offset 11, 132
2290 sw $t2, 128($sp)
2291 .cfi_rel_offset 10, 128
2292 sw $t1, 124($sp)
2293 .cfi_rel_offset 9, 124
2294 sw $t0, 120($sp)
2295 .cfi_rel_offset 8, 120
2296 sw $a3, 116($sp)
2297 .cfi_rel_offset 7, 116
2298 sw $a2, 112($sp)
2299 .cfi_rel_offset 6, 112
2300 sw $a1, 108($sp)
2301 .cfi_rel_offset 5, 108
2302 sw $a0, 104($sp)
2303 .cfi_rel_offset 4, 104
2304 sw $v1, 100($sp)
2305 .cfi_rel_offset 3, 100
2306 sw $v0, 96($sp)
2307 .cfi_rel_offset 2, 96
2308
2309 la $t9, artReadBarrierMark
2310
2311 sdc1 $f18, 88($sp)
2312 sdc1 $f16, 80($sp)
2313 sdc1 $f14, 72($sp)
2314 sdc1 $f12, 64($sp)
2315 sdc1 $f10, 56($sp)
2316 sdc1 $f8, 48($sp)
2317 sdc1 $f6, 40($sp)
2318 sdc1 $f4, 32($sp)
2319 sdc1 $f2, 24($sp)
2320
2321 .ifnc \reg, $a0
2322 move $a0, \reg # pass obj from `reg` in a0
2323 .endif
2324 jalr $t9 # v0 <- artReadBarrierMark(obj)
2325 sdc1 $f0, 16($sp) # in delay slot
2326
2327 lw $ra, 156($sp)
2328 .cfi_restore 31
2329 lw $t8, 152($sp)
2330 .cfi_restore 24
2331 lw $t7, 148($sp)
2332 .cfi_restore 15
2333 lw $t6, 144($sp)
2334 .cfi_restore 14
2335 lw $t5, 140($sp)
2336 .cfi_restore 13
2337 lw $t4, 136($sp)
2338 .cfi_restore 12
2339 lw $t3, 132($sp)
2340 .cfi_restore 11
2341 lw $t2, 128($sp)
2342 .cfi_restore 10
2343 lw $t1, 124($sp)
2344 .cfi_restore 9
2345 lw $t0, 120($sp)
2346 .cfi_restore 8
2347 lw $a3, 116($sp)
2348 .cfi_restore 7
2349 lw $a2, 112($sp)
2350 .cfi_restore 6
2351 lw $a1, 108($sp)
2352 .cfi_restore 5
2353 lw $a0, 104($sp)
2354 .cfi_restore 4
2355 lw $v1, 100($sp)
2356 .cfi_restore 3
2357
2358 .ifnc \reg, $v0
2359 move \reg, $v0 # `reg` <- v0
2360 lw $v0, 96($sp)
2361 .cfi_restore 2
2362 .endif
2363
2364 ldc1 $f18, 88($sp)
2365 ldc1 $f16, 80($sp)
2366 ldc1 $f14, 72($sp)
2367 ldc1 $f12, 64($sp)
2368 ldc1 $f10, 56($sp)
2369 ldc1 $f8, 48($sp)
2370 ldc1 $f6, 40($sp)
2371 ldc1 $f4, 32($sp)
2372 ldc1 $f2, 24($sp)
2373 ldc1 $f0, 16($sp)
2374
2375 jalr $zero, $ra
2376 addiu $sp, $sp, 160
2377 .cfi_adjust_cfa_offset -160
Alexey Frunzea3cb1322017-05-01 18:49:46 -07002378
2379.Lret_forwarding_address\name:
2380 jalr $zero, $ra
2381 // Shift left by the forwarding address shift. This clears out the state bits since they are
2382 // in the top 2 bits of the lock word.
2383 sll \reg, $t9, LOCK_WORD_STATE_FORWARDING_ADDRESS_SHIFT
Alexey Frunze15958152017-02-09 19:08:30 -08002384END \name
2385.endm
2386
2387// Note that art_quick_read_barrier_mark_regXX corresponds to register XX+1.
2388// ZERO (register 0) is reserved.
2389// AT (register 1) is reserved as a temporary/scratch register.
2390READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg01, $v0
2391READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg02, $v1
2392READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg03, $a0
2393READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg04, $a1
2394READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg05, $a2
2395READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg06, $a3
2396READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg07, $t0
2397READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg08, $t1
2398READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg09, $t2
2399READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg10, $t3
2400READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg11, $t4
2401READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg12, $t5
2402READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg13, $t6
2403READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg14, $t7
2404// S0 and S1 (registers 16 and 17) are reserved as suspended and thread registers.
2405READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg17, $s2
2406READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg18, $s3
2407READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg19, $s4
2408READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg20, $s5
2409READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg21, $s6
2410READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg22, $s7
2411// T8 and T9 (registers 24 and 25) are reserved as temporary/scratch registers.
2412// K0, K1, GP, SP (registers 26 - 29) are reserved.
2413READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg29, $s8
2414// RA (register 31) is reserved.
2415
Orion Hodsonac141392017-01-13 11:53:47 +00002416.extern artInvokePolymorphic
2417ENTRY art_quick_invoke_polymorphic
2418 SETUP_SAVE_REFS_AND_ARGS_FRAME
2419 move $a2, rSELF # Make $a2 an alias for the current Thread.
Alexey Frunzec480b982017-01-16 19:03:21 -08002420 addiu $a3, $sp, ARG_SLOT_SIZE # Make $a3 a pointer to the saved frame context.
Orion Hodsonac141392017-01-13 11:53:47 +00002421 sw $zero, 20($sp) # Initialize JValue result.
2422 sw $zero, 16($sp)
Orion Hodsonac141392017-01-13 11:53:47 +00002423 la $t9, artInvokePolymorphic
2424 jalr $t9 # (result, receiver, Thread*, context)
Alexey Frunzec480b982017-01-16 19:03:21 -08002425 addiu $a0, $sp, 16 # Make $a0 a pointer to the JValue result
Orion Hodsonac141392017-01-13 11:53:47 +00002426.macro MATCH_RETURN_TYPE c, handler
2427 li $t0, \c
2428 beq $v0, $t0, \handler
2429.endm
2430 MATCH_RETURN_TYPE 'V', .Lcleanup_and_return
2431 MATCH_RETURN_TYPE 'L', .Lstore_int_result
2432 MATCH_RETURN_TYPE 'I', .Lstore_int_result
2433 MATCH_RETURN_TYPE 'J', .Lstore_long_result
2434 MATCH_RETURN_TYPE 'B', .Lstore_int_result
2435 MATCH_RETURN_TYPE 'C', .Lstore_char_result
2436 MATCH_RETURN_TYPE 'D', .Lstore_double_result
2437 MATCH_RETURN_TYPE 'F', .Lstore_float_result
2438 MATCH_RETURN_TYPE 'S', .Lstore_int_result
Alexey Frunzec480b982017-01-16 19:03:21 -08002439 MATCH_RETURN_TYPE 'Z', .Lstore_boolean_result
Orion Hodsonac141392017-01-13 11:53:47 +00002440.purgem MATCH_RETURN_TYPE
2441 nop
2442 b .Lcleanup_and_return
2443 nop
2444.Lstore_boolean_result:
Alexey Frunzec480b982017-01-16 19:03:21 -08002445 b .Lcleanup_and_return
Orion Hodsonac141392017-01-13 11:53:47 +00002446 lbu $v0, 16($sp) # Move byte from JValue result to return value register.
Orion Hodsonac141392017-01-13 11:53:47 +00002447.Lstore_char_result:
Orion Hodsonac141392017-01-13 11:53:47 +00002448 b .Lcleanup_and_return
Alexey Frunzec480b982017-01-16 19:03:21 -08002449 lhu $v0, 16($sp) # Move char from JValue result to return value register.
Orion Hodsonac141392017-01-13 11:53:47 +00002450.Lstore_double_result:
2451.Lstore_float_result:
2452 LDu $f0, $f1, 16, $sp, $t0 # Move double/float from JValue result to return value register.
2453 b .Lcleanup_and_return
2454 nop
2455.Lstore_long_result:
2456 lw $v1, 20($sp) # Move upper bits from JValue result to return value register.
2457 // Fall-through for lower bits.
2458.Lstore_int_result:
2459 lw $v0, 16($sp) # Move lower bits from JValue result to return value register.
2460 // Fall-through to clean up and return.
2461.Lcleanup_and_return:
Orion Hodsonac141392017-01-13 11:53:47 +00002462 lw $t7, THREAD_EXCEPTION_OFFSET(rSELF) # Load Thread::Current()->exception_
2463 RESTORE_SAVE_REFS_AND_ARGS_FRAME
2464 bnez $t7, 1f # Success if no exception is pending.
2465 nop
2466 jalr $zero, $ra
2467 nop
24681:
2469 DELIVER_PENDING_EXCEPTION
2470END art_quick_invoke_polymorphic