blob: ae6962076b9791f46e77a2c2d24c88c003c77539 [file] [log] [blame]
Andreas Gampe1a5c4062015-01-15 12:10:47 -08001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "asm_support_mips64.S"
18
19#include "arch/quick_alloc_entrypoints.S"
20
21 .set noreorder
22 .balign 16
23
24 /* Deliver the given exception */
25 .extern artDeliverExceptionFromCode
26 /* Deliver an exception pending on a thread */
27 .extern artDeliverPendingExceptionFromCode
28
29 /*
Goran Jakovljevic04568812015-04-23 15:27:23 +020030 * Macro that sets up $gp and stores the previous $gp value to $t8.
31 * This macro modifies v1 and t8.
32 */
33.macro SETUP_GP
34 move $v1, $ra
35 bal 1f
36 nop
371:
38 .cpsetup $ra, $t8, 1b
39 move $ra, $v1
40.endm
41
42 /*
Andreas Gampe1a5c4062015-01-15 12:10:47 -080043 * Macro that sets up the callee save frame to conform with
44 * Runtime::CreateCalleeSaveMethod(kSaveAll)
45 * callee-save: padding + $f24-$f31 + $s0-$s7 + $gp + $ra + $s8 = 19 total + 1x8 bytes padding
46 */
47.macro SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
48 daddiu $sp, $sp, -160
49 .cfi_adjust_cfa_offset 160
50
51 // Ugly compile-time check, but we only have the preprocessor.
52#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVE != 160)
53#error "SAVE_ALL_CALLEE_SAVE_FRAME(MIPS64) size not as expected."
54#endif
55
56 sd $ra, 152($sp)
57 .cfi_rel_offset 31, 152
58 sd $s8, 144($sp)
59 .cfi_rel_offset 30, 144
Goran Jakovljevic04568812015-04-23 15:27:23 +020060 sd $t8, 136($sp) # t8 holds caller's gp, now save it to the stack.
61 .cfi_rel_offset 28, 136 # Value from gp is pushed, so set the cfi offset accordingly.
Andreas Gampe1a5c4062015-01-15 12:10:47 -080062 sd $s7, 128($sp)
63 .cfi_rel_offset 23, 128
64 sd $s6, 120($sp)
65 .cfi_rel_offset 22, 120
66 sd $s5, 112($sp)
67 .cfi_rel_offset 21, 112
68 sd $s4, 104($sp)
69 .cfi_rel_offset 20, 104
70 sd $s3, 96($sp)
71 .cfi_rel_offset 19, 96
72 sd $s2, 88($sp)
73 .cfi_rel_offset 18, 88
74 sd $s1, 80($sp)
75 .cfi_rel_offset 17, 80
76 sd $s0, 72($sp)
77 .cfi_rel_offset 16, 72
78
79 // FP callee-saves
80 s.d $f31, 64($sp)
81 s.d $f30, 56($sp)
82 s.d $f29, 48($sp)
83 s.d $f28, 40($sp)
84 s.d $f27, 32($sp)
85 s.d $f26, 24($sp)
86 s.d $f25, 16($sp)
87 s.d $f24, 8($sp)
88
89 # load appropriate callee-save-method
Lazar Trsic84bc06e2015-06-10 16:05:46 +020090 ld $t1, %got(_ZN3art7Runtime9instance_E)($gp)
91 ld $t1, 0($t1)
Lazar Trsic84bc06e2015-06-10 16:05:46 +020092 ld $t1, RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET($t1)
93 sd $t1, 0($sp) # Place ArtMethod* at bottom of stack.
Andreas Gampe1a5c4062015-01-15 12:10:47 -080094 sd $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF) # Place sp in Thread::Current()->top_quick_frame.
95.endm
96
97 /*
98 * Macro that sets up the callee save frame to conform with
99 * Runtime::CreateCalleeSaveMethod(kRefsOnly). Restoration assumes
100 * non-moving GC.
101 * Does not include rSUSPEND or rSELF
102 * callee-save: padding + $s2-$s7 + $gp + $ra + $s8 = 9 total + 1x8 bytes padding
103 */
104.macro SETUP_REFS_ONLY_CALLEE_SAVE_FRAME
105 daddiu $sp, $sp, -80
106 .cfi_adjust_cfa_offset 80
107
108 // Ugly compile-time check, but we only have the preprocessor.
109#if (FRAME_SIZE_REFS_ONLY_CALLEE_SAVE != 80)
110#error "REFS_ONLY_CALLEE_SAVE_FRAME(MIPS64) size not as expected."
111#endif
112
113 sd $ra, 72($sp)
114 .cfi_rel_offset 31, 72
115 sd $s8, 64($sp)
116 .cfi_rel_offset 30, 64
Goran Jakovljevic04568812015-04-23 15:27:23 +0200117 sd $t8, 56($sp) # t8 holds caller's gp, now save it to the stack.
118 .cfi_rel_offset 28, 56 # Value from gp is pushed, so set the cfi offset accordingly.
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800119 sd $s7, 48($sp)
120 .cfi_rel_offset 23, 48
121 sd $s6, 40($sp)
122 .cfi_rel_offset 22, 40
123 sd $s5, 32($sp)
124 .cfi_rel_offset 21, 32
125 sd $s4, 24($sp)
126 .cfi_rel_offset 20, 24
127 sd $s3, 16($sp)
128 .cfi_rel_offset 19, 16
129 sd $s2, 8($sp)
130 .cfi_rel_offset 18, 8
131 # load appropriate callee-save-method
Lazar Trsic84bc06e2015-06-10 16:05:46 +0200132 ld $t1, %got(_ZN3art7Runtime9instance_E)($gp)
133 ld $t1, 0($t1)
Lazar Trsic84bc06e2015-06-10 16:05:46 +0200134 ld $t1, RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET($t1)
135 sd $t1, 0($sp) # Place Method* at bottom of stack.
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800136 sd $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF) # Place sp in Thread::Current()->top_quick_frame.
137.endm
138
139.macro RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
140 ld $ra, 72($sp)
141 .cfi_restore 31
142 ld $s8, 64($sp)
143 .cfi_restore 30
Goran Jakovljevic04568812015-04-23 15:27:23 +0200144 ld $t8, 56($sp) # Restore gp back to it's temp storage.
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800145 .cfi_restore 28
146 ld $s7, 48($sp)
147 .cfi_restore 23
148 ld $s6, 40($sp)
149 .cfi_restore 22
150 ld $s5, 32($sp)
151 .cfi_restore 21
152 ld $s4, 24($sp)
153 .cfi_restore 20
154 ld $s3, 16($sp)
155 .cfi_restore 19
156 ld $s2, 8($sp)
157 .cfi_restore 18
158 daddiu $sp, $sp, 80
159 .cfi_adjust_cfa_offset -80
Goran Jakovljevic04568812015-04-23 15:27:23 +0200160 .cpreturn
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800161.endm
162
163.macro RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
164 ld $ra, 72($sp)
165 .cfi_restore 31
166 ld $s8, 64($sp)
167 .cfi_restore 30
Goran Jakovljevic04568812015-04-23 15:27:23 +0200168 ld $t8, 56($sp) # Restore gp back to it's temp storage.
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800169 .cfi_restore 28
170 ld $s7, 48($sp)
171 .cfi_restore 23
172 ld $s6, 40($sp)
173 .cfi_restore 22
174 ld $s5, 32($sp)
175 .cfi_restore 21
176 ld $s4, 24($sp)
177 .cfi_restore 20
178 ld $s3, 16($sp)
179 .cfi_restore 19
180 ld $s2, 8($sp)
181 .cfi_restore 18
Goran Jakovljevic04568812015-04-23 15:27:23 +0200182 .cpreturn
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800183 jalr $zero, $ra
184 daddiu $sp, $sp, 80
185 .cfi_adjust_cfa_offset -80
186.endm
187
188// This assumes the top part of these stack frame types are identical.
189#define REFS_AND_ARGS_MINUS_REFS_SIZE (FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE - FRAME_SIZE_REFS_ONLY_CALLEE_SAVE)
190
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800191.macro SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
192 daddiu $sp, $sp, -208
193 .cfi_adjust_cfa_offset 208
194
195 // Ugly compile-time check, but we only have the preprocessor.
196#if (FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE != 208)
197#error "REFS_AND_ARGS_CALLEE_SAVE_FRAME(MIPS64) size not as expected."
198#endif
199
200 sd $ra, 200($sp) # = kQuickCalleeSaveFrame_RefAndArgs_LrOffset
201 .cfi_rel_offset 31, 200
202 sd $s8, 192($sp)
203 .cfi_rel_offset 30, 192
Goran Jakovljevic04568812015-04-23 15:27:23 +0200204 sd $t8, 184($sp) # t8 holds caller's gp, now save it to the stack.
205 .cfi_rel_offset 28, 184 # Value from gp is pushed, so set the cfi offset accordingly.
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800206 sd $s7, 176($sp)
207 .cfi_rel_offset 23, 176
208 sd $s6, 168($sp)
209 .cfi_rel_offset 22, 168
210 sd $s5, 160($sp)
211 .cfi_rel_offset 21, 160
212 sd $s4, 152($sp)
213 .cfi_rel_offset 20, 152
214 sd $s3, 144($sp)
215 .cfi_rel_offset 19, 144
216 sd $s2, 136($sp)
217 .cfi_rel_offset 18, 136
218
219 sd $a7, 128($sp)
220 .cfi_rel_offset 11, 128
221 sd $a6, 120($sp)
222 .cfi_rel_offset 10, 120
223 sd $a5, 112($sp)
224 .cfi_rel_offset 9, 112
225 sd $a4, 104($sp)
226 .cfi_rel_offset 8, 104
227 sd $a3, 96($sp)
228 .cfi_rel_offset 7, 96
229 sd $a2, 88($sp)
230 .cfi_rel_offset 6, 88
231 sd $a1, 80($sp) # = kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset
232 .cfi_rel_offset 5, 80
233
234 s.d $f19, 72($sp)
235 s.d $f18, 64($sp)
236 s.d $f17, 56($sp)
237 s.d $f16, 48($sp)
238 s.d $f15, 40($sp)
239 s.d $f14, 32($sp)
240 s.d $f13, 24($sp) # = kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset
241 s.d $f12, 16($sp) # This isn't necessary to store.
Douglas Leung8223b802015-04-28 17:22:29 -0700242 # 1x8 bytes padding + Method*
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800243.endm
244
Douglas Leung8223b802015-04-28 17:22:29 -0700245 /*
246 * Macro that sets up the callee save frame to conform with
247 * Runtime::CreateCalleeSaveMethod(kRefsAndArgs). Restoration assumes
248 * non-moving GC.
249 * callee-save: padding + $f12-$f19 + $a1-$a7 + $s2-$s7 + $gp + $ra + $s8 = 24 total + 1 words padding + Method*
250 */
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800251.macro SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME
252 SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
253 # load appropriate callee-save-method
Lazar Trsic84bc06e2015-06-10 16:05:46 +0200254 ld $t1, %got(_ZN3art7Runtime9instance_E)($gp)
255 ld $t1, 0($t1)
Lazar Trsic84bc06e2015-06-10 16:05:46 +0200256 ld $t1, RUNTIME_REFS_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET($t1)
257 sd $t1, 0($sp) # Place Method* at bottom of stack.
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800258 sd $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF) # Place sp in Thread::Current()->top_quick_frame.
259.endm
260
Douglas Leung8223b802015-04-28 17:22:29 -0700261.macro SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_WITH_METHOD_IN_A0
262 SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
Mathieu Chartiere401d142015-04-22 13:56:20 -0700263 sd $a0, 0($sp) # Place Method* at bottom of stack.
Douglas Leung8223b802015-04-28 17:22:29 -0700264 sd $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF) # Place sp in Thread::Current()->top_quick_frame.
265.endm
266
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800267.macro RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
268 ld $ra, 200($sp)
269 .cfi_restore 31
270 ld $s8, 192($sp)
271 .cfi_restore 30
Goran Jakovljevic04568812015-04-23 15:27:23 +0200272 ld $t8, 184($sp) # Restore gp back to it's temp storage.
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800273 .cfi_restore 28
274 ld $s7, 176($sp)
275 .cfi_restore 23
276 ld $s6, 168($sp)
277 .cfi_restore 22
278 ld $s5, 160($sp)
279 .cfi_restore 21
280 ld $s4, 152($sp)
281 .cfi_restore 20
282 ld $s3, 144($sp)
283 .cfi_restore 19
284 ld $s2, 136($sp)
285 .cfi_restore 18
286
287 ld $a7, 128($sp)
288 .cfi_restore 11
289 ld $a6, 120($sp)
290 .cfi_restore 10
291 ld $a5, 112($sp)
292 .cfi_restore 9
293 ld $a4, 104($sp)
294 .cfi_restore 8
295 ld $a3, 96($sp)
296 .cfi_restore 7
297 ld $a2, 88($sp)
298 .cfi_restore 6
299 ld $a1, 80($sp)
300 .cfi_restore 5
301
302 l.d $f19, 72($sp)
303 l.d $f18, 64($sp)
304 l.d $f17, 56($sp)
305 l.d $f16, 48($sp)
306 l.d $f15, 40($sp)
307 l.d $f14, 32($sp)
308 l.d $f13, 24($sp)
309 l.d $f12, 16($sp)
310
Goran Jakovljevic04568812015-04-23 15:27:23 +0200311 .cpreturn
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800312 daddiu $sp, $sp, 208
313 .cfi_adjust_cfa_offset -208
314.endm
315
316 /*
317 * Macro that set calls through to artDeliverPendingExceptionFromCode,
318 * where the pending
319 * exception is Thread::Current()->exception_
320 */
321.macro DELIVER_PENDING_EXCEPTION
Goran Jakovljevic04568812015-04-23 15:27:23 +0200322 SETUP_GP
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800323 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME # save callee saves for throw
324 dla $t9, artDeliverPendingExceptionFromCode
325 jalr $zero, $t9 # artDeliverPendingExceptionFromCode(Thread*)
326 move $a0, rSELF # pass Thread::Current
327.endm
328
329.macro RETURN_IF_NO_EXCEPTION
330 ld $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
331 RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
332 bne $t0, $zero, 1f # success if no exception is pending
333 nop
334 jalr $zero, $ra
335 nop
3361:
337 DELIVER_PENDING_EXCEPTION
338.endm
339
340.macro RETURN_IF_ZERO
341 RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
342 bne $v0, $zero, 1f # success?
343 nop
344 jalr $zero, $ra # return on success
345 nop
3461:
347 DELIVER_PENDING_EXCEPTION
348.endm
349
350.macro RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
351 RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
352 beq $v0, $zero, 1f # success?
353 nop
354 jalr $zero, $ra # return on success
355 nop
3561:
357 DELIVER_PENDING_EXCEPTION
358.endm
359
360 /*
Goran Jakovljevic3bc13812016-03-22 17:16:05 +0100361 * On stack replacement stub.
362 * On entry:
363 * a0 = stack to copy
364 * a1 = size of stack
365 * a2 = pc to call
366 * a3 = JValue* result
367 * a4 = shorty
368 * a5 = thread
369 */
370ENTRY art_quick_osr_stub
371 move $t0, $sp # save stack pointer
372 daddiu $t1, $sp, -112 # reserve stack space
373 dsrl $t1, $t1, 4 # enforce 16 byte stack alignment
374 dsll $sp, $t1, 4 # update stack pointer
375
376 // Save callee general purpose registers, SP, T8(GP), RA, A3, and A4 (8x14 bytes)
377 sd $ra, 104($sp)
378 .cfi_rel_offset 31, 104
379 sd $s8, 96($sp)
380 .cfi_rel_offset 30, 96
381 sd $t0, 88($sp) # save original stack pointer stored in t0
382 .cfi_rel_offset 29, 88
383 sd $t8, 80($sp) # t8 holds caller's gp, now save it to the stack.
384 .cfi_rel_offset 28, 80 # Value from gp is pushed, so set the cfi offset accordingly.
385 sd $s7, 72($sp)
386 .cfi_rel_offset 23, 72
387 sd $s6, 64($sp)
388 .cfi_rel_offset 22, 64
389 sd $s5, 56($sp)
390 .cfi_rel_offset 21, 56
391 sd $s4, 48($sp)
392 .cfi_rel_offset 20, 48
393 sd $s3, 40($sp)
394 .cfi_rel_offset 19, 40
395 sd $s2, 32($sp)
396 .cfi_rel_offset 18, 32
397 sd $s1, 24($sp)
398 .cfi_rel_offset 17, 24
399 sd $s0, 16($sp)
400 .cfi_rel_offset 16, 16
401 sd $a4, 8($sp)
402 .cfi_rel_offset 8, 8
403 sd $a3, 0($sp)
404 .cfi_rel_offset 7, 0
405 move rSELF, $a5 # Save managed thread pointer into rSELF
406
407 daddiu $sp, $sp, -16
408 jal .Losr_entry
409 sd $zero, 0($sp) # Store null for ArtMethod* at bottom of frame
410 daddiu $sp, $sp, 16
411
412 // Restore return value address and shorty address
413 ld $a4, 8($sp) # shorty address
414 .cfi_restore 8
415 ld $a3, 0($sp) # result value address
416 .cfi_restore 7
417
418 lbu $t1, 0($a4) # load return type
419 li $t2, 'D' # put char 'D' into t2
420 beq $t1, $t2, .Losr_fp_result # branch if result type char == 'D'
421 li $t2, 'F' # put char 'F' into t2
422 beq $t1, $t2, .Losr_fp_result # branch if result type char == 'F'
423 nop
424 b .Losr_exit
425 dsrl $v1, $v0, 32 # put high half of result in v1
426.Losr_fp_result:
427 mfc1 $v0, $f0
428 mfhc1 $v1, $f0 # put high half of FP result in v1
429.Losr_exit:
430 sw $v0, 0($a3) # store low half of result
431 sw $v1, 4($a3) # store high half of result
432
433 // Restore callee registers
434 ld $ra, 104($sp)
435 .cfi_restore 31
436 ld $s8, 96($sp)
437 .cfi_restore 30
438 ld $t0, 88($sp) # save SP into t0 for now
439 .cfi_restore 29
440 ld $t8, 80($sp) # Restore gp back to it's temp storage.
441 .cfi_restore 28
442 ld $s7, 72($sp)
443 .cfi_restore 23
444 ld $s6, 64($sp)
445 .cfi_restore 22
446 ld $s5, 56($sp)
447 .cfi_restore 21
448 ld $s4, 48($sp)
449 .cfi_restore 20
450 ld $s3, 40($sp)
451 .cfi_restore 19
452 ld $s2, 32($sp)
453 .cfi_restore 18
454 ld $s1, 24($sp)
455 .cfi_restore 17
456 ld $s0, 16($sp)
457 .cfi_restore 16
458 jalr $zero, $ra
459 move $sp, $t0
460
461.Losr_entry:
462 dsubu $sp, $sp, $a1 # Reserve space for callee stack
463 daddiu $a1, $a1, -8
464 daddu $t0, $a1, $sp
465 sw $ra, 0($t0) # Store low half of RA per compiler ABI
466 dsrl $t1, $ra, 32
467 sw $t1, 4($t0) # Store high half of RA per compiler ABI
468
469 // Copy arguments into callee stack
470 // Use simple copy routine for now.
471 // 4 bytes per slot.
472 // a0 = source address
473 // a1 = args length in bytes (does not include 8 bytes for RA)
474 // sp = destination address
475 beqz $a1, .Losr_loop_exit
476 daddiu $a1, $a1, -4
477 daddu $t1, $a0, $a1
478 daddu $t2, $sp, $a1
479.Losr_loop_entry:
480 lw $t0, 0($t1)
481 daddiu $t1, $t1, -4
482 sw $t0, 0($t2)
483 bne $sp, $t2, .Losr_loop_entry
484 daddiu $t2, $t2, -4
485
486.Losr_loop_exit:
487 move $t9, $a2
488 jalr $zero, $t9 # Jump to the OSR entry point.
489 nop
490END art_quick_osr_stub
491
492 /*
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800493 * On entry $a0 is uint32_t* gprs_ and $a1 is uint32_t* fprs_
494 * FIXME: just guessing about the shape of the jmpbuf. Where will pc be?
495 */
Goran Jakovljevic04568812015-04-23 15:27:23 +0200496ENTRY_NO_GP art_quick_do_long_jump
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800497 l.d $f0, 0($a1)
498 l.d $f1, 8($a1)
499 l.d $f2, 16($a1)
500 l.d $f3, 24($a1)
501 l.d $f4, 32($a1)
502 l.d $f5, 40($a1)
503 l.d $f6, 48($a1)
504 l.d $f7, 56($a1)
505 l.d $f8, 64($a1)
506 l.d $f9, 72($a1)
507 l.d $f10, 80($a1)
508 l.d $f11, 88($a1)
509 l.d $f12, 96($a1)
510 l.d $f13, 104($a1)
511 l.d $f14, 112($a1)
512 l.d $f15, 120($a1)
513 l.d $f16, 128($a1)
514 l.d $f17, 136($a1)
515 l.d $f18, 144($a1)
516 l.d $f19, 152($a1)
517 l.d $f20, 160($a1)
518 l.d $f21, 168($a1)
519 l.d $f22, 176($a1)
520 l.d $f23, 184($a1)
521 l.d $f24, 192($a1)
522 l.d $f25, 200($a1)
523 l.d $f26, 208($a1)
524 l.d $f27, 216($a1)
525 l.d $f28, 224($a1)
526 l.d $f29, 232($a1)
527 l.d $f30, 240($a1)
528 l.d $f31, 248($a1)
529 .set push
530 .set nomacro
531 .set noat
532# no need to load zero
533 ld $at, 8($a0)
534 .set pop
535 ld $v0, 16($a0)
536 ld $v1, 24($a0)
537# a0 has to be loaded last
538 ld $a1, 40($a0)
539 ld $a2, 48($a0)
540 ld $a3, 56($a0)
541 ld $a4, 64($a0)
542 ld $a5, 72($a0)
543 ld $a6, 80($a0)
544 ld $a7, 88($a0)
545 ld $t0, 96($a0)
546 ld $t1, 104($a0)
547 ld $t2, 112($a0)
548 ld $t3, 120($a0)
549 ld $s0, 128($a0)
550 ld $s1, 136($a0)
551 ld $s2, 144($a0)
552 ld $s3, 152($a0)
553 ld $s4, 160($a0)
554 ld $s5, 168($a0)
555 ld $s6, 176($a0)
556 ld $s7, 184($a0)
557 ld $t8, 192($a0)
558 ld $t9, 200($a0)
559# no need to load k0, k1
560 ld $gp, 224($a0)
561 ld $sp, 232($a0)
562 ld $s8, 240($a0)
563 ld $ra, 248($a0)
564 ld $a0, 32($a0)
565 move $v0, $zero # clear result registers v0 and v1
Andreas Gampedbf056d2015-09-25 08:24:13 -0700566 jalr $zero, $t9 # do long jump (do not use ra, it must not be clobbered)
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800567 move $v1, $zero
568END art_quick_do_long_jump
569
Maja Gagic6ea651f2015-02-24 16:55:04 +0100570 /*
571 * Called by managed code, saves most registers (forms basis of long jump
572 * context) and passes the bottom of the stack.
573 * artDeliverExceptionFromCode will place the callee save Method* at
Lazar Trsic84bc06e2015-06-10 16:05:46 +0200574 * the bottom of the thread. On entry a0 holds Throwable*
Maja Gagic6ea651f2015-02-24 16:55:04 +0100575 */
576ENTRY art_quick_deliver_exception
577 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
578 dla $t9, artDeliverExceptionFromCode
579 jalr $zero, $t9 # artDeliverExceptionFromCode(Throwable*, Thread*)
580 move $a1, rSELF # pass Thread::Current
581END art_quick_deliver_exception
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800582
Maja Gagic6ea651f2015-02-24 16:55:04 +0100583 /*
584 * Called by managed code to create and deliver a NullPointerException
585 */
586 .extern artThrowNullPointerExceptionFromCode
587ENTRY art_quick_throw_null_pointer_exception
588.Lart_quick_throw_null_pointer_exception_gp_set:
589 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
590 dla $t9, artThrowNullPointerExceptionFromCode
591 jalr $zero, $t9 # artThrowNullPointerExceptionFromCode(Thread*)
592 move $a0, rSELF # pass Thread::Current
593END art_quick_throw_null_pointer_exception
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800594
Maja Gagic6ea651f2015-02-24 16:55:04 +0100595 /*
Nicolas Geoffraye8e11272016-06-28 18:08:46 +0100596 * Call installed by a signal handler to create and deliver a NullPointerException
597 */
598 .extern artThrowNullPointerExceptionFromSignal
599ENTRY art_quick_throw_null_pointer_exception_from_signal
600 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
601 dla $t9, artThrowNullPointerExceptionFromSignal
602 jalr $zero, $t9 # artThrowNullPointerExceptionFromSignal(uinptr_t, Thread*)
603 move $a1, rSELF # pass Thread::Current
604END art_quick_throw_null_pointer_exception
605
606 /*
Maja Gagic6ea651f2015-02-24 16:55:04 +0100607 * Called by managed code to create and deliver an ArithmeticException
608 */
609 .extern artThrowDivZeroFromCode
610ENTRY art_quick_throw_div_zero
611 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
612 dla $t9, artThrowDivZeroFromCode
613 jalr $zero, $t9 # artThrowDivZeroFromCode(Thread*)
614 move $a0, rSELF # pass Thread::Current
615END art_quick_throw_div_zero
616
617 /*
618 * Called by managed code to create and deliver an
619 * ArrayIndexOutOfBoundsException
620 */
621 .extern artThrowArrayBoundsFromCode
622ENTRY art_quick_throw_array_bounds
623.Lart_quick_throw_array_bounds_gp_set:
624 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
625 dla $t9, artThrowArrayBoundsFromCode
626 jalr $zero, $t9 # artThrowArrayBoundsFromCode(index, limit, Thread*)
627 move $a2, rSELF # pass Thread::Current
628END art_quick_throw_array_bounds
629
630 /*
Vladimir Marko87f3fcb2016-04-28 15:52:11 +0100631 * Called by managed code to create and deliver a StringIndexOutOfBoundsException
632 * as if thrown from a call to String.charAt().
633 */
634 .extern artThrowStringBoundsFromCode
635ENTRY art_quick_throw_string_bounds
636.Lart_quick_throw_string_bounds_gp_set:
637 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
638 dla $t9, artThrowStringBoundsFromCode
639 jalr $zero, $t9 # artThrowStringBoundsFromCode(index, limit, Thread*)
640 move $a2, rSELF # pass Thread::Current
641END art_quick_throw_string_bounds
642
643 /*
Maja Gagic6ea651f2015-02-24 16:55:04 +0100644 * Called by managed code to create and deliver a StackOverflowError.
645 */
646 .extern artThrowStackOverflowFromCode
647ENTRY art_quick_throw_stack_overflow
648 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
649 dla $t9, artThrowStackOverflowFromCode
650 jalr $zero, $t9 # artThrowStackOverflowFromCode(Thread*)
651 move $a0, rSELF # pass Thread::Current
652END art_quick_throw_stack_overflow
653
654 /*
655 * Called by managed code to create and deliver a NoSuchMethodError.
656 */
657 .extern artThrowNoSuchMethodFromCode
658ENTRY art_quick_throw_no_such_method
659 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
660 dla $t9, artThrowNoSuchMethodFromCode
661 jalr $zero, $t9 # artThrowNoSuchMethodFromCode(method_idx, Thread*)
662 move $a1, rSELF # pass Thread::Current
663END art_quick_throw_no_such_method
664
665 /*
666 * All generated callsites for interface invokes and invocation slow paths will load arguments
667 * as usual - except instead of loading arg0/$a0 with the target Method*, arg0/$a0 will contain
668 * the method_idx. This wrapper will save arg1-arg3, load the caller's Method*, align the
669 * stack and call the appropriate C helper.
670 * NOTE: "this" is first visable argument of the target, and so can be found in arg1/$a1.
671 *
672 * The helper will attempt to locate the target and return a 128-bit result in $v0/$v1 consisting
673 * of the target Method* in $v0 and method->code_ in $v1.
674 *
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700675 * If unsuccessful, the helper will return null/null. There will be a pending exception in the
Maja Gagic6ea651f2015-02-24 16:55:04 +0100676 * thread and we branch to another stub to deliver it.
677 *
678 * On success this wrapper will restore arguments and *jump* to the target, leaving the ra
679 * pointing back to the original caller.
680 */
Andreas Gampe3031c8d2015-07-13 20:11:06 -0700681.macro INVOKE_TRAMPOLINE_BODY cxx_name
Maja Gagic6ea651f2015-02-24 16:55:04 +0100682 .extern \cxx_name
Maja Gagic6ea651f2015-02-24 16:55:04 +0100683 SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME # save callee saves in case allocation triggers GC
Nicolas Geoffray7ea6a172015-05-19 18:58:54 +0100684 move $a2, rSELF # pass Thread::Current
685 jal \cxx_name # (method_idx, this, Thread*, $sp)
686 move $a3, $sp # pass $sp
Maja Gagic6ea651f2015-02-24 16:55:04 +0100687 move $a0, $v0 # save target Method*
688 move $t9, $v1 # save $v0->code_
689 RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
690 beq $v0, $zero, 1f
691 nop
692 jalr $zero, $t9
693 nop
6941:
695 DELIVER_PENDING_EXCEPTION
Andreas Gampe3031c8d2015-07-13 20:11:06 -0700696.endm
697.macro INVOKE_TRAMPOLINE c_name, cxx_name
698ENTRY \c_name
699 INVOKE_TRAMPOLINE_BODY \cxx_name
Maja Gagic6ea651f2015-02-24 16:55:04 +0100700END \c_name
701.endm
702
Maja Gagic6ea651f2015-02-24 16:55:04 +0100703INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck
704
705INVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck
706INVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck
707INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
708INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800709
710 # On entry:
711 # t0 = shorty
712 # t1 = ptr to arg_array
713 # t2 = number of argument bytes remain
714 # v0 = ptr to stack frame where to copy arg_array
715 # This macro modifies t3, t9 and v0
716.macro LOOP_OVER_SHORTY_LOADING_REG gpu, fpu, label
717 lbu $t3, 0($t0) # get argument type from shorty
718 beqz $t3, \label
719 daddiu $t0, 1
720 li $t9, 68 # put char 'D' into t9
721 beq $t9, $t3, 1f # branch if result type char == 'D'
722 li $t9, 70 # put char 'F' into t9
723 beq $t9, $t3, 2f # branch if result type char == 'F'
724 li $t9, 74 # put char 'J' into t9
725 beq $t9, $t3, 3f # branch if result type char == 'J'
726 nop
Maja Gagic6ea651f2015-02-24 16:55:04 +0100727 lw $\gpu, 0($t1)
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800728 sw $\gpu, 0($v0)
729 daddiu $v0, 4
730 daddiu $t1, 4
731 b 4f
732 daddiu $t2, -4 # delay slot
733
7341: # found double
735 lwu $t3, 0($t1)
736 mtc1 $t3, $\fpu
737 sw $t3, 0($v0)
738 lwu $t3, 4($t1)
739 mthc1 $t3, $\fpu
740 sw $t3, 4($v0)
741 daddiu $v0, 8
742 daddiu $t1, 8
743 b 4f
744 daddiu $t2, -8 # delay slot
745
7462: # found float
747 lwu $t3, 0($t1)
748 mtc1 $t3, $\fpu
749 sw $t3, 0($v0)
750 daddiu $v0, 4
751 daddiu $t1, 4
752 b 4f
753 daddiu $t2, -4 # delay slot
754
7553: # found long (8 bytes)
756 lwu $t3, 0($t1)
757 sw $t3, 0($v0)
758 lwu $t9, 4($t1)
759 sw $t9, 4($v0)
760 dsll $t9, $t9, 32
761 or $\gpu, $t9, $t3
762 daddiu $v0, 8
763 daddiu $t1, 8
764 daddiu $t2, -8
7654:
766.endm
767
768 /*
769 * Invocation stub for quick code.
770 * On entry:
771 * a0 = method pointer
772 * a1 = argument array that must at least contain the this ptr.
773 * a2 = size of argument array in bytes
774 * a3 = (managed) thread pointer
775 * a4 = JValue* result
776 * a5 = shorty
777 */
Goran Jakovljevic04568812015-04-23 15:27:23 +0200778ENTRY_NO_GP art_quick_invoke_stub
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800779 # push a4, a5, s0(rSUSPEND), s1(rSELF), s8, ra onto the stack
780 daddiu $sp, $sp, -48
781 .cfi_adjust_cfa_offset 48
782 sd $ra, 40($sp)
783 .cfi_rel_offset 31, 40
784 sd $s8, 32($sp)
785 .cfi_rel_offset 30, 32
786 sd $s1, 24($sp)
787 .cfi_rel_offset 17, 24
788 sd $s0, 16($sp)
789 .cfi_rel_offset 16, 16
790 sd $a5, 8($sp)
791 .cfi_rel_offset 9, 8
792 sd $a4, 0($sp)
793 .cfi_rel_offset 8, 0
794
795 daddiu $s0, $zero, SUSPEND_CHECK_INTERVAL # reset rSUSPEND to SUSPEND_CHECK_INTERVAL
796 move $s1, $a3 # move managed thread pointer into s1 (rSELF)
797 move $s8, $sp # save sp in s8 (fp)
798
Mathieu Chartiere401d142015-04-22 13:56:20 -0700799 daddiu $t3, $a2, 24 # add 8 for ArtMethod* and 16 for stack alignment
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800800 dsrl $t3, $t3, 4 # shift the frame size right 4
801 dsll $t3, $t3, 4 # shift the frame size left 4 to align to 16 bytes
802 dsubu $sp, $sp, $t3 # reserve stack space for argument array
803
804 daddiu $t0, $a5, 1 # t0 = shorty[1] (skip 1 for return type)
805 daddiu $t1, $a1, 4 # t1 = ptr to arg_array[4] (skip this ptr)
806 daddiu $t2, $a2, -4 # t2 = number of argument bytes remain (skip this ptr)
Nikola Veljkovic80f7a572015-06-02 17:27:53 +0200807 daddiu $v0, $sp, 12 # v0 points to where to copy arg_array
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800808 LOOP_OVER_SHORTY_LOADING_REG a2, f14, call_fn
809 LOOP_OVER_SHORTY_LOADING_REG a3, f15, call_fn
810 LOOP_OVER_SHORTY_LOADING_REG a4, f16, call_fn
811 LOOP_OVER_SHORTY_LOADING_REG a5, f17, call_fn
812 LOOP_OVER_SHORTY_LOADING_REG a6, f18, call_fn
813 LOOP_OVER_SHORTY_LOADING_REG a7, f19, call_fn
814
815 # copy arguments onto stack (t2 should be multiples of 4)
816 ble $t2, $zero, call_fn # t2 = number of argument bytes remain
8171:
818 lw $t3, 0($t1) # load from argument array
819 daddiu $t1, $t1, 4
820 sw $t3, 0($v0) # save to stack
821 daddiu $t2, -4
822 bgt $t2, $zero, 1b # t2 = number of argument bytes remain
823 daddiu $v0, $v0, 4
824
825call_fn:
826 # call method (a0 and a1 have been untouched)
827 lwu $a1, 0($a1) # make a1 = this ptr
Mathieu Chartiere401d142015-04-22 13:56:20 -0700828 sw $a1, 8($sp) # copy this ptr (skip 8 bytes for ArtMethod*)
829 sd $zero, 0($sp) # store null for ArtMethod* at bottom of frame
830 ld $t9, ART_METHOD_QUICK_CODE_OFFSET_64($a0) # get pointer to the code
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800831 jalr $t9 # call the method
832 nop
833 move $sp, $s8 # restore sp
834
835 # pop a4, a5, s1(rSELF), s8, ra off of the stack
836 ld $a4, 0($sp)
837 .cfi_restore 8
838 ld $a5, 8($sp)
839 .cfi_restore 9
840 ld $s0, 16($sp)
841 .cfi_restore 16
842 ld $s1, 24($sp)
843 .cfi_restore 17
844 ld $s8, 32($sp)
845 .cfi_restore 30
846 ld $ra, 40($sp)
847 .cfi_restore 31
848 daddiu $sp, $sp, 48
849 .cfi_adjust_cfa_offset -48
850
851 # a4 = JValue* result
852 # a5 = shorty string
853 lbu $t1, 0($a5) # get result type from shorty
854 li $t2, 68 # put char 'D' into t2
855 beq $t1, $t2, 1f # branch if result type char == 'D'
856 li $t3, 70 # put char 'F' into t3
857 beq $t1, $t3, 1f # branch if result type char == 'F'
858 sw $v0, 0($a4) # store the result
859 dsrl $v1, $v0, 32
860 jalr $zero, $ra
861 sw $v1, 4($a4) # store the other half of the result
8621:
863 mfc1 $v0, $f0
864 mfhc1 $v1, $f0
865 sw $v0, 0($a4) # store the result
866 jalr $zero, $ra
867 sw $v1, 4($a4) # store the other half of the result
868END art_quick_invoke_stub
869
870 /*
871 * Invocation static stub for quick code.
872 * On entry:
873 * a0 = method pointer
874 * a1 = argument array that must at least contain the this ptr.
875 * a2 = size of argument array in bytes
876 * a3 = (managed) thread pointer
877 * a4 = JValue* result
878 * a5 = shorty
879 */
Goran Jakovljevic04568812015-04-23 15:27:23 +0200880ENTRY_NO_GP art_quick_invoke_static_stub
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800881
882 # push a4, a5, s0(rSUSPEND), s1(rSELF), s8, ra, onto the stack
883 daddiu $sp, $sp, -48
884 .cfi_adjust_cfa_offset 48
885 sd $ra, 40($sp)
886 .cfi_rel_offset 31, 40
887 sd $s8, 32($sp)
888 .cfi_rel_offset 30, 32
889 sd $s1, 24($sp)
890 .cfi_rel_offset 17, 24
891 sd $s0, 16($sp)
892 .cfi_rel_offset 16, 16
893 sd $a5, 8($sp)
894 .cfi_rel_offset 9, 8
895 sd $a4, 0($sp)
896 .cfi_rel_offset 8, 0
897
898 daddiu $s0, $zero, SUSPEND_CHECK_INTERVAL # reset rSUSPEND to SUSPEND_CHECK_INTERVAL
899 move $s1, $a3 # move managed thread pointer into s1 (rSELF)
900 move $s8, $sp # save sp in s8 (fp)
901
Mathieu Chartiere401d142015-04-22 13:56:20 -0700902 daddiu $t3, $a2, 24 # add 8 for ArtMethod* and 16 for stack alignment
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800903 dsrl $t3, $t3, 4 # shift the frame size right 4
904 dsll $t3, $t3, 4 # shift the frame size left 4 to align to 16 bytes
905 dsubu $sp, $sp, $t3 # reserve stack space for argument array
906
907 daddiu $t0, $a5, 1 # t0 = shorty[1] (skip 1 for return type)
908 move $t1, $a1 # t1 = arg_array
909 move $t2, $a2 # t2 = number of argument bytes remain
Mathieu Chartiere401d142015-04-22 13:56:20 -0700910 daddiu $v0, $sp, 8 # v0 points to where to copy arg_array
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800911 LOOP_OVER_SHORTY_LOADING_REG a1, f13, call_sfn
912 LOOP_OVER_SHORTY_LOADING_REG a2, f14, call_sfn
913 LOOP_OVER_SHORTY_LOADING_REG a3, f15, call_sfn
914 LOOP_OVER_SHORTY_LOADING_REG a4, f16, call_sfn
915 LOOP_OVER_SHORTY_LOADING_REG a5, f17, call_sfn
916 LOOP_OVER_SHORTY_LOADING_REG a6, f18, call_sfn
917 LOOP_OVER_SHORTY_LOADING_REG a7, f19, call_sfn
918
919 # copy arguments onto stack (t2 should be multiples of 4)
920 ble $t2, $zero, call_sfn # t2 = number of argument bytes remain
9211:
922 lw $t3, 0($t1) # load from argument array
923 daddiu $t1, $t1, 4
924 sw $t3, 0($v0) # save to stack
925 daddiu $t2, -4
926 bgt $t2, $zero, 1b # t2 = number of argument bytes remain
927 daddiu $v0, $v0, 4
928
929call_sfn:
930 # call method (a0 has been untouched)
Mathieu Chartiere401d142015-04-22 13:56:20 -0700931 sd $zero, 0($sp) # store null for ArtMethod* at bottom of frame
932 ld $t9, ART_METHOD_QUICK_CODE_OFFSET_64($a0) # get pointer to the code
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800933 jalr $t9 # call the method
934 nop
935 move $sp, $s8 # restore sp
936
937 # pop a4, a5, s0(rSUSPEND), s1(rSELF), s8, ra off of the stack
938 ld $a4, 0($sp)
939 .cfi_restore 8
940 ld $a5, 8($sp)
941 .cfi_restore 9
942 ld $s0, 16($sp)
943 .cfi_restore 16
944 ld $s1, 24($sp)
945 .cfi_restore 17
946 ld $s8, 32($sp)
947 .cfi_restore 30
948 ld $ra, 40($sp)
949 .cfi_restore 31
950 daddiu $sp, $sp, 48
951 .cfi_adjust_cfa_offset -48
952
953 # a4 = JValue* result
954 # a5 = shorty string
955 lbu $t1, 0($a5) # get result type from shorty
956 li $t2, 68 # put char 'D' into t2
957 beq $t1, $t2, 1f # branch if result type char == 'D'
958 li $t3, 70 # put char 'F' into t3
959 beq $t1, $t3, 1f # branch if result type char == 'F'
960 sw $v0, 0($a4) # store the result
961 dsrl $v1, $v0, 32
962 jalr $zero, $ra
963 sw $v1, 4($a4) # store the other half of the result
9641:
965 mfc1 $v0, $f0
966 mfhc1 $v1, $f0
967 sw $v0, 0($a4) # store the result
968 jalr $zero, $ra
969 sw $v1, 4($a4) # store the other half of the result
970END art_quick_invoke_static_stub
971
Maja Gagic6ea651f2015-02-24 16:55:04 +0100972 /*
973 * Entry from managed code that calls artHandleFillArrayDataFromCode and
974 * delivers exception on failure.
975 */
976 .extern artHandleFillArrayDataFromCode
977ENTRY art_quick_handle_fill_data
978 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case exception allocation triggers GC
Mathieu Chartiere401d142015-04-22 13:56:20 -0700979 ld $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +0100980 jal artHandleFillArrayDataFromCode # (payload offset, Array*, method, Thread*)
981 move $a3, rSELF # pass Thread::Current
982 RETURN_IF_ZERO
983END art_quick_handle_fill_data
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800984
Maja Gagic6ea651f2015-02-24 16:55:04 +0100985 /*
986 * Entry from managed code that calls artLockObjectFromCode, may block for GC.
987 */
988 .extern artLockObjectFromCode
989ENTRY art_quick_lock_object
990 beq $a0, $zero, .Lart_quick_throw_null_pointer_exception_gp_set
991 nop
992 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case we block
993 jal artLockObjectFromCode # (Object* obj, Thread*)
994 move $a1, rSELF # pass Thread::Current
995 RETURN_IF_ZERO
996END art_quick_lock_object
Andreas Gampe1a5c4062015-01-15 12:10:47 -0800997
Andreas Gampec7ed09b2016-04-25 20:08:55 -0700998ENTRY art_quick_lock_object_no_inline
999 beq $a0, $zero, .Lart_quick_throw_null_pointer_exception_gp_set
1000 nop
1001 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case we block
1002 jal artLockObjectFromCode # (Object* obj, Thread*)
1003 move $a1, rSELF # pass Thread::Current
1004 RETURN_IF_ZERO
1005END art_quick_lock_object_no_inline
1006
Maja Gagic6ea651f2015-02-24 16:55:04 +01001007 /*
1008 * Entry from managed code that calls artUnlockObjectFromCode and delivers exception on failure.
1009 */
1010 .extern artUnlockObjectFromCode
1011ENTRY art_quick_unlock_object
1012 beq $a0, $zero, .Lart_quick_throw_null_pointer_exception_gp_set
1013 nop
1014 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case exception allocation triggers GC
1015 jal artUnlockObjectFromCode # (Object* obj, Thread*)
1016 move $a1, rSELF # pass Thread::Current
1017 RETURN_IF_ZERO
1018END art_quick_unlock_object
1019
Andreas Gampec7ed09b2016-04-25 20:08:55 -07001020ENTRY art_quick_unlock_object_no_inline
1021 beq $a0, $zero, .Lart_quick_throw_null_pointer_exception_gp_set
1022 nop
1023 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case exception allocation triggers GC
1024 jal artUnlockObjectFromCode # (Object* obj, Thread*)
1025 move $a1, rSELF # pass Thread::Current
1026 RETURN_IF_ZERO
1027END art_quick_unlock_object_no_inline
1028
Maja Gagic6ea651f2015-02-24 16:55:04 +01001029 /*
1030 * Entry from managed code that calls artCheckCastFromCode and delivers exception on failure.
1031 */
1032 .extern artThrowClassCastException
1033ENTRY art_quick_check_cast
1034 daddiu $sp, $sp, -32
1035 .cfi_adjust_cfa_offset 32
1036 sd $ra, 24($sp)
1037 .cfi_rel_offset 31, 24
1038 sd $t9, 16($sp)
1039 sd $a1, 8($sp)
1040 sd $a0, 0($sp)
1041 jal artIsAssignableFromCode
Goran Jakovljevic04568812015-04-23 15:27:23 +02001042 .cpreturn # Restore gp from t8 in branch delay slot.
1043 # t8 may be clobbered in artIsAssignableFromCode.
Maja Gagic6ea651f2015-02-24 16:55:04 +01001044 beq $v0, $zero, .Lthrow_class_cast_exception
1045 ld $ra, 24($sp)
1046 jalr $zero, $ra
1047 daddiu $sp, $sp, 32
1048 .cfi_adjust_cfa_offset -32
1049.Lthrow_class_cast_exception:
1050 ld $t9, 16($sp)
1051 ld $a1, 8($sp)
1052 ld $a0, 0($sp)
1053 daddiu $sp, $sp, 32
1054 .cfi_adjust_cfa_offset -32
Goran Jakovljevic04568812015-04-23 15:27:23 +02001055 SETUP_GP
Maja Gagic6ea651f2015-02-24 16:55:04 +01001056 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
1057 dla $t9, artThrowClassCastException
1058 jalr $zero, $t9 # artThrowClassCastException (Class*, Class*, Thread*)
1059 move $a2, rSELF # pass Thread::Current
1060END art_quick_check_cast
1061
Man Cao1aee9002015-07-14 22:31:42 -07001062
1063 /*
1064 * Restore rReg's value from offset($sp) if rReg is not the same as rExclude.
1065 * nReg is the register number for rReg.
1066 */
1067.macro POP_REG_NE rReg, nReg, offset, rExclude
1068 .ifnc \rReg, \rExclude
1069 ld \rReg, \offset($sp) # restore rReg
1070 .cfi_restore \nReg
1071 .endif
1072.endm
1073
1074 /*
1075 * Macro to insert read barrier, only used in art_quick_aput_obj.
1076 * rObj and rDest are registers, offset is a defined literal such as MIRROR_OBJECT_CLASS_OFFSET.
1077 * TODO: When read barrier has a fast path, add heap unpoisoning support for the fast path.
1078 */
1079.macro READ_BARRIER rDest, rObj, offset
1080#ifdef USE_READ_BARRIER
1081 # saved registers used in art_quick_aput_obj: a0-a2, t0-t1, t9, ra. 16B-aligned.
1082 daddiu $sp, $sp, -64
1083 .cfi_adjust_cfa_offset 64
1084 sd $ra, 56($sp)
1085 .cfi_rel_offset 31, 56
1086 sd $t9, 48($sp)
1087 .cfi_rel_offset 25, 48
1088 sd $t1, 40($sp)
1089 .cfi_rel_offset 13, 40
1090 sd $t0, 32($sp)
1091 .cfi_rel_offset 12, 32
1092 sd $a2, 16($sp) # padding slot at offset 24 (padding can be any slot in the 64B)
1093 .cfi_rel_offset 6, 16
1094 sd $a1, 8($sp)
1095 .cfi_rel_offset 5, 8
1096 sd $a0, 0($sp)
1097 .cfi_rel_offset 4, 0
1098
Man Cao63069212015-08-21 15:51:39 -07001099 # move $a0, \rRef # pass ref in a0 (no-op for now since parameter ref is unused)
Man Cao1aee9002015-07-14 22:31:42 -07001100 .ifnc \rObj, $a1
1101 move $a1, \rObj # pass rObj
1102 .endif
1103 daddiu $a2, $zero, \offset # pass offset
1104 jal artReadBarrierSlow # artReadBarrierSlow(ref, rObj, offset)
1105 .cpreturn # Restore gp from t8 in branch delay slot.
1106 # t8 may be clobbered in artReadBarrierSlow.
1107 # No need to unpoison return value in v0, artReadBarrierSlow() would do the unpoisoning.
1108 move \rDest, $v0 # save return value in rDest
1109 # (rDest cannot be v0 in art_quick_aput_obj)
1110
1111 ld $a0, 0($sp) # restore registers except rDest
1112 # (rDest can only be t0 or t1 in art_quick_aput_obj)
1113 .cfi_restore 4
1114 ld $a1, 8($sp)
1115 .cfi_restore 5
1116 ld $a2, 16($sp)
1117 .cfi_restore 6
1118 POP_REG_NE $t0, 12, 32, \rDest
1119 POP_REG_NE $t1, 13, 40, \rDest
1120 ld $t9, 48($sp)
1121 .cfi_restore 25
1122 ld $ra, 56($sp) # restore $ra
1123 .cfi_restore 31
1124 daddiu $sp, $sp, 64
1125 .cfi_adjust_cfa_offset -64
1126 SETUP_GP # set up gp because we are not returning
1127#else
1128 lwu \rDest, \offset(\rObj)
1129 UNPOISON_HEAP_REF \rDest
1130#endif // USE_READ_BARRIER
1131.endm
1132
Maja Gagic6ea651f2015-02-24 16:55:04 +01001133 /*
1134 * Entry from managed code for array put operations of objects where the value being stored
1135 * needs to be checked for compatibility.
1136 * a0 = array, a1 = index, a2 = value
1137 */
1138ENTRY art_quick_aput_obj_with_null_and_bound_check
1139 bne $a0, $zero, .Lart_quick_aput_obj_with_bound_check_gp_set
1140 nop
1141 b .Lart_quick_throw_null_pointer_exception_gp_set
1142 nop
1143END art_quick_aput_obj_with_null_and_bound_check
1144
1145ENTRY art_quick_aput_obj_with_bound_check
1146 lwu $t0, MIRROR_ARRAY_LENGTH_OFFSET($a0)
1147 sltu $t1, $a1, $t0
1148 bne $t1, $zero, .Lart_quick_aput_obj_gp_set
1149 nop
1150 move $a0, $a1
1151 b .Lart_quick_throw_array_bounds_gp_set
1152 move $a1, $t0
1153END art_quick_aput_obj_with_bound_check
1154
1155ENTRY art_quick_aput_obj
1156 beq $a2, $zero, .Ldo_aput_null
1157 nop
Man Cao1aee9002015-07-14 22:31:42 -07001158 READ_BARRIER $t0, $a0, MIRROR_OBJECT_CLASS_OFFSET
1159 READ_BARRIER $t1, $a2, MIRROR_OBJECT_CLASS_OFFSET
1160 READ_BARRIER $t0, $t0, MIRROR_CLASS_COMPONENT_TYPE_OFFSET
Maja Gagic6ea651f2015-02-24 16:55:04 +01001161 bne $t1, $t0, .Lcheck_assignability # value's type == array's component type - trivial assignability
1162 nop
1163.Ldo_aput:
1164 dsll $a1, $a1, 2
1165 daddu $t0, $a0, $a1
Hiroshi Yamauchibfa5eb62015-05-29 15:04:41 -07001166 POISON_HEAP_REF $a2
Maja Gagic6ea651f2015-02-24 16:55:04 +01001167 sw $a2, MIRROR_OBJECT_ARRAY_DATA_OFFSET($t0)
1168 ld $t0, THREAD_CARD_TABLE_OFFSET(rSELF)
1169 dsrl $t1, $a0, 7
1170 daddu $t1, $t1, $t0
1171 sb $t0, ($t1)
1172 jalr $zero, $ra
Goran Jakovljevic04568812015-04-23 15:27:23 +02001173 .cpreturn # Restore gp from t8 in branch delay slot.
Maja Gagic6ea651f2015-02-24 16:55:04 +01001174.Ldo_aput_null:
1175 dsll $a1, $a1, 2
1176 daddu $t0, $a0, $a1
1177 sw $a2, MIRROR_OBJECT_ARRAY_DATA_OFFSET($t0)
1178 jalr $zero, $ra
Goran Jakovljevic04568812015-04-23 15:27:23 +02001179 .cpreturn # Restore gp from t8 in branch delay slot.
Maja Gagic6ea651f2015-02-24 16:55:04 +01001180.Lcheck_assignability:
1181 daddiu $sp, $sp, -64
1182 .cfi_adjust_cfa_offset 64
1183 sd $ra, 56($sp)
1184 .cfi_rel_offset 31, 56
1185 sd $t9, 24($sp)
1186 sd $a2, 16($sp)
1187 sd $a1, 8($sp)
1188 sd $a0, 0($sp)
1189 move $a1, $t1
1190 move $a0, $t0
1191 jal artIsAssignableFromCode # (Class*, Class*)
Goran Jakovljevic04568812015-04-23 15:27:23 +02001192 .cpreturn # Restore gp from t8 in branch delay slot.
1193 # t8 may be clobbered in artIsAssignableFromCode.
Maja Gagic6ea651f2015-02-24 16:55:04 +01001194 ld $ra, 56($sp)
1195 ld $t9, 24($sp)
1196 ld $a2, 16($sp)
1197 ld $a1, 8($sp)
1198 ld $a0, 0($sp)
1199 daddiu $sp, $sp, 64
1200 .cfi_adjust_cfa_offset -64
Goran Jakovljevic04568812015-04-23 15:27:23 +02001201 SETUP_GP
Maja Gagic6ea651f2015-02-24 16:55:04 +01001202 bne $v0, $zero, .Ldo_aput
1203 nop
1204 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
1205 move $a1, $a2
1206 dla $t9, artThrowArrayStoreException
1207 jalr $zero, $t9 # artThrowArrayStoreException(Class*, Class*, Thread*)
1208 move $a2, rSELF # pass Thread::Current
1209END art_quick_aput_obj
1210
1211 /*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001212 * Called by managed code to resolve a static field and load a boolean primitive value.
1213 */
1214 .extern artGetBooleanStaticFromCode
1215ENTRY art_quick_get_boolean_static
1216 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001217 ld $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001218 jal artGetBooleanStaticFromCode # (uint32_t field_idx, const Method* referrer, Thread*)
1219 move $a2, rSELF # pass Thread::Current
1220 RETURN_IF_NO_EXCEPTION
1221END art_quick_get_boolean_static
1222
1223 /*
1224 * Called by managed code to resolve a static field and load a byte primitive value.
1225 */
1226 .extern artGetByteStaticFromCode
1227ENTRY art_quick_get_byte_static
1228 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001229 ld $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001230 jal artGetByteStaticFromCode # (uint32_t field_idx, const Method* referrer, Thread*)
1231 move $a2, rSELF # pass Thread::Current
1232 RETURN_IF_NO_EXCEPTION
1233END art_quick_get_byte_static
1234
1235 /*
1236 * Called by managed code to resolve a static field and load a char primitive value.
1237 */
1238 .extern artGetCharStaticFromCode
1239ENTRY art_quick_get_char_static
1240 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001241 ld $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001242 jal artGetCharStaticFromCode # (uint32_t field_idx, const Method* referrer, Thread*)
1243 move $a2, rSELF # pass Thread::Current
1244 RETURN_IF_NO_EXCEPTION
1245END art_quick_get_char_static
1246
1247 /*
1248 * Called by managed code to resolve a static field and load a short primitive value.
1249 */
1250 .extern artGetShortStaticFromCode
1251ENTRY art_quick_get_short_static
1252 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001253 ld $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001254 jal artGetShortStaticFromCode # (uint32_t field_idx, const Method* referrer, Thread*)
1255 move $a2, rSELF # pass Thread::Current
1256 RETURN_IF_NO_EXCEPTION
1257END art_quick_get_short_static
1258
1259 /*
1260 * Called by managed code to resolve a static field and load a 32-bit primitive value.
1261 */
1262 .extern artGet32StaticFromCode
1263ENTRY art_quick_get32_static
1264 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001265 ld $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001266 jal artGet32StaticFromCode # (uint32_t field_idx, const Method* referrer, Thread*)
1267 move $a2, rSELF # pass Thread::Current
1268 RETURN_IF_NO_EXCEPTION
1269END art_quick_get32_static
1270
1271 /*
1272 * Called by managed code to resolve a static field and load a 64-bit primitive value.
1273 */
1274 .extern artGet64StaticFromCode
1275ENTRY art_quick_get64_static
1276 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001277 ld $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001278 jal artGet64StaticFromCode # (uint32_t field_idx, const Method* referrer, Thread*)
1279 move $a2, rSELF # pass Thread::Current
1280 RETURN_IF_NO_EXCEPTION
1281END art_quick_get64_static
1282
1283 /*
1284 * Called by managed code to resolve a static field and load an object reference.
1285 */
1286 .extern artGetObjStaticFromCode
1287ENTRY art_quick_get_obj_static
1288 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001289 ld $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001290 jal artGetObjStaticFromCode # (uint32_t field_idx, const Method* referrer, Thread*)
1291 move $a2, rSELF # pass Thread::Current
1292 RETURN_IF_NO_EXCEPTION
1293END art_quick_get_obj_static
1294
1295 /*
1296 * Called by managed code to resolve an instance field and load a boolean primitive value.
1297 */
1298 .extern artGetBooleanInstanceFromCode
1299ENTRY art_quick_get_boolean_instance
1300 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001301 ld $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001302 jal artGetBooleanInstanceFromCode # (field_idx, Object*, referrer, Thread*)
1303 move $a3, rSELF # pass Thread::Current
1304 RETURN_IF_NO_EXCEPTION
1305END art_quick_get_boolean_instance
1306
1307 /*
1308 * Called by managed code to resolve an instance field and load a byte primitive value.
1309 */
1310 .extern artGetByteInstanceFromCode
1311ENTRY art_quick_get_byte_instance
1312 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001313 ld $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001314 jal artGetByteInstanceFromCode # (field_idx, Object*, referrer, Thread*)
1315 move $a3, rSELF # pass Thread::Current
1316 RETURN_IF_NO_EXCEPTION
1317END art_quick_get_byte_instance
1318
1319 /*
1320 * Called by managed code to resolve an instance field and load a char primitive value.
1321 */
1322 .extern artGetCharInstanceFromCode
1323ENTRY art_quick_get_char_instance
1324 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001325 ld $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001326 jal artGetCharInstanceFromCode # (field_idx, Object*, referrer, Thread*)
1327 move $a3, rSELF # pass Thread::Current
1328 RETURN_IF_NO_EXCEPTION
1329END art_quick_get_char_instance
1330
1331 /*
1332 * Called by managed code to resolve an instance field and load a short primitive value.
1333 */
1334 .extern artGetShortInstanceFromCode
1335ENTRY art_quick_get_short_instance
1336 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001337 ld $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001338 jal artGetShortInstanceFromCode # (field_idx, Object*, referrer, Thread*)
1339 move $a3, rSELF # pass Thread::Current
1340 RETURN_IF_NO_EXCEPTION
1341END art_quick_get_short_instance
1342
1343 /*
1344 * Called by managed code to resolve an instance field and load a 32-bit primitive value.
1345 */
1346 .extern artGet32InstanceFromCode
1347ENTRY art_quick_get32_instance
1348 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001349 ld $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001350 jal artGet32InstanceFromCode # (field_idx, Object*, referrer, Thread*)
1351 move $a3, rSELF # pass Thread::Current
1352 RETURN_IF_NO_EXCEPTION
1353END art_quick_get32_instance
1354
1355 /*
1356 * Called by managed code to resolve an instance field and load a 64-bit primitive value.
1357 */
1358 .extern artGet64InstanceFromCode
1359ENTRY art_quick_get64_instance
1360 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001361 ld $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001362 jal artGet64InstanceFromCode # (field_idx, Object*, referrer, Thread*)
1363 move $a3, rSELF # pass Thread::Current
1364 RETURN_IF_NO_EXCEPTION
1365END art_quick_get64_instance
1366
1367 /*
1368 * Called by managed code to resolve an instance field and load an object reference.
1369 */
1370 .extern artGetObjInstanceFromCode
1371ENTRY art_quick_get_obj_instance
1372 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001373 ld $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001374 jal artGetObjInstanceFromCode # (field_idx, Object*, referrer, Thread*)
1375 move $a3, rSELF # pass Thread::Current
1376 RETURN_IF_NO_EXCEPTION
1377END art_quick_get_obj_instance
1378
1379 /*
1380 * Called by managed code to resolve a static field and store a 8-bit primitive value.
1381 */
1382 .extern artSet8StaticFromCode
1383ENTRY art_quick_set8_static
1384 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001385 ld $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001386 jal artSet8StaticFromCode # (field_idx, new_val, referrer, Thread*)
1387 move $a3, rSELF # pass Thread::Current
1388 RETURN_IF_ZERO
1389END art_quick_set8_static
1390
1391 /*
1392 * Called by managed code to resolve a static field and store a 16-bit primitive value.
1393 */
1394 .extern artSet16StaticFromCode
1395ENTRY art_quick_set16_static
1396 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001397 ld $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001398 jal artSet16StaticFromCode # (field_idx, new_val, referrer, Thread*)
1399 move $a3, rSELF # pass Thread::Current
1400 RETURN_IF_ZERO
1401END art_quick_set16_static
1402
1403 /*
1404 * Called by managed code to resolve a static field and store a 32-bit primitive value.
1405 */
1406 .extern artSet32StaticFromCode
1407ENTRY art_quick_set32_static
1408 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001409 ld $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001410 jal artSet32StaticFromCode # (field_idx, new_val, referrer, Thread*)
1411 move $a3, rSELF # pass Thread::Current
1412 RETURN_IF_ZERO
1413END art_quick_set32_static
1414
1415 /*
1416 * Called by managed code to resolve a static field and store a 64-bit primitive value.
1417 */
1418 .extern artSet64StaticFromCode
1419ENTRY art_quick_set64_static
1420 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Calin Juravlee460d1d2015-09-29 04:52:17 +01001421 # a2 contains the new val
Mathieu Chartiere401d142015-04-22 13:56:20 -07001422 ld $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001423 jal artSet64StaticFromCode # (field_idx, referrer, new_val, Thread*)
1424 move $a3, rSELF # pass Thread::Current
1425 RETURN_IF_ZERO
1426END art_quick_set64_static
1427
1428 /*
1429 * Called by managed code to resolve a static field and store an object reference.
1430 */
1431 .extern artSetObjStaticFromCode
1432ENTRY art_quick_set_obj_static
1433 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001434 ld $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001435 jal artSetObjStaticFromCode # (field_idx, new_val, referrer, Thread*)
1436 move $a3, rSELF # pass Thread::Current
1437 RETURN_IF_ZERO
1438END art_quick_set_obj_static
1439
1440 /*
1441 * Called by managed code to resolve an instance field and store a 8-bit primitive value.
1442 */
1443 .extern artSet8InstanceFromCode
1444ENTRY art_quick_set8_instance
1445 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001446 ld $a3, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001447 jal artSet8InstanceFromCode # (field_idx, Object*, new_val, referrer, Thread*)
1448 move $a4, rSELF # pass Thread::Current
1449 RETURN_IF_ZERO
1450END art_quick_set8_instance
1451
1452 /*
1453 * Called by managed code to resolve an instance field and store a 16-bit primitive value.
1454 */
1455 .extern artSet16InstanceFromCode
1456ENTRY art_quick_set16_instance
1457 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001458 ld $a3, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001459 jal artSet16InstanceFromCode # (field_idx, Object*, new_val, referrer, Thread*)
1460 move $a4, rSELF # pass Thread::Current
1461 RETURN_IF_ZERO
1462END art_quick_set16_instance
1463
1464 /*
1465 * Called by managed code to resolve an instance field and store a 32-bit primitive value.
1466 */
1467 .extern artSet32InstanceFromCode
1468ENTRY art_quick_set32_instance
1469 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001470 ld $a3, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001471 jal artSet32InstanceFromCode # (field_idx, Object*, new_val, referrer, Thread*)
1472 move $a4, rSELF # pass Thread::Current
1473 RETURN_IF_ZERO
1474END art_quick_set32_instance
1475
1476 /*
1477 * Called by managed code to resolve an instance field and store a 64-bit primitive value.
1478 */
1479 .extern artSet64InstanceFromCode
1480ENTRY art_quick_set64_instance
1481 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001482 ld $a3, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001483 jal artSet64InstanceFromCode # (field_idx, Object*, new_val, referrer, Thread*)
1484 move $a4, rSELF # pass Thread::Current
1485 RETURN_IF_ZERO
1486END art_quick_set64_instance
1487
1488 /*
1489 * Called by managed code to resolve an instance field and store an object reference.
1490 */
1491 .extern artSetObjInstanceFromCode
1492ENTRY art_quick_set_obj_instance
1493 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Mathieu Chartiere401d142015-04-22 13:56:20 -07001494 ld $a3, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp) # pass referrer's Method*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001495 jal artSetObjInstanceFromCode # (field_idx, Object*, new_val, referrer, Thread*)
1496 move $a4, rSELF # pass Thread::Current
1497 RETURN_IF_ZERO
1498END art_quick_set_obj_instance
1499
Vladimir Marko5ea536a2015-04-20 20:11:30 +01001500// Macro to facilitate adding new allocation entrypoints.
1501.macro ONE_ARG_DOWNCALL name, entrypoint, return
1502 .extern \entrypoint
1503ENTRY \name
Maja Gagic6ea651f2015-02-24 16:55:04 +01001504 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
Vladimir Marko5ea536a2015-04-20 20:11:30 +01001505 jal \entrypoint
1506 move $a1, rSELF # pass Thread::Current
1507 \return
1508END \name
1509.endm
Andreas Gampe1a5c4062015-01-15 12:10:47 -08001510
1511// Macro to facilitate adding new allocation entrypoints.
1512.macro TWO_ARG_DOWNCALL name, entrypoint, return
Maja Gagic6ea651f2015-02-24 16:55:04 +01001513 .extern \entrypoint
Andreas Gampe1a5c4062015-01-15 12:10:47 -08001514ENTRY \name
Maja Gagic6ea651f2015-02-24 16:55:04 +01001515 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
1516 jal \entrypoint
1517 move $a2, rSELF # pass Thread::Current
1518 \return
Andreas Gampe1a5c4062015-01-15 12:10:47 -08001519END \name
1520.endm
1521
1522.macro THREE_ARG_DOWNCALL name, entrypoint, return
Maja Gagic6ea651f2015-02-24 16:55:04 +01001523 .extern \entrypoint
Andreas Gampe1a5c4062015-01-15 12:10:47 -08001524ENTRY \name
Maja Gagic6ea651f2015-02-24 16:55:04 +01001525 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
1526 jal \entrypoint
1527 move $a3, rSELF # pass Thread::Current
1528 \return
Andreas Gampe1a5c4062015-01-15 12:10:47 -08001529END \name
1530.endm
1531
Vladimir Markoe85e1232015-04-28 14:14:58 +01001532.macro FOUR_ARG_DOWNCALL name, entrypoint, return
1533 .extern \entrypoint
1534ENTRY \name
1535 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
1536 jal \entrypoint
1537 move $a4, rSELF # pass Thread::Current
1538 \return
1539END \name
1540.endm
1541
Andreas Gampe1a5c4062015-01-15 12:10:47 -08001542// Generate the allocation entrypoints for each allocator.
Goran Jakovljevic982a9a82015-12-21 12:00:54 +01001543GENERATE_ALLOC_ENTRYPOINTS_FOR_EACH_ALLOCATOR
Hiroshi Yamauchi10d4c082016-02-24 12:51:18 -08001544
Goran Jakovljevic982a9a82015-12-21 12:00:54 +01001545// A hand-written override for GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_rosalloc, RosAlloc).
1546ENTRY art_quick_alloc_object_rosalloc
1547
1548 # Fast path rosalloc allocation
1549 # a0: type_idx
1550 # a1: ArtMethod*
1551 # s1: Thread::Current
1552 # -----------------------------
1553 # t0: class
1554 # t1: object size
1555 # t2: rosalloc run
1556 # t3: thread stack top offset
1557 # a4: thread stack bottom offset
1558 # v0: free list head
1559 #
1560 # a5, a6 : temps
1561
1562 ld $t0, ART_METHOD_DEX_CACHE_TYPES_OFFSET_64($a1) # Load dex cache resolved types array.
1563
1564 dsll $a5, $a0, COMPRESSED_REFERENCE_SIZE_SHIFT # Shift the value.
1565 daddu $a5, $t0, $a5 # Compute the index.
1566 lwu $t0, 0($a5) # Load class (t0).
1567 beqzc $t0, .Lart_quick_alloc_object_rosalloc_slow_path
1568
1569 li $a6, MIRROR_CLASS_STATUS_INITIALIZED
1570 lwu $a5, MIRROR_CLASS_STATUS_OFFSET($t0) # Check class status.
1571 bnec $a5, $a6, .Lart_quick_alloc_object_rosalloc_slow_path
1572
1573 # Add a fake dependence from the following access flag and size loads to the status load. This
1574 # is to prevent those loads from being reordered above the status load and reading wrong values.
1575 xor $a5, $a5, $a5
1576 daddu $t0, $t0, $a5
1577
1578 lwu $a5, MIRROR_CLASS_ACCESS_FLAGS_OFFSET($t0) # Check if access flags has
1579 li $a6, ACCESS_FLAGS_CLASS_IS_FINALIZABLE # kAccClassIsFinalizable.
1580 and $a6, $a5, $a6
1581 bnezc $a6, .Lart_quick_alloc_object_rosalloc_slow_path
1582
1583 ld $t3, THREAD_LOCAL_ALLOC_STACK_TOP_OFFSET($s1) # Check if thread local allocation stack
1584 ld $a4, THREAD_LOCAL_ALLOC_STACK_END_OFFSET($s1) # has any room left.
1585 bgeuc $t3, $a4, .Lart_quick_alloc_object_rosalloc_slow_path
1586
1587 lwu $t1, MIRROR_CLASS_OBJECT_SIZE_OFFSET($t0) # Load object size (t1).
1588 li $a5, ROSALLOC_MAX_THREAD_LOCAL_BRACKET_SIZE # Check if size is for a thread local
1589 # allocation.
1590 bltuc $a5, $t1, .Lart_quick_alloc_object_rosalloc_slow_path
1591
1592 # Compute the rosalloc bracket index from the size. Allign up the size by the rosalloc bracket
1593 # quantum size and divide by the quantum size and subtract by 1.
1594 daddiu $t1, $t1, -1 # Decrease obj size and shift right by
1595 dsrl $t1, $t1, ROSALLOC_BRACKET_QUANTUM_SIZE_SHIFT # quantum.
1596
1597 dsll $t2, $t1, POINTER_SIZE_SHIFT
1598 daddu $t2, $t2, $s1
1599 ld $t2, THREAD_ROSALLOC_RUNS_OFFSET($t2) # Load rosalloc run (t2).
1600
1601 # Load the free list head (v0).
1602 # NOTE: this will be the return val.
1603 ld $v0, (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_HEAD_OFFSET)($t2)
1604 beqzc $v0, .Lart_quick_alloc_object_rosalloc_slow_path
1605
1606 # Load the next pointer of the head and update the list head with the next pointer.
1607 ld $a5, ROSALLOC_SLOT_NEXT_OFFSET($v0)
1608 sd $a5, (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_HEAD_OFFSET)($t2)
1609
1610 # Store the class pointer in the header. This also overwrites the first pointer. The offsets are
1611 # asserted to match.
1612
1613#if ROSALLOC_SLOT_NEXT_OFFSET != MIRROR_OBJECT_CLASS_OFFSET
1614#error "Class pointer needs to overwrite next pointer."
1615#endif
1616
1617 POISON_HEAP_REF $t0
1618 sw $t0, MIRROR_OBJECT_CLASS_OFFSET($v0)
1619
1620 # Push the new object onto the thread local allocation stack and increment the thread local
1621 # allocation stack top.
1622 sd $v0, 0($t3)
1623 daddiu $t3, $t3, COMPRESSED_REFERENCE_SIZE
1624 sd $t3, THREAD_LOCAL_ALLOC_STACK_TOP_OFFSET($s1)
1625
1626 # Decrement the size of the free list.
1627 lw $a5, (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_SIZE_OFFSET)($t2)
1628 addiu $a5, $a5, -1
1629 sw $a5, (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_SIZE_OFFSET)($t2)
1630
1631 sync # Fence.
1632
1633 jalr $zero, $ra
1634 .cpreturn # Restore gp from t8 in branch delay slot.
1635
1636.Lart_quick_alloc_object_rosalloc_slow_path:
1637 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME
1638 jal artAllocObjectFromCodeRosAlloc
1639 move $a2 ,$s1 # Pass self as argument.
1640 RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
1641
1642END art_quick_alloc_object_rosalloc
Andreas Gampe1a5c4062015-01-15 12:10:47 -08001643
Hiroshi Yamauchi10d4c082016-02-24 12:51:18 -08001644GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_tlab, TLAB)
1645GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_region_tlab, RegionTLAB)
1646
Maja Gagic6ea651f2015-02-24 16:55:04 +01001647 /*
Vladimir Marko5ea536a2015-04-20 20:11:30 +01001648 * Entry from managed code to resolve a string, this stub will allocate a String and deliver an
1649 * exception on error. On success the String is returned. A0 holds the string index. The fast
1650 * path check for hit in strings cache has already been performed.
1651 */
1652ONE_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
1653
1654 /*
1655 * Entry from managed code when uninitialized static storage, this stub will run the class
1656 * initializer and deliver the exception on error. On success the static storage base is
1657 * returned.
1658 */
1659ONE_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
1660
1661 /*
1662 * Entry from managed code when dex cache misses for a type_idx.
1663 */
1664ONE_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
1665
1666 /*
1667 * Entry from managed code when type_idx needs to be checked for access and dex cache may also
1668 * miss.
1669 */
1670ONE_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
1671
1672 /*
Maja Gagic6ea651f2015-02-24 16:55:04 +01001673 * Called by managed code when the value in rSUSPEND has been decremented to 0.
1674 */
1675 .extern artTestSuspendFromCode
1676ENTRY art_quick_test_suspend
1677 lh $a0, THREAD_FLAGS_OFFSET(rSELF)
1678 bne $a0, $zero, 1f
1679 daddiu rSUSPEND, $zero, SUSPEND_CHECK_INTERVAL # reset rSUSPEND to SUSPEND_CHECK_INTERVAL
1680 jalr $zero, $ra
Goran Jakovljevic04568812015-04-23 15:27:23 +02001681 .cpreturn # Restore gp from t8 in branch delay slot.
Maja Gagic6ea651f2015-02-24 16:55:04 +010016821:
1683 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME # save callee saves for stack crawl
1684 jal artTestSuspendFromCode # (Thread*)
1685 move $a0, rSELF
1686 RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
1687END art_quick_test_suspend
Douglas Leung6461d192015-01-30 18:13:58 -08001688
1689 /*
1690 * Called by managed code that is attempting to call a method on a proxy class. On entry
1691 * r0 holds the proxy method; r1, r2 and r3 may contain arguments.
1692 */
1693 .extern artQuickProxyInvokeHandler
1694ENTRY art_quick_proxy_invoke_handler
Douglas Leung8223b802015-04-28 17:22:29 -07001695 SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_WITH_METHOD_IN_A0
Douglas Leung6461d192015-01-30 18:13:58 -08001696 move $a2, rSELF # pass Thread::Current
1697 jal artQuickProxyInvokeHandler # (Method* proxy method, receiver, Thread*, SP)
1698 move $a3, $sp # pass $sp
1699 ld $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
1700 daddiu $sp, $sp, REFS_AND_ARGS_MINUS_REFS_SIZE # skip a0-a7 and f12-f19
1701 RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
1702 bne $t0, $zero, 1f
1703 dmtc1 $v0, $f0 # place return value to FP return value
1704 jalr $zero, $ra
1705 dmtc1 $v1, $f1 # place return value to FP return value
17061:
1707 DELIVER_PENDING_EXCEPTION
1708END art_quick_proxy_invoke_handler
1709
Maja Gagic6ea651f2015-02-24 16:55:04 +01001710 /*
Goran Jakovljevic59028d92016-03-29 18:05:03 +02001711 * Called to resolve an imt conflict.
1712 * a0 is the conflict ArtMethod.
1713 * t0 is a hidden argument that holds the target interface method's dex method index.
1714 *
1715 * Mote that this stub writes to a0, t0 and t1.
Maja Gagic6ea651f2015-02-24 16:55:04 +01001716 */
1717ENTRY art_quick_imt_conflict_trampoline
Goran Jakovljevic59028d92016-03-29 18:05:03 +02001718 ld $t1, 0($sp) # Load referrer.
1719 ld $t1, ART_METHOD_DEX_CACHE_METHODS_OFFSET_64($t1) # Load dex cache methods array.
1720 dsll $t0, $t0, POINTER_SIZE_SHIFT # Calculate offset.
1721 daddu $t0, $t1, $t0 # Add offset to base.
1722 ld $t0, 0($t0) # Load interface method.
1723 ld $a0, ART_METHOD_JNI_OFFSET_64($a0) # Load ImtConflictTable.
1724
1725.Limt_table_iterate:
1726 ld $t1, 0($a0) # Load next entry in ImtConflictTable.
1727 # Branch if found.
1728 beq $t1, $t0, .Limt_table_found
1729 nop
1730 # If the entry is null, the interface method is not in the ImtConflictTable.
1731 beqzc $t1, .Lconflict_trampoline
1732 # Iterate over the entries of the ImtConflictTable.
1733 daddiu $a0, $a0, 2 * __SIZEOF_POINTER__ # Iterate to the next entry.
1734 bc .Limt_table_iterate
1735
1736.Limt_table_found:
1737 # We successfully hit an entry in the table. Load the target method and jump to it.
1738 ld $a0, __SIZEOF_POINTER__($a0)
1739 ld $t9, ART_METHOD_QUICK_CODE_OFFSET_64($a0)
1740 jr $t9
1741 .cpreturn # Restore gp from t8 in branch delay slot.
1742
1743.Lconflict_trampoline:
1744 # Call the runtime stub to populate the ImtConflictTable and jump to the resolved method.
Andreas Gampe3031c8d2015-07-13 20:11:06 -07001745 INVOKE_TRAMPOLINE_BODY artInvokeInterfaceTrampoline
Maja Gagic6ea651f2015-02-24 16:55:04 +01001746END art_quick_imt_conflict_trampoline
Andreas Gampecc7c39d2015-01-30 17:04:45 -08001747
1748 .extern artQuickResolutionTrampoline
1749ENTRY art_quick_resolution_trampoline
1750 SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME
1751 move $a2, rSELF # pass Thread::Current
1752 jal artQuickResolutionTrampoline # (Method* called, receiver, Thread*, SP)
1753 move $a3, $sp # pass $sp
1754 beq $v0, $zero, 1f
Mathieu Chartiere401d142015-04-22 13:56:20 -07001755 ld $a0, 0($sp) # load resolved method in $a0
Andreas Gampecc7c39d2015-01-30 17:04:45 -08001756 # artQuickResolutionTrampoline puts resolved method in *SP
1757 RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
1758 move $t9, $v0 # code pointer must be in $t9 to generate the global pointer
1759 jalr $zero, $t9 # tail call to method
1760 nop
17611:
1762 RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
1763 DELIVER_PENDING_EXCEPTION
1764END art_quick_resolution_trampoline
Andreas Gampe1a5c4062015-01-15 12:10:47 -08001765
1766 .extern artQuickGenericJniTrampoline
1767 .extern artQuickGenericJniEndTrampoline
1768ENTRY art_quick_generic_jni_trampoline
Douglas Leung8223b802015-04-28 17:22:29 -07001769 SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_WITH_METHOD_IN_A0
Andreas Gampe1a5c4062015-01-15 12:10:47 -08001770 move $s8, $sp # save $sp
1771
1772 # prepare for call to artQuickGenericJniTrampoline(Thread*, SP)
1773 move $a0, rSELF # pass Thread::Current
1774 move $a1, $sp # pass $sp
1775 jal artQuickGenericJniTrampoline # (Thread*, SP)
1776 daddiu $sp, $sp, -5120 # reserve space on the stack
1777
1778 # The C call will have registered the complete save-frame on success.
1779 # The result of the call is:
1780 # v0: ptr to native code, 0 on error.
1781 # v1: ptr to the bottom of the used area of the alloca, can restore stack till here.
1782 beq $v0, $zero, 1f # check entry error
1783 move $t9, $v0 # save the code ptr
1784 move $sp, $v1 # release part of the alloca
1785
1786 # Load parameters from stack into registers
1787 ld $a0, 0($sp)
1788 ld $a1, 8($sp)
1789 ld $a2, 16($sp)
1790 ld $a3, 24($sp)
1791 ld $a4, 32($sp)
1792 ld $a5, 40($sp)
1793 ld $a6, 48($sp)
1794 ld $a7, 56($sp)
1795 # Load FPRs the same as GPRs. Look at BuildNativeCallFrameStateMachine.
1796 l.d $f12, 0($sp)
1797 l.d $f13, 8($sp)
1798 l.d $f14, 16($sp)
1799 l.d $f15, 24($sp)
1800 l.d $f16, 32($sp)
1801 l.d $f17, 40($sp)
1802 l.d $f18, 48($sp)
1803 l.d $f19, 56($sp)
1804 jalr $t9 # native call
1805 daddiu $sp, $sp, 64
1806
1807 # result sign extension is handled in C code
1808 # prepare for call to artQuickGenericJniEndTrampoline(Thread*, result, result_f)
1809 move $a0, rSELF # pass Thread::Current
1810 move $a1, $v0
1811 jal artQuickGenericJniEndTrampoline
1812 dmfc1 $a2, $f0
1813
1814 ld $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
Nicolas Geoffray126d6592015-03-03 14:28:35 +00001815 bne $t0, $zero, 1f # check for pending exceptions
Andreas Gampe1a5c4062015-01-15 12:10:47 -08001816 move $sp, $s8 # tear down the alloca
1817
1818 # tear dpown the callee-save frame
1819 RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
1820
1821 jalr $zero, $ra
1822 dmtc1 $v0, $f0 # place return value to FP return value
1823
18241:
Nicolas Geoffray126d6592015-03-03 14:28:35 +00001825 ld $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF)
1826 # This will create a new save-all frame, required by the runtime.
Andreas Gampe1a5c4062015-01-15 12:10:47 -08001827 DELIVER_PENDING_EXCEPTION
1828END art_quick_generic_jni_trampoline
1829
1830 .extern artQuickToInterpreterBridge
1831ENTRY art_quick_to_interpreter_bridge
1832 SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME
1833 move $a1, rSELF # pass Thread::Current
1834 jal artQuickToInterpreterBridge # (Method* method, Thread*, SP)
1835 move $a2, $sp # pass $sp
1836 ld $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
1837 daddiu $sp, $sp, REFS_AND_ARGS_MINUS_REFS_SIZE # skip a0-a7 and f12-f19
1838 RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
1839 bne $t0, $zero, 1f
1840 dmtc1 $v0, $f0 # place return value to FP return value
1841 jalr $zero, $ra
1842 dmtc1 $v1, $f1 # place return value to FP return value
18431:
1844 DELIVER_PENDING_EXCEPTION
1845END art_quick_to_interpreter_bridge
1846
1847 /*
1848 * Routine that intercepts method calls and returns.
1849 */
1850 .extern artInstrumentationMethodEntryFromCode
1851 .extern artInstrumentationMethodExitFromCode
1852ENTRY art_quick_instrumentation_entry
1853 SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME
1854 daddiu $sp, $sp, -16 # space for saving arg0
1855 .cfi_adjust_cfa_offset 16
1856 sd $a0, 0($sp) # save arg0
1857 move $a3, $ra # pass $ra
1858 jal artInstrumentationMethodEntryFromCode # (Method*, Object*, Thread*, RA)
1859 move $a2, rSELF # pass Thread::Current
1860 move $t9, $v0 # $t9 holds reference to code
1861 ld $a0, 0($sp) # restore arg0
1862 daddiu $sp, $sp, 16 # remove args
1863 .cfi_adjust_cfa_offset -16
1864 RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
1865 jalr $t9 # call method
1866 nop
1867END art_quick_instrumentation_entry
1868 /* intentional fallthrough */
1869 .global art_quick_instrumentation_exit
1870art_quick_instrumentation_exit:
1871 .cfi_startproc
Goran Jakovljevic04568812015-04-23 15:27:23 +02001872 SETUP_GP
Andreas Gampe1a5c4062015-01-15 12:10:47 -08001873 move $ra, $zero # link register is to here, so clobber with 0 for later checks
1874 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME
1875 move $t0, $sp # remember bottom of caller's frame
1876 daddiu $sp, $sp, -16 # save return values and set up args
1877 .cfi_adjust_cfa_offset 16
1878 sd $v0, 0($sp)
1879 .cfi_rel_offset 2, 0
1880 s.d $f0, 8($sp)
1881 mov.d $f15, $f0 # pass fpr result
1882 move $a2, $v0 # pass gpr result
1883 move $a1, $t0 # pass $sp
Andreas Gampe1a5c4062015-01-15 12:10:47 -08001884 move $a0, rSELF # pass Thread::Current
Goran Jakovljevic04568812015-04-23 15:27:23 +02001885 jal artInstrumentationMethodExitFromCode # (Thread*, SP, gpr_res, fpr_res)
1886 .cpreturn # Restore gp from t8 in branch delay slot. gp is not used anymore,
1887 # and t8 may be clobbered in artInstrumentationMethodExitFromCode.
1888
Douglas Leungf96e8bd2015-03-27 15:38:30 -07001889 move $t9, $v0 # set aside returned link register
Andreas Gampe1a5c4062015-01-15 12:10:47 -08001890 move $ra, $v1 # set link register for deoptimization
1891 ld $v0, 0($sp) # restore return values
1892 l.d $f0, 8($sp)
Douglas Leungf96e8bd2015-03-27 15:38:30 -07001893 jalr $zero, $t9 # return
Andreas Gampe1a5c4062015-01-15 12:10:47 -08001894 daddiu $sp, $sp, 16+FRAME_SIZE_REFS_ONLY_CALLEE_SAVE # 16 bytes of saved values + ref_only callee save frame
1895 .cfi_adjust_cfa_offset -(16+FRAME_SIZE_REFS_ONLY_CALLEE_SAVE)
1896END art_quick_instrumentation_exit
1897
Maja Gagic6ea651f2015-02-24 16:55:04 +01001898 /*
1899 * Instrumentation has requested that we deoptimize into the interpreter. The deoptimization
1900 * will long jump to the upcall with a special exception of -1.
1901 */
1902 .extern artDeoptimize
1903 .extern artEnterInterpreterFromDeoptimize
1904ENTRY art_quick_deoptimize
1905 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
1906 jal artDeoptimize # artDeoptimize(Thread*, SP)
1907 # Returns caller method's frame size.
1908 move $a0, rSELF # pass Thread::current
1909END art_quick_deoptimize
1910
Sebastien Hertz07474662015-08-25 15:12:33 +00001911 /*
1912 * Compiled code has requested that we deoptimize into the interpreter. The deoptimization
1913 * will long jump to the upcall with a special exception of -1.
1914 */
1915 .extern artDeoptimizeFromCompiledCode
1916ENTRY art_quick_deoptimize_from_compiled_code
1917 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
1918 jal artDeoptimizeFromCompiledCode # artDeoptimizeFromCompiledCode(Thread*, SP)
1919 # Returns caller method's frame size.
1920 move $a0, rSELF # pass Thread::current
1921END art_quick_deoptimize_from_compiled_code
1922
Chris Larsen9701c2e2015-09-04 17:22:47 -07001923 .set push
1924 .set noat
1925/* java.lang.String.compareTo(String anotherString) */
1926ENTRY_NO_GP art_quick_string_compareto
1927/* $a0 holds address of "this" */
1928/* $a1 holds address of "anotherString" */
1929 beq $a0,$a1,9f # this and anotherString are the same object
1930 move $v0,$zero
1931
1932 lw $a2,MIRROR_STRING_COUNT_OFFSET($a0) # this.length()
1933 lw $a3,MIRROR_STRING_COUNT_OFFSET($a1) # anotherString.length()
Chris Larsencf283da2016-01-19 16:45:35 -08001934 MINu $t2, $a2, $a3
1935# $t2 now holds min(this.length(),anotherString.length())
Chris Larsen9701c2e2015-09-04 17:22:47 -07001936
1937 beqz $t2,9f # while min(this.length(),anotherString.length())-i != 0
1938 subu $v0,$a2,$a3 # if $t2==0 return
1939 # (this.length() - anotherString.length())
19401:
1941 lhu $t0,MIRROR_STRING_VALUE_OFFSET($a0) # while this.charAt(i) == anotherString.charAt(i)
1942 lhu $t1,MIRROR_STRING_VALUE_OFFSET($a1)
1943 bne $t0,$t1,9f # if this.charAt(i) != anotherString.charAt(i)
1944 subu $v0,$t0,$t1 # return (this.charAt(i) - anotherString.charAt(i))
1945 daddiu $a0,$a0,2 # point at this.charAt(i++)
1946 subu $t2,$t2,1 # new value of
1947 # min(this.length(),anotherString.length())-i
1948 bnez $t2,1b
1949 daddiu $a1,$a1,2 # point at anotherString.charAt(i++)
1950 subu $v0,$a2,$a3
1951
19529:
1953 j $ra
1954 nop
1955END art_quick_string_compareto
1956
1957/* java.lang.String.indexOf(int ch, int fromIndex=0) */
1958ENTRY_NO_GP art_quick_indexof
1959/* $a0 holds address of "this" */
Chris Larsencf283da2016-01-19 16:45:35 -08001960/* $a1 holds "ch" */
1961/* $a2 holds "fromIndex" */
Chris Larsen9701c2e2015-09-04 17:22:47 -07001962 lw $t0,MIRROR_STRING_COUNT_OFFSET($a0) # this.length()
Chris Larsencf283da2016-01-19 16:45:35 -08001963 slt $at, $a2, $zero # if fromIndex < 0
1964 seleqz $a2, $a2, $at # fromIndex = 0;
1965 subu $t0,$t0,$a2 # this.length() - fromIndex
1966 blez $t0,6f # if this.length()-fromIndex <= 0
Chris Larsen9701c2e2015-09-04 17:22:47 -07001967 li $v0,-1 # return -1;
1968
1969 sll $v0,$a2,1 # $a0 += $a2 * 2
1970 daddu $a0,$a0,$v0 # " " " " "
Chris Larsencf283da2016-01-19 16:45:35 -08001971 move $v0,$a2 # Set i to fromIndex.
Chris Larsen9701c2e2015-09-04 17:22:47 -07001972
19731:
1974 lhu $t3,MIRROR_STRING_VALUE_OFFSET($a0) # if this.charAt(i) == ch
1975 beq $t3,$a1,6f # return i;
1976 daddu $a0,$a0,2 # i++
1977 subu $t0,$t0,1 # this.length() - i
1978 bnez $t0,1b # while this.length() - i > 0
1979 addu $v0,$v0,1 # i++
1980
1981 li $v0,-1 # if this.length() - i <= 0
1982 # return -1;
1983
19846:
1985 j $ra
1986 nop
1987END art_quick_indexof
1988
1989 .set pop