quick_entrypoints_arm64.S revision b95a5345ae4217b70ca36f0cced92f68dda7caf5
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_arm64.S"
18
19#include "arch/quick_alloc_entrypoints.S"
20
21
22    /*
23     * Macro that sets up the callee save frame to conform with
24     * Runtime::CreateCalleeSaveMethod(kSaveAll)
25     */
26.macro SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
27    adrp x9, :got:_ZN3art7Runtime9instance_E
28    ldr x9, [x9, #:got_lo12:_ZN3art7Runtime9instance_E]
29
30    // Our registers aren't intermixed - just spill in order.
31    ldr x9,[x9]  // x9 = & (art::Runtime * art::Runtime.instance_) .
32
33    // x9 = (ArtMethod*) Runtime.instance_.callee_save_methods[kRefAndArgs]  .
34    ldr x9, [x9, RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET ]
35
36    sub sp, sp, #368
37    .cfi_adjust_cfa_offset 368
38
39    // FP args
40    stp d1, d2,   [sp, #8]
41    stp d2, d3, [sp, #24]
42    stp d4, d5, [sp, #40]
43    stp d6, d7, [sp, #56]
44
45    // FP callee-saves
46    stp d8, d9,   [sp, #72]
47    stp d10, d11, [sp, #88]
48    stp d12, d13, [sp, #104]
49    stp d14, d15, [sp, #120]
50
51    stp d16, d17,   [sp, #136]
52    stp d18, d19,   [sp, #152]
53    stp d20, d21,   [sp, #168]
54    stp d22, d23,   [sp, #184]
55    stp d24, d25,   [sp, #200]
56    stp d26, d27,   [sp, #216]
57    stp d28, d29,   [sp, #232]
58    stp d30, d31,   [sp, #248]
59
60
61    // Callee saved.
62    stp xSELF, x19, [sp, #264]
63    stp x20, x21, [sp, #280]
64    stp x22, x23, [sp, #296]
65    stp x24, x25, [sp, #312]
66    stp x26, x27, [sp, #328]
67    stp x28, xFP, [sp, #344]    // Save FP.
68    str xLR, [sp, #360]
69
70    .cfi_offset x18,72
71    .cfi_offset x19,80
72    .cfi_offset x20,88
73    .cfi_offset x21,96
74    .cfi_offset x22,104
75    .cfi_offset x23,112
76    .cfi_offset x24,120
77    .cfi_offset x25,128
78    .cfi_offset x26,136
79    .cfi_offset x27,144
80    .cfi_offset x28,152
81    .cfi_offset x29,160
82    .cfi_offset x30,168
83
84    // Loads appropriate callee-save-method
85    str x9, [sp]    // Store ArtMethod* Runtime::callee_save_methods_[kRefsAndArgs]
86
87.endm
88
89    /*
90     * Macro that sets up the callee save frame to conform with
91     * Runtime::CreateCalleeSaveMethod(kRefsOnly).
92     */
93.macro SETUP_REF_ONLY_CALLEE_SAVE_FRAME
94    brk 0
95.endm
96
97.macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
98    brk 0
99.endm
100
101.macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
102    brk 0
103.endm
104
105
106.macro SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
107    sub sp, sp, #304
108    .cfi_adjust_cfa_offset 304
109
110    stp d0, d1,   [sp, #16]
111    stp d2, d3,   [sp, #32]
112    stp d4, d5,   [sp, #48]
113    stp d6, d7,   [sp, #64]
114    stp d8, d9,   [sp, #80]
115    stp d10, d11, [sp, #96]
116    stp d12, d13, [sp, #112]
117    stp d14, d15, [sp, #128]
118
119    stp x1,  x2, [sp, #144]
120    stp x3,  x4, [sp, #160]
121    stp x5,  x6, [sp, #176]
122    stp x7,  xSELF, [sp, #192]
123    stp x19, x20, [sp, #208]
124    stp x21, x22, [sp, #224]
125    stp x23, x24, [sp, #240]
126    stp x25, x26, [sp, #256]
127    stp x27, x28, [sp, #272]
128    stp xFP, xLR, [sp, #288]
129
130    .cfi_offset x1,144
131    .cfi_offset x2,152
132    .cfi_offset x3,160
133    .cfi_offset x4,168
134    .cfi_offset x5,176
135    .cfi_offset x6,184
136    .cfi_offset x7,192
137    .cfi_offset x18,200
138    .cfi_offset x19,208
139    .cfi_offset x20,216
140    .cfi_offset x21,224
141    .cfi_offset x22,232
142    .cfi_offset x23,240
143    .cfi_offset x24,248
144    .cfi_offset x25,256
145    .cfi_offset x26,264
146    .cfi_offset x27,272
147    .cfi_offset x28,280
148    .cfi_offset x29,288
149    .cfi_offset x30,296
150.endm
151
152    /*
153     * Macro that sets up the callee save frame to conform with
154     * Runtime::CreateCalleeSaveMethod(kRefsAndArgs).
155     *
156     * TODO This is probably too conservative - saving FP & LR.
157     */
158.macro SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
159    adrp x9, :got:_ZN3art7Runtime9instance_E
160    ldr x9, [x9, #:got_lo12:_ZN3art7Runtime9instance_E]
161
162    // Our registers aren't intermixed - just spill in order.
163    ldr x9,[x9]  // x9 = & (art::Runtime * art::Runtime.instance_) .
164
165    // x9 = (ArtMethod*) Runtime.instance_.callee_save_methods[kRefAndArgs]  .
166    ldr x9, [x9, RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET ]
167
168    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
169
170    str x9, [sp]    // Store ArtMethod* Runtime::callee_save_methods_[kRefsAndArgs]
171.endm
172
173.macro RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
174
175    ldp d0, d1,   [sp, #16]
176    ldp d2, d3,   [sp, #32]
177    ldp d4, d5,   [sp, #48]
178    ldp d6, d7,   [sp, #64]
179    ldp d8, d9,   [sp, #80]
180    ldp d10, d11, [sp, #96]
181    ldp d12, d13, [sp, #112]
182    ldp d14, d15, [sp, #128]
183
184    // args.
185    ldp x1,  x2, [sp, #144]
186    ldp x3,  x4, [sp, #160]
187    ldp x5,  x6, [sp, #176]
188    ldp x7,  xSELF, [sp, #192]
189    ldp x19, x20, [sp, #208]
190    ldp x21, x22, [sp, #224]
191    ldp x23, x24, [sp, #240]
192    ldp x25, x26, [sp, #256]
193    ldp x27, x28, [sp, #272]
194    ldp xFP, xLR, [sp, #288]
195
196    add sp, sp, #304
197    .cfi_adjust_cfa_offset -304
198.endm
199
200.macro RETURN_IF_RESULT_IS_ZERO
201    brk 0
202.endm
203
204.macro RETURN_IF_RESULT_IS_NON_ZERO
205    brk 0
206.endm
207
208    /*
209     * Macro that set calls through to artDeliverPendingExceptionFromCode, where the pending
210     * exception is Thread::Current()->exception_
211     */
212.macro DELIVER_PENDING_EXCEPTION
213    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
214    mov x0, xSELF
215    mov x1, sp
216
217    // Point of no return.
218    b artDeliverPendingExceptionFromCode  // artDeliverPendingExceptionFromCode(Thread*, SP)
219    brk 0  // Unreached
220.endm
221
222.macro RETURN_OR_DELIVER_PENDING_EXCEPTION
223    ldr x9, [xSELF, # THREAD_EXCEPTION_OFFSET]   // Get exception field.
224    cbnz x9, 1f
225    ret
2261:
227    DELIVER_PENDING_EXCEPTION
228.endm
229
230.macro NO_ARG_RUNTIME_EXCEPTION c_name, cxx_name
231    .extern \cxx_name
232ENTRY \c_name
233    brk 0
234END \c_name
235.endm
236
237.macro ONE_ARG_RUNTIME_EXCEPTION c_name, cxx_name
238    .extern \cxx_name
239ENTRY \c_name
240    brk 0
241END \c_name
242.endm
243
244.macro TWO_ARG_RUNTIME_EXCEPTION c_name, cxx_name
245    .extern \cxx_name
246ENTRY \c_name
247    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
248    brk 0
249END \c_name
250.endm
251
252    /*
253     * Called by managed code, saves callee saves and then calls artThrowException
254     * that will place a mock Method* at the bottom of the stack. Arg1 holds the exception.
255     */
256ONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception, artDeliverExceptionFromCode
257
258    /*
259     * Called by managed code to create and deliver a NullPointerException.
260     */
261NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
262
263    /*
264     * Called by managed code to create and deliver an ArithmeticException.
265     */
266NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode
267
268    /*
269     * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
270     * index, arg2 holds limit.
271     */
272TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
273
274    /*
275     * Called by managed code to create and deliver a StackOverflowError.
276     */
277NO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow, artThrowStackOverflowFromCode
278
279    /*
280     * Called by managed code to create and deliver a NoSuchMethodError.
281     */
282ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method, artThrowNoSuchMethodFromCode
283
284    /*
285     * TODO arm64 specifics need to be fleshed out.
286     * All generated callsites for interface invokes and invocation slow paths will load arguments
287     * as usual - except instead of loading x0 with the target Method*, x0 will contain
288     * the method_idx.  This wrapper will save x1-x3, load the caller's Method*, align the
289     * stack and call the appropriate C helper.
290     * NOTE: "this" is first visible argument of the target, and so can be found in x1.
291     *
292     * The helper will attempt to locate the target and return a result in x0 consisting
293     * of the target Method* in x0 and method->code_ in x1.
294     *
295     * If unsuccessful, the helper will return NULL/NULL. There will be a pending exception in the
296     * thread and we branch to another stub to deliver it.
297     *
298     * On success this wrapper will restore arguments and *jump* to the target, leaving the lr
299     * pointing back to the original caller.
300     */
301.macro INVOKE_TRAMPOLINE c_name, cxx_name
302    .extern \cxx_name
303ENTRY \c_name
304    brk 0
305END \c_name
306.endm
307
308INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline, artInvokeInterfaceTrampoline
309INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck
310
311INVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck
312INVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck
313INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
314INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
315
316/*
317 *  extern"C" void art_quick_invoke_stub(ArtMethod *method,   x0
318 *                                       uint32_t  *args,     x1
319 *                                       uint32_t argsize,    w2
320 *                                       Thread *self,        x3
321 *                                       JValue *result,      x4
322 *                                       char   *shorty);     x5
323 *  +----------------------+
324 *  |                      |
325 *  |  C/C++ frame         |
326 *  |       LR''           |
327 *  |       FP''           | <- SP'
328 *  +----------------------+
329 *  +----------------------+
330 *  |        SP'           |
331 *  |        X5            |
332 *  |        X4            |        Saved registers
333 *  |        LR'           |
334 *  |        FP'           | <- FP
335 *  +----------------------+
336 *  | uint32_t out[n-1]    |
337 *  |    :      :          |        Outs
338 *  | uint32_t out[0]      |
339 *  | ArtMethod* NULL      | <- SP
340 *  +----------------------+
341 *
342 * Outgoing registers:
343 *  x0    - Method*
344 *  x1-x7 - integer parameters.
345 *  d0-d7 - Floating point parameters.
346 *  xSELF = self
347 *  SP = & of ArtMethod*
348 *  x1 = "this" pointer.
349 *
350 */
351ENTRY art_quick_invoke_stub
352    // Spill registers as per AACPS64 calling convention.
353
354SAVE_SIZE=5*8   // x4, x5, LR & FP saved.
355SAVE_SIZE_AND_METHOD=SAVE_SIZE+8
356
357    mov x9, sp     // Save stack pointer.
358
359    mov x10, xFP   // Save frame pointer
360    .cfi_register x29,x10
361    add x11, x2, # SAVE_SIZE_AND_METHOD // calculate size of frame.
362
363    sub x11, sp, x11 // Calculate SP position - saves + ArtMethod* +  args
364
365    and x11, x11, # ~0xf  // Enforce 16 byte stack alignment.
366
367    sub xFP, x9, #SAVE_SIZE   // Calculate new FP. Don't store here until SP moved.
368    .cfi_def_cfa_register x29
369
370    mov sp, x11        // set new SP.
371
372    str x9, [xFP, #32]     // Save old stack pointer.
373
374    .cfi_offset x9, 32
375
376    stp x4, x5, [xFP, #16]  // Save result and shorty addresses.
377
378    .cfi_offset x4, 16
379    .cfi_offset x5, 24
380
381    stp x10, xLR, [xFP]   // Store lr & old fp @ fp
382
383    .cfi_offset x30, 0
384    .cfi_offset x10, 8
385
386    mov xSELF, x3       // Move thread pointer into SELF register.
387
388    // Copy arguments into stack frame.
389    // Use simple copy routine for now.
390    // 4 bytes per slot.
391    // X1 - source address
392    // W2 - args length
393    // X10 - destination address.
394    add x9, sp, #8     // Destination address is bottom of stack + NULL.
395
396    // w2 = argsize parameter.
397.LcopyParams:
398    cmp w2, #0
399    beq .LendCopyParams
400    sub w2, w2, #4      // Need 65536 bytes of range.
401    ldr w10, [x1, x2]
402    str w10, [x9, x2]
403
404    b .LcopyParams
405
406.LendCopyParams:
407
408    // Store NULL into Method* at bottom of frame.
409    str xzr, [sp]
410
411    // Fill registers x/w1 to x/w7 and s/d0 to s/d7 with parameters.
412    // Parse the passed shorty to determine which register to load.
413    // Load addresses for routines that load WXSD registers.
414    adr  x11, .LstoreW2
415    adr  x12, .LstoreX2
416    adr  x13, .LstoreS0
417    adr  x14, .LstoreD0
418
419    // Initialize routine offsets to 0 for integers and floats.
420    // x8 for integers, x15 for floating point.
421    mov x8, #0
422    mov x15, #0
423
424    add x10, x5, #1         // Load shorty address, plus one to skip return value.
425    ldr w1, [x9],#4         // Load "this" parameter, and increment arg pointer.
426
427    // Loop to fill registers.
428.LfillRegisters:
429    ldrb w17, [x10], #1       // Load next character in signature, and increment.
430    cbz w17, .LcallFunction   // Exit at end of signature. Shorty 0 terminated.
431
432    cmp  w17, #'F' // is this a float?
433    bne .LisDouble
434
435    cmp x15, # 8*12         // Skip this load if all registers full.
436    beq .LfillRegisters
437
438    add x17, x13, x15       // Calculate subroutine to jump to.
439    br  x17
440
441.LisDouble:
442    cmp w17, #'D'           // is this a double?
443    bne .LisLong
444
445    cmp x15, # 8*12         // Skip this load if all registers full.
446    beq .LfillRegisters
447
448
449    add x17, x14, x15       // Calculate subroutine to jump to.
450    br x17
451
452.LisLong:
453    cmp w17, #'J'           // is this a long?
454    bne .LisOther
455
456    cmp x8, # 7*12          // Skip this load if all registers full.
457    beq .LfillRegisters
458
459    add x17, x12, x8        // Calculate subroutine to jump to.
460    br x17
461
462
463.LisOther:                  // Everything else takes one vReg.
464    cmp x8, # 7*12          // Skip this load if all registers full.
465    beq .LfillRegisters
466    add x17, x11, x8        // Calculate subroutine to jump to.
467    br x17
468
469// Macro for loading a parameter into a register.
470//  counter - the register with offset into these tables
471//  size - the size of the register - 4 or 8 bytes.
472//  register - the name of the register to be loaded.
473.macro LOADREG counter size register return
474    ldr \register , [x9], #\size
475    add \counter, \counter, 12
476    b \return
477.endm
478
479// Store ints.
480.LstoreW2:
481    LOADREG x8 4 w2 .LfillRegisters
482    LOADREG x8 4 w3 .LfillRegisters
483    LOADREG x8 4 w4 .LfillRegisters
484    LOADREG x8 4 w5 .LfillRegisters
485    LOADREG x8 4 w6 .LfillRegisters
486    LOADREG x8 4 w7 .LfillRegisters
487
488// Store longs.
489.LstoreX2:
490    LOADREG x8 8 x2 .LfillRegisters
491    LOADREG x8 8 x3 .LfillRegisters
492    LOADREG x8 8 x4 .LfillRegisters
493    LOADREG x8 8 x5 .LfillRegisters
494    LOADREG x8 8 x6 .LfillRegisters
495    LOADREG x8 8 x7 .LfillRegisters
496
497// Store singles.
498.LstoreS0:
499    LOADREG x15 4 s0 .LfillRegisters
500    LOADREG x15 4 s1 .LfillRegisters
501    LOADREG x15 4 s2 .LfillRegisters
502    LOADREG x15 4 s3 .LfillRegisters
503    LOADREG x15 4 s4 .LfillRegisters
504    LOADREG x15 4 s5 .LfillRegisters
505    LOADREG x15 4 s6 .LfillRegisters
506    LOADREG x15 4 s7 .LfillRegisters
507
508// Store doubles.
509.LstoreD0:
510    LOADREG x15 8 d0 .LfillRegisters
511    LOADREG x15 8 d1 .LfillRegisters
512    LOADREG x15 8 d2 .LfillRegisters
513    LOADREG x15 8 d3 .LfillRegisters
514    LOADREG x15 8 d4 .LfillRegisters
515    LOADREG x15 8 d5 .LfillRegisters
516    LOADREG x15 8 d6 .LfillRegisters
517    LOADREG x15 8 d7 .LfillRegisters
518
519
520.LcallFunction:
521
522    // load method-> METHOD_QUICK_CODE_OFFSET
523    ldr x9, [x0 , #METHOD_QUICK_CODE_OFFSET]
524    // Branch to method.
525    blr x9
526
527    // Restore return value address and shorty address.
528    ldp x4,x5, [xFP, #16]
529    .cfi_restore x4
530    .cfi_restore x5
531
532    // Store result (w0/x0/s0/d0) appropriately, depending on resultType.
533    ldrb w10, [x5]
534
535    // Don't set anything for a void type.
536    cmp w10, #'V'
537    beq .Lexit_art_quick_invoke_stub
538
539    cmp w10, #'D'
540    bne .Lreturn_is_float
541    str d0, [x4]
542    b .Lexit_art_quick_invoke_stub
543
544.Lreturn_is_float:
545    cmp w10, #'F'
546    bne .Lreturn_is_int
547    str s0, [x4]
548    b .Lexit_art_quick_invoke_stub
549
550    // Just store x0. Doesn't matter if it is 64 or 32 bits.
551.Lreturn_is_int:
552    str x0, [x4]
553
554.Lexit_art_quick_invoke_stub:
555    ldr x2, [x29, #32]   // Restore stack pointer.
556    mov sp, x2
557    .cfi_restore sp
558
559    ldp x29, x30, [x29]    // Restore old frame pointer and link register.
560    .cfi_restore x29
561    .cfi_restore x30
562
563    ret
564END art_quick_invoke_stub
565
566/*  extern"C"
567 *     void art_quick_invoke_static_stub(ArtMethod *method,   x0
568 *                                       uint32_t  *args,     x1
569 *                                       uint32_t argsize,    w2
570 *                                       Thread *self,        x3
571 *                                       JValue *result,      x4
572 *                                       char   *shorty);     x5
573 */
574ENTRY art_quick_invoke_static_stub
575    // Spill registers as per AACPS64 calling convention.
576
577SAVE_SIZE=5*8   // x4, x5, SP, LR & FP saved
578SAVE_SIZE_AND_METHOD=SAVE_SIZE+8
579
580    mov x9, sp     // Save stack pointer.
581
582    mov x10, xFP   // Save frame pointer
583    .cfi_register x29,x10
584    add x11, x2, # SAVE_SIZE_AND_METHOD // calculate size of frame.
585
586    sub x11, sp, x11 // Calculate SP position - saves + ArtMethod* +  args
587
588    and x11, x11, # ~0xf  // Enforce 16 byte stack alignment.
589
590    sub xFP, x9, #SAVE_SIZE   // Calculate new FP. Don't store here until SP moved.
591
592    mov sp, x11        // set new SP.
593
594    .cfi_def_cfa_register   29
595
596    str x9, [xFP, #32]     // Save old stack pointer.
597
598    .cfi_offset x9, 32
599
600    stp x4, x5, [xFP, #16]  // Save result and shorty addresses.
601
602    .cfi_offset x4, 16
603    .cfi_offset x5, 24
604
605    stp x10, xLR, [x29]   // Store lr & old fp @ fp
606
607    .cfi_offset x30, 0
608    .cfi_offset x10, 8
609
610    mov xSELF, x3       // Move thread pointer into SELF register.
611
612    // Copy arguments into stack frame.
613    // Use simple copy routine for now.
614    // 4 bytes per slot.
615    // X1 - source address
616    // W2 - args length
617    // X10 - destination address.
618    add x9, sp, #8     // Destination address is bottom of stack + NULL.
619
620    // w2 = argsize parameter.
621.LcopyParams2:
622    cmp w2, #0
623    beq .LendCopyParams2
624    sub w2, w2, #4      // Need 65536 bytes of range.
625    ldr w10, [x1, x2]
626    str w10, [x9, x2]
627
628    b .LcopyParams2
629
630.LendCopyParams2:
631
632    // Store NULL into Method* at bottom of frame.
633    str xzr, [sp]
634
635    // Fill registers x/w1 to x/w7 and s/d0 to s/d7 with parameters.
636    // Parse the passed shorty to determine which register to load.
637    // Load addresses for routines that load WXSD registers.
638    adr  x11, .LstoreW1_2
639    adr  x12, .LstoreX1_2
640    adr  x13, .LstoreS0_2
641    adr  x14, .LstoreD0_2
642
643    // Initialize routine offsets to 0 for integers and floats.
644    // x8 for integers, x15 for floating point.
645    mov x8, #0
646    mov x15, #0
647
648    add x10, x5, #1     // Load shorty address, plus one to skip return value.
649
650    // Loop to fill registers.
651.LfillRegisters2:
652    ldrb w17, [x10], #1         // Load next character in signature, and increment.
653    cbz w17, .LcallFunction2    // Exit at end of signature. Shorty 0 terminated.
654
655    cmp  w17, #'F'          // is this a float?
656    bne .LisDouble2
657
658    cmp x15, # 8*12         // Skip this load if all registers full.
659    beq .LfillRegisters2
660
661    add x17, x13, x15       // Calculate subroutine to jump to.
662    br  x17
663
664.LisDouble2:
665    cmp w17, #'D'           // is this a double?
666    bne .LisLong2
667
668    cmp x15, # 8*12         // Skip this load if all registers full.
669    beq .LfillRegisters2
670
671
672    add x17, x14, x15       // Calculate subroutine to jump to.
673    br x17
674
675.LisLong2:
676    cmp w17, #'J'           // is this a long?
677    bne .LisOther2
678
679    cmp x8, # 7*12          // Skip this load if all registers full.
680    beq .LfillRegisters2
681
682    add x17, x12, x8        // Calculate subroutine to jump to.
683    br x17
684
685
686.LisOther2:                 // Everything else takes one vReg.
687    cmp x8, # 7*12          // Skip this load if all registers full.
688    beq .LfillRegisters2
689    add x17, x11, x8        // Calculate subroutine to jump to.
690    br x17
691
692// Store ints.
693.LstoreW1_2:
694    LOADREG x8 4 w1 .LfillRegisters2
695    LOADREG x8 4 w2 .LfillRegisters2
696    LOADREG x8 4 w3 .LfillRegisters2
697    LOADREG x8 4 w4 .LfillRegisters2
698    LOADREG x8 4 w5 .LfillRegisters2
699    LOADREG x8 4 w6 .LfillRegisters2
700    LOADREG x8 4 w7 .LfillRegisters2
701
702// Store longs.
703.LstoreX1_2:
704    LOADREG x8 8 x1 .LfillRegisters2
705    LOADREG x8 8 x2 .LfillRegisters2
706    LOADREG x8 8 x3 .LfillRegisters2
707    LOADREG x8 8 x4 .LfillRegisters2
708    LOADREG x8 8 x5 .LfillRegisters2
709    LOADREG x8 8 x6 .LfillRegisters2
710    LOADREG x8 8 x7 .LfillRegisters2
711
712// Store singles.
713.LstoreS0_2:
714    LOADREG x15 4 s0 .LfillRegisters2
715    LOADREG x15 4 s1 .LfillRegisters2
716    LOADREG x15 4 s2 .LfillRegisters2
717    LOADREG x15 4 s3 .LfillRegisters2
718    LOADREG x15 4 s4 .LfillRegisters2
719    LOADREG x15 4 s5 .LfillRegisters2
720    LOADREG x15 4 s6 .LfillRegisters2
721    LOADREG x15 4 s7 .LfillRegisters2
722
723// Store doubles.
724.LstoreD0_2:
725    LOADREG x15 8 d0 .LfillRegisters2
726    LOADREG x15 8 d1 .LfillRegisters2
727    LOADREG x15 8 d2 .LfillRegisters2
728    LOADREG x15 8 d3 .LfillRegisters2
729    LOADREG x15 8 d4 .LfillRegisters2
730    LOADREG x15 8 d5 .LfillRegisters2
731    LOADREG x15 8 d6 .LfillRegisters2
732    LOADREG x15 8 d7 .LfillRegisters2
733
734
735.LcallFunction2:
736
737    // load method-> METHOD_QUICK_CODE_OFFSET.
738    ldr x9, [x0 , #METHOD_QUICK_CODE_OFFSET]
739    // Branch to method.
740    blr x9
741
742    // Restore return value address and shorty address.
743    ldp x4, x5, [xFP, #16]
744    .cfi_restore x4
745    .cfi_restore x5
746
747    // Store result (w0/x0/s0/d0) appropriately, depending on resultType.
748    ldrb w10, [x5]
749
750    // Don't set anything for a void type.
751    cmp w10, #'V'
752    beq .Lexit_art_quick_invoke_stub2
753
754    cmp w10, #'D'
755    bne .Lreturn_is_float2
756    str d0, [x4]
757    b .Lexit_art_quick_invoke_stub2
758
759.Lreturn_is_float2:
760    cmp w10, #'F'
761    bne .Lreturn_is_int2
762    str s0, [x4]
763    b .Lexit_art_quick_invoke_stub2
764
765    // Just store x0. Doesn't matter if it is 64 or 32 bits.
766.Lreturn_is_int2:
767    str x0, [x4]
768
769.Lexit_art_quick_invoke_stub2:
770
771    ldr x2, [xFP, #32]   // Restore stack pointer.
772    mov sp, x2
773    .cfi_restore sp
774
775    ldp xFP, xLR, [xFP]    // Restore old frame pointer and link register.
776    .cfi_restore x29
777    .cfi_restore x30
778
779    ret
780END art_quick_invoke_static_stub
781
782// UNIMPLEMENTED art_quick_do_long_jump
783
784    /*
785     * On entry x0 is uintptr_t* gprs_ and x1 is uint64_t* fprs_
786     */
787
788ENTRY art_quick_do_long_jump
789    // Load FPRs
790    ldp d0, d1, [x1], #16
791    ldp d2, d3, [x1], #16
792    ldp d4, d5, [x1], #16
793    ldp d6, d7, [x1], #16
794    ldp d8, d9, [x1], #16
795    ldp d10, d11, [x1], #16
796    ldp d12, d13, [x1], #16
797    ldp d14, d15, [x1], #16
798    ldp d16, d17, [x1], #16
799    ldp d18, d19, [x1], #16
800    ldp d20, d21, [x1], #16
801    ldp d22, d23, [x1], #16
802    ldp d24, d25, [x1], #16
803    ldp d26, d27, [x1], #16
804    ldp d28, d29, [x1], #16
805    ldp d30, d31, [x1]
806
807    // Load GPRs
808    // TODO: lots of those are smashed, could optimize.
809    add x0, x0, #30*8
810    ldp x30, x1, [x0], #-16
811    ldp x28, x29, [x0], #-16
812    ldp x26, x27, [x0], #-16
813    ldp x24, x25, [x0], #-16
814    ldp x22, x23, [x0], #-16
815    ldp x20, x21, [x0], #-16
816    ldp x18, x19, [x0], #-16
817    ldp x16, x17, [x0], #-16
818    ldp x14, x15, [x0], #-16
819    ldp x12, x13, [x0], #-16
820    ldp x10, x11, [x0], #-16
821    ldp x8, x9, [x0], #-16
822    ldp x6, x7, [x0], #-16
823    ldp x4, x5, [x0], #-16
824    ldp x2, x3, [x0], #-16
825    mov sp, x1
826
827    // TODO: Is it really OK to use LR for the target PC?
828    mov x0, #0
829    mov x1, #0
830    br  xLR
831END art_quick_do_long_jump
832
833UNIMPLEMENTED art_quick_handle_fill_data
834
835UNIMPLEMENTED art_quick_lock_object
836UNIMPLEMENTED art_quick_unlock_object
837UNIMPLEMENTED art_quick_check_cast
838UNIMPLEMENTED art_quick_aput_obj_with_null_and_bound_check
839UNIMPLEMENTED art_quick_aput_obj_with_bound_check
840UNIMPLEMENTED art_quick_aput_obj
841UNIMPLEMENTED art_quick_initialize_static_storage
842UNIMPLEMENTED art_quick_initialize_type
843UNIMPLEMENTED art_quick_initialize_type_and_verify_access
844UNIMPLEMENTED art_quick_get32_static
845UNIMPLEMENTED art_quick_get64_static
846UNIMPLEMENTED art_quick_get_obj_static
847UNIMPLEMENTED art_quick_get32_instance
848UNIMPLEMENTED art_quick_get64_instance
849UNIMPLEMENTED art_quick_get_obj_instance
850UNIMPLEMENTED art_quick_set32_static
851UNIMPLEMENTED art_quick_set64_static
852UNIMPLEMENTED art_quick_set_obj_static
853UNIMPLEMENTED art_quick_set32_instance
854UNIMPLEMENTED art_quick_set64_instance
855UNIMPLEMENTED art_quick_set_obj_instance
856UNIMPLEMENTED art_quick_resolve_string
857
858// Macro to facilitate adding new allocation entrypoints.
859.macro TWO_ARG_DOWNCALL name, entrypoint, return
860    .extern \entrypoint
861ENTRY \name
862    brk 0
863END \name
864.endm
865
866// Macro to facilitate adding new array allocation entrypoints.
867.macro THREE_ARG_DOWNCALL name, entrypoint, return
868    .extern \entrypoint
869ENTRY \name
870    brk 0
871END \name
872.endm
873
874// Generate the allocation entrypoints for each allocator.
875GENERATE_ALL_ALLOC_ENTRYPOINTS
876
877UNIMPLEMENTED art_quick_test_suspend
878
879/**
880 * Returned by ClassLinker::GetOatCodeFor
881 *
882 */
883UNIMPLEMENTED art_quick_proxy_invoke_handler
884
885UNIMPLEMENTED art_quick_imt_conflict_trampoline
886
887
888ENTRY art_quick_resolution_trampoline
889    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
890    mov x2, xSELF
891    mov x3, sp
892    bl artQuickResolutionTrampoline  // (called, receiver, Thread*, SP)
893    mov x9, x0           // Remember returned code pointer in x9.
894    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
895    cbz x9, 1f
896    br x0
8971:
898    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
899    DELIVER_PENDING_EXCEPTION
900END art_quick_resolution_trampoline
901
902/*
903 * Generic JNI frame layout:
904 *
905 * #-------------------#
906 * |                   |
907 * | caller method...  |
908 * #-------------------#    <--- SP on entry
909 * | Return X30/LR     |
910 * | X29/FP            |    callee save
911 * | X28               |    callee save
912 * | X27               |    callee save
913 * | X26               |    callee save
914 * | X25               |    callee save
915 * | X24               |    callee save
916 * | X23               |    callee save
917 * | X22               |    callee save
918 * | X21               |    callee save
919 * | X20               |    callee save
920 * | X19               |    callee save
921 * | X7                |    arg7
922 * | X6                |    arg6
923 * | X5                |    arg5
924 * | X4                |    arg4
925 * | X3                |    arg3
926 * | X2                |    arg2
927 * | X1                |    arg1
928 * | D15               |    float arg 8
929 * | D14               |    float arg 8
930 * | D13               |    float arg 8
931 * | D12               |    callee save
932 * | D11               |    callee save
933 * | D10               |    callee save
934 * | D9                |    callee save
935 * | D8                |    callee save
936 * | D7                |    float arg 8
937 * | D6                |    float arg 7
938 * | D5                |    float arg 6
939 * | D4                |    float arg 5
940 * | D3                |    float arg 4
941 * | D2                |    float arg 3
942 * | D1                |    float arg 2
943 * | D0                |    float arg 1
944 * | RDI/Method*       |  <- X0
945 * #-------------------#
946 * | local ref cookie  | // 4B
947 * |   SIRT size       | // 4B
948 * #-------------------#
949 * | JNI Call Stack    |
950 * #-------------------#    <--- SP on native call
951 * |                   |
952 * | Stack for Regs    |    The trampoline assembly will pop these values
953 * |                   |    into registers for native call
954 * #-------------------#
955 * | Native code ptr   |
956 * #-------------------#
957 * | Free scratch      |
958 * #-------------------#
959 * | Ptr to (1)        |    <--- SP
960 * #-------------------#
961 */
962    /*
963     * Called to do a generic JNI down-call
964     */
965ENTRY art_quick_generic_jni_trampoline
966    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
967    str x0, [sp, #0]  // Store native ArtMethod* to bottom of stack.
968
969    // Save SP , so we can have static CFI info.
970    mov x28, sp
971    .cfi_def_cfa_register x28
972
973    // This looks the same, but is different: this will be updated to point to the bottom
974    // of the frame when the SIRT is inserted.
975    mov xFP, sp
976
977    mov x8, #5120
978    sub sp, sp, x8
979
980    // prepare for artQuickGenericJniTrampoline call
981    // (Thread*,  SP)
982    //    x0      x1   <= C calling convention
983    //   xSELF    xFP  <= where they are
984
985    mov x0, xSELF   // Thread*
986    mov x1, xFP
987    bl artQuickGenericJniTrampoline  // (Thread*, sp)
988
989    // Get the updated pointer. This is the bottom of the frame _with_ SIRT.
990    ldr xFP, [sp]
991    add x9, sp, #8
992
993    cmp x0, #0
994    b.mi .Lentry_error      // Check for error, negative value.
995
996    // release part of the alloca.
997    add x9, x9, x0
998
999    // Get the code pointer
1000    ldr xIP0, [x9, #0]
1001
1002    // Load parameters from frame into registers.
1003    // TODO Check with artQuickGenericJniTrampoline.
1004    //      Also, check again APPCS64 - the stack arguments are interleaved.
1005    ldp x0, x1, [x9, #8]
1006    ldp x2, x3, [x9, #24]
1007    ldp x4, x5, [x9, #40]
1008    ldp x6, x7, [x9, #56]
1009
1010    ldp d0, d1, [x9, #72]
1011    ldp d2, d3, [x9, #88]
1012    ldp d4, d5, [x9, #104]
1013    ldp d6, d7, [x9, #120]
1014
1015    add sp, x9, #136
1016
1017    blr xIP0           // native call.
1018
1019    // Restore self pointer.
1020    ldr xSELF, [x28, #200]
1021
1022    // result sign extension is handled in C code
1023    // prepare for artQuickGenericJniEndTrampoline call
1024    // (Thread*,  SP, result, result_f)
1025    //   x0       x1   x2       x3       <= C calling convention
1026    mov x5, x0      // Save return value
1027    mov x0, xSELF   // Thread register
1028    mov x1, xFP     // Stack pointer
1029    mov x2, x5      // Result (from saved)
1030    fmov x3, d0     // d0 will contain floating point result, but needs to go into x3
1031
1032    bl artQuickGenericJniEndTrampoline
1033
1034    // Tear down the alloca.
1035    mov sp, x28
1036    .cfi_def_cfa_register sp
1037
1038    // Restore self pointer.
1039    ldr xSELF, [x28, #200]
1040
1041    // Pending exceptions possible.
1042    ldr x1, [xSELF, THREAD_EXCEPTION_OFFSET]
1043    cbnz x1, .Lexception_in_native
1044
1045    // Tear down the callee-save frame.
1046    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
1047
1048    // store into fpr, for when it's a fpr return...
1049    fmov d0, x0
1050    ret
1051
1052.Lentry_error:
1053    mov sp, x28
1054    .cfi_def_cfa_register sp
1055    ldr xSELF, [x28, #200]
1056.Lexception_in_native:
1057    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
1058    DELIVER_PENDING_EXCEPTION
1059
1060END art_quick_generic_jni_trampoline
1061
1062/*
1063 * Called to bridge from the quick to interpreter ABI. On entry the arguments match those
1064 * of a quick call:
1065 * x0 = method being called/to bridge to.
1066 * x1..x7, d0..d7 = arguments to that method.
1067 */
1068ENTRY art_quick_to_interpreter_bridge
1069    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME   // Set up frame and save arguments.
1070
1071    //  x0 will contain mirror::ArtMethod* method.
1072    mov x1, xSELF                          // How to get Thread::Current() ???
1073    mov x2, sp
1074
1075    // uint64_t artQuickToInterpreterBridge(mirror::ArtMethod* method, Thread* self,
1076    //                                      mirror::ArtMethod** sp)
1077    bl   artQuickToInterpreterBridge
1078
1079    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME  // TODO: no need to restore arguments in this case.
1080
1081    fmov d0, x0
1082
1083    RETURN_OR_DELIVER_PENDING_EXCEPTION
1084END art_quick_to_interpreter_bridge
1085
1086UNIMPLEMENTED art_quick_instrumentation_entry
1087UNIMPLEMENTED art_quick_instrumentation_exit
1088UNIMPLEMENTED art_quick_deoptimize
1089UNIMPLEMENTED art_quick_mul_long
1090UNIMPLEMENTED art_quick_shl_long
1091UNIMPLEMENTED art_quick_shr_long
1092UNIMPLEMENTED art_quick_ushr_long
1093UNIMPLEMENTED art_quick_indexof
1094UNIMPLEMENTED art_quick_string_compareto
1095