1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Copyright (C) 2012 The Android Open Source Project
3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
459d709d503bab6e2b61931737e662dd293b40578ccornelius * Licensed under the Apache License, Version 2.0 (the "License");
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * you may not use this file except in compliance with the License.
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * You may obtain a copy of the License at
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *      http://www.apache.org/licenses/LICENSE-2.0
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Unless required by applicable law or agreed to in writing, software
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * distributed under the License is distributed on an "AS IS" BASIS,
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * See the License for the specific language governing permissions and
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * limitations under the License.
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "asm_support_x86_64.S"
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO0(SETUP_FP_CALLEE_SAVE_FRAME)
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Create space for ART FP callee-saved registers
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    subq MACRO_LITERAL(4 * 8), %rsp
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CFI_ADJUST_CFA_OFFSET(4 * 8)
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm12, 0(%rsp)
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm13, 8(%rsp)
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm14, 16(%rsp)
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm15, 24(%rsp)
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO0(RESTORE_FP_CALLEE_SAVE_FRAME)
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Restore ART FP callee-saved registers
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 0(%rsp), %xmm12
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 8(%rsp), %xmm13
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 16(%rsp), %xmm14
3427f654740f2a26ad62a5c155af9199af9e69b889claireho    movq 24(%rsp), %xmm15
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    addq MACRO_LITERAL(4 * 8), %rsp
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CFI_ADJUST_CFA_OFFSET(- 4 * 8)
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// For x86, the CFA is esp+4, the address above the pushed return address on the stack.
4027f654740f2a26ad62a5c155af9199af9e69b889claireho
4127f654740f2a26ad62a5c155af9199af9e69b889claireho    /*
4227f654740f2a26ad62a5c155af9199af9e69b889claireho     * Macro that sets up the callee save frame to conform with
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Runtime::CreateCalleeSaveMethod(kSaveAll)
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO0(SETUP_SAVE_ALL_CALLEE_SAVE_FRAME)
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(__APPLE__)
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int3
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int3
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // R10 := Runtime::Current()
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq _ZN3art7Runtime9instance_E@GOTPCREL(%rip), %r10
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq (%r10), %r10
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Save callee save registers to agree with core spills bitmap.
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r15  // Callee save.
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r14  // Callee save.
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r13  // Callee save.
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r12  // Callee save.
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rbp  // Callee save.
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rbx  // Callee save.
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Create space for FPR args, plus padding for alignment
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    subq LITERAL(4 * 8), %rsp
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CFI_ADJUST_CFA_OFFSET(4 * 8)
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Save FPRs.
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm12, 0(%rsp)
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm13, 8(%rsp)
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm14, 16(%rsp)
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm15, 24(%rsp)
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    subq MACRO_LITERAL(8), %rsp  // Space for Method* (also aligns the frame).
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CFI_ADJUST_CFA_OFFSET(8)
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // R10 := ArtMethod* for save all callee save frame method.
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    THIS_LOAD_REQUIRES_READ_BARRIER
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET(%r10), %r10
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Store ArtMethod* to bottom of stack.
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %r10, 0(%rsp)
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Ugly compile-time check, but we only have the preprocessor.
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Last +8: implicit return address pushed on stack when caller made call.
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVE != 6*8 + 4*8 + 8 + 8)
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#error "SAVE_ALL_CALLEE_SAVE_FRAME(X86_64) size not as expected."
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif  // __APPLE__
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Macro that sets up the callee save frame to conform with
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Runtime::CreateCalleeSaveMethod(kRefsOnly)
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO0(SETUP_REF_ONLY_CALLEE_SAVE_FRAME)
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(__APPLE__)
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int3
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int3
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // R10 := Runtime::Current()
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq _ZN3art7Runtime9instance_E@GOTPCREL(%rip), %r10
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq (%r10), %r10
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Save callee and GPR args, mixed together to agree with core spills bitmap.
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r15  // Callee save.
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r14  // Callee save.
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r13  // Callee save.
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r12  // Callee save.
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rbp  // Callee save.
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rbx  // Callee save.
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Create space for FPR args, plus padding for alignment
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    subq LITERAL(8 + 4*8), %rsp
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CFI_ADJUST_CFA_OFFSET(8 + 4*8)
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Save FPRs.
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm12, 8(%rsp)
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm13, 16(%rsp)
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm14, 24(%rsp)
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm15, 32(%rsp)
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // R10 := ArtMethod* for refs only callee save frame method.
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    THIS_LOAD_REQUIRES_READ_BARRIER
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET(%r10), %r10
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Store ArtMethod* to bottom of stack.
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %r10, 0(%rsp)
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Ugly compile-time check, but we only have the preprocessor.
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Last +8: implicit return address pushed on stack when caller made call.
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if (FRAME_SIZE_REFS_ONLY_CALLEE_SAVE != 6*8 + 4*8 + 8 + 8)
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#error "REFS_ONLY_CALLEE_SAVE_FRAME(X86_64) size not as expected."
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif  // __APPLE__
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO0(RESTORE_REF_ONLY_CALLEE_SAVE_FRAME)
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 8(%rsp), %xmm12
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 16(%rsp), %xmm13
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 24(%rsp), %xmm14
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 32(%rsp), %xmm15
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    addq LITERAL(8 + 4*8), %rsp
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CFI_ADJUST_CFA_OFFSET(-8 - 4*8)
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // TODO: optimize by not restoring callee-saves restored by the ABI
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP rbx
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP rbp
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP r12
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP r13
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP r14
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP r15
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Macro that sets up the callee save frame to conform with
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Runtime::CreateCalleeSaveMethod(kRefsAndArgs)
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO0(SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME)
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(__APPLE__)
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int3
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int3
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // R10 := Runtime::Current()
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq _ZN3art7Runtime9instance_E@GOTPCREL(%rip), %r10
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq (%r10), %r10
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Save callee and GPR args, mixed together to agree with core spills bitmap.
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r15  // Callee save.
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r14  // Callee save.
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r13  // Callee save.
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r12  // Callee save.
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r9   // Quick arg 5.
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r8   // Quick arg 4.
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rsi  // Quick arg 1.
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rbp  // Callee save.
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rbx  // Callee save.
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rdx  // Quick arg 2.
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rcx  // Quick arg 3.
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Create space for FPR args and create 2 slots, 1 of padding and 1 for the ArtMethod*.
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    subq MACRO_LITERAL(80 + 4 * 8), %rsp
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CFI_ADJUST_CFA_OFFSET(80 + 4 * 8)
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // R10 := ArtMethod* for ref and args callee save frame method.
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    THIS_LOAD_REQUIRES_READ_BARRIER
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET(%r10), %r10
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Save FPRs.
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm0, 16(%rsp)
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm1, 24(%rsp)
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm2, 32(%rsp)
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm3, 40(%rsp)
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm4, 48(%rsp)
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm5, 56(%rsp)
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm6, 64(%rsp)
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm7, 72(%rsp)
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm12, 80(%rsp)
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm13, 88(%rsp)
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm14, 96(%rsp)
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm15, 104(%rsp)
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Store ArtMethod* to bottom of stack.
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %r10, 0(%rsp)
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Ugly compile-time check, but we only have the preprocessor.
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Last +8: implicit return address pushed on stack when caller made call.
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if (FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE != 11*8 + 4*8 + 80 + 8)
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#error "REFS_AND_ARGS_CALLEE_SAVE_FRAME(X86_64) size not as expected."
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif  // __APPLE__
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO0(RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME)
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Restore FPRs.
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 16(%rsp), %xmm0
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 24(%rsp), %xmm1
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 32(%rsp), %xmm2
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 40(%rsp), %xmm3
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 48(%rsp), %xmm4
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 56(%rsp), %xmm5
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 64(%rsp), %xmm6
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 72(%rsp), %xmm7
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 80(%rsp), %xmm12
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 88(%rsp), %xmm13
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 96(%rsp), %xmm14
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 104(%rsp), %xmm15
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    addq MACRO_LITERAL(80 + 4 * 8), %rsp
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CFI_ADJUST_CFA_OFFSET(-(80 + 4 * 8))
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Restore callee and GPR args, mixed together to agree with core spills bitmap.
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP rcx
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP rdx
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP rbx
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP rbp
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP rsi
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP r8
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP r9
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP r12
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP r13
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP r14
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP r15
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Macro that set calls through to artDeliverPendingExceptionFromCode, where the pending
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * exception is Thread::Current()->exception_.
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO0(DELIVER_PENDING_EXCEPTION)
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME         // save callee saves for throw
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // (Thread*, SP) setup
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_SELF_OFFSET, %rdi
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsp, %rsi
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call SYMBOL(artDeliverPendingExceptionFromCode)  // artDeliverPendingExceptionFromCode(Thread*, SP)
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UNREACHABLE
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO2(NO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DEFINE_FUNCTION VAR(c_name, 0)
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Outgoing argument set up
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsp, %rsi                    // pass SP
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_SELF_OFFSET, %rdi  // pass Thread::Current()
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call VAR(cxx_name, 1)     // cxx_name(Thread*, SP)
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UNREACHABLE
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    END_FUNCTION VAR(c_name, 0)
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO2(ONE_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DEFINE_FUNCTION VAR(c_name, 0)
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Outgoing argument set up
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsp, %rdx                    // pass SP
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_SELF_OFFSET, %rsi  // pass Thread::Current()
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call VAR(cxx_name, 1)     // cxx_name(arg1, Thread*, SP)
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UNREACHABLE
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    END_FUNCTION VAR(c_name, 0)
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO2(TWO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DEFINE_FUNCTION VAR(c_name, 0)
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Outgoing argument set up
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsp, %rcx                    // pass SP
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_SELF_OFFSET, %rdx  // pass Thread::Current()
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call VAR(cxx_name, 1)     // cxx_name(Thread*, SP)
268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UNREACHABLE
269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    END_FUNCTION VAR(c_name, 0)
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Called by managed code to create and deliver a NullPointerException.
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruNO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Called by managed code to create and deliver an ArithmeticException.
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruNO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Called by managed code to create and deliver a StackOverflowError.
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruNO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow, artThrowStackOverflowFromCode
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Called by managed code, saves callee saves and then calls artThrowException
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * that will place a mock Method* at the bottom of the stack. Arg1 holds the exception.
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception, artDeliverExceptionFromCode
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Called by managed code to create and deliver a NoSuchMethodError.
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method, artThrowNoSuchMethodFromCode
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * index, arg2 holds limit.
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * All generated callsites for interface invokes and invocation slow paths will load arguments
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * as usual - except instead of loading arg0/rdi with the target Method*, arg0/rdi will contain
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * the method_idx.  This wrapper will save arg1-arg3, load the caller's Method*, align the
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * stack and call the appropriate C helper.
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * NOTE: "this" is first visible argument of the target, and so can be found in arg1/rsi.
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * The helper will attempt to locate the target and return a 128-bit result in rax/rdx consisting
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * of the target Method* in rax and method->code_ in rdx.
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * If unsuccessful, the helper will return NULL/????. There will be a pending exception in the
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * thread and we branch to another stub to deliver it.
316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * On success this wrapper will restore arguments and *jump* to the target, leaving the return
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * location on the stack.
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Adapted from x86 code.
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO2(INVOKE_TRAMPOLINE, c_name, cxx_name)
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DEFINE_FUNCTION VAR(c_name, 0)
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME  // save callee saves in case allocation triggers GC
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Helper signature is always
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // (method_idx, *this_object, *caller_method, *self, sp)
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE(%rsp), %edx  // pass caller Method*
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_SELF_OFFSET, %rcx                      // pass Thread
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsp, %r8                                         // pass SP
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
332b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    call VAR(cxx_name, 1)                   // cxx_name(arg1, arg2, caller method*, Thread*, SP)
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                                           // save the code pointer
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rax, %rdi
335b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    movq %rdx, %rax
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    testq %rdi, %rdi
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jz 1f
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Tail call to intended method.
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jmp *%rax
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru1:
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DELIVER_PENDING_EXCEPTION
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    END_FUNCTION VAR(c_name, 0)
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruINVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline, artInvokeInterfaceTrampoline
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruINVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruINVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruINVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruINVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruINVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Helper for quick invocation stub to set up XMM registers. Assumes r10 == shorty,
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * r11 == arg_array. Clobbers r10, r11 and al. Branches to xmm_setup_finished if it encounters
36050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * the end of the shorty.
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
36250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoMACRO2(LOOP_OVER_SHORTY_LOADING_XMMS, xmm_reg, finished)
36350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho1: // LOOP
36450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    movb (%r10), %al              // al := *shorty
36550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    addq MACRO_LITERAL(1), %r10   // shorty++
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cmpb MACRO_LITERAL(0), %al    // if (al == '\0') goto xmm_setup_finished
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    je VAR(finished, 1)
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cmpb MACRO_LITERAL(68), %al   // if (al == 'D') goto FOUND_DOUBLE
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    je 2f
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cmpb MACRO_LITERAL(70), %al   // if (al == 'F') goto FOUND_FLOAT
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    je 3f
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    addq MACRO_LITERAL(4), %r11   // arg_array++
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //  Handle extra space in arg array taken by a long.
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cmpb MACRO_LITERAL(74), %al   // if (al != 'J') goto LOOP
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jne 1b
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    addq MACRO_LITERAL(4), %r11   // arg_array++
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jmp 1b                        // goto LOOP
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru2:  // FOUND_DOUBLE
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movsd (%r11), REG_VAR(xmm_reg, 0)
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    addq MACRO_LITERAL(8), %r11   // arg_array+=2
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jmp 4f
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru3:  // FOUND_FLOAT
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movss (%r11), REG_VAR(xmm_reg, 0)
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    addq MACRO_LITERAL(4), %r11   // arg_array++
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru4:
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
3878393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
3888393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    /*
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Helper for quick invocation stub to set up GPR registers. Assumes r10 == shorty,
3908393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius     * r11 == arg_array. Clobbers r10, r11 and al. Branches to gpr_setup_finished if it encounters
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * the end of the shorty.
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO3(LOOP_OVER_SHORTY_LOADING_GPRS, gpr_reg64, gpr_reg32, finished)
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru1: // LOOP
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movb (%r10), %al              // al := *shorty
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    addq MACRO_LITERAL(1), %r10   // shorty++
39727f654740f2a26ad62a5c155af9199af9e69b889claireho    cmpb MACRO_LITERAL(0), %al    // if (al == '\0') goto gpr_setup_finished
39827f654740f2a26ad62a5c155af9199af9e69b889claireho    je  VAR(finished, 2)
39927f654740f2a26ad62a5c155af9199af9e69b889claireho    cmpb MACRO_LITERAL(74), %al   // if (al == 'J') goto FOUND_LONG
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    je 2f
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cmpb MACRO_LITERAL(70), %al   // if (al == 'F') goto SKIP_FLOAT
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    je 3f
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cmpb MACRO_LITERAL(68), %al   // if (al == 'D') goto SKIP_DOUBLE
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    je 4f
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl (%r11), REG_VAR(gpr_reg32, 1)
406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    addq MACRO_LITERAL(4), %r11   // arg_array++
407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jmp 5f
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru2:  // FOUND_LONG
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq (%r11), REG_VAR(gpr_reg64, 0)
410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    addq MACRO_LITERAL(8), %r11   // arg_array+=2
411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jmp 5f
412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru3:  // SKIP_FLOAT
413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    addq MACRO_LITERAL(4), %r11   // arg_array++
414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jmp 1b
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru4:  // SKIP_DOUBLE
416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    addq MACRO_LITERAL(8), %r11   // arg_array+=2
417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jmp 1b
418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru5:
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Quick invocation stub.
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * On entry:
424b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     *   [sp] = return address
425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *   rdi = method pointer
426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *   rsi = argument array that must at least contain the this pointer.
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *   rdx = size of argument array in bytes
428b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     *   rcx = (managed) thread pointer
429b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     *   r8 = JValue* result
430b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     *   r9 = char* shorty
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDEFINE_FUNCTION art_quick_invoke_stub
43327f654740f2a26ad62a5c155af9199af9e69b889claireho#if defined(__APPLE__)
43427f654740f2a26ad62a5c155af9199af9e69b889claireho    int3
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int3
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Set up argument XMM registers.
4388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    leaq 1(%r9), %r10             // R10 := shorty + 1  ; ie skip return arg character.
4398393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    leaq 4(%rsi), %r11            // R11 := arg_array + 4 ; ie skip this pointer.
4408393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    LOOP_OVER_SHORTY_LOADING_XMMS xmm0, .Lxmm_setup_finished
4418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    LOOP_OVER_SHORTY_LOADING_XMMS xmm1, .Lxmm_setup_finished
4428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    LOOP_OVER_SHORTY_LOADING_XMMS xmm2, .Lxmm_setup_finished
4438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    LOOP_OVER_SHORTY_LOADING_XMMS xmm3, .Lxmm_setup_finished
4448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    LOOP_OVER_SHORTY_LOADING_XMMS xmm4, .Lxmm_setup_finished
4458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    LOOP_OVER_SHORTY_LOADING_XMMS xmm5, .Lxmm_setup_finished
4468393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    LOOP_OVER_SHORTY_LOADING_XMMS xmm6, .Lxmm_setup_finished
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LOOP_OVER_SHORTY_LOADING_XMMS xmm7, .Lxmm_setup_finished
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    .balign 16
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru.Lxmm_setup_finished:
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rbp                      // Save rbp.
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r8                       // Save r8/result*.
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r9                       // Save r9/shorty*.
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsp, %rbp               // Copy value of stack pointer into base pointer.
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CFI_DEF_CFA_REGISTER(rbp)
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl %edx, %r10d
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    addl LITERAL(60), %edx        // Reserve space for return addr, StackReference<method>, rbp,
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  // r8 and r9 in frame.
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    andl LITERAL(0xFFFFFFF0), %edx    // Align frame size to 16 bytes.
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    subl LITERAL(32), %edx        // Remove space for return address, rbp, r8 and r9.
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    subq %rdx, %rsp               // Reserve stack space for argument array.
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if (STACK_REFERENCE_SIZE != 4)
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#error "STACK_REFERENCE_SIZE(X86_64) size not as expected."
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl LITERAL(0), (%rsp)       // Store NULL for method*
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl %r10d, %ecx              // Place size of args in rcx.
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rdi, %rax               // RAX := method to be called
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsi, %r11               // R11 := arg_array
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    leaq 4(%rsp), %rdi            // Rdi is pointing just above the StackReference<method> in the
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  // stack arguments.
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Copy arg array into stack.
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    rep movsb                     // while (rcx--) { *rdi++ = *rsi++ }
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    leaq 1(%r9), %r10             // R10 := shorty + 1  ; ie skip return arg character
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rax, %rdi               // RDI := method to be called
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl (%r11), %esi             // RSI := this pointer
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    addq LITERAL(4), %r11         // arg_array++
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LOOP_OVER_SHORTY_LOADING_GPRS rdx, edx, .Lgpr_setup_finished
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LOOP_OVER_SHORTY_LOADING_GPRS rcx, ecx, .Lgpr_setup_finished
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LOOP_OVER_SHORTY_LOADING_GPRS r8, r8d, .Lgpr_setup_finished
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LOOP_OVER_SHORTY_LOADING_GPRS r9, r9d, .Lgpr_setup_finished
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru.Lgpr_setup_finished:
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call *METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method.
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rbp, %rsp               // Restore stack pointer.
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CFI_DEF_CFA_REGISTER(rsp)
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP r9                        // Pop r9 - shorty*.
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP r8                        // Pop r8 - result*.
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP rbp                       // Pop rbp
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cmpb LITERAL(68), (%r9)       // Test if result type char == 'D'.
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    je .Lreturn_double_quick
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cmpb LITERAL(70), (%r9)       // Test if result type char == 'F'.
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    je .Lreturn_float_quick
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rax, (%r8)              // Store the result assuming its a long, int or Object*
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ret
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru.Lreturn_double_quick:
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movsd %xmm0, (%r8)           // Store the double floating point result.
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ret
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru.Lreturn_float_quick:
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movss %xmm0, (%r8)           // Store the floating point result.
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ret
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif  // __APPLE__
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_FUNCTION art_quick_invoke_stub
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Quick invocation stub.
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * On entry:
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *   [sp] = return address
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *   rdi = method pointer
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *   rsi = argument array or NULL if no arguments.
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *   rdx = size of argument array in bytes
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *   rcx = (managed) thread pointer
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *   r8 = JValue* result
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *   r9 = char* shorty
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDEFINE_FUNCTION art_quick_invoke_static_stub
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(__APPLE__)
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int3
51927f654740f2a26ad62a5c155af9199af9e69b889claireho    int3
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Set up argument XMM registers.
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    leaq 1(%r9), %r10             // R10 := shorty + 1  ; ie skip return arg character
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsi, %r11               // R11 := arg_array
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LOOP_OVER_SHORTY_LOADING_XMMS xmm0, .Lxmm_setup_finished2
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LOOP_OVER_SHORTY_LOADING_XMMS xmm1, .Lxmm_setup_finished2
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LOOP_OVER_SHORTY_LOADING_XMMS xmm2, .Lxmm_setup_finished2
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LOOP_OVER_SHORTY_LOADING_XMMS xmm3, .Lxmm_setup_finished2
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LOOP_OVER_SHORTY_LOADING_XMMS xmm4, .Lxmm_setup_finished2
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LOOP_OVER_SHORTY_LOADING_XMMS xmm5, .Lxmm_setup_finished2
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LOOP_OVER_SHORTY_LOADING_XMMS xmm6, .Lxmm_setup_finished2
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LOOP_OVER_SHORTY_LOADING_XMMS xmm7, .Lxmm_setup_finished2
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    .balign 16
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru.Lxmm_setup_finished2:
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rbp                      // Save rbp.
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r8                       // Save r8/result*.
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r9                       // Save r9/shorty*.
5378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    movq %rsp, %rbp               // Copy value of stack pointer into base pointer.
5388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    CFI_DEF_CFA_REGISTER(rbp)
5398393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
5408393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    movl %edx, %r10d
5418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    addl LITERAL(60), %edx        // Reserve space for return addr, StackReference<method>, rbp,
5428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                  // r8 and r9 in frame.
543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    andl LITERAL(0xFFFFFFF0), %edx    // Align frame size to 16 bytes.
544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    subl LITERAL(32), %edx        // Remove space for return address, rbp, r8 and r9.
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    subq %rdx, %rsp               // Reserve stack space for argument array.
54627f654740f2a26ad62a5c155af9199af9e69b889claireho
54727f654740f2a26ad62a5c155af9199af9e69b889claireho#if (STACK_REFERENCE_SIZE != 4)
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#error "STACK_REFERENCE_SIZE(X86_64) size not as expected."
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl LITERAL(0), (%rsp)       // Store NULL for method*
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
5528393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    movl %r10d, %ecx              // Place size of args in rcx.
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rdi, %rax               // RAX := method to be called
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsi, %r11               // R11 := arg_array
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    leaq 4(%rsp), %rdi            // Rdi is pointing just above the StackReference<method> in the
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  // stack arguments.
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Copy arg array into stack.
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    rep movsb                     // while (rcx--) { *rdi++ = *rsi++ }
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    leaq 1(%r9), %r10             // R10 := shorty + 1  ; ie skip return arg character
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rax, %rdi               // RDI := method to be called
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LOOP_OVER_SHORTY_LOADING_GPRS rsi, esi, .Lgpr_setup_finished2
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LOOP_OVER_SHORTY_LOADING_GPRS rdx, edx, .Lgpr_setup_finished2
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LOOP_OVER_SHORTY_LOADING_GPRS rcx, ecx, .Lgpr_setup_finished2
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LOOP_OVER_SHORTY_LOADING_GPRS r8, r8d, .Lgpr_setup_finished2
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LOOP_OVER_SHORTY_LOADING_GPRS r9, r9d, .Lgpr_setup_finished2
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru.Lgpr_setup_finished2:
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call *METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method.
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rbp, %rsp               // Restore stack pointer.
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CFI_DEF_CFA_REGISTER(rsp)
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP r9                        // Pop r9 - shorty*.
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP r8                        // Pop r8 - result*.
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP rbp                       // Pop rbp
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cmpb LITERAL(68), (%r9)       // Test if result type char == 'D'.
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    je .Lreturn_double_quick2
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cmpb LITERAL(70), (%r9)       // Test if result type char == 'F'.
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    je .Lreturn_float_quick2
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rax, (%r8)              // Store the result assuming its a long, int or Object*
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ret
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru.Lreturn_double_quick2:
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movsd %xmm0, (%r8)           // Store the double floating point result.
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ret
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru.Lreturn_float_quick2:
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movss %xmm0, (%r8)           // Store the floating point result.
5848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    ret
5858393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#endif  // __APPLE__
5868393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusEND_FUNCTION art_quick_invoke_static_stub
5878393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
5888393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    /*
5898393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius     * Long jump stub.
5908393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius     * On entry:
5918393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius     *   rdi = gprs
5928393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius     *   rsi = fprs
5938393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius     */
5948393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusDEFINE_FUNCTION art_quick_do_long_jump
5958393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#if defined(__APPLE__)
5968393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    int3
5978393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    int3
5988393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#else
5998393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // Restore FPRs.
6008393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    movq 0(%rsi), %xmm0
6018393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    movq 8(%rsi), %xmm1
6028393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    movq 16(%rsi), %xmm2
6038393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    movq 24(%rsi), %xmm3
6048393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    movq 32(%rsi), %xmm4
6058393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    movq 40(%rsi), %xmm5
6068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    movq 48(%rsi), %xmm6
6078393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    movq 56(%rsi), %xmm7
6088393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    movq 64(%rsi), %xmm8
6098393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    movq 72(%rsi), %xmm9
6108393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    movq 80(%rsi), %xmm10
6118393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    movq 88(%rsi), %xmm11
61259d709d503bab6e2b61931737e662dd293b40578ccornelius    movq 96(%rsi), %xmm12
6138393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    movq 104(%rsi), %xmm13
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq 112(%rsi), %xmm14
6158393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    movq 120(%rsi), %xmm15
6168393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // Restore FPRs.
6178393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    movq %rdi, %rsp   // RSP points to gprs.
6188393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // Load all registers except RSP and RIP with values in gprs.
6198393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    popq %r15
6208393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    popq %r14
6218393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    popq %r13
6228393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    popq %r12
6238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    popq %r11
6248393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    popq %r10
6258393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    popq %r9
6268393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    popq %r8
6278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    popq %rdi
6288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    popq %rsi
6298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    popq %rbp
6308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    addq LITERAL(8), %rsp   // Skip rsp
6318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    popq %rbx
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    popq %rdx
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    popq %rcx
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    popq %rax
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    popq %rsp      // Load stack pointer.
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ret            // From higher in the stack pop rip.
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif  // __APPLE__
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_FUNCTION art_quick_do_long_jump
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO3(NO_ARG_DOWNCALL, c_name, cxx_name, return_macro)
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DEFINE_FUNCTION VAR(c_name, 0)
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save ref containing registers for GC
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Outgoing argument set up
6448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    movq %rsp, %rsi                   // pass SP
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_SELF_OFFSET, %rdi // pass Thread::Current()
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call VAR(cxx_name, 1)         // cxx_name(Thread*, SP)
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME  // restore frame up to return address
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CALL_MACRO(return_macro, 2)       // return or deliver exception
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    END_FUNCTION VAR(c_name, 0)
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO3(ONE_ARG_DOWNCALL, c_name, cxx_name, return_macro)
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DEFINE_FUNCTION VAR(c_name, 0)
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SETUP_REF_ONLY_CALLEE_SAVE_FRAME   // save ref containing registers for GC
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Outgoing argument set up
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsp, %rdx                    // pass SP
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_SELF_OFFSET, %rsi  // pass Thread::Current()
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call VAR(cxx_name, 1)          // cxx_name(arg0, Thread*, SP)
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME  // restore frame up to return address
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CALL_MACRO(return_macro, 2)        // return or deliver exception
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    END_FUNCTION VAR(c_name, 0)
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO3(TWO_ARG_DOWNCALL, c_name, cxx_name, return_macro)
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DEFINE_FUNCTION VAR(c_name, 0)
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SETUP_REF_ONLY_CALLEE_SAVE_FRAME   // save ref containing registers for GC
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Outgoing argument set up
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsp, %rcx                    // pass SP
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_SELF_OFFSET, %rdx  // pass Thread::Current()
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call VAR(cxx_name, 1)          // cxx_name(arg0, arg1, Thread*, SP)
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME  // restore frame up to return address
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CALL_MACRO(return_macro, 2)       // return or deliver exception
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    END_FUNCTION VAR(c_name, 0)
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO3(THREE_ARG_DOWNCALL, c_name, cxx_name, return_macro)
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DEFINE_FUNCTION VAR(c_name, 0)
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SETUP_REF_ONLY_CALLEE_SAVE_FRAME   // save ref containing registers for GC
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Outgoing argument set up
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsp, %r8                     // pass SP
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_SELF_OFFSET, %rcx  // pass Thread::Current()
682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call VAR(cxx_name, 1)          // cxx_name(arg0, arg1, arg2, Thread*, SP)
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CALL_MACRO(return_macro, 2)        // return or deliver exception
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    END_FUNCTION VAR(c_name, 0)
686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO3(ONE_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro)
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DEFINE_FUNCTION VAR(c_name, 0)
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl 8(%rsp), %esi                 // pass referrer
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SETUP_REF_ONLY_CALLEE_SAVE_FRAME
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       // arg0 is in rdi
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_SELF_OFFSET, %rdx  // pass Thread::Current()
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsp, %rcx                    // pass SP
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call VAR(cxx_name, 1)          // cxx_name(arg0, referrer, Thread*, SP)
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CALL_MACRO(return_macro, 2)
698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    END_FUNCTION VAR(c_name, 0)
699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO3(TWO_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro)
702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DEFINE_FUNCTION VAR(c_name, 0)
703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl 8(%rsp), %edx                 // pass referrer
704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SETUP_REF_ONLY_CALLEE_SAVE_FRAME
705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       // arg0 and arg1 are in rdi/rsi
706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_SELF_OFFSET, %rcx  // pass Thread::Current()
707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsp, %r8                     // pass SP
708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call VAR(cxx_name, 1)          // (arg0, arg1, referrer, Thread*, SP)
709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CALL_MACRO(return_macro, 2)
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    END_FUNCTION VAR(c_name, 0)
712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO3(THREE_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro)
715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DEFINE_FUNCTION VAR(c_name, 0)
716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl 8(%rsp), %ecx                 // pass referrer
717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SETUP_REF_ONLY_CALLEE_SAVE_FRAME
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       // arg0, arg1, and arg2 are in rdi/rsi/rdx
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_SELF_OFFSET, %r8    // pass Thread::Current()
720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsp, %r9                     // pass SP
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call VAR(cxx_name, 1)          // cxx_name(arg0, arg1, arg2, referrer, Thread*, SP)
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CALL_MACRO(return_macro, 2)        // return or deliver exception
724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    END_FUNCTION VAR(c_name, 0)
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO0(RETURN_IF_RESULT_IS_NON_ZERO)
728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    testq %rax, %rax               // rax == 0 ?
729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jz  1f                         // if rax == 0 goto 1
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ret                            // return
731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru1:                                 // deliver exception on current thread
732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DELIVER_PENDING_EXCEPTION
733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO0(RETURN_IF_EAX_ZERO)
736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    testl %eax, %eax               // eax == 0 ?
737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jnz  1f                        // if eax != 0 goto 1
738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ret                            // return
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru1:                                 // deliver exception on current thread
740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DELIVER_PENDING_EXCEPTION
741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMACRO0(RETURN_OR_DELIVER_PENDING_EXCEPTION)
744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_EXCEPTION_OFFSET, %rcx // get exception field
745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    testq %rcx, %rcx               // rcx == 0 ?
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jnz 1f                         // if rcx != 0 goto 1
747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ret                            // return
748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru1:                                 // deliver exception on current thread
749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DELIVER_PENDING_EXCEPTION
750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_MACRO
751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Generate the allocation entrypoints for each allocator.
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// TODO: use arch/quick_alloc_entrypoints.S. Currently we don't as we need to use concatenation
754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// macros to work around differences between OS/X's as and binutils as (OS/X lacks named arguments
755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// to macros and the VAR macro won't concatenate arguments properly), this also breaks having
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// multi-line macros that use each other (hence using 1 macro per newline below).
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(c_suffix, cxx_suffix) \
758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  TWO_ARG_DOWNCALL art_quick_alloc_object ## c_suffix, artAllocObjectFromCode ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(c_suffix, cxx_suffix) \
760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  TWO_ARG_DOWNCALL art_quick_alloc_object_resolved ## c_suffix, artAllocObjectFromCodeResolved ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(c_suffix, cxx_suffix) \
762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  TWO_ARG_DOWNCALL art_quick_alloc_object_initialized ## c_suffix, artAllocObjectFromCodeInitialized ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(c_suffix, cxx_suffix) \
764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  TWO_ARG_DOWNCALL art_quick_alloc_object_with_access_check ## c_suffix, artAllocObjectFromCodeWithAccessCheck ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(c_suffix, cxx_suffix) \
766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  THREE_ARG_DOWNCALL art_quick_alloc_array ## c_suffix, artAllocArrayFromCode ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(c_suffix, cxx_suffix) \
768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  THREE_ARG_DOWNCALL art_quick_alloc_array_resolved ## c_suffix, artAllocArrayFromCodeResolved ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(c_suffix, cxx_suffix) \
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  THREE_ARG_DOWNCALL art_quick_alloc_array_with_access_check ## c_suffix, artAllocArrayFromCodeWithAccessCheck ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(c_suffix, cxx_suffix) \
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  THREE_ARG_DOWNCALL art_quick_check_and_alloc_array ## c_suffix, artCheckAndAllocArrayFromCode ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(c_suffix, cxx_suffix) \
7748393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  THREE_ARG_DOWNCALL art_quick_check_and_alloc_array_with_access_check ## c_suffix, artCheckAndAllocArrayFromCodeWithAccessCheck ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
7758393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
7768393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_dlmalloc, DlMalloc)
7778393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_dlmalloc, DlMalloc)
7788393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_dlmalloc, DlMalloc)
7798393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_dlmalloc, DlMalloc)
7808393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_dlmalloc, DlMalloc)
7818393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_dlmalloc, DlMalloc)
7828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc, DlMalloc)
7838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusGENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_dlmalloc, DlMalloc)
7848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusGENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc, DlMalloc)
785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_dlmalloc_instrumented, DlMallocInstrumented)
787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_dlmalloc_instrumented, DlMallocInstrumented)
788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_dlmalloc_instrumented, DlMallocInstrumented)
789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_dlmalloc_instrumented, DlMallocInstrumented)
790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_dlmalloc_instrumented, DlMallocInstrumented)
791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_dlmalloc_instrumented, DlMallocInstrumented)
792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc_instrumented, DlMallocInstrumented)
793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_dlmalloc_instrumented, DlMallocInstrumented)
794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc_instrumented, DlMallocInstrumented)
795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_rosalloc, RosAlloc)
797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_rosalloc, RosAlloc)
798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_rosalloc, RosAlloc)
799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_rosalloc, RosAlloc)
800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_rosalloc, RosAlloc)
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_rosalloc, RosAlloc)
802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc, RosAlloc)
803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_rosalloc, RosAlloc)
804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc, RosAlloc)
805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_rosalloc_instrumented, RosAllocInstrumented)
807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_rosalloc_instrumented, RosAllocInstrumented)
808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_rosalloc_instrumented, RosAllocInstrumented)
809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_rosalloc_instrumented, RosAllocInstrumented)
810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_rosalloc_instrumented, RosAllocInstrumented)
811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_rosalloc_instrumented, RosAllocInstrumented)
812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc_instrumented, RosAllocInstrumented)
813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_rosalloc_instrumented, RosAllocInstrumented)
814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc_instrumented, RosAllocInstrumented)
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_bump_pointer, BumpPointer)
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_bump_pointer, BumpPointer)
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_bump_pointer, BumpPointer)
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_bump_pointer, BumpPointer)
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_bump_pointer, BumpPointer)
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_bump_pointer, BumpPointer)
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer, BumpPointer)
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_bump_pointer, BumpPointer)
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer, BumpPointer)
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_bump_pointer_instrumented, BumpPointerInstrumented)
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_bump_pointer_instrumented, BumpPointerInstrumented)
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_bump_pointer_instrumented, BumpPointerInstrumented)
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_bump_pointer_instrumented, BumpPointerInstrumented)
830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_bump_pointer_instrumented, BumpPointerInstrumented)
831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_bump_pointer_instrumented, BumpPointerInstrumented)
832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer_instrumented, BumpPointerInstrumented)
833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_bump_pointer_instrumented, BumpPointerInstrumented)
834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer_instrumented, BumpPointerInstrumented)
835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_tlab, TLAB)
837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_tlab, TLAB)
838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_tlab, TLAB)
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_tlab, TLAB)
840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_tlab, TLAB)
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_tlab, TLAB)
842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab, TLAB)
843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_tlab, TLAB)
844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab, TLAB)
845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_tlab_instrumented, TLABInstrumented)
847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_tlab_instrumented, TLABInstrumented)
848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_tlab_instrumented, TLABInstrumented)
849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_tlab_instrumented, TLABInstrumented)
850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_tlab_instrumented, TLABInstrumented)
851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_tlab_instrumented, TLABInstrumented)
852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab_instrumented, TLABInstrumented)
853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_tlab_instrumented, TLABInstrumented)
854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab_instrumented, TLABInstrumented)
855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTWO_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO
857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTWO_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO
858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTWO_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO
859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO
860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTWO_ARG_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO
862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDEFINE_FUNCTION art_quick_lock_object
864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    testl %edi, %edi                      // Null check object/rdi.
865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jz   .Lslow_lock
866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru.Lretry_lock:
867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl LOCK_WORD_OFFSET(%edi), %ecx     // ecx := lock word.
868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    test LITERAL(0xC0000000), %ecx        // Test the 2 high bits.
869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jne  .Lslow_lock                      // Slow path if either of the two high bits are set.
870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl %gs:THREAD_ID_OFFSET, %edx       // edx := thread id
871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    test %ecx, %ecx
872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jnz  .Lalready_thin                   // Lock word contains a thin lock.
873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // unlocked case - %edx holds thread id with count of 0
874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    xor  %eax, %eax                       // eax == 0 for comparison with lock word in cmpxchg
875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    lock cmpxchg  %edx, LOCK_WORD_OFFSET(%edi)
876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jnz  .Lretry_lock                     // cmpxchg failed retry
877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ret
878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru.Lalready_thin:
879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cmpw %cx, %dx                         // do we hold the lock already?
880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jne  .Lslow_lock
881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    addl LITERAL(65536), %ecx             // increment recursion count
882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    test LITERAL(0xC0000000), %ecx        // overflowed if either of top two bits are set
883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jne  .Lslow_lock                      // count overflowed so go slow
884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl %ecx, LOCK_WORD_OFFSET(%edi)     // update lockword, cmpxchg not necessary as we hold lock
885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ret
886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru.Lslow_lock:
887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SETUP_REF_ONLY_CALLEE_SAVE_FRAME
888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_SELF_OFFSET, %rsi     // pass Thread::Current()
889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsp, %rdx                       // pass SP
890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call SYMBOL(artLockObjectFromCode)  // artLockObjectFromCode(object, Thread*, SP)
891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME    // restore frame up to return address
892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_IF_EAX_ZERO
893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_FUNCTION art_quick_lock_object
894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDEFINE_FUNCTION art_quick_unlock_object
896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    testl %edi, %edi                      // null check object/edi
897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jz   .Lslow_unlock
898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl LOCK_WORD_OFFSET(%edi), %ecx     // ecx := lock word
899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl %gs:THREAD_ID_OFFSET, %edx       // edx := thread id
900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    test LITERAL(0xC0000000), %ecx
901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jnz  .Lslow_unlock                    // lock word contains a monitor
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cmpw %cx, %dx                         // does the thread id match?
903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jne  .Lslow_unlock
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cmpl LITERAL(65536), %ecx
905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jae  .Lrecursive_thin_unlock
906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl LITERAL(0), LOCK_WORD_OFFSET(%edi)
907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ret
908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru.Lrecursive_thin_unlock:
909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    subl LITERAL(65536), %ecx
910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    mov  %ecx, LOCK_WORD_OFFSET(%edi)
911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ret
912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru.Lslow_unlock:
913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SETUP_REF_ONLY_CALLEE_SAVE_FRAME
914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_SELF_OFFSET, %rsi     // pass Thread::Current()
915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsp, %rdx                       // pass SP
916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call SYMBOL(artUnlockObjectFromCode)  // artUnlockObjectFromCode(object, Thread*, SP)
917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME    // restore frame up to return address
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_IF_EAX_ZERO
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_FUNCTION art_quick_unlock_object
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDEFINE_FUNCTION art_quick_check_cast
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rdi                          // Save args for exc
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rsi
924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SETUP_FP_CALLEE_SAVE_FRAME
925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call SYMBOL(artIsAssignableFromCode)  // (Class* klass, Class* ref_klass)
926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    testq %rax, %rax
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jz 1f                             // jump forward if not assignable
928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RESTORE_FP_CALLEE_SAVE_FRAME
929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    addq LITERAL(16), %rsp            // pop arguments
930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CFI_ADJUST_CFA_OFFSET(-16)
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ret
933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru1:
934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RESTORE_FP_CALLEE_SAVE_FRAME
935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP rsi                           // Pop arguments
936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP rdi
937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    mov %rsp, %rcx                    // pass SP
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    mov %gs:THREAD_SELF_OFFSET, %rdx  // pass Thread::Current()
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call SYMBOL(artThrowClassCastException) // (Class* a, Class* b, Thread*, SP)
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int3                              // unreached
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_FUNCTION art_quick_check_cast
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Entry from managed code for array put operations of objects where the value being stored
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * needs to be checked for compatibility.
948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *
949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Currently all the parameters should fit into the 32b portions of the registers. Index always
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * will. So we optimize for a tighter encoding. The 64b versions are in comments.
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * rdi(edi) = array, rsi(esi) = index, rdx(edx) = value
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDEFINE_FUNCTION art_quick_aput_obj_with_null_and_bound_check
955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(__APPLE__)
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int3
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int3
958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    testl %edi, %edi
960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  testq %rdi, %rdi
961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jnz art_quick_aput_obj_with_bound_check
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jmp art_quick_throw_null_pointer_exception
963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif  // __APPLE__
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_FUNCTION art_quick_aput_obj_with_null_and_bound_check
965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDEFINE_FUNCTION art_quick_aput_obj_with_bound_check
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(__APPLE__)
969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int3
970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int3
971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl ARRAY_LENGTH_OFFSET(%edi), %ecx
973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  movl ARRAY_LENGTH_OFFSET(%rdi), %ecx      // This zero-extends, so value(%rcx)=value(%ecx)
974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cmpl %ecx, %esi
975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jb art_quick_aput_obj
976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    mov %esi, %edi
977b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//  mov %rsi, %rdi
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    mov %ecx, %esi
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  mov %rcx, %rsi
980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jmp art_quick_throw_array_bounds
981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif  // __APPLE__
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_FUNCTION art_quick_aput_obj_with_bound_check
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
984b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
985b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruDEFINE_FUNCTION art_quick_aput_obj
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    testl %edx, %edx                // store of null
987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  test %rdx, %rdx
988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jz .Ldo_aput_null
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl CLASS_OFFSET(%edi), %ecx
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  movq CLASS_OFFSET(%rdi), %rcx
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl CLASS_COMPONENT_TYPE_OFFSET(%ecx), %ecx
992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  movq CLASS_COMPONENT_TYPE_OFFSET(%rcx), %rcx
993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cmpl CLASS_OFFSET(%edx), %ecx // value's type == array's component type - trivial assignability
994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  cmpq CLASS_OFFSET(%rdx), %rcx
995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jne .Lcheck_assignability
996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru.Ldo_aput:
997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl %edx, OBJECT_ARRAY_DATA_OFFSET(%edi, %esi, 4)
998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  movq %rdx, OBJECT_ARRAY_DATA_OFFSET(%rdi, %rsi, 4)
999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_CARD_TABLE_OFFSET, %rdx
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    shrl LITERAL(7), %edi
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  shrl LITERAL(7), %rdi
1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movb %dl, (%rdx, %rdi)                       // Note: this assumes that top 32b of %rdi are zero
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ret
1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru.Ldo_aput_null:
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl %edx, OBJECT_ARRAY_DATA_OFFSET(%edi, %esi, 4)
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  movq %rdx, OBJECT_ARRAY_DATA_OFFSET(%rdi, %rsi, 4)
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ret
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru.Lcheck_assignability:
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Save arguments.
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rdi
1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rsi
1012b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    PUSH rdx
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    subq LITERAL(8), %rsp        // Alignment padding.
1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CFI_ADJUST_CFA_OFFSET(8)
1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SETUP_FP_CALLEE_SAVE_FRAME
1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  // "Uncompress" = do nothing, as already zero-extended on load.
1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl CLASS_OFFSET(%edx), %esi // Pass arg2 = value's class.
1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rcx, %rdi               // Pass arg1 = array's component type.
1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call SYMBOL(artIsAssignableFromCode)  // (Class* a, Class* b)
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Exception?
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    testq %rax, %rax
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jz   .Lthrow_array_store_exception
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RESTORE_FP_CALLEE_SAVE_FRAME
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Restore arguments.
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    addq LITERAL(8), %rsp
1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CFI_ADJUST_CFA_OFFSET(-8)
1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP  rdx
1032b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    POP  rsi
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP  rdi
1034b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1035b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    movl %edx, OBJECT_ARRAY_DATA_OFFSET(%edi, %esi, 4)
1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  movq %rdx, OBJECT_ARRAY_DATA_OFFSET(%rdi, %rsi, 4)
103727f654740f2a26ad62a5c155af9199af9e69b889claireho    movq %gs:THREAD_CARD_TABLE_OFFSET, %rdx
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    shrl LITERAL(7), %edi
1039b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//  shrl LITERAL(7), %rdi
1040b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    movb %dl, (%rdx, %rdi)                       // Note: this assumes that top 32b of %rdi are zero
1041b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//  movb %dl, (%rdx, %rdi)
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ret
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru.Lthrow_array_store_exception:
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RESTORE_FP_CALLEE_SAVE_FRAME
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Restore arguments.
1046b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    addq LITERAL(8), %rsp
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CFI_ADJUST_CFA_OFFSET(-8)
1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    POP  rdx
1049b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    POP  rsi
1050b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    POP  rdi
1051b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // Save all registers as basis for long jump context.
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1054b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // Outgoing argument set up.
1055b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    movq %rsp, %rcx                         // Pass arg 4 = SP.
1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rdx, %rsi                         // Pass arg 2 = value.
1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_SELF_OFFSET, %rdx // Pass arg 3 = Thread::Current().
1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                            // Pass arg 1 = array.
1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call SYMBOL(artThrowArrayStoreException) // (array, value, Thread*, SP)
1061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int3                          // unreached
1062b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruEND_FUNCTION art_quick_aput_obj
1063b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1064b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// TODO: This is quite silly on X86_64 now.
1065b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruDEFINE_FUNCTION art_quick_memcpy
1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call PLT_SYMBOL(memcpy)       // (void*, const void*, size_t)
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ret
1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_FUNCTION art_quick_memcpy
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruNO_ARG_DOWNCALL art_quick_test_suspend, artTestSuspendFromCode, ret
1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUNIMPLEMENTED art_quick_ldiv
1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUNIMPLEMENTED art_quick_lmod
1074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUNIMPLEMENTED art_quick_lmul
1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUNIMPLEMENTED art_quick_lshl
1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUNIMPLEMENTED art_quick_lshr
1077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUNIMPLEMENTED art_quick_lushr
1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTHREE_ARG_REF_DOWNCALL art_quick_set32_instance, artSet32InstanceFromCode, RETURN_IF_EAX_ZERO
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTHREE_ARG_DOWNCALL art_quick_set64_instance, artSet64InstanceFromCode, RETURN_IF_EAX_ZERO
1081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTHREE_ARG_REF_DOWNCALL art_quick_set_obj_instance, artSetObjInstanceFromCode, RETURN_IF_EAX_ZERO
1082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTWO_ARG_REF_DOWNCALL art_quick_get32_instance, artGet32InstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTWO_ARG_REF_DOWNCALL art_quick_get64_instance, artGet64InstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTWO_ARG_REF_DOWNCALL art_quick_get_obj_instance, artGetObjInstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTWO_ARG_REF_DOWNCALL art_quick_set32_static, artSet32StaticFromCode, RETURN_IF_EAX_ZERO
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTWO_ARG_REF_DOWNCALL art_quick_set_obj_static, artSetObjStaticFromCode, RETURN_IF_EAX_ZERO
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1090b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruONE_ARG_REF_DOWNCALL art_quick_get32_static, artGet32StaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1091b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruONE_ARG_REF_DOWNCALL art_quick_get64_static, artGet64StaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruONE_ARG_REF_DOWNCALL art_quick_get_obj_static, artGetObjStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1093b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1094b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// This is singled out as the argument order is different.
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDEFINE_FUNCTION art_quick_set64_static
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsi, %rdx                    // pass new_val
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl 8(%rsp), %esi                 // pass referrer
1098b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    SETUP_REF_ONLY_CALLEE_SAVE_FRAME
1099b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                       // field_idx is in rdi
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_SELF_OFFSET, %rcx  // pass Thread::Current()
1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsp, %r8                     // pass SP
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call SYMBOL(artSet64StaticFromCode)  // (field_idx, referrer, new_val, Thread*, SP)
1103b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_IF_EAX_ZERO                 // return or deliver exception
1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_FUNCTION art_quick_set64_static
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDEFINE_FUNCTION art_quick_proxy_invoke_handler
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Save callee and GPR args, mixed together to agree with core spills bitmap of ref. and args
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // callee save frame.
1111b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    PUSH r15  // Callee save.
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r14  // Callee save.
1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r13  // Callee save.
1114b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    PUSH r12  // Callee save.
1115b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    PUSH r9   // Quick arg 5.
1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r8   // Quick arg 4.
1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rsi  // Quick arg 1.
1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rbp  // Callee save.
1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rbx  // Callee save.
1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rdx  // Quick arg 2.
1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rcx  // Quick arg 3.
1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Create space for FPR args and create 2 slots, 1 of padding and 1 for the ArtMethod*.
1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    subq LITERAL(80 + 4*8), %rsp
1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CFI_ADJUST_CFA_OFFSET(80 + 4*8)
1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Save FPRs.
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm0, 16(%rsp)
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm1, 24(%rsp)
1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm2, 32(%rsp)
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm3, 40(%rsp)
1130b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    movq %xmm4, 48(%rsp)
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm5, 56(%rsp)
1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm6, 64(%rsp)
1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm7, 72(%rsp)
1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm12, 80(%rsp)
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm13, 88(%rsp)
1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm14, 96(%rsp)
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm15, 104(%rsp)
1138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Store proxy method to bottom of stack.
1139b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    movq %rdi, 0(%rsp)
1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_SELF_OFFSET, %rdx  // Pass Thread::Current().
1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rsp, %rcx                    // Pass SP.
1142b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    call SYMBOL(artQuickProxyInvokeHandler) // (proxy method, receiver, Thread*, SP)
1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rax, %xmm0                   // Copy return value in case of float returns.
1144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    addq LITERAL(168 + 4*8), %rsp            // Pop arguments.
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CFI_ADJUST_CFA_OFFSET(-168 - 4*8)
1146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_OR_DELIVER_PENDING_EXCEPTION
1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_FUNCTION art_quick_proxy_invoke_handler
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Called to resolve an imt conflict.
1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * rax is a hidden argument that holds the target method's dex method index.
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDEFINE_FUNCTION art_quick_imt_conflict_trampoline
1154b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#if defined(__APPLE__)
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int3
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int3
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl 8(%rsp), %edi            // load caller Method*
1159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl METHOD_DEX_CACHE_METHODS_OFFSET(%rdi), %edi  // load dex_cache_resolved_methods
1160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movl OBJECT_ARRAY_DATA_OFFSET(%rdi, %rax, 4), %edi  // load the target method
1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jmp art_quick_invoke_interface_trampoline
1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif  // __APPLE__
1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_FUNCTION art_quick_imt_conflict_trampoline
1164b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDEFINE_FUNCTION art_quick_resolution_trampoline
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %gs:THREAD_SELF_OFFSET, %rdx
116850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    movq %rsp, %rcx
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call SYMBOL(artQuickResolutionTrampoline) // (called, receiver, Thread*, SP)
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rax, %r10               // Remember returned code pointer in R10.
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq (%rsp), %rdi             // Load called method into RDI.
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    testq %r10, %r10              // If code pointer is NULL goto deliver pending exception.
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jz 1f
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jmp *%r10                     // Tail call into method.
1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru1:
1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DELIVER_PENDING_EXCEPTION
1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruEND_FUNCTION art_quick_resolution_trampoline
1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Generic JNI frame layout:
1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * #-------------------#
1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * |                   |
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | caller method...  |
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * #-------------------#    <--- SP on entry
1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *          |
1188b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *          V
1189b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * #-------------------#
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | caller method...  |
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * #-------------------#
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | Return            |
1194b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * | R15               |    callee save
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | R14               |    callee save
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | R13               |    callee save
1197b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * | R12               |    callee save
1198b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * | R9                |    arg5
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | R8                |    arg4
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | RSI/R6            |    arg1
1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | RBP/R5            |    callee save
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | RBX/R3            |    callee save
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | RDX/R2            |    arg2
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | RCX/R1            |    arg3
1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | XMM7              |    float arg 8
1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | XMM6              |    float arg 7
1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | XMM5              |    float arg 6
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | XMM4              |    float arg 5
1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | XMM3              |    float arg 4
1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | XMM2              |    float arg 3
1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | XMM1              |    float arg 2
1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | XMM0              |    float arg 1
1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | Padding           |
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | RDI/Method*       |  <- sp
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * #-------------------#
1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | Scratch Alloca    |    5K scratch space
1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * #---------#---------#
1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * |         | sp*     |
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | Tramp.  #---------#
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | args    | thread  |
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | Tramp.  #---------#
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * |         | method  |
1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * #-------------------#    <--- SP on artQuickGenericJniTrampoline
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *           |
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *           v              artQuickGenericJniTrampoline
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * #-------------------#
1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | caller method...  |
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * #-------------------#
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | Return            |
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | Callee-Save Data  |
1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * #-------------------#
1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | handle scope      |
1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * #-------------------#
1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | Method*           |    <--- (1)
1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * #-------------------#
1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | local ref cookie  | // 4B
1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | handle scope size | // 4B   TODO: roll into call stack alignment?
1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * #-------------------#
1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | JNI Call Stack    |
1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * #-------------------#    <--- SP on native call
1243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * |                   |
1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | Stack for Regs    |    The trampoline assembly will pop these values
1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * |                   |    into registers for native call
1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * #-------------------#
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | Native code ptr   |
1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * #-------------------#
1249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | Free scratch      |
1250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * #-------------------#
1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * | Ptr to (1)        |    <--- RSP
1252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * #-------------------#
1253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
1255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Called to do a generic JNI down-call
1256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
1257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDEFINE_FUNCTION_NO_HIDE art_quick_generic_jni_trampoline
1258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Save callee and GPR args, mixed together to agree with core spills bitmap.
1259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r15  // Callee save.
1260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r14  // Callee save.
1261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r13  // Callee save.
1262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r12  // Callee save.
1263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r9   // Quick arg 5.
1264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH r8   // Quick arg 4.
1265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rsi  // Quick arg 1.
1266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rbp  // Callee save.
1267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rbx  // Callee save.
1268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rdx  // Quick arg 2.
1269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PUSH rcx  // Quick arg 3.
1270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Create space for FPR args and create 2 slots, 1 of padding and 1 for the ArtMethod*.
1271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    subq LITERAL(80 + 4*8), %rsp
1272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CFI_ADJUST_CFA_OFFSET(80 + 4*8)
1273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Save FPRs.
1274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm0, 16(%rsp)
1275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm1, 24(%rsp)
1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm2, 32(%rsp)
1277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm3, 40(%rsp)
1278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm4, 48(%rsp)
1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm5, 56(%rsp)
1280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm6, 64(%rsp)
1281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm7, 72(%rsp)
1282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm12, 80(%rsp)
1283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm13, 88(%rsp)
1284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm14, 96(%rsp)
1285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %xmm15, 104(%rsp)
1286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    movq %rdi, 0(%rsp)              // Store native ArtMethod* to bottom of stack.
128727f654740f2a26ad62a5c155af9199af9e69b889claireho    movq %rsp, %rbp                 // save SP at (old) callee-save frame
128827f654740f2a26ad62a5c155af9199af9e69b889claireho    CFI_DEF_CFA_REGISTER(rbp)
128927f654740f2a26ad62a5c155af9199af9e69b889claireho    //
129027f654740f2a26ad62a5c155af9199af9e69b889claireho    // reserve a lot of space
129127f654740f2a26ad62a5c155af9199af9e69b889claireho    //
129227f654740f2a26ad62a5c155af9199af9e69b889claireho    //      4    local state ref
129327f654740f2a26ad62a5c155af9199af9e69b889claireho    //      4    padding
129427f654740f2a26ad62a5c155af9199af9e69b889claireho    //   4196    4k scratch space, enough for 2x 256 8-byte parameters (TODO: handle scope overhead?)
129559d709d503bab6e2b61931737e662dd293b40578ccornelius    //     16    handle scope member fields ?
129659d709d503bab6e2b61931737e662dd293b40578ccornelius    // +  112    14x 8-byte stack-2-register space
129727f654740f2a26ad62a5c155af9199af9e69b889claireho    // ------
129827f654740f2a26ad62a5c155af9199af9e69b889claireho    //   4332
129927f654740f2a26ad62a5c155af9199af9e69b889claireho    // 16-byte aligned: 4336
130027f654740f2a26ad62a5c155af9199af9e69b889claireho    // Note: 14x8 = 7*16, so the stack stays aligned for the native call...
130127f654740f2a26ad62a5c155af9199af9e69b889claireho    //       Also means: the padding is somewhere in the middle
130227f654740f2a26ad62a5c155af9199af9e69b889claireho    //
130327f654740f2a26ad62a5c155af9199af9e69b889claireho    //
130427f654740f2a26ad62a5c155af9199af9e69b889claireho    // New test: use 5K and release
130527f654740f2a26ad62a5c155af9199af9e69b889claireho    // 5k = 5120
130627f654740f2a26ad62a5c155af9199af9e69b889claireho    subq LITERAL(5120), %rsp
130727f654740f2a26ad62a5c155af9199af9e69b889claireho    // prepare for artQuickGenericJniTrampoline call
130827f654740f2a26ad62a5c155af9199af9e69b889claireho    // (Thread*,  SP)
130927f654740f2a26ad62a5c155af9199af9e69b889claireho    //    rdi    rsi      <= C calling convention
131027f654740f2a26ad62a5c155af9199af9e69b889claireho    //  gs:...   rbp      <= where they are
131127f654740f2a26ad62a5c155af9199af9e69b889claireho    movq %gs:THREAD_SELF_OFFSET, %rdi
131227f654740f2a26ad62a5c155af9199af9e69b889claireho    movq %rbp, %rsi
131327f654740f2a26ad62a5c155af9199af9e69b889claireho    call SYMBOL(artQuickGenericJniTrampoline)  // (Thread*, sp)
1314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1315    // The C call will have registered the complete save-frame on success.
1316    // The result of the call is:
1317    // %rax: pointer to native code, 0 on error.
1318    // %rdx: pointer to the bottom of the used area of the alloca, can restore stack till there.
1319
1320    // Check for error = 0.
1321    test %rax, %rax
1322    jz .Lentry_error
1323
1324    // Release part of the alloca.
1325    movq %rdx, %rsp
1326
1327    // pop from the register-passing alloca region
1328    // what's the right layout?
1329    popq %rdi
1330    popq %rsi
1331    popq %rdx
1332    popq %rcx
1333    popq %r8
1334    popq %r9
1335    // TODO: skip floating point if unused, some flag.
1336    movq 0(%rsp), %xmm0
1337    movq 8(%rsp), %xmm1
1338    movq 16(%rsp), %xmm2
1339    movq 24(%rsp), %xmm3
1340    movq 32(%rsp), %xmm4
1341    movq 40(%rsp), %xmm5
1342    movq 48(%rsp), %xmm6
1343    movq 56(%rsp), %xmm7
1344    addq LITERAL(64), %rsp          // floating-point done
1345
1346    // native call
1347    call *%rax
1348
1349    // result sign extension is handled in C code
1350    // prepare for artQuickGenericJniEndTrampoline call
1351    // (Thread*,  result, result_f)
1352    //   rdi      rsi   rdx       <= C calling convention
1353    //  gs:...    rax   xmm0      <= where they are
1354    movq %gs:THREAD_SELF_OFFSET, %rdi
1355    movq %rax, %rsi
1356    movq %xmm0, %rdx
1357    call SYMBOL(artQuickGenericJniEndTrampoline)
1358
1359    // Tear down the alloca.
1360    movq %rbp, %rsp
1361    CFI_DEF_CFA_REGISTER(rsp)
1362
1363    // Pending exceptions possible.
1364    // TODO: use cmpq, needs direct encoding because of gas bug
1365    movq %gs:THREAD_EXCEPTION_OFFSET, %rcx
1366    test %rcx, %rcx
1367    jnz .Lexception_in_native
1368
1369    // Tear down the callee-save frame.
1370    // Load FPRs.
1371    // movq %xmm0, 16(%rsp)         // doesn't make sense!!!
1372    movq 24(%rsp), %xmm1            // neither does this!!!
1373    movq 32(%rsp), %xmm2
1374    movq 40(%rsp), %xmm3
1375    movq 48(%rsp), %xmm4
1376    movq 56(%rsp), %xmm5
1377    movq 64(%rsp), %xmm6
1378    movq 72(%rsp), %xmm7
1379    movq 80(%rsp), %xmm12
1380    movq 88(%rsp), %xmm13
1381    movq 96(%rsp), %xmm14
1382    movq 104(%rsp), %xmm15
1383    // was 80 bytes
1384    addq LITERAL(80 + 4*8), %rsp
1385    CFI_ADJUST_CFA_OFFSET(-80 - 4*8)
1386    // Save callee and GPR args, mixed together to agree with core spills bitmap.
1387    POP rcx  // Arg.
1388    POP rdx  // Arg.
1389    POP rbx  // Callee save.
1390    POP rbp  // Callee save.
1391    POP rsi  // Arg.
1392    POP r8   // Arg.
1393    POP r9   // Arg.
1394    POP r12  // Callee save.
1395    POP r13  // Callee save.
1396    POP r14  // Callee save.
1397    POP r15  // Callee save.
1398    // store into fpr, for when it's a fpr return...
1399    movq %rax, %xmm0
1400    ret
1401.Lentry_error:
1402    movq %rbp, %rsp
1403    CFI_DEF_CFA_REGISTER(rsp)
1404.Lexception_in_native:
1405    // TODO: the handle scope contains the this pointer which is used by the debugger for exception
1406    //       delivery.
1407    movq %xmm0, 16(%rsp)         // doesn't make sense!!!
1408    movq 24(%rsp), %xmm1            // neither does this!!!
1409    movq 32(%rsp), %xmm2
1410    movq 40(%rsp), %xmm3
1411    movq 48(%rsp), %xmm4
1412    movq 56(%rsp), %xmm5
1413    movq 64(%rsp), %xmm6
1414    movq 72(%rsp), %xmm7
1415    movq 80(%rsp), %xmm12
1416    movq 88(%rsp), %xmm13
1417    movq 96(%rsp), %xmm14
1418    movq 104(%rsp), %xmm15
1419    // was 80 + 32 bytes
1420    addq LITERAL(80 + 4*8), %rsp
1421    CFI_ADJUST_CFA_OFFSET(-80 - 4*8)
1422    // Save callee and GPR args, mixed together to agree with core spills bitmap.
1423    POP rcx  // Arg.
1424    POP rdx  // Arg.
1425    POP rbx  // Callee save.
1426    POP rbp  // Callee save.
1427    POP rsi  // Arg.
1428    POP r8   // Arg.
1429    POP r9   // Arg.
1430    POP r12  // Callee save.
1431    POP r13  // Callee save.
1432    POP r14  // Callee save.
1433    POP r15  // Callee save.
1434
1435    DELIVER_PENDING_EXCEPTION
1436END_FUNCTION art_quick_generic_jni_trampoline
1437
1438    /*
1439     * Called to bridge from the quick to interpreter ABI. On entry the arguments match those
1440     * of a quick call:
1441     * RDI = method being called / to bridge to.
1442     * RSI, RDX, RCX, R8, R9 are arguments to that method.
1443     */
1444DEFINE_FUNCTION_NO_HIDE art_quick_to_interpreter_bridge
1445    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME   // Set up frame and save arguments.
1446    movq %gs:THREAD_SELF_OFFSET, %rsi      // RSI := Thread::Current()
1447    movq %rsp, %rdx                        // RDX := sp
1448    call SYMBOL(artQuickToInterpreterBridge)  // (method, Thread*, SP)
1449    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME  // TODO: no need to restore arguments in this case.
1450    movq %rax, %xmm0                   // Place return value also into floating point return value.
1451    RETURN_OR_DELIVER_PENDING_EXCEPTION    // return or deliver exception
1452END_FUNCTION art_quick_to_interpreter_bridge
1453
1454    /*
1455     * Routine that intercepts method calls and returns.
1456     */
1457DEFINE_FUNCTION art_quick_instrumentation_entry
1458#if defined(__APPLE__)
1459    int3
1460    int3
1461#else
1462    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
1463
1464    movq %rdi, %r12               // Preserve method pointer in a callee-save.
1465
1466    movq %gs:THREAD_SELF_OFFSET, %rdx   // Pass thread.
1467    movq %rsp, %rcx                     // Pass SP.
1468    movq FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE-8(%rsp), %r8   // Pass return PC.
1469
1470    call SYMBOL(artInstrumentationMethodEntryFromCode) // (Method*, Object*, Thread*, SP, LR)
1471
1472                                  // %rax = result of call.
1473    movq %r12, %rdi               // Reload method pointer.
1474
1475    leaq art_quick_instrumentation_exit(%rip), %r12   // Set up return through instrumentation
1476    movq %r12, FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE-8(%rsp) // exit.
1477
1478    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
1479
1480    jmp *%rax                     // Tail call to intended method.
1481#endif  // __APPLE__
1482END_FUNCTION art_quick_instrumentation_entry
1483
1484DEFINE_FUNCTION art_quick_instrumentation_exit
1485    pushq LITERAL(0)          // Push a fake return PC as there will be none on the stack.
1486
1487    SETUP_REF_ONLY_CALLEE_SAVE_FRAME
1488
1489    // We need to save rax and xmm0. We could use a callee-save from SETUP_REF_ONLY, but then
1490    // we would need to fully restore it. As there are a good number of callee-save registers, it
1491    // seems easier to have an extra small stack area. But this should be revisited.
1492
1493    movq  %rsp, %rsi                          // Pass SP.
1494
1495    PUSH rax                  // Save integer result.
1496    subq LITERAL(8), %rsp     // Save floating-point result.
1497    CFI_ADJUST_CFA_OFFSET(8)
1498    movq %xmm0, (%rsp)
1499
1500    movq  %gs:THREAD_SELF_OFFSET, %rdi        // Pass Thread.
1501    movq  %rax, %rdx                          // Pass integer result.
1502    movq  %xmm0, %rcx                         // Pass floating-point result.
1503
1504    call SYMBOL(artInstrumentationMethodExitFromCode)   // (Thread*, SP, gpr_res, fpr_res)
1505
1506    movq  %rax, %rdi          // Store return PC
1507    movq  %rdx, %rsi          // Store second return PC in hidden arg.
1508
1509    movq (%rsp), %xmm0        // Restore floating-point result.
1510    addq LITERAL(8), %rsp
1511    CFI_ADJUST_CFA_OFFSET(-8)
1512    POP rax                   // Restore integer result.
1513
1514    addq LITERAL(FRAME_SIZE_REFS_ONLY_CALLEE_SAVE), %rsp   // Drop save frame and fake return pc.
1515
1516    jmp   *%rdi               // Return.
1517END_FUNCTION art_quick_instrumentation_exit
1518
1519    /*
1520     * Instrumentation has requested that we deoptimize into the interpreter. The deoptimization
1521     * will long jump to the upcall with a special exception of -1.
1522     */
1523DEFINE_FUNCTION art_quick_deoptimize
1524    pushq %rsi                     // Fake that we were called. Use hidden arg.
1525    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
1526                                   // Stack should be aligned now.
1527    movq %rsp, %rsi                           // Pass SP.
1528    movq %gs:THREAD_SELF_OFFSET, %rdi         // Pass Thread.
1529    call SYMBOL(artDeoptimize) // artDeoptimize(Thread*, SP)
1530    int3                           // Unreachable.
1531END_FUNCTION art_quick_deoptimize
1532
1533
1534    /*
1535     * String's compareTo.
1536     *
1537     * On entry:
1538     *    rdi:   this string object (known non-null)
1539     *    rsi:   comp string object (known non-null)
1540     */
1541DEFINE_FUNCTION art_quick_string_compareto
1542    movl STRING_COUNT_OFFSET(%edi), %r8d
1543    movl STRING_COUNT_OFFSET(%esi), %r9d
1544    movl STRING_VALUE_OFFSET(%edi), %r10d
1545    movl STRING_VALUE_OFFSET(%esi), %r11d
1546    movl STRING_OFFSET_OFFSET(%edi), %eax
1547    movl STRING_OFFSET_OFFSET(%esi), %ecx
1548    /* Build pointers to the start of string data */
1549    leal STRING_DATA_OFFSET(%r10d, %eax, 2), %esi
1550    leal STRING_DATA_OFFSET(%r11d, %ecx, 2), %edi
1551    /* Calculate min length and count diff */
1552    movl  %r8d, %ecx
1553    movl  %r8d, %eax
1554    subl  %r9d, %eax
1555    cmovg %r9d, %ecx
1556    /*
1557     * At this point we have:
1558     *   eax: value to return if first part of strings are equal
1559     *   ecx: minimum among the lengths of the two strings
1560     *   esi: pointer to this string data
1561     *   edi: pointer to comp string data
1562     */
1563    jecxz .Lkeep_length
1564    repe cmpsw                    // find nonmatching chars in [%esi] and [%edi], up to length %ecx
1565    jne .Lnot_equal
1566.Lkeep_length:
1567    ret
1568    .balign 16
1569.Lnot_equal:
1570    movzwl  -2(%esi), %eax        // get last compared char from this string
1571    movzwl  -2(%edi), %ecx        // get last compared char from comp string
1572    subl  %ecx, %eax              // return the difference
1573    ret
1574END_FUNCTION art_quick_string_compareto
1575
1576UNIMPLEMENTED art_quick_memcmp16
1577
1578DEFINE_FUNCTION art_quick_assignable_from_code
1579    SETUP_FP_CALLEE_SAVE_FRAME
1580    call SYMBOL(artIsAssignableFromCode)       // (const mirror::Class*, const mirror::Class*)
1581    RESTORE_FP_CALLEE_SAVE_FRAME
1582    ret
1583END_FUNCTION art_quick_assignable_from_code
1584
1585
1586// Return from a nested signal:
1587// Entry:
1588//  rdi: address of jmp_buf in TLS
1589
1590DEFINE_FUNCTION art_nested_signal_return
1591                                    // first arg to longjmp is already in correct register
1592    movq LITERAL(1), %rsi           // second arg to longjmp (1)
1593    call PLT_SYMBOL(longjmp)
1594    int3                            // won't get here
1595END_FUNCTION art_nested_signal_return
1596
1597
1598