1b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith/*
2b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * Copyright (C) 2014 The Android Open Source Project
3b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *
4b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * Licensed under the Apache License, Version 2.0 (the "License");
5b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * you may not use this file except in compliance with the License.
6b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * You may obtain a copy of the License at
7b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *
8b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *      http://www.apache.org/licenses/LICENSE-2.0
9b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *
10b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * Unless required by applicable law or agreed to in writing, software
11b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * distributed under the License is distributed on an "AS IS" BASIS,
12b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * See the License for the specific language governing permissions and
14b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * limitations under the License.
15b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith */
16b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
17b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith#include "asm_support_arm64.S"
18b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
19b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith#include "arch/quick_alloc_entrypoints.S"
20b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
21b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
22b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    /*
23b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * Macro that sets up the callee save frame to conform with
24b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * Runtime::CreateCalleeSaveMethod(kSaveAll)
25b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     */
26b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.macro SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
27b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    adrp xIP0, :got:_ZN3art7Runtime9instance_E
28b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldr xIP0, [xIP0, #:got_lo12:_ZN3art7Runtime9instance_E]
29b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
30b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Our registers aren't intermixed - just spill in order.
31b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldr xIP0, [xIP0]  // xIP0 = & (art::Runtime * art::Runtime.instance_) .
32b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
33b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // xIP0 = (ArtMethod*) Runtime.instance_.callee_save_methods[kRefAndArgs]  .
34ab088118d33caafb00815ab72ac0fd7374169f64Hiroshi Yamauchi    THIS_LOAD_REQUIRES_READ_BARRIER
35b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldr xIP0, [xIP0, RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET ]
36b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
37b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    sub sp, sp, #176
38b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_adjust_cfa_offset 176
39b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
405c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe    // Ugly compile-time check, but we only have the preprocessor.
41b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVE != 176)
425c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe#error "SAVE_ALL_CALLEE_SAVE_FRAME(ARM64) size not as expected."
435c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe#endif
445c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
45b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // FP callee-saves
46b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp d8, d9,   [sp, #8]
47b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp d10, d11, [sp, #24]
48b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp d12, d13, [sp, #40]
49b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp d14, d15, [sp, #56]
50b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
51b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // Reserved registers
52b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp xSELF, xSUSPEND, [sp, #72]
53b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x18, 72
54b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x19, 80
5503906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
56b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // callee-saves
57b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x20, x21, [sp, #88]
58b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x20, 88
59b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x21, 96
6003906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
61b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x22, x23, [sp, #104]
62b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x22, 104
63b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x23, 112
6403906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
65b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x24, x25, [sp, #120]
66b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x24, 120
67b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x25, 128
6803906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
69b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x26, x27, [sp, #136]
70b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x26, 136
71b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x27, 144
7203906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
73b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x28, x29, [sp, #152]
74b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x28, 152
75b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x29, 160
76b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
77b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    str xLR, [sp, #168]
78b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x30, 168
79b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
80b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Loads appropriate callee-save-method
81b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    str xIP0, [sp]    // Store ArtMethod* Runtime::callee_save_methods_[kRefsAndArgs]
82b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.endm
83b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
84b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    /*
85b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * Macro that sets up the callee save frame to conform with
86b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * Runtime::CreateCalleeSaveMethod(kRefsOnly).
87b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     */
88b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.macro SETUP_REF_ONLY_CALLEE_SAVE_FRAME
89b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    adrp xIP0, :got:_ZN3art7Runtime9instance_E
90b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldr xIP0, [xIP0, #:got_lo12:_ZN3art7Runtime9instance_E]
915c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
925c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe    // Our registers aren't intermixed - just spill in order.
93b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldr xIP0, [xIP0]  // xIP0 = & (art::Runtime * art::Runtime.instance_) .
945c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
95b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // xIP0 = (ArtMethod*) Runtime.instance_.callee_save_methods[kRefAndArgs]  .
96ab088118d33caafb00815ab72ac0fd7374169f64Hiroshi Yamauchi    THIS_LOAD_REQUIRES_READ_BARRIER
97b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldr xIP0, [xIP0, RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET ]
985c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
99b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    sub sp, sp, #96
100b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_adjust_cfa_offset 96
1015c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
1025c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe    // Ugly compile-time check, but we only have the preprocessor.
103b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu#if (FRAME_SIZE_REFS_ONLY_CALLEE_SAVE != 96)
1045c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe#error "REFS_ONLY_CALLEE_SAVE_FRAME(ARM64) size not as expected."
1055c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe#endif
1065c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
107b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // Callee-saves
108b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x20, x21,  [sp, #8]
109b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x20, 8
110b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x21, 16
1115c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
112b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x22, x23, [sp, #24]
113b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x22, 24
114b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x23, 32
1155c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
116b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x24, x25, [sp, #40]
117b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x24, 40
118b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x25, 48
1195c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
120b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x26, x27, [sp, #56]
121b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x26, 56
122b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x27, 64
1235c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
124b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x28, x29, [sp, #72]
125b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x28, 72
126b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x29, 80
1275c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
128b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // LR
129b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    str xLR, [sp, #88]
130b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x30, 88
1315c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
132b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // Save xSELF to xETR.
133b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    mov xETR, xSELF
1345c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
1355c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe    // Loads appropriate callee-save-method
136b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    str xIP0, [sp]    // Store ArtMethod* Runtime::callee_save_methods_[kRefsAndArgs]
137b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.endm
138b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
139b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu// TODO: Probably no need to restore registers preserved by aapcs64.
140b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
141b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // Restore xSELF.
142b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    mov xSELF, xETR
14300c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe
144b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // Callee-saves
145b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldp x20, x21,  [sp, #8]
14600c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    .cfi_restore x20
14700c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    .cfi_restore x21
14800c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe
149b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldp x22, x23, [sp, #24]
15000c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    .cfi_restore x22
15100c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    .cfi_restore x23
15200c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe
153b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldp x24, x25, [sp, #40]
15400c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    .cfi_restore x24
15500c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    .cfi_restore x25
15600c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe
157b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldp x26, x27, [sp, #56]
15800c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    .cfi_restore x26
15900c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    .cfi_restore x27
16000c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe
161b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldp x28, x29, [sp, #72]
16200c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    .cfi_restore x28
16300c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    .cfi_restore x29
16400c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe
165b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // LR
166b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldr xLR, [sp, #88]
16700c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    .cfi_restore x30
16800c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe
169b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    add sp, sp, #96
170b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_adjust_cfa_offset -96
171b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.endm
172b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
173d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe.macro POP_REF_ONLY_CALLEE_SAVE_FRAME
174b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // Restore xSELF as it might be scratched.
175b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    mov xSELF, xETR
176b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // ETR
177b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldr xETR, [sp, #16]
178b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_restore x21
179b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu
180b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    add sp, sp, #96
181b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_adjust_cfa_offset -96
182d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe.endm
183d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe
184b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
18548241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
18648241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    ret
187b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.endm
188b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
189b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
190b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.macro SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
191b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    sub sp, sp, #224
192b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_adjust_cfa_offset 224
193b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1945c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe    // Ugly compile-time check, but we only have the preprocessor.
195b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu#if (FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE != 224)
1965c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe#error "REFS_AND_ARGS_CALLEE_SAVE_FRAME(ARM64) size not as expected."
1975c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe#endif
1985c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
199b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // FP args
200b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp d0, d1, [sp, #16]
201b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp d2, d3, [sp, #32]
202b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp d4, d5, [sp, #48]
203b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp d6, d7, [sp, #64]
204b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu
205b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // args and x20(callee-save)
206b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x1,  x2, [sp, #80]
207b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x1, 80
208b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x2, 88
209b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu
210b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x3,  x4, [sp, #96]
211b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x3, 96
212b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x4, 104
213b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu
214b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x5,  x6, [sp, #112]
215b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x5, 112
216b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x6, 120
217b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu
218b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x7, x20, [sp, #128]
219b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x7, 128
220b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x20, 136
221b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu
222b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // Callee-saves.
223b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x21, x22, [sp, #144]
224b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x21, 144
225b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x22, 152
226b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu
227b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x23, x24, [sp, #160]
228b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x23, 160
229b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x24, 168
230b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu
231b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x25, x26, [sp, #176]
232b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x25, 176
233b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x26, 184
234b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu
235b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x27, x28, [sp, #192]
236b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x27, 192
237b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x28, 200
238b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu
239b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // x29(callee-save) and LR
240b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x29, xLR, [sp, #208]
241b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x29, 208
242b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_rel_offset x30, 216
243b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu
244b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // Save xSELF to xETR.
245b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    mov xETR, xSELF
246b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.endm
247b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
248b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    /*
249b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * Macro that sets up the callee save frame to conform with
250b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * Runtime::CreateCalleeSaveMethod(kRefsAndArgs).
251b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     *
252b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * TODO This is probably too conservative - saving FP & LR.
253b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     */
254b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.macro SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
255b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    adrp xIP0, :got:_ZN3art7Runtime9instance_E
256b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldr xIP0, [xIP0, #:got_lo12:_ZN3art7Runtime9instance_E]
257b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
258b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Our registers aren't intermixed - just spill in order.
259b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldr xIP0, [xIP0]  // xIP0 = & (art::Runtime * art::Runtime.instance_) .
260b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
261b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // xIP0 = (ArtMethod*) Runtime.instance_.callee_save_methods[kRefAndArgs]  .
262ab088118d33caafb00815ab72ac0fd7374169f64Hiroshi Yamauchi    THIS_LOAD_REQUIRES_READ_BARRIER
263b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldr xIP0, [xIP0, RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET ]
264b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
265b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
266b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
267b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    str xIP0, [sp]    // Store ArtMethod* Runtime::callee_save_methods_[kRefsAndArgs]
268b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.endm
269b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
270b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu// TODO: Probably no need to restore registers preserved by aapcs64.
271b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.macro RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
272b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // Restore xSELF.
273b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    mov xSELF, xETR
274b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
275b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // FP args
276b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldp d0, d1, [sp, #16]
277b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldp d2, d3, [sp, #32]
278b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldp d4, d5, [sp, #48]
279b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldp d6, d7, [sp, #64]
280b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu
281b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // args and x20(callee-save)
282b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldp x1,  x2, [sp, #80]
28303906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x1
28403906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x2
28503906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
286b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldp x3,  x4, [sp, #96]
28703906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x3
28803906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x4
28903906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
290b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldp x5,  x6, [sp, #112]
29103906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x5
29203906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x6
29303906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
294b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldp x7, x20, [sp, #128]
29503906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x7
29603906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x20
29703906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
298b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // Callee-saves.
299b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldp x21, x22, [sp, #144]
30003906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x21
30103906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x22
30203906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
303b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldp x23, x24, [sp, #160]
30403906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x23
30503906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x24
30603906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
307b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldp x25, x26, [sp, #176]
30803906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x25
30903906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x26
31003906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
311b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldp x27, x28, [sp, #192]
31203906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x27
31303906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x28
31403906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
315b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // x29(callee-save) and LR
316b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldp x29, xLR, [sp, #208]
31703906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x29
31803906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x30
319b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
320b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    add sp, sp, #224
321b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    .cfi_adjust_cfa_offset -224
322b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.endm
323b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
324b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.macro RETURN_IF_RESULT_IS_ZERO
32500c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    cbnz x0, 1f                // result non-zero branch over
32600c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    ret                        // return
32700c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe1:
328b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.endm
329b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
330b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.macro RETURN_IF_RESULT_IS_NON_ZERO
33100c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    cbz x0, 1f                 // result zero branch over
33200c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    ret                        // return
33300c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe1:
334b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.endm
335b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
336b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    /*
337b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * Macro that set calls through to artDeliverPendingExceptionFromCode, where the pending
338b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * exception is Thread::Current()->exception_
339b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     */
340b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.macro DELIVER_PENDING_EXCEPTION
341b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
342b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    mov x0, xSELF
343b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    mov x1, sp
344b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
345b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Point of no return.
346b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    b artDeliverPendingExceptionFromCode  // artDeliverPendingExceptionFromCode(Thread*, SP)
347b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    brk 0  // Unreached
348b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.endm
349b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
3506e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe.macro RETURN_OR_DELIVER_PENDING_EXCEPTION_REG reg
3516e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    ldr \reg, [xSELF, # THREAD_EXCEPTION_OFFSET]   // Get exception field.
3526e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    cbnz \reg, 1f
353b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ret
354b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith1:
355b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    DELIVER_PENDING_EXCEPTION
356b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.endm
357b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
3586e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe.macro RETURN_OR_DELIVER_PENDING_EXCEPTION
359b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    RETURN_OR_DELIVER_PENDING_EXCEPTION_REG xIP0
3606e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe.endm
3616e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe
3626e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe// Same as above with x1. This is helpful in stubs that want to avoid clobbering another register.
3636e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe.macro RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
3646e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    RETURN_OR_DELIVER_PENDING_EXCEPTION_REG x1
3656e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe.endm
3666e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe
3676e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe.macro RETURN_IF_W0_IS_ZERO_OR_DELIVER
3686e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    cbnz w0, 1f                // result non-zero branch over
3696e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    ret                        // return
3706e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe1:
3716e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    DELIVER_PENDING_EXCEPTION
3726e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe.endm
3736e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe
374b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.macro NO_ARG_RUNTIME_EXCEPTION c_name, cxx_name
375b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    .extern \cxx_name
376b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithENTRY \c_name
3775c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
378b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    mov x0, xSELF                     // pass Thread::Current
3795c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe    mov x1, sp                        // pass SP
3805c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe    b   \cxx_name                     // \cxx_name(Thread*, SP)
381b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithEND \c_name
382b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.endm
383b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
384b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.macro ONE_ARG_RUNTIME_EXCEPTION c_name, cxx_name
385b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    .extern \cxx_name
386b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithENTRY \c_name
38775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context.
388b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    mov x1, xSELF                     // pass Thread::Current.
38975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu    mov x2, sp                        // pass SP.
3905c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe    b   \cxx_name                     // \cxx_name(arg, Thread*, SP).
391b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    brk 0
392b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithEND \c_name
393b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.endm
394b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
395b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.macro TWO_ARG_RUNTIME_EXCEPTION c_name, cxx_name
396b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    .extern \cxx_name
397b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithENTRY \c_name
398b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
399b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    mov x2, xSELF                     // pass Thread::Current
4005c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe    mov x3, sp                        // pass SP
4015c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe    b   \cxx_name                     // \cxx_name(arg1, arg2, Thread*, SP)
402b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    brk 0
403b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithEND \c_name
404b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.endm
405b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
406b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    /*
407b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * Called by managed code, saves callee saves and then calls artThrowException
408b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * that will place a mock Method* at the bottom of the stack. Arg1 holds the exception.
409b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     */
410b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception, artDeliverExceptionFromCode
411b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
412b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    /*
413b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * Called by managed code to create and deliver a NullPointerException.
414b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     */
415b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithNO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
416b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
417b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    /*
418b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * Called by managed code to create and deliver an ArithmeticException.
419b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     */
420b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithNO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode
421b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
422b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    /*
423b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
424b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * index, arg2 holds limit.
425b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     */
426b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithTWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
427b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
428b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    /*
429b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * Called by managed code to create and deliver a StackOverflowError.
430b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     */
431b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithNO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow, artThrowStackOverflowFromCode
432b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
433b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    /*
434b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * Called by managed code to create and deliver a NoSuchMethodError.
435b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     */
436b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method, artThrowNoSuchMethodFromCode
437b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
438b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    /*
439b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * All generated callsites for interface invokes and invocation slow paths will load arguments
44051f763506c7bb34420242e88e1631550f94d6417Andreas Gampe     * as usual - except instead of loading arg0/x0 with the target Method*, arg0/x0 will contain
44151f763506c7bb34420242e88e1631550f94d6417Andreas Gampe     * the method_idx.  This wrapper will save arg1-arg3, load the caller's Method*, align the
442b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * stack and call the appropriate C helper.
44351f763506c7bb34420242e88e1631550f94d6417Andreas Gampe     * NOTE: "this" is first visible argument of the target, and so can be found in arg1/x1.
444b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     *
44551f763506c7bb34420242e88e1631550f94d6417Andreas Gampe     * The helper will attempt to locate the target and return a 128-bit result in x0/x1 consisting
446b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * of the target Method* in x0 and method->code_ in x1.
447b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     *
44851f763506c7bb34420242e88e1631550f94d6417Andreas Gampe     * If unsuccessful, the helper will return NULL/????. There will be a pending exception in the
449b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * thread and we branch to another stub to deliver it.
450b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     *
451b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * On success this wrapper will restore arguments and *jump* to the target, leaving the lr
452b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * pointing back to the original caller.
45351f763506c7bb34420242e88e1631550f94d6417Andreas Gampe     *
45451f763506c7bb34420242e88e1631550f94d6417Andreas Gampe     * Adapted from ARM32 code.
45551f763506c7bb34420242e88e1631550f94d6417Andreas Gampe     *
456b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu     * Clobbers xIP0.
457b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     */
458b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.macro INVOKE_TRAMPOLINE c_name, cxx_name
459b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    .extern \cxx_name
460b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithENTRY \c_name
46151f763506c7bb34420242e88e1631550f94d6417Andreas Gampe    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME  // save callee saves in case allocation triggers GC
46251f763506c7bb34420242e88e1631550f94d6417Andreas Gampe    // Helper signature is always
46351f763506c7bb34420242e88e1631550f94d6417Andreas Gampe    // (method_idx, *this_object, *caller_method, *self, sp)
46451f763506c7bb34420242e88e1631550f94d6417Andreas Gampe
46541c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov    ldr    w2, [sp, #FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE]  // pass caller Method*
46651f763506c7bb34420242e88e1631550f94d6417Andreas Gampe    mov    x3, xSELF                      // pass Thread::Current
46751f763506c7bb34420242e88e1631550f94d6417Andreas Gampe    mov    x4, sp
46851f763506c7bb34420242e88e1631550f94d6417Andreas Gampe    bl     \cxx_name                      // (method_idx, this, caller, Thread*, SP)
469b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    mov    xIP0, x1                       // save Method*->code_
47051f763506c7bb34420242e88e1631550f94d6417Andreas Gampe    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
47151f763506c7bb34420242e88e1631550f94d6417Andreas Gampe    cbz    x0, 1f                         // did we find the target? if not go to exception delivery
472b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    br     xIP0                           // tail call to target
47351f763506c7bb34420242e88e1631550f94d6417Andreas Gampe1:
47451f763506c7bb34420242e88e1631550f94d6417Andreas Gampe    DELIVER_PENDING_EXCEPTION
475b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithEND \c_name
476b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.endm
477b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
478b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithINVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline, artInvokeInterfaceTrampoline
479b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithINVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck
480b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
481b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithINVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck
482b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithINVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck
483b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithINVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
484b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithINVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
485b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
48603906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
48703906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe.macro INVOKE_STUB_CREATE_FRAME
48803906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
489b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng XuSAVE_SIZE=6*8   // x4, x5, xSUSPEND, SP, LR & FP saved.
490cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas GampeSAVE_SIZE_AND_METHOD=SAVE_SIZE+STACK_REFERENCE_SIZE
491cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe
49203906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
49348241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    mov x9, sp                             // Save stack pointer.
49403906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_register sp,x9
49503906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
49648241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    add x10, x2, # SAVE_SIZE_AND_METHOD    // calculate size of frame.
49748241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    sub x10, sp, x10                       // Calculate SP position - saves + ArtMethod* +  args
49848241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    and x10, x10, # ~0xf                   // Enforce 16 byte stack alignment.
49948241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    mov sp, x10                            // Set new SP.
50003906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
50148241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    sub x10, x9, #SAVE_SIZE                // Calculate new FP (later). Done here as we must move SP
50248241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    .cfi_def_cfa_register x10              // before this.
50303906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_adjust_cfa_offset SAVE_SIZE
50403906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
505b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    stp x9, xSUSPEND, [x10, #32]           // Save old stack pointer and xSUSPEND
50603906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_rel_offset sp, 32
507cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe    .cfi_rel_offset x19, 40
50803906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
50948241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    stp x4, x5, [x10, #16]                 // Save result and shorty addresses.
51003906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_rel_offset x4, 16
51103906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_rel_offset x5, 24
51203906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
51348241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    stp xFP, xLR, [x10]                    // Store LR & FP.
51403906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_rel_offset x29, 0
51503906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_rel_offset x30, 8
51603906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
51748241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    mov xFP, x10                           // Use xFP now, as it's callee-saved.
51803906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_def_cfa_register x29
51948241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    mov xSELF, x3                          // Move thread pointer into SELF register.
52048241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    mov wSUSPEND, #SUSPEND_CHECK_INTERVAL  // reset wSUSPEND to suspend check interval
52103906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
52203906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    // Copy arguments into stack frame.
52303906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    // Use simple copy routine for now.
52403906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    // 4 bytes per slot.
52503906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    // X1 - source address
52603906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    // W2 - args length
52703906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    // X9 - destination address.
52803906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    // W10 - temporary
529cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe    add x9, sp, #4                         // Destination address is bottom of stack + NULL.
53003906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
53103906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    // Use \@ to differentiate between macro invocations.
53203906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe.LcopyParams\@:
53303906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    cmp w2, #0
53403906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    beq .LendCopyParams\@
53503906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    sub w2, w2, #4      // Need 65536 bytes of range.
53603906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    ldr w10, [x1, x2]
53703906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    str w10, [x9, x2]
53803906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
53903906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    b .LcopyParams\@
54003906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
54103906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe.LendCopyParams\@:
54203906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
543cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe    // Store NULL into StackReference<Method>* at bottom of frame.
544cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe    str wzr, [sp]
54503906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
546cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe#if (STACK_REFERENCE_SIZE != 4)
547cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe#error "STACK_REFERENCE_SIZE(ARM64) size not as expected."
548cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe#endif
54903906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe.endm
55003906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
55103906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe.macro INVOKE_STUB_CALL_AND_RETURN
55203906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
55303906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    // load method-> METHOD_QUICK_CODE_OFFSET
554e832e64a7e82d7f72aedbd7d798fb929d458ee8fMathieu Chartier    ldr x9, [x0 , #METHOD_QUICK_CODE_OFFSET_64]
55503906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    // Branch to method.
55603906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    blr x9
55703906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
55803906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    // Restore return value address and shorty address.
55903906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    ldp x4,x5, [xFP, #16]
56003906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x4
56103906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x5
56203906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
56303906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    // Store result (w0/x0/s0/d0) appropriately, depending on resultType.
56403906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    ldrb w10, [x5]
56503906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
56603906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    // Don't set anything for a void type.
56703906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    cmp w10, #'V'
56803906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    beq .Lexit_art_quick_invoke_stub\@
56903906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
57003906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    cmp w10, #'D'
57103906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    bne .Lreturn_is_float\@
57203906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    str d0, [x4]
57303906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    b .Lexit_art_quick_invoke_stub\@
57403906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
57503906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe.Lreturn_is_float\@:
57603906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    cmp w10, #'F'
57703906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    bne .Lreturn_is_int\@
57803906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    str s0, [x4]
57903906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    b .Lexit_art_quick_invoke_stub\@
58003906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
58103906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    // Just store x0. Doesn't matter if it is 64 or 32 bits.
58203906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe.Lreturn_is_int\@:
58303906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    str x0, [x4]
58403906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
58503906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe.Lexit_art_quick_invoke_stub\@:
586b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldp x2, xSUSPEND, [xFP, #32]   // Restore stack pointer and xSUSPEND.
587cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe    .cfi_restore x19
58803906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    mov sp, x2
58903906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore sp
59003906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
591d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    ldp xFP, xLR, [xFP]    // Restore old frame pointer and link register.
59203906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x29
59303906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    .cfi_restore x30
59403906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
59503906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    ret
59603906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
59703906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe.endm
59803906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
59903906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
600b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith/*
601b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  extern"C" void art_quick_invoke_stub(ArtMethod *method,   x0
602b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *                                       uint32_t  *args,     x1
603b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *                                       uint32_t argsize,    w2
604b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *                                       Thread *self,        x3
605b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *                                       JValue *result,      x4
606b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *                                       char   *shorty);     x5
607b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  +----------------------+
608b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  |                      |
609b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  |  C/C++ frame         |
610b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  |       LR''           |
611b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  |       FP''           | <- SP'
612b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  +----------------------+
613b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  +----------------------+
614b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu *  |        x19           | <- Used as wSUSPEND, won't be restored by managed code.
615b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  |        SP'           |
616b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  |        X5            |
617b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  |        X4            |        Saved registers
618b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  |        LR'           |
619b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  |        FP'           | <- FP
620b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  +----------------------+
621b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  | uint32_t out[n-1]    |
622b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  |    :      :          |        Outs
623b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  | uint32_t out[0]      |
624cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe *  | StackRef<ArtMethod>  | <- SP  value=null
625b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  +----------------------+
626b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *
627b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * Outgoing registers:
628b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  x0    - Method*
629b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  x1-x7 - integer parameters.
630b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  d0-d7 - Floating point parameters.
631b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  xSELF = self
63248241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu *  wSUSPEND = suspend count
633b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  SP = & of ArtMethod*
634b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *  x1 = "this" pointer.
635b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *
636b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith */
637b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithENTRY art_quick_invoke_stub
638b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Spill registers as per AACPS64 calling convention.
63903906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    INVOKE_STUB_CREATE_FRAME
640b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
641b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Fill registers x/w1 to x/w7 and s/d0 to s/d7 with parameters.
642b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Parse the passed shorty to determine which register to load.
643b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Load addresses for routines that load WXSD registers.
644b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    adr  x11, .LstoreW2
645b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    adr  x12, .LstoreX2
646b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    adr  x13, .LstoreS0
647b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    adr  x14, .LstoreD0
648b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
649b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Initialize routine offsets to 0 for integers and floats.
650b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // x8 for integers, x15 for floating point.
651b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    mov x8, #0
652b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    mov x15, #0
653b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
654b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    add x10, x5, #1         // Load shorty address, plus one to skip return value.
655b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldr w1, [x9],#4         // Load "this" parameter, and increment arg pointer.
656b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
657b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Loop to fill registers.
658b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.LfillRegisters:
659b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldrb w17, [x10], #1       // Load next character in signature, and increment.
660b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    cbz w17, .LcallFunction   // Exit at end of signature. Shorty 0 terminated.
661b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
662b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    cmp  w17, #'F' // is this a float?
663b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    bne .LisDouble
664b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
665b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    cmp x15, # 8*12         // Skip this load if all registers full.
66603906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    beq .Ladvance4
667b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
668b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    add x17, x13, x15       // Calculate subroutine to jump to.
669b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    br  x17
670b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
671b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.LisDouble:
672b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    cmp w17, #'D'           // is this a double?
673b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    bne .LisLong
674b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
675b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    cmp x15, # 8*12         // Skip this load if all registers full.
67603906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    beq .Ladvance8
677b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
678b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    add x17, x14, x15       // Calculate subroutine to jump to.
679b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    br x17
680b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
681b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.LisLong:
682b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    cmp w17, #'J'           // is this a long?
683b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    bne .LisOther
684b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
6859de65ff3a9c49b91d80be292020f012f3d0a24efAndreas Gampe    cmp x8, # 6*12          // Skip this load if all registers full.
68603906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    beq .Ladvance8
687b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
688b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    add x17, x12, x8        // Calculate subroutine to jump to.
689b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    br x17
690b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
691b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.LisOther:                  // Everything else takes one vReg.
6929de65ff3a9c49b91d80be292020f012f3d0a24efAndreas Gampe    cmp x8, # 6*12          // Skip this load if all registers full.
69303906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    beq .Ladvance4
69403906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
695b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    add x17, x11, x8        // Calculate subroutine to jump to.
696b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    br x17
697b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
69803906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe.Ladvance4:
69903906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    add x9, x9, #4
70003906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    b .LfillRegisters
70103906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
70203906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe.Ladvance8:
70303906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    add x9, x9, #8
70403906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    b .LfillRegisters
70503906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
706b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith// Macro for loading a parameter into a register.
707b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith//  counter - the register with offset into these tables
708b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith//  size - the size of the register - 4 or 8 bytes.
709b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith//  register - the name of the register to be loaded.
710b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.macro LOADREG counter size register return
711b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldr \register , [x9], #\size
712b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    add \counter, \counter, 12
713b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    b \return
714b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.endm
715b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
716b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith// Store ints.
717b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.LstoreW2:
718b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 4 w2 .LfillRegisters
719b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 4 w3 .LfillRegisters
720b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 4 w4 .LfillRegisters
721b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 4 w5 .LfillRegisters
722b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 4 w6 .LfillRegisters
723b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 4 w7 .LfillRegisters
724b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
725b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith// Store longs.
726b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.LstoreX2:
727b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 8 x2 .LfillRegisters
728b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 8 x3 .LfillRegisters
729b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 8 x4 .LfillRegisters
730b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 8 x5 .LfillRegisters
731b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 8 x6 .LfillRegisters
732b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 8 x7 .LfillRegisters
733b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
734b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith// Store singles.
735b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.LstoreS0:
736b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 4 s0 .LfillRegisters
737b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 4 s1 .LfillRegisters
738b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 4 s2 .LfillRegisters
739b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 4 s3 .LfillRegisters
740b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 4 s4 .LfillRegisters
741b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 4 s5 .LfillRegisters
742b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 4 s6 .LfillRegisters
743b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 4 s7 .LfillRegisters
744b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
745b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith// Store doubles.
746b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.LstoreD0:
747b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 8 d0 .LfillRegisters
748b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 8 d1 .LfillRegisters
749b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 8 d2 .LfillRegisters
750b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 8 d3 .LfillRegisters
751b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 8 d4 .LfillRegisters
752b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 8 d5 .LfillRegisters
753b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 8 d6 .LfillRegisters
754b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 8 d7 .LfillRegisters
755b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
756b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
757b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.LcallFunction:
758b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
75903906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    INVOKE_STUB_CALL_AND_RETURN
760b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
761b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithEND art_quick_invoke_stub
762b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
763b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith/*  extern"C"
764b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *     void art_quick_invoke_static_stub(ArtMethod *method,   x0
765b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *                                       uint32_t  *args,     x1
766b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *                                       uint32_t argsize,    w2
767b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *                                       Thread *self,        x3
768b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *                                       JValue *result,      x4
769b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *                                       char   *shorty);     x5
770b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith */
771b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithENTRY art_quick_invoke_static_stub
772b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Spill registers as per AACPS64 calling convention.
77303906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    INVOKE_STUB_CREATE_FRAME
774b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
775b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Fill registers x/w1 to x/w7 and s/d0 to s/d7 with parameters.
776b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Parse the passed shorty to determine which register to load.
777b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Load addresses for routines that load WXSD registers.
778b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    adr  x11, .LstoreW1_2
779b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    adr  x12, .LstoreX1_2
780b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    adr  x13, .LstoreS0_2
781b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    adr  x14, .LstoreD0_2
782b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
783b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Initialize routine offsets to 0 for integers and floats.
784b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // x8 for integers, x15 for floating point.
785b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    mov x8, #0
786b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    mov x15, #0
787b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
788b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    add x10, x5, #1     // Load shorty address, plus one to skip return value.
789b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
790b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Loop to fill registers.
791b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.LfillRegisters2:
792b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldrb w17, [x10], #1         // Load next character in signature, and increment.
793b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    cbz w17, .LcallFunction2    // Exit at end of signature. Shorty 0 terminated.
794b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
795b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    cmp  w17, #'F'          // is this a float?
796b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    bne .LisDouble2
797b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
798b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    cmp x15, # 8*12         // Skip this load if all registers full.
79903906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    beq .Ladvance4_2
800b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
801b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    add x17, x13, x15       // Calculate subroutine to jump to.
802b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    br  x17
803b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
804b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.LisDouble2:
805b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    cmp w17, #'D'           // is this a double?
806b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    bne .LisLong2
807b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
808b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    cmp x15, # 8*12         // Skip this load if all registers full.
80903906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    beq .Ladvance8_2
810b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
811b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    add x17, x14, x15       // Calculate subroutine to jump to.
812b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    br x17
813b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
814b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.LisLong2:
815b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    cmp w17, #'J'           // is this a long?
816b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    bne .LisOther2
817b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
818b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    cmp x8, # 7*12          // Skip this load if all registers full.
81903906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    beq .Ladvance8_2
820b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
821b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    add x17, x12, x8        // Calculate subroutine to jump to.
822b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    br x17
823b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
824b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.LisOther2:                 // Everything else takes one vReg.
825b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    cmp x8, # 7*12          // Skip this load if all registers full.
82603906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    beq .Ladvance4_2
82703906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
828b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    add x17, x11, x8        // Calculate subroutine to jump to.
829b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    br x17
830b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
83103906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe.Ladvance4_2:
83203906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    add x9, x9, #4
83303906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    b .LfillRegisters2
83403906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
83503906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe.Ladvance8_2:
83603906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    add x9, x9, #8
83703906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    b .LfillRegisters2
83803906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
839b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith// Store ints.
840b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.LstoreW1_2:
841b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 4 w1 .LfillRegisters2
842b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 4 w2 .LfillRegisters2
843b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 4 w3 .LfillRegisters2
844b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 4 w4 .LfillRegisters2
845b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 4 w5 .LfillRegisters2
846b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 4 w6 .LfillRegisters2
847b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 4 w7 .LfillRegisters2
848b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
849b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith// Store longs.
850b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.LstoreX1_2:
851b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 8 x1 .LfillRegisters2
852b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 8 x2 .LfillRegisters2
853b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 8 x3 .LfillRegisters2
854b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 8 x4 .LfillRegisters2
855b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 8 x5 .LfillRegisters2
856b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 8 x6 .LfillRegisters2
857b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x8 8 x7 .LfillRegisters2
858b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
859b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith// Store singles.
860b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.LstoreS0_2:
861b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 4 s0 .LfillRegisters2
862b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 4 s1 .LfillRegisters2
863b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 4 s2 .LfillRegisters2
864b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 4 s3 .LfillRegisters2
865b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 4 s4 .LfillRegisters2
866b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 4 s5 .LfillRegisters2
867b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 4 s6 .LfillRegisters2
868b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 4 s7 .LfillRegisters2
869b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
870b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith// Store doubles.
871b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.LstoreD0_2:
872b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 8 d0 .LfillRegisters2
873b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 8 d1 .LfillRegisters2
874b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 8 d2 .LfillRegisters2
875b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 8 d3 .LfillRegisters2
876b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 8 d4 .LfillRegisters2
877b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 8 d5 .LfillRegisters2
878b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 8 d6 .LfillRegisters2
879b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    LOADREG x15 8 d7 .LfillRegisters2
880b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
881b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
882b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.LcallFunction2:
883b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
88403906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe    INVOKE_STUB_CALL_AND_RETURN
885b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
886b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithEND art_quick_invoke_static_stub
887b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
88803906cffb1a59931c1c871ac3a0ffb1c4476bbb4Andreas Gampe
889b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
890b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    /*
891b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * On entry x0 is uintptr_t* gprs_ and x1 is uint64_t* fprs_
892b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     */
893b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
894b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithENTRY art_quick_do_long_jump
895b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Load FPRs
896b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp d0, d1, [x1], #16
897b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp d2, d3, [x1], #16
898b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp d4, d5, [x1], #16
899b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp d6, d7, [x1], #16
900b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp d8, d9, [x1], #16
901b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp d10, d11, [x1], #16
902b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp d12, d13, [x1], #16
903b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp d14, d15, [x1], #16
904b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp d16, d17, [x1], #16
905b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp d18, d19, [x1], #16
906b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp d20, d21, [x1], #16
907b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp d22, d23, [x1], #16
908b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp d24, d25, [x1], #16
909b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp d26, d27, [x1], #16
910b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp d28, d29, [x1], #16
911b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp d30, d31, [x1]
912b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
913b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Load GPRs
914b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // TODO: lots of those are smashed, could optimize.
915b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    add x0, x0, #30*8
916b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp x30, x1, [x0], #-16
917b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp x28, x29, [x0], #-16
918b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp x26, x27, [x0], #-16
919b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp x24, x25, [x0], #-16
920b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp x22, x23, [x0], #-16
921b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp x20, x21, [x0], #-16
922b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp x18, x19, [x0], #-16
923b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp x16, x17, [x0], #-16
924b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp x14, x15, [x0], #-16
925b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp x12, x13, [x0], #-16
926b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp x10, x11, [x0], #-16
927b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp x8, x9, [x0], #-16
928b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp x6, x7, [x0], #-16
929b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp x4, x5, [x0], #-16
930b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ldp x2, x3, [x0], #-16
931b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    mov sp, x1
932b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
933b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // TODO: Is it really OK to use LR for the target PC?
934b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    mov x0, #0
935b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    mov x1, #0
936b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    br  xLR
937b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithEND art_quick_do_long_jump
938b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
939f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    /*
940f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe     * Entry from managed code that calls artHandleFillArrayDataFromCode and delivers exception on
941f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe     * failure.
942f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe     */
943f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    .extern artHandleFillArrayDataFromCode
944f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas GampeENTRY art_quick_handle_fill_data
945f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // Save callee saves in case exception allocation triggers GC.
946f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    mov    x2, xSELF                       // Pass Thread::Current.
947f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    mov    x3, sp                          // Pass SP.
948f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    bl     artHandleFillArrayDataFromCode  // (Array*, const DexFile::Payload*, Thread*, SP)
949f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
950f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    RETURN_IF_RESULT_IS_ZERO
951f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    DELIVER_PENDING_EXCEPTION
952f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas GampeEND art_quick_handle_fill_data
953b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
9544fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    /*
9554fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe     * Entry from managed code that calls artLockObjectFromCode, may block for GC. x0 holds the
9564fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe     * possibly null object to lock.
9574fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe     *
9584fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe     * Derived from arm32 code.
9594fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe     */
9604fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    .extern artLockObjectFromCode
9614fc046e78efbc98541388cdda986b5d8a2b951adAndreas GampeENTRY art_quick_lock_object
9624fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    cbz    w0, .Lslow_lock
9634fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    add    x4, x0, #LOCK_WORD_OFFSET  // exclusive load/store had no immediate anymore
9644fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe.Lretry_lock:
9654fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    ldr    w2, [xSELF, #THREAD_ID_OFFSET] // TODO: Can the thread ID really change during the loop?
9664fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    ldxr   w1, [x4]
9674fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    cbnz   w1, .Lnot_unlocked         // already thin locked
9684fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    stxr   w3, w2, [x4]
9694fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    cbnz   w3, .Lstrex_fail           // store failed, retry
970675967d981a3d17aaedf4ca6e07cc3a76e066921Andreas Gampe    dmb    ishld                      // full (LoadLoad|LoadStore) memory barrier
9714fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    ret
9724fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe.Lstrex_fail:
9734fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    b .Lretry_lock                    // unlikely forward branch, need to reload and recheck r1/r2
9744fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe.Lnot_unlocked:
9754fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    lsr    w3, w1, 30
9764fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    cbnz   w3, .Lslow_lock            // if either of the top two bits are set, go slow path
9774fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    eor    w2, w1, w2                 // lock_word.ThreadId() ^ self->ThreadId()
9784fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    uxth   w2, w2                     // zero top 16 bits
9794fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    cbnz   w2, .Lslow_lock            // lock word and self thread id's match -> recursive lock
9804fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe                                      // else contention, go to slow path
9814fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    add    w2, w1, #65536             // increment count in lock word placing in w2 for storing
9824fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    lsr    w1, w2, 30                 // if either of the top two bits are set, we overflowed.
9834fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    cbnz   w1, .Lslow_lock            // if we overflow the count go slow path
9844fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    str    w2, [x0, #LOCK_WORD_OFFSET]// no need for stxr as we hold the lock
9854fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    ret
9864fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe.Lslow_lock:
9874fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case we block
9884fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    mov    x1, xSELF                  // pass Thread::Current
9894fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    mov    x2, sp                     // pass SP
9904fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    bl     artLockObjectFromCode      // (Object* obj, Thread*, SP)
9914fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
9924fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    RETURN_IF_W0_IS_ZERO_OR_DELIVER
9934fc046e78efbc98541388cdda986b5d8a2b951adAndreas GampeEND art_quick_lock_object
9944fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe
9954fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    /*
9964fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe     * Entry from managed code that calls artUnlockObjectFromCode and delivers exception on failure.
9974fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe     * x0 holds the possibly null object to lock.
9984fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe     *
9994fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe     * Derived from arm32 code.
10004fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe     */
10014fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    .extern artUnlockObjectFromCode
10024fc046e78efbc98541388cdda986b5d8a2b951adAndreas GampeENTRY art_quick_unlock_object
10034fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    cbz    x0, .Lslow_unlock
10044fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    ldr    w1, [x0, #LOCK_WORD_OFFSET]
10054fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    lsr    w2, w1, 30
10064fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    cbnz   w2, .Lslow_unlock          // if either of the top two bits are set, go slow path
10074fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    ldr    w2, [xSELF, #THREAD_ID_OFFSET]
10084fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    eor    w3, w1, w2                 // lock_word.ThreadId() ^ self->ThreadId()
10094fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    uxth   w3, w3                     // zero top 16 bits
10104fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    cbnz   w3, .Lslow_unlock          // do lock word and self thread id's match?
10114fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    cmp    w1, #65536
10124fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    bpl    .Lrecursive_thin_unlock
10134fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    // transition to unlocked, w3 holds 0
1014675967d981a3d17aaedf4ca6e07cc3a76e066921Andreas Gampe    dmb    ish                        // full (LoadStore|StoreStore) memory barrier
10154fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    str    w3, [x0, #LOCK_WORD_OFFSET]
10164fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    ret
10174fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe.Lrecursive_thin_unlock:
10184fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    sub    w1, w1, #65536
10194fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    str    w1, [x0, #LOCK_WORD_OFFSET]
10204fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    ret
10214fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe.Lslow_unlock:
10224fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case exception allocation triggers GC
10234fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    mov    x1, xSELF                  // pass Thread::Current
10244fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    mov    x2, sp                     // pass SP
10254fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    bl     artUnlockObjectFromCode    // (Object* obj, Thread*, SP)
10264fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
10274fc046e78efbc98541388cdda986b5d8a2b951adAndreas Gampe    RETURN_IF_W0_IS_ZERO_OR_DELIVER
10284fc046e78efbc98541388cdda986b5d8a2b951adAndreas GampeEND art_quick_unlock_object
1029525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe
1030525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    /*
1031525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe     * Entry from managed code that calls artIsAssignableFromCode and on failure calls
1032525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe     * artThrowClassCastException.
1033525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe     */
1034525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    .extern artThrowClassCastException
1035525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas GampeENTRY art_quick_check_cast
1036525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    // Store arguments and link register
1037525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    sub sp, sp, #32                     // Stack needs to be 16b aligned on calls
1038525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    .cfi_adjust_cfa_offset 32
1039525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    stp x0, x1, [sp]
1040525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    .cfi_rel_offset x0, 0
1041525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    .cfi_rel_offset x1, 8
1042525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    stp xSELF, xLR, [sp, #16]
1043525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    .cfi_rel_offset x18, 16
1044525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    .cfi_rel_offset x30, 24
1045525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe
1046525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    // Call runtime code
1047525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    bl artIsAssignableFromCode
1048525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe
1049525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    // Check for exception
1050525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    cbz x0, .Lthrow_class_cast_exception
1051525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe
1052525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    // Restore and return
1053525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    ldp x0, x1, [sp]
1054525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    .cfi_restore x0
1055525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    .cfi_restore x1
1056525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    ldp xSELF, xLR, [sp, #16]
1057525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    .cfi_restore x18
1058525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    .cfi_restore x30
1059525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    add sp, sp, #32
1060525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    .cfi_adjust_cfa_offset -32
1061525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    ret
1062525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe
1063525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe.Lthrow_class_cast_exception:
1064525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    // Restore
1065525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    ldp x0, x1, [sp]
1066525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    .cfi_restore x0
1067525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    .cfi_restore x1
1068525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    ldp xSELF, xLR, [sp, #16]
1069525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    .cfi_restore x18
1070525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    .cfi_restore x30
1071525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    add sp, sp, #32
1072525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    .cfi_adjust_cfa_offset -32
1073525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe
1074525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
1075525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    mov x2, xSELF                     // pass Thread::Current
1076525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    mov x3, sp                        // pass SP
1077525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    b artThrowClassCastException      // (Class*, Class*, Thread*, SP)
1078525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe    brk 0                             // We should not return here...
1079525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas GampeEND art_quick_check_cast
1080525cde2dd7cc7ad4212765ad3975cf260a934d3eAndreas Gampe
1081f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    /*
1082f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe     * Entry from managed code for array put operations of objects where the value being stored
1083f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe     * needs to be checked for compatibility.
1084f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe     * x0 = array, x1 = index, x2 = value
1085f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe     *
1086f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe     * Currently all values should fit into w0/w1/w2, and w1 always will as indices are 32b. We
1087f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe     * assume, though, that the upper 32b are zeroed out. At least for x1/w1 we can do better by
1088f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe     * using index-zero-extension in load/stores.
1089f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe     *
1090f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe     * Temporaries: x3, x4
1091f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe     * TODO: x4 OK? ip seems wrong here.
1092f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe     */
1093f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas GampeENTRY art_quick_aput_obj_with_null_and_bound_check
1094f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    tst x0, x0
1095f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    bne art_quick_aput_obj_with_bound_check
1096f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    b art_quick_throw_null_pointer_exception
1097f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas GampeEND art_quick_aput_obj_with_null_and_bound_check
1098f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe
1099f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas GampeENTRY art_quick_aput_obj_with_bound_check
1100f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    ldr w3, [x0, #ARRAY_LENGTH_OFFSET]
1101f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    cmp w3, w1
1102f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    bhi art_quick_aput_obj
1103f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    mov x0, x1
1104f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    mov x1, x3
1105f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    b art_quick_throw_array_bounds
1106f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas GampeEND art_quick_aput_obj_with_bound_check
1107f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe
1108f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas GampeENTRY art_quick_aput_obj
1109f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    cbz x2, .Ldo_aput_null
1110f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    ldr w3, [x0, #CLASS_OFFSET]                          // Heap reference = 32b
1111f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe                                                         // This also zero-extends to x3
1112f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    ldr w4, [x2, #CLASS_OFFSET]                          // Heap reference = 32b
1113f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe                                                         // This also zero-extends to x4
1114f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    ldr w3, [x3, #CLASS_COMPONENT_TYPE_OFFSET]           // Heap reference = 32b
1115f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe                                                         // This also zero-extends to x3
1116f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    cmp w3, w4  // value's type == array's component type - trivial assignability
1117f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    bne .Lcheck_assignability
1118f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe.Ldo_aput:
1119f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    add x3, x0, #OBJECT_ARRAY_DATA_OFFSET
1120f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe                                                         // "Compress" = do nothing
1121f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    str w2, [x3, x1, lsl #2]                             // Heap reference = 32b
1122f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    ldr x3, [xSELF, #THREAD_CARD_TABLE_OFFSET]
1123f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    lsr x0, x0, #7
1124f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    strb w3, [x3, x0]
1125f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    ret
1126f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe.Ldo_aput_null:
1127f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    add x3, x0, #OBJECT_ARRAY_DATA_OFFSET
1128f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe                                                         // "Compress" = do nothing
1129f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    str w2, [x3, x1, lsl #2]                             // Heap reference = 32b
1130f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    ret
1131f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe.Lcheck_assignability:
1132f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    // Store arguments and link register
1133f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    sub sp, sp, #48                     // Stack needs to be 16b aligned on calls
1134f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    .cfi_adjust_cfa_offset 48
1135f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    stp x0, x1, [sp]
1136f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    .cfi_rel_offset x0, 0
1137f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    .cfi_rel_offset x1, 8
1138f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    stp x2, xSELF, [sp, #16]
1139f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    .cfi_rel_offset x2, 16
1140f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    .cfi_rel_offset x18, 24
1141f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    str xLR, [sp, #32]
1142f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    .cfi_rel_offset x30, 32
1143f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe
1144f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    // Call runtime code
1145f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    mov x0, x3              // Heap reference, 32b, "uncompress" = do nothing, already zero-extended
1146f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    mov x1, x4              // Heap reference, 32b, "uncompress" = do nothing, already zero-extended
1147f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    bl artIsAssignableFromCode
1148f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe
1149f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    // Check for exception
1150f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    cbz x0, .Lthrow_array_store_exception
1151f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe
1152f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    // Restore
1153f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    ldp x0, x1, [sp]
1154f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    .cfi_restore x0
1155f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    .cfi_restore x1
1156f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    ldp x2, xSELF, [sp, #16]
1157f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    .cfi_restore x2
1158f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    .cfi_restore x18
1159f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    ldr xLR, [sp, #32]
1160f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    .cfi_restore x30
1161f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    add sp, sp, #48
1162f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    .cfi_adjust_cfa_offset -48
1163f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe
1164f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    add x3, x0, #OBJECT_ARRAY_DATA_OFFSET
1165f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe                                                          // "Compress" = do nothing
1166f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    str w2, [x3, x1, lsl #2]                              // Heap reference = 32b
1167f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    ldr x3, [xSELF, #THREAD_CARD_TABLE_OFFSET]
1168f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    lsr x0, x0, #7
1169f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    strb w3, [x3, x0]
1170f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    ret
1171f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe.Lthrow_array_store_exception:
1172f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    ldp x0, x1, [sp]
1173f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    .cfi_restore x0
1174f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    .cfi_restore x1
1175f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    ldp x2, xSELF, [sp, #16]
1176f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    .cfi_restore x2
1177f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    .cfi_restore x18
1178f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    ldr xLR, [sp, #32]
1179f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    .cfi_restore x30
1180f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    add sp, sp, #48
1181f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    .cfi_adjust_cfa_offset -48
1182f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe
1183f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
1184f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    mov x1, x2                    // Pass value.
1185f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    mov x2, xSELF                 // Pass Thread::Current.
1186f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    mov x3, sp                    // Pass SP.
1187f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    b artThrowArrayStoreException // (Object*, Object*, Thread*, SP).
1188f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe    brk 0                         // Unreached.
1189f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas GampeEND art_quick_aput_obj
1190f4e910badbaa5aa48efbf697715f4815f0ebc7e4Andreas Gampe
1191b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith// Macro to facilitate adding new allocation entrypoints.
1192b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.macro TWO_ARG_DOWNCALL name, entrypoint, return
1193b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    .extern \entrypoint
1194b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithENTRY \name
119500c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case of GC
119600c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    mov    x2, xSELF                  // pass Thread::Current
119700c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    mov    x3, sp                     // pass SP
119800c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    bl     \entrypoint                // (uint32_t type_idx, Method* method, Thread*, SP)
119900c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
120000c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    \return
120100c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    DELIVER_PENDING_EXCEPTION
1202b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithEND \name
1203b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.endm
1204b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1205b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith// Macro to facilitate adding new array allocation entrypoints.
1206b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.macro THREE_ARG_DOWNCALL name, entrypoint, return
1207b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    .extern \entrypoint
1208b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithENTRY \name
120900c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case of GC
121000c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    mov    x3, xSELF                  // pass Thread::Current
121100c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    mov    x4, sp                     // pass SP
121200c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    bl     \entrypoint
121300c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
121400c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    \return
121500c1e6d5fa6c2c20f25c38591b9780114bf7ddbfAndreas Gampe    DELIVER_PENDING_EXCEPTION
1216b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithEND \name
1217b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.endm
1218b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
12196e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe// Macros taking opportunity of code similarities for downcalls with referrer.
12206e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe.macro ONE_ARG_REF_DOWNCALL name, entrypoint, return
12216e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    .extern \entrypoint
12226e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas GampeENTRY \name
12236e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case of GC
1224cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe    ldr    w1, [sp, #FRAME_SIZE_REFS_ONLY_CALLEE_SAVE] // Load referrer
12256e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    mov    x2, xSELF                  // pass Thread::Current
12266e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    mov    x3, sp                     // pass SP
12276e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    bl     \entrypoint                // (uint32_t type_idx, Method* method, Thread*, SP)
12286e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
12296e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    \return
12306e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas GampeEND \name
12316e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe.endm
12326e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe
12336e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe.macro TWO_ARG_REF_DOWNCALL name, entrypoint, return
12346e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    .extern \entrypoint
12356e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas GampeENTRY \name
12366e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case of GC
1237cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe    ldr    w2, [sp, #FRAME_SIZE_REFS_ONLY_CALLEE_SAVE] // Load referrer
12386e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    mov    x3, xSELF                  // pass Thread::Current
12396e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    mov    x4, sp                     // pass SP
12406e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    bl     \entrypoint
12416e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
12426e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    \return
12436e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas GampeEND \name
12446e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe.endm
12456e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe
12466e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe.macro THREE_ARG_REF_DOWNCALL name, entrypoint, return
12476e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    .extern \entrypoint
12486e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas GampeENTRY \name
12496e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case of GC
1250cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe    ldr    w3, [sp, #FRAME_SIZE_REFS_ONLY_CALLEE_SAVE] // Load referrer
12516e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    mov    x4, xSELF                  // pass Thread::Current
12526e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    mov    x5, sp                     // pass SP
12536e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    bl     \entrypoint
12546e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
12556e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    \return
12566e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas GampeEND \name
12576e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe.endm
12586e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe
1259dfd891a61a1642b3c0d532e0cec73255cf4b9afbMatteo Franchin    /*
1260dfd891a61a1642b3c0d532e0cec73255cf4b9afbMatteo Franchin     * Entry from managed code when uninitialized static storage, this stub will run the class
1261dfd891a61a1642b3c0d532e0cec73255cf4b9afbMatteo Franchin     * initializer and deliver the exception on error. On success the static storage base is
1262dfd891a61a1642b3c0d532e0cec73255cf4b9afbMatteo Franchin     * returned.
1263dfd891a61a1642b3c0d532e0cec73255cf4b9afbMatteo Franchin     */
1264dfd891a61a1642b3c0d532e0cec73255cf4b9afbMatteo FranchinTWO_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO
1265dfd891a61a1642b3c0d532e0cec73255cf4b9afbMatteo Franchin
12666aac355810d83babbd834df07cf1a38f44ad11c2Andreas GampeTWO_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO
12676aac355810d83babbd834df07cf1a38f44ad11c2Andreas GampeTWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO
1268dfd891a61a1642b3c0d532e0cec73255cf4b9afbMatteo Franchin
12696e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas GampeONE_ARG_REF_DOWNCALL art_quick_get32_static, artGet32StaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
12706e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas GampeONE_ARG_REF_DOWNCALL art_quick_get64_static, artGet64StaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
12716e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas GampeONE_ARG_REF_DOWNCALL art_quick_get_obj_static, artGetObjStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
12726e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe
12736e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas GampeTWO_ARG_REF_DOWNCALL art_quick_get32_instance, artGet32InstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
12746e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas GampeTWO_ARG_REF_DOWNCALL art_quick_get64_instance, artGet64InstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
12756e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas GampeTWO_ARG_REF_DOWNCALL art_quick_get_obj_instance, artGetObjInstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
12766e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe
12776e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas GampeTWO_ARG_REF_DOWNCALL art_quick_set32_static, artSet32StaticFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
12786e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas GampeTWO_ARG_REF_DOWNCALL art_quick_set_obj_static, artSetObjStaticFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
12796e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe
12806e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas GampeTHREE_ARG_REF_DOWNCALL art_quick_set32_instance, artSet32InstanceFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
12816e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas GampeTHREE_ARG_DOWNCALL art_quick_set64_instance, artSet64InstanceFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
12826e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas GampeTHREE_ARG_REF_DOWNCALL art_quick_set_obj_instance, artSetObjInstanceFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
12836e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe
12846e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe// This is separated out as the argument order is different.
12856e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    .extern artSet64StaticFromCode
12866e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas GampeENTRY art_quick_set64_static
12876e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case of GC
12886e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    mov    x3, x1                     // Store value
1289cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe    ldr    w1, [sp, #FRAME_SIZE_REFS_ONLY_CALLEE_SAVE] // Load referrer
12906e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    mov    x2, x3                     // Put value param
12916e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    mov    x3, xSELF                  // pass Thread::Current
12926e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    mov    x4, sp                     // pass SP
12936e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    bl     artSet64StaticFromCode
12946e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
12956e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe    RETURN_IF_W0_IS_ZERO_OR_DELIVER
12966e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas GampeEND art_quick_set64_static
12976e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe
1298dfd891a61a1642b3c0d532e0cec73255cf4b9afbMatteo Franchin    /*
1299dfd891a61a1642b3c0d532e0cec73255cf4b9afbMatteo Franchin     * Entry from managed code to resolve a string, this stub will allocate a String and deliver an
1300dfd891a61a1642b3c0d532e0cec73255cf4b9afbMatteo Franchin     * exception on error. On success the String is returned. x0 holds the referring method,
1301dfd891a61a1642b3c0d532e0cec73255cf4b9afbMatteo Franchin     * w1 holds the string index. The fast path check for hit in strings cache has already been
1302dfd891a61a1642b3c0d532e0cec73255cf4b9afbMatteo Franchin     * performed.
1303dfd891a61a1642b3c0d532e0cec73255cf4b9afbMatteo Franchin     */
1304dfd891a61a1642b3c0d532e0cec73255cf4b9afbMatteo FranchinTWO_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO
13056e4e59c674f4d58421512dbcfc57a99e27b6b5c8Andreas Gampe
1306b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith// Generate the allocation entrypoints for each allocator.
1307b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithGENERATE_ALL_ALLOC_ENTRYPOINTS
1308b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
130948241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    /*
131048241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu     * Called by managed code when the value in wSUSPEND has been decremented to 0.
131148241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu     */
131248241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    .extern artTestSuspendFromCode
131348241e786121e1c4c050d9cfad3d22de270a3e75Zheng XuENTRY art_quick_test_suspend
131448241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    ldrh   w0, [xSELF, #THREAD_FLAGS_OFFSET]  // get xSELF->state_and_flags.as_struct.flags
131548241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    mov    wSUSPEND, #SUSPEND_CHECK_INTERVAL  // reset wSUSPEND to SUSPEND_CHECK_INTERVAL
131648241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    cbnz   w0, .Lneed_suspend                 // check flags == 0
131748241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    ret                                       // return if flags == 0
131848241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu.Lneed_suspend:
131948241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    mov    x0, xSELF
132048241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    SETUP_REF_ONLY_CALLEE_SAVE_FRAME          // save callee saves for stack crawl
132148241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    mov    x1, sp
132248241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    bl     artTestSuspendFromCode             // (Thread*, SP)
132348241e786121e1c4c050d9cfad3d22de270a3e75Zheng Xu    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
132448241e786121e1c4c050d9cfad3d22de270a3e75Zheng XuEND art_quick_test_suspend
1325b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
13267204c04dd86ae8ce05690e38737b2abf017a0a69Stuart MonteithENTRY art_quick_implicit_suspend
13277204c04dd86ae8ce05690e38737b2abf017a0a69Stuart Monteith    mov    x0, xSELF
13287204c04dd86ae8ce05690e38737b2abf017a0a69Stuart Monteith    SETUP_REF_ONLY_CALLEE_SAVE_FRAME          // save callee saves for stack crawl
13297204c04dd86ae8ce05690e38737b2abf017a0a69Stuart Monteith    mov    x1, sp
13307204c04dd86ae8ce05690e38737b2abf017a0a69Stuart Monteith    bl     artTestSuspendFromCode             // (Thread*, SP)
13317204c04dd86ae8ce05690e38737b2abf017a0a69Stuart Monteith    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
13327204c04dd86ae8ce05690e38737b2abf017a0a69Stuart MonteithEND art_quick_implicit_suspend
13337204c04dd86ae8ce05690e38737b2abf017a0a69Stuart Monteith
1334e62a07eac9ba2bef01f373832dd810a2cee9f348Andreas Gampe     /*
1335e62a07eac9ba2bef01f373832dd810a2cee9f348Andreas Gampe     * Called by managed code that is attempting to call a method on a proxy class. On entry
1336e62a07eac9ba2bef01f373832dd810a2cee9f348Andreas Gampe     * x0 holds the proxy method and x1 holds the receiver; The frame size of the invoked proxy
1337e62a07eac9ba2bef01f373832dd810a2cee9f348Andreas Gampe     * method agrees with a ref and args callee save frame.
1338e62a07eac9ba2bef01f373832dd810a2cee9f348Andreas Gampe     */
1339e62a07eac9ba2bef01f373832dd810a2cee9f348Andreas Gampe     .extern artQuickProxyInvokeHandler
1340e62a07eac9ba2bef01f373832dd810a2cee9f348Andreas GampeENTRY art_quick_proxy_invoke_handler
1341e62a07eac9ba2bef01f373832dd810a2cee9f348Andreas Gampe    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
1342e62a07eac9ba2bef01f373832dd810a2cee9f348Andreas Gampe    str     x0, [sp, #0]                // place proxy method at bottom of frame
1343e62a07eac9ba2bef01f373832dd810a2cee9f348Andreas Gampe    mov     x2, xSELF                   // pass Thread::Current
1344e62a07eac9ba2bef01f373832dd810a2cee9f348Andreas Gampe    mov     x3, sp                      // pass SP
1345e62a07eac9ba2bef01f373832dd810a2cee9f348Andreas Gampe    bl      artQuickProxyInvokeHandler  // (Method* proxy method, receiver, Thread*, SP)
1346b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // Use xETR as xSELF might be scratched by native function above.
1347b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldr     x2, [xETR, THREAD_EXCEPTION_OFFSET]
1348e62a07eac9ba2bef01f373832dd810a2cee9f348Andreas Gampe    cbnz    x2, .Lexception_in_proxy    // success if no exception is pending
1349d1e9167713e485d9264e856b68ffb568f22f1dc9Andreas Gampe    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME // Restore frame
1350d1e9167713e485d9264e856b68ffb568f22f1dc9Andreas Gampe    fmov    d0, x0                      // Store result in d0 in case it was float or double
1351e62a07eac9ba2bef01f373832dd810a2cee9f348Andreas Gampe    ret                                 // return on success
1352e62a07eac9ba2bef01f373832dd810a2cee9f348Andreas Gampe.Lexception_in_proxy:
1353e62a07eac9ba2bef01f373832dd810a2cee9f348Andreas Gampe    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
1354e62a07eac9ba2bef01f373832dd810a2cee9f348Andreas Gampe    DELIVER_PENDING_EXCEPTION
1355e62a07eac9ba2bef01f373832dd810a2cee9f348Andreas GampeEND art_quick_proxy_invoke_handler
1356b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
135751f763506c7bb34420242e88e1631550f94d6417Andreas Gampe    /*
1358b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu     * Called to resolve an imt conflict. xIP1 is a hidden argument that holds the target method's
135951f763506c7bb34420242e88e1631550f94d6417Andreas Gampe     * dex method index.
136051f763506c7bb34420242e88e1631550f94d6417Andreas Gampe     */
136151f763506c7bb34420242e88e1631550f94d6417Andreas GampeENTRY art_quick_imt_conflict_trampoline
1362cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe    ldr    w0, [sp, #0]                                // load caller Method*
136351f763506c7bb34420242e88e1631550f94d6417Andreas Gampe    ldr    w0, [x0, #METHOD_DEX_CACHE_METHODS_OFFSET]  // load dex_cache_resolved_methods
136451f763506c7bb34420242e88e1631550f94d6417Andreas Gampe    add    x0, x0, #OBJECT_ARRAY_DATA_OFFSET           // get starting address of data
1365b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldr    w0, [x0, xIP1, lsl 2]                       // load the target method
136651f763506c7bb34420242e88e1631550f94d6417Andreas Gampe    b art_quick_invoke_interface_trampoline
136751f763506c7bb34420242e88e1631550f94d6417Andreas GampeEND art_quick_imt_conflict_trampoline
1368b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1369b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithENTRY art_quick_resolution_trampoline
1370b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
1371b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    mov x2, xSELF
1372b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    mov x3, sp
1373b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    bl artQuickResolutionTrampoline  // (called, receiver, Thread*, SP)
1374dfd891a61a1642b3c0d532e0cec73255cf4b9afbMatteo Franchin    cbz x0, 1f
1375b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    mov xIP0, x0            // Remember returned code pointer in xIP0.
1376cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe    ldr w0, [sp, #0]        // artQuickResolutionTrampoline puts called method in *SP.
1377b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
1378b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    br xIP0
1379b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith1:
1380b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
1381b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    DELIVER_PENDING_EXCEPTION
1382b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithEND art_quick_resolution_trampoline
1383b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1384b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith/*
1385b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * Generic JNI frame layout:
1386b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *
1387b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * #-------------------#
1388b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * |                   |
1389b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | caller method...  |
1390b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * #-------------------#    <--- SP on entry
1391b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | Return X30/LR     |
1392b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | X29/FP            |    callee save
1393b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | X28               |    callee save
1394b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | X27               |    callee save
1395b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | X26               |    callee save
1396b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | X25               |    callee save
1397b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | X24               |    callee save
1398b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | X23               |    callee save
1399b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | X22               |    callee save
1400b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | X21               |    callee save
1401b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | X20               |    callee save
1402b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | X7                |    arg7
1403b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | X6                |    arg6
1404b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | X5                |    arg5
1405b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | X4                |    arg4
1406b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | X3                |    arg3
1407b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | X2                |    arg2
1408b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | X1                |    arg1
1409b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | D7                |    float arg 8
1410b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | D6                |    float arg 7
1411b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | D5                |    float arg 6
1412b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | D4                |    float arg 5
1413b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | D3                |    float arg 4
1414b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | D2                |    float arg 3
1415b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | D1                |    float arg 2
1416b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | D0                |    float arg 1
1417cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe * | Method*           | <- X0
1418b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * #-------------------#
1419b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | local ref cookie  | // 4B
1420421c53742610c053543f8c84e04d5e0c5185d68cMathieu Chartier * | handle scope size | // 4B
1421b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * #-------------------#
1422b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | JNI Call Stack    |
1423b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * #-------------------#    <--- SP on native call
1424b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * |                   |
1425b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | Stack for Regs    |    The trampoline assembly will pop these values
1426b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * |                   |    into registers for native call
1427b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * #-------------------#
1428b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | Native code ptr   |
1429b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * #-------------------#
1430b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | Free scratch      |
1431b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * #-------------------#
1432b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * | Ptr to (1)        |    <--- SP
1433b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * #-------------------#
1434b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith */
1435b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    /*
1436b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     * Called to do a generic JNI down-call
1437b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith     */
1438235e77bd9f19e4faefda109be40f8744f3a66f40Andreas GampeENTRY_NO_HIDE art_quick_generic_jni_trampoline
1439b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
1440b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    str x0, [sp, #0]  // Store native ArtMethod* to bottom of stack.
1441b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1442b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Save SP , so we can have static CFI info.
1443b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    mov x28, sp
1444b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    .cfi_def_cfa_register x28
1445b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1446b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // This looks the same, but is different: this will be updated to point to the bottom
1447eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    // of the frame when the handle scope is inserted.
1448b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    mov xFP, sp
1449b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1450b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    mov xIP0, #5120
1451b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    sub sp, sp, xIP0
1452b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1453b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // prepare for artQuickGenericJniTrampoline call
1454b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // (Thread*,  SP)
1455b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    //    x0      x1   <= C calling convention
1456b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    //   xSELF    xFP  <= where they are
1457b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1458b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    mov x0, xSELF   // Thread*
1459b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    mov x1, xFP
1460b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    bl artQuickGenericJniTrampoline  // (Thread*, sp)
1461b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1462c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    // The C call will have registered the complete save-frame on success.
1463c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    // The result of the call is:
1464c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    // x0: pointer to native code, 0 on error.
1465c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    // x1: pointer to the bottom of the used area of the alloca, can restore stack till there.
1466b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1467c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    // Check for error = 0.
1468c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    cbz x0, .Lentry_error
1469b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1470c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    // Release part of the alloca.
1471c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    mov sp, x1
1472b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1473c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    // Save the code pointer
1474c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    mov xIP0, x0
1475b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1476b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Load parameters from frame into registers.
1477b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // TODO Check with artQuickGenericJniTrampoline.
1478b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    //      Also, check again APPCS64 - the stack arguments are interleaved.
1479c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    ldp x0, x1, [sp]
1480c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    ldp x2, x3, [sp, #16]
1481c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    ldp x4, x5, [sp, #32]
1482c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    ldp x6, x7, [sp, #48]
1483b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1484c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    ldp d0, d1, [sp, #64]
1485c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    ldp d2, d3, [sp, #80]
1486c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    ldp d4, d5, [sp, #96]
1487c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    ldp d6, d7, [sp, #112]
1488b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1489c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    add sp, sp, #128
1490b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1491b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    blr xIP0        // native call.
1492b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1493b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // result sign extension is handled in C code
1494b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // prepare for artQuickGenericJniEndTrampoline call
1495c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    // (Thread*, result, result_f)
1496c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    //    x0       x1       x2        <= C calling convention
1497c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    mov x1, x0      // Result (from saved)
1498b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    mov x0, xETR    // Thread register, original xSELF might be scratched by native code.
1499c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    fmov x2, d0     // d0 will contain floating point result, but needs to go into x2
1500b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1501b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    bl artQuickGenericJniEndTrampoline
1502b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1503b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Tear down the alloca.
1504b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    mov sp, x28
1505b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    .cfi_def_cfa_register sp
1506b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1507b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Pending exceptions possible.
1508b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    // Use xETR as xSELF might be scratched by native code
1509b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldr x1, [xETR, THREAD_EXCEPTION_OFFSET]
1510b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    cbnz x1, .Lexception_in_native
1511b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1512b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // Tear down the callee-save frame.
1513b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
1514b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1515b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // store into fpr, for when it's a fpr return...
1516b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    fmov d0, x0
1517b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    ret
1518b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1519b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.Lentry_error:
1520b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    mov sp, x28
1521b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    .cfi_def_cfa_register sp
1522b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith.Lexception_in_native:
1523b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
1524b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    DELIVER_PENDING_EXCEPTION
1525b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1526b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithEND art_quick_generic_jni_trampoline
1527b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1528b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith/*
1529b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * Called to bridge from the quick to interpreter ABI. On entry the arguments match those
1530b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * of a quick call:
1531b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * x0 = method being called/to bridge to.
1532b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * x1..x7, d0..d7 = arguments to that method.
1533b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith */
1534235e77bd9f19e4faefda109be40f8744f3a66f40Andreas GampeENTRY_NO_HIDE art_quick_to_interpreter_bridge
1535b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME   // Set up frame and save arguments.
1536b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1537b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    //  x0 will contain mirror::ArtMethod* method.
1538b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    mov x1, xSELF                          // How to get Thread::Current() ???
1539b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    mov x2, sp
1540b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1541b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    // uint64_t artQuickToInterpreterBridge(mirror::ArtMethod* method, Thread* self,
1542b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    //                                      mirror::ArtMethod** sp)
1543b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    bl   artQuickToInterpreterBridge
1544b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1545b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME  // TODO: no need to restore arguments in this case.
1546b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1547b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    fmov d0, x0
1548b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1549b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    RETURN_OR_DELIVER_PENDING_EXCEPTION
1550b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithEND art_quick_to_interpreter_bridge
1551b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
1552d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe
1553d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe//
1554d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe// Instrumentation-related stubs
1555d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe//
1556d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    .extern artInstrumentationMethodEntryFromCode
1557d58342caa97108ba413bad467c285c0377f138f5Andreas GampeENTRY art_quick_instrumentation_entry
1558d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
1559d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe
1560b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    mov   x20, x0             // Preserve method reference in a callee-save.
1561d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe
1562d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    mov   x2, xSELF
1563d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    mov   x3, sp
1564d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    mov   x4, xLR
1565d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    bl    artInstrumentationMethodEntryFromCode  // (Method*, Object*, Thread*, SP, LR)
1566d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe
1567b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    mov   xIP0, x0            // x0 = result of call.
1568b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    mov   x0, x20             // Reload method reference.
1569d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe
1570d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME  // Note: will restore xSELF
1571d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    adr   xLR, art_quick_instrumentation_exit
1572b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    br    xIP0                // Tail-call method with lr set to art_quick_instrumentation_exit.
1573d58342caa97108ba413bad467c285c0377f138f5Andreas GampeEND art_quick_instrumentation_entry
1574d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe
1575d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    .extern artInstrumentationMethodExitFromCode
1576d58342caa97108ba413bad467c285c0377f138f5Andreas GampeENTRY art_quick_instrumentation_exit
1577d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    mov   xLR, #0             // Clobber LR for later checks.
1578d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe
1579d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    SETUP_REF_ONLY_CALLEE_SAVE_FRAME
1580d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe
1581d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    // We need to save x0 and d0. We could use a callee-save from SETUP_REF_ONLY, but then
1582d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    // we would need to fully restore it. As there are a lot of callee-save registers, it seems
1583d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    // easier to have an extra small stack area.
1584d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe
158570f8d4b107e1f87c23df51efa360b3f4e90bce91Sebastien Hertz    str x0, [sp, #-16]!       // Save integer result.
1586d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    .cfi_adjust_cfa_offset 16
1587d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    str d0,  [sp, #8]         // Save floating-point result.
1588d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe
1589d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    add   x1, sp, #16         // Pass SP.
1590d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    mov   x2, x0              // Pass integer result.
1591d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    fmov  x3, d0              // Pass floating-point result.
159270f8d4b107e1f87c23df51efa360b3f4e90bce91Sebastien Hertz    mov   x0, xSELF           // Pass Thread.
1593d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    bl   artInstrumentationMethodExitFromCode    // (Thread*, SP, gpr_res, fpr_res)
1594d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe
1595b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    mov   xIP0, x0            // Return address from instrumentation call.
1596d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    mov   xLR, x1             // r1 is holding link register if we're to bounce to deoptimize
1597d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe
1598d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    ldr   d0, [sp, #8]        // Restore floating-point result.
1599d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    ldr   x0, [sp], 16        // Restore integer result, and drop stack area.
1600d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    .cfi_adjust_cfa_offset 16
1601d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe
1602d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    POP_REF_ONLY_CALLEE_SAVE_FRAME
1603d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe
1604b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    br    xIP0                // Tail-call out.
1605d58342caa97108ba413bad467c285c0377f138f5Andreas GampeEND art_quick_instrumentation_exit
1606d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe
1607d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    /*
1608d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe     * Instrumentation has requested that we deoptimize into the interpreter. The deoptimization
1609d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe     * will long jump to the upcall with a special exception of -1.
1610d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe     */
1611d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    .extern artDeoptimize
1612d58342caa97108ba413bad467c285c0377f138f5Andreas GampeENTRY art_quick_deoptimize
1613d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
1614d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    mov    x0, xSELF          // Pass thread.
1615d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    mov    x1, sp             // Pass SP.
1616d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe    bl     artDeoptimize      // artDeoptimize(Thread*, SP)
161786797a791d692f81def5c1b5f0918992c49ed122Serban Constantinescu    brk 0
1618d58342caa97108ba413bad467c285c0377f138f5Andreas GampeEND art_quick_deoptimize
1619d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe
1620d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe
1621169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    /*
1622169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu     * String's indexOf.
1623169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu     *
1624169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu     * TODO: Not very optimized.
1625169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu     * On entry:
1626169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu     *    x0:   string object (known non-null)
1627169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu     *    w1:   char to match (known <= 0xFFFF)
1628169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu     *    w2:   Starting offset in string data
1629169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu     */
1630169489b4f4be8c5dd880ba6f152948324d22ff79Serban ConstantinescuENTRY art_quick_indexof
1631169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    ldr   w3, [x0, #STRING_COUNT_OFFSET]
1632169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    ldr   w4, [x0, #STRING_OFFSET_OFFSET]
1633169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    ldr   w0, [x0, #STRING_VALUE_OFFSET] // x0 ?
1634169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu
1635169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    /* Clamp start to [0..count] */
1636169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    cmp   w2, #0
1637169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    csel  w2, wzr, w2, lt
1638169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    cmp   w2, w3
1639169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    csel  w2, w3, w2, gt
1640169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu
1641169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    /* Build a pointer to the start of the string data */
1642169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    add   x0, x0, #STRING_DATA_OFFSET
1643169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    add   x0, x0, x4, lsl #1
1644169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu
1645169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    /* Save a copy to compute result */
1646169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    mov   x5, x0
1647169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu
1648169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    /* Build pointer to start of data to compare and pre-bias */
1649169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    add   x0, x0, x2, lsl #1
1650169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    sub   x0, x0, #2
1651169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu
1652169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    /* Compute iteration count */
1653169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    sub   w2, w3, w2
1654169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu
1655169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    /*
1656169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu     * At this point we have:
1657169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu     *  x0: start of the data to test
1658169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu     *  w1: char to compare
1659169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu     *  w2: iteration count
1660169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu     *  x5: original start of string data
1661169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu     */
1662169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu
1663169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    subs  w2, w2, #4
1664169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    b.lt  .Lindexof_remainder
1665169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu
1666169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu.Lindexof_loop4:
1667169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    ldrh  w6, [x0, #2]!
1668169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    ldrh  w7, [x0, #2]!
1669b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldrh  wIP0, [x0, #2]!
1670b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    ldrh  wIP1, [x0, #2]!
1671169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    cmp   w6, w1
1672169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    b.eq  .Lmatch_0
1673169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    cmp   w7, w1
1674169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    b.eq  .Lmatch_1
1675b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    cmp   wIP0, w1
1676169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    b.eq  .Lmatch_2
1677b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu    cmp   wIP1, w1
1678169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    b.eq  .Lmatch_3
1679169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    subs  w2, w2, #4
1680169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    b.ge  .Lindexof_loop4
1681169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu
1682169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu.Lindexof_remainder:
1683169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    adds  w2, w2, #4
1684169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    b.eq  .Lindexof_nomatch
1685169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu
1686169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu.Lindexof_loop1:
1687169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    ldrh  w6, [x0, #2]!
1688169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    cmp   w6, w1
1689169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    b.eq  .Lmatch_3
1690169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    subs  w2, w2, #1
1691169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    b.ne  .Lindexof_loop1
1692169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu
1693169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu.Lindexof_nomatch:
1694169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    mov   x0, #-1
1695169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    ret
1696169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu
1697169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu.Lmatch_0:
1698169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    sub   x0, x0, #6
1699169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    sub   x0, x0, x5
1700169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    asr   x0, x0, #1
1701169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    ret
1702169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu.Lmatch_1:
1703169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    sub   x0, x0, #4
1704169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    sub   x0, x0, x5
1705169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    asr   x0, x0, #1
1706169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    ret
1707169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu.Lmatch_2:
1708169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    sub   x0, x0, #2
1709169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    sub   x0, x0, x5
1710169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    asr   x0, x0, #1
1711169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    ret
1712169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu.Lmatch_3:
1713169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    sub   x0, x0, x5
1714169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    asr   x0, x0, #1
1715169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    ret
1716169489b4f4be8c5dd880ba6f152948324d22ff79Serban ConstantinescuEND art_quick_indexof
1717266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1718266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe   /*
1719266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     * String's compareTo.
1720266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     *
1721266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     * TODO: Not very optimized.
1722266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     *
1723266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     * On entry:
1724266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     *    x0:   this object pointer
1725266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     *    x1:   comp object pointer
1726266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     *
1727266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     */
172886797a791d692f81def5c1b5f0918992c49ed122Serban Constantinescu    .extern __memcmp16
1729266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas GampeENTRY art_quick_string_compareto
1730266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    mov    x2, x0         // x0 is return, use x2 for first input.
1731266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    sub    x0, x2, x1     // Same string object?
1732266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    cbnz   x0,1f
1733266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    ret
1734266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe1:                        // Different string objects.
1735266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1736266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    ldr    w6, [x2, #STRING_OFFSET_OFFSET]
1737266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    ldr    w5, [x1, #STRING_OFFSET_OFFSET]
1738266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    ldr    w4, [x2, #STRING_COUNT_OFFSET]
1739266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    ldr    w3, [x1, #STRING_COUNT_OFFSET]
1740266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    ldr    w2, [x2, #STRING_VALUE_OFFSET]
1741266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    ldr    w1, [x1, #STRING_VALUE_OFFSET]
1742266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1743266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    /*
1744266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     * Now:           CharArray*    Offset   Count
1745266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     *    first arg      x2          w6        w4
1746266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     *   second arg      x1          w5        w3
1747266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     */
1748266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1749266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    // x0 := str1.length(w4) - str2.length(w3). ldr zero-extended w3/w4 into x3/x4.
1750266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    subs x0, x4, x3
1751266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    // Min(count1, count2) into w3.
1752266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    csel x3, x3, x4, ge
1753266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1754266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    // Build pointer into string data.
1755266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1756266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    // Add offset in array (substr etc.) (sign extend and << 1).
1757266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    add x2, x2, w6, sxtw #1
1758266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    add x1, x1, w5, sxtw #1
1759266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1760266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    // Add offset in CharArray to array.
1761266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    add x2, x2, #STRING_DATA_OFFSET
1762266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    add x1, x1, #STRING_DATA_OFFSET
1763266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1764169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu    // TODO: Tune this value.
1765266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    // Check for long string, do memcmp16 for them.
1766266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    cmp w3, #28  // Constant from arm32.
1767266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    bgt .Ldo_memcmp16
1768266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1769266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    /*
1770266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     * Now:
1771266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     *   x2: *first string data
1772266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     *   x1: *second string data
1773266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     *   w3: iteration count
1774266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     *   x0: return value if comparison equal
1775266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     *   x4, x5, x6, x7: free
1776266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe     */
1777266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1778266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    // Do a simple unrolled loop.
1779266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe.Lloop:
1780266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    // At least two more elements?
1781266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    subs w3, w3, #2
1782266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    b.lt .Lremainder_or_done
1783266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1784266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    ldrh w4, [x2], #2
1785266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    ldrh w5, [x1], #2
1786266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1787266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    ldrh w6, [x2], #2
1788266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    ldrh w7, [x1], #2
1789266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1790266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    subs w4, w4, w5
1791266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    b.ne .Lw4_result
1792266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1793266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    subs w6, w6, w7
1794266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    b.ne .Lw6_result
1795266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1796266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    b .Lloop
1797266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1798266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe.Lremainder_or_done:
1799266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    adds w3, w3, #1
1800266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    b.eq .Lremainder
1801266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    ret
1802266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1803266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe.Lremainder:
1804266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    ldrh w4, [x2], #2
1805266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    ldrh w5, [x1], #2
1806266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    subs w4, w4, w5
1807266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    b.ne .Lw4_result
1808266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    ret
1809266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1810266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe// Result is in w4
1811266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe.Lw4_result:
1812266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    sxtw x0, w4
1813266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    ret
1814266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1815266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe// Result is in w6
1816266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe.Lw6_result:
1817266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    sxtw x0, w6
1818266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    ret
1819266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1820266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe.Ldo_memcmp16:
1821d74824bdd01b2a76b310e1275a1114d39833a708Zheng Xu    mov x14, x0                  // Save x0 and LR. __memcmp16 does not use these temps.
1822d74824bdd01b2a76b310e1275a1114d39833a708Zheng Xu    mov x15, xLR                 //                 TODO: Codify and check that?
1823266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1824266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    mov x0, x2
1825266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    uxtw x2, w3
182686797a791d692f81def5c1b5f0918992c49ed122Serban Constantinescu    bl __memcmp16
1827266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
1828d74824bdd01b2a76b310e1275a1114d39833a708Zheng Xu    mov xLR, x15                 // Restore LR.
1829266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe
183086797a791d692f81def5c1b5f0918992c49ed122Serban Constantinescu    cmp x0, #0                   // Check the memcmp difference.
1831d74824bdd01b2a76b310e1275a1114d39833a708Zheng Xu    csel x0, x0, x14, ne         // x0 := x0 != 0 ? x14(prev x0=length diff) : x1.
1832266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas Gampe    ret
1833266340d30a2ed52a4ea0ff64492d6aac857a3e24Andreas GampeEND art_quick_string_compareto
18340210d11658becc2bf02fe79788c87276a857d0e9Zheng Xu
18350210d11658becc2bf02fe79788c87276a857d0e9Zheng Xu// Macro to facilitate adding new entrypoints which call to native function directly.
18360210d11658becc2bf02fe79788c87276a857d0e9Zheng Xu// Currently, xSELF is the only thing we need to take care of between managed code and AAPCS.
18370210d11658becc2bf02fe79788c87276a857d0e9Zheng Xu// But we might introduce more differences.
18380210d11658becc2bf02fe79788c87276a857d0e9Zheng Xu.macro NATIVE_DOWNCALL name, entrypoint
18390210d11658becc2bf02fe79788c87276a857d0e9Zheng Xu    .extern \entrypoint
18400210d11658becc2bf02fe79788c87276a857d0e9Zheng XuENTRY \name
184186797a791d692f81def5c1b5f0918992c49ed122Serban Constantinescu    stp    xSELF, xLR, [sp, #-16]!
18420210d11658becc2bf02fe79788c87276a857d0e9Zheng Xu    bl     \entrypoint
184386797a791d692f81def5c1b5f0918992c49ed122Serban Constantinescu    ldp    xSELF, xLR, [sp], #16
18440210d11658becc2bf02fe79788c87276a857d0e9Zheng Xu    ret
18450210d11658becc2bf02fe79788c87276a857d0e9Zheng XuEND \name
18460210d11658becc2bf02fe79788c87276a857d0e9Zheng Xu.endm
18470210d11658becc2bf02fe79788c87276a857d0e9Zheng Xu
18480210d11658becc2bf02fe79788c87276a857d0e9Zheng XuNATIVE_DOWNCALL art_quick_fmod fmod
18490210d11658becc2bf02fe79788c87276a857d0e9Zheng XuNATIVE_DOWNCALL art_quick_fmodf fmodf
18500210d11658becc2bf02fe79788c87276a857d0e9Zheng XuNATIVE_DOWNCALL art_quick_memcpy memcpy
185186797a791d692f81def5c1b5f0918992c49ed122Serban ConstantinescuNATIVE_DOWNCALL art_quick_assignable_from_code artIsAssignableFromCode
1852