quick_entrypoints_mips64.S revision cc7c39d747f5802282adcc51ffe44405f116f84b
1/*
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    /*
30     * Macro that sets up the callee save frame to conform with
31     * Runtime::CreateCalleeSaveMethod(kSaveAll)
32     * callee-save: padding + $f24-$f31 + $s0-$s7 + $gp + $ra + $s8 = 19 total + 1x8 bytes padding
33     */
34.macro SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
35    daddiu $sp, $sp, -160
36    .cfi_adjust_cfa_offset 160
37
38     // Ugly compile-time check, but we only have the preprocessor.
39#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVE != 160)
40#error "SAVE_ALL_CALLEE_SAVE_FRAME(MIPS64) size not as expected."
41#endif
42
43    sd     $ra, 152($sp)
44    .cfi_rel_offset 31, 152
45    sd     $s8, 144($sp)
46    .cfi_rel_offset 30, 144
47    sd     $gp, 136($sp)
48    .cfi_rel_offset 28, 136
49    sd     $s7, 128($sp)
50    .cfi_rel_offset 23, 128
51    sd     $s6, 120($sp)
52    .cfi_rel_offset 22, 120
53    sd     $s5, 112($sp)
54    .cfi_rel_offset 21, 112
55    sd     $s4, 104($sp)
56    .cfi_rel_offset 20, 104
57    sd     $s3,  96($sp)
58    .cfi_rel_offset 19, 96
59    sd     $s2,  88($sp)
60    .cfi_rel_offset 18, 88
61    sd     $s1,  80($sp)
62    .cfi_rel_offset 17, 80
63    sd     $s0,  72($sp)
64    .cfi_rel_offset 16, 72
65
66    // FP callee-saves
67    s.d    $f31, 64($sp)
68    s.d    $f30, 56($sp)
69    s.d    $f29, 48($sp)
70    s.d    $f28, 40($sp)
71    s.d    $f27, 32($sp)
72    s.d    $f26, 24($sp)
73    s.d    $f25, 16($sp)
74    s.d    $f24,  8($sp)
75
76    # load appropriate callee-save-method
77    ld      $v0, %got(_ZN3art7Runtime9instance_E)($gp)
78    ld      $v0, 0($v0)
79    THIS_LOAD_REQUIRES_READ_BARRIER
80    ld      $v0, RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET($v0)
81    sw      $v0, 0($sp)                                # Place Method* at bottom of stack.
82    sd      $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF)  # Place sp in Thread::Current()->top_quick_frame.
83.endm
84
85    /*
86     * Macro that sets up the callee save frame to conform with
87     * Runtime::CreateCalleeSaveMethod(kRefsOnly). Restoration assumes
88     * non-moving GC.
89     * Does not include rSUSPEND or rSELF
90     * callee-save: padding + $s2-$s7 + $gp + $ra + $s8 = 9 total + 1x8 bytes padding
91     */
92.macro SETUP_REFS_ONLY_CALLEE_SAVE_FRAME
93    daddiu $sp, $sp, -80
94    .cfi_adjust_cfa_offset 80
95
96    // Ugly compile-time check, but we only have the preprocessor.
97#if (FRAME_SIZE_REFS_ONLY_CALLEE_SAVE != 80)
98#error "REFS_ONLY_CALLEE_SAVE_FRAME(MIPS64) size not as expected."
99#endif
100
101    sd     $ra, 72($sp)
102    .cfi_rel_offset 31, 72
103    sd     $s8, 64($sp)
104    .cfi_rel_offset 30, 64
105    sd     $gp, 56($sp)
106    .cfi_rel_offset 28, 56
107    sd     $s7, 48($sp)
108    .cfi_rel_offset 23, 48
109    sd     $s6, 40($sp)
110    .cfi_rel_offset 22, 40
111    sd     $s5, 32($sp)
112    .cfi_rel_offset 21, 32
113    sd     $s4, 24($sp)
114    .cfi_rel_offset 20, 24
115    sd     $s3, 16($sp)
116    .cfi_rel_offset 19, 16
117    sd     $s2, 8($sp)
118    .cfi_rel_offset 18, 8
119    # load appropriate callee-save-method
120    ld      $v0, %got(_ZN3art7Runtime9instance_E)($gp)
121    ld      $v0, 0($v0)
122    THIS_LOAD_REQUIRES_READ_BARRIER
123    ld      $v0, RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET($v0)
124    sw      $v0, 0($sp)                                # Place Method* at bottom of stack.
125    sd      $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF)  # Place sp in Thread::Current()->top_quick_frame.
126.endm
127
128.macro RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
129    ld     $ra, 72($sp)
130    .cfi_restore 31
131    ld     $s8, 64($sp)
132    .cfi_restore 30
133    ld     $gp, 56($sp)
134    .cfi_restore 28
135    ld     $s7, 48($sp)
136    .cfi_restore 23
137    ld     $s6, 40($sp)
138    .cfi_restore 22
139    ld     $s5, 32($sp)
140    .cfi_restore 21
141    ld     $s4, 24($sp)
142    .cfi_restore 20
143    ld     $s3, 16($sp)
144    .cfi_restore 19
145    ld     $s2, 8($sp)
146    .cfi_restore 18
147    daddiu $sp, $sp, 80
148    .cfi_adjust_cfa_offset -80
149.endm
150
151.macro RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
152    ld     $ra, 72($sp)
153    .cfi_restore 31
154    ld     $s8, 64($sp)
155    .cfi_restore 30
156    ld     $gp, 56($sp)
157    .cfi_restore 28
158    ld     $s7, 48($sp)
159    .cfi_restore 23
160    ld     $s6, 40($sp)
161    .cfi_restore 22
162    ld     $s5, 32($sp)
163    .cfi_restore 21
164    ld     $s4, 24($sp)
165    .cfi_restore 20
166    ld     $s3, 16($sp)
167    .cfi_restore 19
168    ld     $s2, 8($sp)
169    .cfi_restore 18
170    jalr   $zero, $ra
171    daddiu $sp, $sp, 80
172    .cfi_adjust_cfa_offset -80
173.endm
174
175// This assumes the top part of these stack frame types are identical.
176#define REFS_AND_ARGS_MINUS_REFS_SIZE (FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE - FRAME_SIZE_REFS_ONLY_CALLEE_SAVE)
177
178    /*
179     * Macro that sets up the callee save frame to conform with
180     * Runtime::CreateCalleeSaveMethod(kRefsAndArgs). Restoration assumes
181     * non-moving GC.
182     * callee-save: padding + $f12-$f19 + $a1-$a7 + $s2-$s7 + $gp + $ra + $s8 = 24 total + 1 words padding + Method*
183     */
184.macro SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
185    daddiu  $sp, $sp, -208
186    .cfi_adjust_cfa_offset 208
187
188    // Ugly compile-time check, but we only have the preprocessor.
189#if (FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE != 208)
190#error "REFS_AND_ARGS_CALLEE_SAVE_FRAME(MIPS64) size not as expected."
191#endif
192
193    sd     $ra, 200($sp)           # = kQuickCalleeSaveFrame_RefAndArgs_LrOffset
194    .cfi_rel_offset 31, 200
195    sd     $s8, 192($sp)
196    .cfi_rel_offset 30, 192
197    sd     $gp, 184($sp)
198    .cfi_rel_offset 28, 184
199    sd     $s7, 176($sp)
200    .cfi_rel_offset 23, 176
201    sd     $s6, 168($sp)
202    .cfi_rel_offset 22, 168
203    sd     $s5, 160($sp)
204    .cfi_rel_offset 21, 160
205    sd     $s4, 152($sp)
206    .cfi_rel_offset 20, 152
207    sd     $s3, 144($sp)
208    .cfi_rel_offset 19, 144
209    sd     $s2, 136($sp)
210    .cfi_rel_offset 18, 136
211
212    sd     $a7, 128($sp)
213    .cfi_rel_offset 11, 128
214    sd     $a6, 120($sp)
215    .cfi_rel_offset 10, 120
216    sd     $a5, 112($sp)
217    .cfi_rel_offset 9, 112
218    sd     $a4, 104($sp)
219    .cfi_rel_offset 8, 104
220    sd     $a3,  96($sp)
221    .cfi_rel_offset 7, 96
222    sd     $a2,  88($sp)
223    .cfi_rel_offset 6, 88
224    sd     $a1,  80($sp)           # = kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset
225    .cfi_rel_offset 5, 80
226
227    s.d    $f19, 72($sp)
228    s.d    $f18, 64($sp)
229    s.d    $f17, 56($sp)
230    s.d    $f16, 48($sp)
231    s.d    $f15, 40($sp)
232    s.d    $f14, 32($sp)
233    s.d    $f13, 24($sp)           # = kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset
234    s.d    $f12, 16($sp)           # This isn't necessary to store.
235
236    # 1x8 bytes paddig + Method*
237    ld      $v0, %got(_ZN3art7Runtime9instance_E)($gp)
238    ld      $v0, 0($v0)
239    THIS_LOAD_REQUIRES_READ_BARRIER
240    ld      $v0, RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET($v0)
241    sw      $v0, 0($sp)                                # Place Method* at bottom of stack.
242    sd      $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF)  # Place sp in Thread::Current()->top_quick_frame.
243.endm
244
245.macro SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME
246    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
247    # load appropriate callee-save-method
248    ld      $v0, %got(_ZN3art7Runtime9instance_E)($gp)
249    ld      $v0, 0($v0)
250    THIS_LOAD_REQUIRES_READ_BARRIER
251    ld      $v0, RUNTIME_REFS_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET($v0)
252    sw      $v0, 0($sp)                                # Place Method* at bottom of stack.
253    sd      $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF)  # Place sp in Thread::Current()->top_quick_frame.
254.endm
255
256.macro RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
257    ld     $ra, 200($sp)
258    .cfi_restore 31
259    ld     $s8, 192($sp)
260    .cfi_restore 30
261    ld     $gp, 184($sp)
262    .cfi_restore 28
263    ld     $s7, 176($sp)
264    .cfi_restore 23
265    ld     $s6, 168($sp)
266    .cfi_restore 22
267    ld     $s5, 160($sp)
268    .cfi_restore 21
269    ld     $s4, 152($sp)
270    .cfi_restore 20
271    ld     $s3, 144($sp)
272    .cfi_restore 19
273    ld     $s2, 136($sp)
274    .cfi_restore 18
275
276    ld     $a7, 128($sp)
277    .cfi_restore 11
278    ld     $a6, 120($sp)
279    .cfi_restore 10
280    ld     $a5, 112($sp)
281    .cfi_restore 9
282    ld     $a4, 104($sp)
283    .cfi_restore 8
284    ld     $a3,  96($sp)
285    .cfi_restore 7
286    ld     $a2,  88($sp)
287    .cfi_restore 6
288    ld     $a1,  80($sp)
289    .cfi_restore 5
290
291    l.d    $f19, 72($sp)
292    l.d    $f18, 64($sp)
293    l.d    $f17, 56($sp)
294    l.d    $f16, 48($sp)
295    l.d    $f15, 40($sp)
296    l.d    $f14, 32($sp)
297    l.d    $f13, 24($sp)
298    l.d    $f12, 16($sp)
299
300    daddiu $sp, $sp, 208
301    .cfi_adjust_cfa_offset -208
302.endm
303
304    /*
305     * Macro that set calls through to artDeliverPendingExceptionFromCode,
306     * where the pending
307     * exception is Thread::Current()->exception_
308     */
309.macro DELIVER_PENDING_EXCEPTION
310    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME     # save callee saves for throw
311    dla     $t9, artDeliverPendingExceptionFromCode
312    jalr    $zero, $t9                   # artDeliverPendingExceptionFromCode(Thread*)
313    move    $a0, rSELF                   # pass Thread::Current
314.endm
315
316.macro RETURN_IF_NO_EXCEPTION
317    ld     $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
318    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
319    bne    $t0, $zero, 1f                      # success if no exception is pending
320    nop
321    jalr   $zero, $ra
322    nop
3231:
324    DELIVER_PENDING_EXCEPTION
325.endm
326
327.macro RETURN_IF_ZERO
328    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
329    bne    $v0, $zero, 1f                # success?
330    nop
331    jalr   $zero, $ra                    # return on success
332    nop
3331:
334    DELIVER_PENDING_EXCEPTION
335.endm
336
337.macro RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
338    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
339    beq    $v0, $zero, 1f                # success?
340    nop
341    jalr   $zero, $ra                    # return on success
342    nop
3431:
344    DELIVER_PENDING_EXCEPTION
345.endm
346
347    /*
348     * On entry $a0 is uint32_t* gprs_ and $a1 is uint32_t* fprs_
349     * FIXME: just guessing about the shape of the jmpbuf.  Where will pc be?
350     */
351ENTRY art_quick_do_long_jump
352    l.d     $f0, 0($a1)
353    l.d     $f1, 8($a1)
354    l.d     $f2, 16($a1)
355    l.d     $f3, 24($a1)
356    l.d     $f4, 32($a1)
357    l.d     $f5, 40($a1)
358    l.d     $f6, 48($a1)
359    l.d     $f7, 56($a1)
360    l.d     $f8, 64($a1)
361    l.d     $f9, 72($a1)
362    l.d     $f10, 80($a1)
363    l.d     $f11, 88($a1)
364    l.d     $f12, 96($a1)
365    l.d     $f13, 104($a1)
366    l.d     $f14, 112($a1)
367    l.d     $f15, 120($a1)
368    l.d     $f16, 128($a1)
369    l.d     $f17, 136($a1)
370    l.d     $f18, 144($a1)
371    l.d     $f19, 152($a1)
372    l.d     $f20, 160($a1)
373    l.d     $f21, 168($a1)
374    l.d     $f22, 176($a1)
375    l.d     $f23, 184($a1)
376    l.d     $f24, 192($a1)
377    l.d     $f25, 200($a1)
378    l.d     $f26, 208($a1)
379    l.d     $f27, 216($a1)
380    l.d     $f28, 224($a1)
381    l.d     $f29, 232($a1)
382    l.d     $f30, 240($a1)
383    l.d     $f31, 248($a1)
384    .set push
385    .set nomacro
386    .set noat
387# no need to load zero
388    ld      $at, 8($a0)
389    .set pop
390    ld      $v0, 16($a0)
391    ld      $v1, 24($a0)
392# a0 has to be loaded last
393    ld      $a1, 40($a0)
394    ld      $a2, 48($a0)
395    ld      $a3, 56($a0)
396    ld      $a4, 64($a0)
397    ld      $a5, 72($a0)
398    ld      $a6, 80($a0)
399    ld      $a7, 88($a0)
400    ld      $t0, 96($a0)
401    ld      $t1, 104($a0)
402    ld      $t2, 112($a0)
403    ld      $t3, 120($a0)
404    ld      $s0, 128($a0)
405    ld      $s1, 136($a0)
406    ld      $s2, 144($a0)
407    ld      $s3, 152($a0)
408    ld      $s4, 160($a0)
409    ld      $s5, 168($a0)
410    ld      $s6, 176($a0)
411    ld      $s7, 184($a0)
412    ld      $t8, 192($a0)
413    ld      $t9, 200($a0)
414# no need to load k0, k1
415    ld      $gp, 224($a0)
416    ld      $sp, 232($a0)
417    ld      $s8, 240($a0)
418    ld      $ra, 248($a0)
419    ld      $a0, 32($a0)
420    move    $v0, $zero          # clear result registers v0 and v1
421    jalr    $zero, $ra          # do long jump
422    move    $v1, $zero
423END art_quick_do_long_jump
424
425UNIMPLEMENTED art_quick_deliver_exception
426UNIMPLEMENTED art_quick_throw_null_pointer_exception
427UNIMPLEMENTED art_quick_throw_div_zero
428UNIMPLEMENTED art_quick_throw_array_bounds
429UNIMPLEMENTED art_quick_throw_stack_overflow
430UNIMPLEMENTED art_quick_throw_no_such_method
431
432UNIMPLEMENTED art_quick_invoke_interface_trampoline
433UNIMPLEMENTED art_quick_invoke_interface_trampoline_with_access_check
434
435UNIMPLEMENTED art_quick_invoke_static_trampoline_with_access_check
436UNIMPLEMENTED art_quick_invoke_direct_trampoline_with_access_check
437UNIMPLEMENTED art_quick_invoke_super_trampoline_with_access_check
438UNIMPLEMENTED art_quick_invoke_virtual_trampoline_with_access_check
439
440    # On entry:
441    #   t0 = shorty
442    #   t1 = ptr to arg_array
443    #   t2 = number of argument bytes remain
444    #   v0 = ptr to stack frame where to copy arg_array
445    # This macro modifies t3, t9 and v0
446.macro LOOP_OVER_SHORTY_LOADING_REG gpu, fpu, label
447    lbu    $t3, 0($t0)           # get argument type from shorty
448    beqz   $t3, \label
449    daddiu $t0, 1
450    li     $t9, 68               # put char 'D' into t9
451    beq    $t9, $t3, 1f          # branch if result type char == 'D'
452    li     $t9, 70               # put char 'F' into t9
453    beq    $t9, $t3, 2f          # branch if result type char == 'F'
454    li     $t9, 74               # put char 'J' into t9
455    beq    $t9, $t3, 3f          # branch if result type char == 'J'
456    nop
457    lwu    $\gpu, 0($t1)
458    sw     $\gpu, 0($v0)
459    daddiu $v0, 4
460    daddiu $t1, 4
461    b      4f
462    daddiu $t2, -4               # delay slot
463
4641:  # found double
465    lwu    $t3, 0($t1)
466    mtc1   $t3, $\fpu
467    sw     $t3, 0($v0)
468    lwu    $t3, 4($t1)
469    mthc1  $t3, $\fpu
470    sw     $t3, 4($v0)
471    daddiu $v0, 8
472    daddiu $t1, 8
473    b      4f
474    daddiu $t2, -8               # delay slot
475
4762:  # found float
477    lwu    $t3, 0($t1)
478    mtc1   $t3, $\fpu
479    sw     $t3, 0($v0)
480    daddiu $v0, 4
481    daddiu $t1, 4
482    b      4f
483    daddiu $t2, -4               # delay slot
484
4853:  # found long (8 bytes)
486    lwu    $t3, 0($t1)
487    sw     $t3, 0($v0)
488    lwu    $t9, 4($t1)
489    sw     $t9, 4($v0)
490    dsll   $t9, $t9, 32
491    or     $\gpu, $t9, $t3
492    daddiu $v0, 8
493    daddiu $t1, 8
494    daddiu $t2, -8
4954:
496.endm
497
498    /*
499     * Invocation stub for quick code.
500     * On entry:
501     *   a0 = method pointer
502     *   a1 = argument array that must at least contain the this ptr.
503     *   a2 = size of argument array in bytes
504     *   a3 = (managed) thread pointer
505     *   a4 = JValue* result
506     *   a5 = shorty
507     */
508ENTRY art_quick_invoke_stub
509    # push a4, a5, s0(rSUSPEND), s1(rSELF), s8, ra onto the stack
510    daddiu $sp, $sp, -48
511    .cfi_adjust_cfa_offset 48
512    sd     $ra, 40($sp)
513    .cfi_rel_offset 31, 40
514    sd     $s8, 32($sp)
515    .cfi_rel_offset 30, 32
516    sd     $s1, 24($sp)
517    .cfi_rel_offset 17, 24
518    sd     $s0, 16($sp)
519    .cfi_rel_offset 16, 16
520    sd     $a5, 8($sp)
521    .cfi_rel_offset 9, 8
522    sd     $a4, 0($sp)
523    .cfi_rel_offset 8, 0
524
525    daddiu $s0, $zero, SUSPEND_CHECK_INTERVAL   # reset rSUSPEND to SUSPEND_CHECK_INTERVAL
526    move   $s1, $a3              # move managed thread pointer into s1 (rSELF)
527    move   $s8, $sp              # save sp in s8 (fp)
528
529    daddiu $t3, $a2, 20          # add 4 for method* and 16 for stack alignment
530    dsrl   $t3, $t3, 4           # shift the frame size right 4
531    dsll   $t3, $t3, 4           # shift the frame size left 4 to align to 16 bytes
532    dsubu  $sp, $sp, $t3         # reserve stack space for argument array
533
534    daddiu $t0, $a5, 1           # t0 = shorty[1] (skip 1 for return type)
535    daddiu $t1, $a1, 4           # t1 = ptr to arg_array[4] (skip this ptr)
536    daddiu $t2, $a2, -4          # t2 = number of argument bytes remain (skip this ptr)
537    daddiu $v0, $sp, 8           # v0 points to where to copy arg_array
538    LOOP_OVER_SHORTY_LOADING_REG a2, f14, call_fn
539    LOOP_OVER_SHORTY_LOADING_REG a3, f15, call_fn
540    LOOP_OVER_SHORTY_LOADING_REG a4, f16, call_fn
541    LOOP_OVER_SHORTY_LOADING_REG a5, f17, call_fn
542    LOOP_OVER_SHORTY_LOADING_REG a6, f18, call_fn
543    LOOP_OVER_SHORTY_LOADING_REG a7, f19, call_fn
544
545    # copy arguments onto stack (t2 should be multiples of 4)
546    ble    $t2, $zero, call_fn   # t2 = number of argument bytes remain
5471:
548    lw     $t3, 0($t1)           # load from argument array
549    daddiu $t1, $t1, 4
550    sw     $t3, 0($v0)           # save to stack
551    daddiu $t2, -4
552    bgt    $t2, $zero, 1b        # t2 = number of argument bytes remain
553    daddiu $v0, $v0, 4
554
555call_fn:
556    # call method (a0 and a1 have been untouched)
557    lwu    $a1, 0($a1)           # make a1 = this ptr
558    sw     $a1, 4($sp)           # copy this ptr (skip 4 bytes for method*)
559    sw     $zero, 0($sp)         # store NULL for method* at bottom of frame
560    ld     $t9, MIRROR_ART_METHOD_QUICK_CODE_OFFSET_64($a0)  # get pointer to the code
561    jalr   $t9                   # call the method
562    nop
563    move   $sp, $s8              # restore sp
564
565    # pop a4, a5, s1(rSELF), s8, ra off of the stack
566    ld     $a4, 0($sp)
567    .cfi_restore 8
568    ld     $a5, 8($sp)
569    .cfi_restore 9
570    ld     $s0, 16($sp)
571    .cfi_restore 16
572    ld     $s1, 24($sp)
573    .cfi_restore 17
574    ld     $s8, 32($sp)
575    .cfi_restore 30
576    ld     $ra, 40($sp)
577    .cfi_restore 31
578    daddiu $sp, $sp, 48
579    .cfi_adjust_cfa_offset -48
580
581    # a4 = JValue* result
582    # a5 = shorty string
583    lbu   $t1, 0($a5)           # get result type from shorty
584    li    $t2, 68               # put char 'D' into t2
585    beq   $t1, $t2, 1f          # branch if result type char == 'D'
586    li    $t3, 70               # put char 'F' into t3
587    beq   $t1, $t3, 1f          # branch if result type char == 'F'
588    sw    $v0, 0($a4)           # store the result
589    dsrl  $v1, $v0, 32
590    jalr  $zero, $ra
591    sw    $v1, 4($a4)           # store the other half of the result
5921:
593    mfc1  $v0, $f0
594    mfhc1 $v1, $f0
595    sw    $v0, 0($a4)           # store the result
596    jalr  $zero, $ra
597    sw    $v1, 4($a4)           # store the other half of the result
598END art_quick_invoke_stub
599
600    /*
601     * Invocation static stub for quick code.
602     * On entry:
603     *   a0 = method pointer
604     *   a1 = argument array that must at least contain the this ptr.
605     *   a2 = size of argument array in bytes
606     *   a3 = (managed) thread pointer
607     *   a4 = JValue* result
608     *   a5 = shorty
609     */
610ENTRY art_quick_invoke_static_stub
611
612    # push a4, a5, s0(rSUSPEND), s1(rSELF), s8, ra, onto the stack
613    daddiu $sp, $sp, -48
614    .cfi_adjust_cfa_offset 48
615    sd     $ra, 40($sp)
616    .cfi_rel_offset 31, 40
617    sd     $s8, 32($sp)
618    .cfi_rel_offset 30, 32
619    sd     $s1, 24($sp)
620    .cfi_rel_offset 17, 24
621    sd     $s0, 16($sp)
622    .cfi_rel_offset 16, 16
623    sd     $a5, 8($sp)
624    .cfi_rel_offset 9, 8
625    sd     $a4, 0($sp)
626    .cfi_rel_offset 8, 0
627
628    daddiu $s0, $zero, SUSPEND_CHECK_INTERVAL   # reset rSUSPEND to SUSPEND_CHECK_INTERVAL
629    move   $s1, $a3              # move managed thread pointer into s1 (rSELF)
630    move   $s8, $sp              # save sp in s8 (fp)
631
632    daddiu $t3, $a2, 20          # add 4 for method* and 16 for stack alignment
633    dsrl   $t3, $t3, 4           # shift the frame size right 4
634    dsll   $t3, $t3, 4           # shift the frame size left 4 to align to 16 bytes
635    dsubu  $sp, $sp, $t3         # reserve stack space for argument array
636
637    daddiu $t0, $a5, 1           # t0 = shorty[1] (skip 1 for return type)
638    move   $t1, $a1              # t1 = arg_array
639    move   $t2, $a2              # t2 = number of argument bytes remain
640    daddiu $v0, $sp, 4           # v0 points to where to copy arg_array
641    LOOP_OVER_SHORTY_LOADING_REG a1, f13, call_sfn
642    LOOP_OVER_SHORTY_LOADING_REG a2, f14, call_sfn
643    LOOP_OVER_SHORTY_LOADING_REG a3, f15, call_sfn
644    LOOP_OVER_SHORTY_LOADING_REG a4, f16, call_sfn
645    LOOP_OVER_SHORTY_LOADING_REG a5, f17, call_sfn
646    LOOP_OVER_SHORTY_LOADING_REG a6, f18, call_sfn
647    LOOP_OVER_SHORTY_LOADING_REG a7, f19, call_sfn
648
649    # copy arguments onto stack (t2 should be multiples of 4)
650    ble    $t2, $zero, call_sfn  # t2 = number of argument bytes remain
6511:
652    lw     $t3, 0($t1)           # load from argument array
653    daddiu $t1, $t1, 4
654    sw     $t3, 0($v0)           # save to stack
655    daddiu $t2, -4
656    bgt    $t2, $zero, 1b        # t2 = number of argument bytes remain
657    daddiu $v0, $v0, 4
658
659call_sfn:
660    # call method (a0 has been untouched)
661    sw     $zero, 0($sp)         # store NULL for method* at bottom of frame
662    ld     $t9, MIRROR_ART_METHOD_QUICK_CODE_OFFSET_64($a0)  # get pointer to the code
663    jalr   $t9                   # call the method
664    nop
665    move   $sp, $s8              # restore sp
666
667    # pop a4, a5, s0(rSUSPEND), s1(rSELF), s8, ra off of the stack
668    ld     $a4, 0($sp)
669    .cfi_restore 8
670    ld     $a5, 8($sp)
671    .cfi_restore 9
672    ld     $s0, 16($sp)
673    .cfi_restore 16
674    ld     $s1, 24($sp)
675    .cfi_restore 17
676    ld     $s8, 32($sp)
677    .cfi_restore 30
678    ld     $ra, 40($sp)
679    .cfi_restore 31
680    daddiu $sp, $sp, 48
681    .cfi_adjust_cfa_offset -48
682
683    # a4 = JValue* result
684    # a5 = shorty string
685    lbu   $t1, 0($a5)           # get result type from shorty
686    li    $t2, 68               # put char 'D' into t2
687    beq   $t1, $t2, 1f          # branch if result type char == 'D'
688    li    $t3, 70               # put char 'F' into t3
689    beq   $t1, $t3, 1f          # branch if result type char == 'F'
690    sw    $v0, 0($a4)           # store the result
691    dsrl  $v1, $v0, 32
692    jalr  $zero, $ra
693    sw    $v1, 4($a4)           # store the other half of the result
6941:
695    mfc1  $v0, $f0
696    mfhc1 $v1, $f0
697    sw    $v0, 0($a4)           # store the result
698    jalr  $zero, $ra
699    sw    $v1, 4($a4)           # store the other half of the result
700END art_quick_invoke_static_stub
701
702
703
704UNIMPLEMENTED art_quick_handle_fill_data
705UNIMPLEMENTED art_quick_lock_object
706UNIMPLEMENTED art_quick_unlock_object
707UNIMPLEMENTED art_quick_check_cast
708UNIMPLEMENTED art_quick_aput_obj_with_null_and_bound_check
709UNIMPLEMENTED art_quick_aput_obj_with_bound_check
710UNIMPLEMENTED art_quick_aput_obj
711UNIMPLEMENTED art_quick_initialize_static_storage
712UNIMPLEMENTED art_quick_initialize_type
713UNIMPLEMENTED art_quick_initialize_type_and_verify_access
714UNIMPLEMENTED art_quick_get_boolean_static
715UNIMPLEMENTED art_quick_get_byte_static
716UNIMPLEMENTED art_quick_get_char_static
717UNIMPLEMENTED art_quick_get_short_static
718UNIMPLEMENTED art_quick_get32_static
719UNIMPLEMENTED art_quick_get64_static
720UNIMPLEMENTED art_quick_get_obj_static
721UNIMPLEMENTED art_quick_get_boolean_instance
722UNIMPLEMENTED art_quick_get_byte_instance
723UNIMPLEMENTED art_quick_get_char_instance
724UNIMPLEMENTED art_quick_get_short_instance
725UNIMPLEMENTED art_quick_get32_instance
726UNIMPLEMENTED art_quick_get64_instance
727UNIMPLEMENTED art_quick_get_obj_instance
728UNIMPLEMENTED art_quick_set8_static
729UNIMPLEMENTED art_quick_set16_static
730UNIMPLEMENTED art_quick_set32_static
731UNIMPLEMENTED art_quick_set64_static
732UNIMPLEMENTED art_quick_set_obj_static
733UNIMPLEMENTED art_quick_set8_instance
734UNIMPLEMENTED art_quick_set16_instance
735UNIMPLEMENTED art_quick_set32_instance
736UNIMPLEMENTED art_quick_set64_instance
737UNIMPLEMENTED art_quick_set_obj_instance
738UNIMPLEMENTED art_quick_resolve_string
739
740// Macro to facilitate adding new allocation entrypoints.
741.macro TWO_ARG_DOWNCALL name, entrypoint, return
742ENTRY \name
743    break
744    break
745END \name
746.endm
747
748.macro THREE_ARG_DOWNCALL name, entrypoint, return
749ENTRY \name
750    break
751    break
752END \name
753.endm
754
755// Generate the allocation entrypoints for each allocator.
756GENERATE_ALL_ALLOC_ENTRYPOINTS
757
758UNIMPLEMENTED art_quick_test_suspend
759UNIMPLEMENTED art_quick_proxy_invoke_handler
760UNIMPLEMENTED art_quick_imt_conflict_trampoline
761
762    .extern artQuickResolutionTrampoline
763ENTRY art_quick_resolution_trampoline
764    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME
765    move    $a2, rSELF             # pass Thread::Current
766    jal     artQuickResolutionTrampoline  # (Method* called, receiver, Thread*, SP)
767    move    $a3, $sp               # pass $sp
768    beq     $v0, $zero, 1f
769    lwu     $a0, 0($sp)            # load resolved method in $a0
770                                   # artQuickResolutionTrampoline puts resolved method in *SP
771    RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
772    move    $t9, $v0               # code pointer must be in $t9 to generate the global pointer
773    jalr    $zero, $t9             # tail call to method
774    nop
7751:
776    RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
777    DELIVER_PENDING_EXCEPTION
778END art_quick_resolution_trampoline
779
780    .extern artQuickGenericJniTrampoline
781    .extern artQuickGenericJniEndTrampoline
782ENTRY art_quick_generic_jni_trampoline
783    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
784    sd      $a0, 0($sp)            # store native ArtMethod* to bottom of stack
785    move    $s8, $sp               # save $sp
786
787    # prepare for call to artQuickGenericJniTrampoline(Thread*, SP)
788    move    $a0, rSELF             # pass Thread::Current
789    move    $a1, $sp               # pass $sp
790    jal     artQuickGenericJniTrampoline   # (Thread*, SP)
791    daddiu  $sp, $sp, -5120        # reserve space on the stack
792
793    # The C call will have registered the complete save-frame on success.
794    # The result of the call is:
795    # v0: ptr to native code, 0 on error.
796    # v1: ptr to the bottom of the used area of the alloca, can restore stack till here.
797    beq     $v0, $zero, 1f         # check entry error
798    move    $t9, $v0               # save the code ptr
799    move    $sp, $v1               # release part of the alloca
800
801    # Load parameters from stack into registers
802    ld      $a0,   0($sp)
803    ld      $a1,   8($sp)
804    ld      $a2,  16($sp)
805    ld      $a3,  24($sp)
806    ld      $a4,  32($sp)
807    ld      $a5,  40($sp)
808    ld      $a6,  48($sp)
809    ld      $a7,  56($sp)
810    # Load FPRs the same as GPRs. Look at BuildNativeCallFrameStateMachine.
811    l.d     $f12,  0($sp)
812    l.d     $f13,  8($sp)
813    l.d     $f14, 16($sp)
814    l.d     $f15, 24($sp)
815    l.d     $f16, 32($sp)
816    l.d     $f17, 40($sp)
817    l.d     $f18, 48($sp)
818    l.d     $f19, 56($sp)
819    jalr    $t9                    # native call
820    daddiu  $sp, $sp, 64
821
822    # result sign extension is handled in C code
823    # prepare for call to artQuickGenericJniEndTrampoline(Thread*, result, result_f)
824    move    $a0, rSELF             # pass Thread::Current
825    move    $a1, $v0
826    jal     artQuickGenericJniEndTrampoline
827    dmfc1   $a2, $f0
828
829    ld      $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
830    bne     $t0, $zero, 2f         # check for pending exceptions
831    move    $sp, $s8               # tear down the alloca
832
833    # tear dpown the callee-save frame
834    RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
835
836    jalr    $zero, $ra
837    dmtc1   $v0, $f0               # place return value to FP return value
838
8391:
840    move    $sp, $s8               # tear down the alloca
8412:
842    RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
843    DELIVER_PENDING_EXCEPTION
844END art_quick_generic_jni_trampoline
845
846    .extern artQuickToInterpreterBridge
847ENTRY art_quick_to_interpreter_bridge
848    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME
849    move    $a1, rSELF             # pass Thread::Current
850    jal     artQuickToInterpreterBridge    # (Method* method, Thread*, SP)
851    move    $a2, $sp               # pass $sp
852    ld      $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
853    daddiu  $sp, $sp, REFS_AND_ARGS_MINUS_REFS_SIZE  # skip a0-a7 and f12-f19
854    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
855    bne     $t0, $zero, 1f
856    dmtc1   $v0, $f0               # place return value to FP return value
857    jalr    $zero, $ra
858    dmtc1   $v1, $f1               # place return value to FP return value
8591:
860    DELIVER_PENDING_EXCEPTION
861END art_quick_to_interpreter_bridge
862
863    /*
864     * Routine that intercepts method calls and returns.
865     */
866    .extern artInstrumentationMethodEntryFromCode
867    .extern artInstrumentationMethodExitFromCode
868ENTRY art_quick_instrumentation_entry
869    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME
870    daddiu   $sp, $sp, -16     # space for saving arg0
871    .cfi_adjust_cfa_offset 16
872    sd       $a0, 0($sp)       # save arg0
873    move     $a3, $ra          # pass $ra
874    jal      artInstrumentationMethodEntryFromCode  # (Method*, Object*, Thread*, RA)
875    move     $a2, rSELF        # pass Thread::Current
876    move     $t9, $v0          # $t9 holds reference to code
877    ld       $a0, 0($sp)       # restore arg0
878    daddiu   $sp, $sp, 16      # remove args
879    .cfi_adjust_cfa_offset -16
880    RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
881    jalr     $t9               # call method
882    nop
883END art_quick_instrumentation_entry
884    /* intentional fallthrough */
885    .global art_quick_instrumentation_exit
886art_quick_instrumentation_exit:
887    .cfi_startproc
888    daddiu   $t9, $ra, 4       # put current address into $t9 to rebuild $gp
889    .cpload  $t9
890    move     $ra, $zero        # link register is to here, so clobber with 0 for later checks
891    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME
892    move     $t0, $sp          # remember bottom of caller's frame
893    daddiu   $sp, $sp, -16     # save return values and set up args
894    .cfi_adjust_cfa_offset 16
895    sd       $v0, 0($sp)
896    .cfi_rel_offset 2, 0
897    s.d      $f0, 8($sp)
898    mov.d    $f15, $f0         # pass fpr result
899    move     $a2, $v0          # pass gpr result
900    move     $a1, $t0          # pass $sp
901    jal      artInstrumentationMethodExitFromCode  # (Thread*, SP, gpr_res, fpr_res)
902    move     $a0, rSELF        # pass Thread::Current
903    move     $t0, $v0          # set aside returned link register
904    move     $ra, $v1          # set link register for deoptimization
905    ld       $v0, 0($sp)       # restore return values
906    l.d      $f0, 8($sp)
907    jalr     $zero, $t0        # return
908    daddiu   $sp, $sp, 16+FRAME_SIZE_REFS_ONLY_CALLEE_SAVE  # 16 bytes of saved values + ref_only callee save frame
909    .cfi_adjust_cfa_offset -(16+FRAME_SIZE_REFS_ONLY_CALLEE_SAVE)
910END art_quick_instrumentation_exit
911
912UNIMPLEMENTED art_quick_deoptimize
913UNIMPLEMENTED art_quick_indexof
914UNIMPLEMENTED art_quick_string_compareto
915