10f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes/*
20f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * Copyright (C) 2012 The Android Open Source Project
30f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes *
40f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
50f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * you may not use this file except in compliance with the License.
60f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * You may obtain a copy of the License at
70f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes *
80f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
90f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes *
100f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * Unless required by applicable law or agreed to in writing, software
110f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
120f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * See the License for the specific language governing permissions and
140f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * limitations under the License.
150f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes */
160f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes
177655f29fabc0a12765de828914a18314382e5a35Ian Rogers#include "asm_support_x86.S"
185e284224e5525ee0a8494a73d84c8ef86e022a0aElliott Hughes
194adeab196d160f70b4865fb8be048ddd2ac7ab82Hiroshi Yamauchi#include "arch/quick_alloc_entrypoints.S"
204adeab196d160f70b4865fb8be048ddd2ac7ab82Hiroshi Yamauchi
21bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison// For x86, the CFA is esp+4, the address above the pushed return address on the stack.
22bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison
2357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    /*
2457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     * Macro that sets up the callee save frame to conform with
257caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers     * Runtime::CreateCalleeSaveMethod(kSaveAll)
2657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     */
271d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersMACRO2(SETUP_SAVE_ALL_CALLEE_SAVE_FRAME, got_reg, temp_reg)
28aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH edi  // Save callee saves (ebx is saved/restored by the upcall)
29aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH esi
30aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH ebp
314360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    subl MACRO_LITERAL(12), %esp  // Grow stack by 3 words.
321d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(12)
334360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    SETUP_GOT_NOSAVE RAW_VAR(got_reg)
341d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    // Load Runtime::instance_ from GOT.
354360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg)), REG_VAR(temp_reg)
364360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    movl (REG_VAR(temp_reg)), REG_VAR(temp_reg)
371d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    // Push save all callee-save method.
384360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    pushl RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET(REG_VAR(temp_reg))
391d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(4)
401d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    // Store esp as the top quick frame.
411d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    movl %esp, %fs:THREAD_TOP_QUICK_FRAME_OFFSET
425c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe    // Ugly compile-time check, but we only have the preprocessor.
435c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe    // Last +4: implicit return address pushed on stack when caller made call.
445c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVE != 3*4 + 16 + 4)
455c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe#error "SAVE_ALL_CALLEE_SAVE_FRAME(X86) size not as expected."
465c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe#endif
47787ec205ee545b9c08f4fc6d3823cb43d10083afElliott HughesEND_MACRO
4857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
497caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    /*
507caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers     * Macro that sets up the callee save frame to conform with
517caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers     * Runtime::CreateCalleeSaveMethod(kRefsOnly)
527caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers     */
531d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersMACRO2(SETUP_REFS_ONLY_CALLEE_SAVE_FRAME, got_reg, temp_reg)
54aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH edi  // Save callee saves (ebx is saved/restored by the upcall)
55aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH esi
56aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH ebp
574360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    subl MACRO_LITERAL(12), %esp  // Grow stack by 3 words.
581d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(12)
594360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    SETUP_GOT_NOSAVE RAW_VAR(got_reg)
601d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    // Load Runtime::instance_ from GOT.
614360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg)), REG_VAR(temp_reg)
624360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    movl (REG_VAR(temp_reg)), REG_VAR(temp_reg)
631d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    // Push save all callee-save method.
644360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    pushl RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET(REG_VAR(temp_reg))
651d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(4)
661d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    // Store esp as the top quick frame.
671d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    movl %esp, %fs:THREAD_TOP_QUICK_FRAME_OFFSET
685c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
695c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe    // Ugly compile-time check, but we only have the preprocessor.
705c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe    // Last +4: implicit return address pushed on stack when caller made call.
715c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe#if (FRAME_SIZE_REFS_ONLY_CALLEE_SAVE != 3*4 + 16 + 4)
725c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe#error "REFS_ONLY_CALLEE_SAVE_FRAME(X86) size not as expected."
735c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe#endif
747caad77632ae121c9f64c488e3f8f710e2c4813dIan RogersEND_MACRO
757caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers
76a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    /*
77a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray     * Macro that sets up the callee save frame to conform with
78a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray     * Runtime::CreateCalleeSaveMethod(kRefsOnly)
79a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray     * and preserves the value of got_reg at entry.
80a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray     */
81a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas GeoffrayMACRO2(SETUP_REFS_ONLY_CALLEE_SAVE_FRAME_PRESERVE_GOT_REG, got_reg, temp_reg)
82a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    PUSH edi  // Save callee saves (ebx is saved/restored by the upcall)
83a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    PUSH esi
84a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    PUSH ebp
85a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    pushl REG_VAR(got_reg)  // Save got_reg
86a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    subl MACRO_LITERAL(8), %esp  // Grow stack by 2 words.
87a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    CFI_ADJUST_CFA_OFFSET(8)
88a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray
89a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    SETUP_GOT_NOSAVE RAW_VAR(got_reg)
90a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    // Load Runtime::instance_ from GOT.
91a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg)), REG_VAR(temp_reg)
92a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    movl (REG_VAR(temp_reg)), REG_VAR(temp_reg)
93a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    // Push save all callee-save method.
94a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    pushl RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET(REG_VAR(temp_reg))
95a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    CFI_ADJUST_CFA_OFFSET(4)
96a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    // Store esp as the top quick frame.
97a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    movl %esp, %fs:THREAD_TOP_QUICK_FRAME_OFFSET
98a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    // Restore got_reg.
99a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    movl 12(%esp), REG_VAR(got_reg)
100a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray
101a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    // Ugly compile-time check, but we only have the preprocessor.
102a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    // Last +4: implicit return address pushed on stack when caller made call.
103a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray#if (FRAME_SIZE_REFS_ONLY_CALLEE_SAVE != 3*4 + 16 + 4)
104a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray#error "REFS_ONLY_CALLEE_SAVE_FRAME(X86) size not as expected."
105a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray#endif
106a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas GeoffrayEND_MACRO
107a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray
1081d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersMACRO0(RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME)
10947d00c0a893b13b69e4bac1836e10cc3e1812d41Ian Rogers    addl MACRO_LITERAL(16), %esp  // Unwind stack up to saved values
110bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe    CFI_ADJUST_CFA_OFFSET(-16)
1112a6c7b7c21adcd4493542604305585b852ccf554Mathieu Chartier    POP ebp  // Restore callee saves (ebx is saved/restored by the upcall)
1122a6c7b7c21adcd4493542604305585b852ccf554Mathieu Chartier    POP esi
1132a6c7b7c21adcd4493542604305585b852ccf554Mathieu Chartier    POP edi
114787ec205ee545b9c08f4fc6d3823cb43d10083afElliott HughesEND_MACRO
11557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
11657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    /*
11757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     * Macro that sets up the callee save frame to conform with
1187caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers     * Runtime::CreateCalleeSaveMethod(kRefsAndArgs)
11957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     */
1201d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersMACRO2(SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME, got_reg, temp_reg)
121aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH edi  // Save callee saves
122aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH esi
123aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH ebp
124aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH ebx  // Save args
125aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH edx
126aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH ecx
127966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Create space for FPR args.
128966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    subl MACRO_LITERAL(4 * 8), %esp
129966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    CFI_ADJUST_CFA_OFFSET(4 * 8)
130966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Save FPRs.
131966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd %xmm0, 0(%esp)
132966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd %xmm1, 8(%esp)
133966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd %xmm2, 16(%esp)
134966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd %xmm3, 24(%esp)
135966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
1364360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    SETUP_GOT_NOSAVE RAW_VAR(got_reg)
1371d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    // Load Runtime::instance_ from GOT.
1384360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg)), REG_VAR(temp_reg)
1394360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    movl (REG_VAR(temp_reg)), REG_VAR(temp_reg)
1401d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    // Push save all callee-save method.
1414360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    pushl RUNTIME_REFS_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET(REG_VAR(temp_reg))
1421d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(4)
1431d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    // Store esp as the stop quick frame.
1441d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    movl %esp, %fs:THREAD_TOP_QUICK_FRAME_OFFSET
1455c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe
1465c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe    // Ugly compile-time check, but we only have the preprocessor.
1475c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe    // Last +4: implicit return address pushed on stack when caller made call.
148966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell#if (FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE != 7*4 + 4*8 + 4)
1495c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe#error "REFS_AND_ARGS_CALLEE_SAVE_FRAME(X86) size not as expected."
1505c1e4352614d61fed6868567e58b96682828cb4dAndreas Gampe#endif
151787ec205ee545b9c08f4fc6d3823cb43d10083afElliott HughesEND_MACRO
15257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
1531d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    /*
1541d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers     * Macro that sets up the callee save frame to conform with
1551d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers     * Runtime::CreateCalleeSaveMethod(kRefsAndArgs) where the method is passed in EAX.
1561d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers     */
1571d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersMACRO0(SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_WITH_METHOD_IN_EAX)
158966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Save callee and GPR args, mixed together to agree with core spills bitmap.
1591d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    PUSH edi  // Save callee saves
1601d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    PUSH esi
1611d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    PUSH ebp
1621d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    PUSH ebx  // Save args
1631d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    PUSH edx
1641d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    PUSH ecx
165966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
166966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Create space for FPR args.
167966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    subl MACRO_LITERAL(32), %esp
168966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    CFI_ADJUST_CFA_OFFSET(32)
169966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
170966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Save FPRs.
171966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd %xmm0, 0(%esp)
172966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd %xmm1, 8(%esp)
173966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd %xmm2, 16(%esp)
174966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd %xmm3, 24(%esp)
175966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
1761d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    PUSH eax  // Store the ArtMethod reference at the bottom of the stack.
1771d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    // Store esp as the stop quick frame.
1781d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    movl %esp, %fs:THREAD_TOP_QUICK_FRAME_OFFSET
1791d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersEND_MACRO
1801d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers
1811d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersMACRO0(RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME)
182966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Restore FPRs. EAX is still on the stack.
183966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd 4(%esp), %xmm0
184966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd 12(%esp), %xmm1
185966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd 20(%esp), %xmm2
186966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd 28(%esp), %xmm3
187966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
188966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    addl MACRO_LITERAL(36), %esp  // Remove FPRs and EAX.
189966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    CFI_ADJUST_CFA_OFFSET(-36)
190966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
1914360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    POP ecx                       // Restore args except eax
192aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    POP edx
193aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    POP ebx
1944360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    POP ebp                       // Restore callee saves
195aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    POP esi
196aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    POP edi
197787ec205ee545b9c08f4fc6d3823cb43d10083afElliott HughesEND_MACRO
19857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
199966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell// Restore register and jump to routine
200966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell// Inputs:  EDI contains pointer to code.
201966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell// Notes: Need to pop EAX too (restores Method*)
202966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P MendellMACRO0(RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME_AND_JUMP)
203966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    POP eax  // Restore Method*
204966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
205966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Restore FPRs.
206966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd 0(%esp), %xmm0
207966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd 8(%esp), %xmm1
208966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd 16(%esp), %xmm2
209966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd 24(%esp), %xmm3
210966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
211966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    addl MACRO_LITERAL(32), %esp  // Remove FPRs.
212966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    CFI_ADJUST_CFA_OFFSET(-32)
213966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
214966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    POP ecx  // Restore args except eax
215966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    POP edx
216966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    POP ebx
217966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    POP ebp  // Restore callee saves
218966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    POP esi
219966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    xchgl 0(%esp),%edi // restore EDI and place code pointer as only value on stack
220966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    ret
221966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P MendellEND_MACRO
222966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
22357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    /*
22457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     * Macro that set calls through to artDeliverPendingExceptionFromCode, where the pending
22557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     * exception is Thread::Current()->exception_.
22657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     */
227787ec205ee545b9c08f4fc6d3823cb43d10083afElliott HughesMACRO0(DELIVER_PENDING_EXCEPTION)
2281d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME ebx, ebx  // save callee saves for throw
22957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    // Outgoing argument set up
2304360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    subl MACRO_LITERAL(12), %esp              // Alignment padding
2311d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(12)
2321d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    pushl %fs:THREAD_SELF_OFFSET               // pass Thread::Current()
2333f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
2341d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    call SYMBOL(artDeliverPendingExceptionFromCode)  // artDeliverPendingExceptionFromCode(Thread*)
2354360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    UNREACHABLE
236787ec205ee545b9c08f4fc6d3823cb43d10083afElliott HughesEND_MACRO
23757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
238787ec205ee545b9c08f4fc6d3823cb43d10083afElliott HughesMACRO2(NO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
2394360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    DEFINE_FUNCTION VAR(c_name)
2401d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  ebx, ebx  // save all registers as basis for long jump context
24157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    // Outgoing argument set up
2424360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    subl MACRO_LITERAL(12), %esp                // alignment padding
2431d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(12)
2444360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    pushl %fs:THREAD_SELF_OFFSET                // pass Thread::Current()
2453f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
2464360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    call CALLVAR(cxx_name)                      // cxx_name(Thread*)
2474360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    UNREACHABLE
2484360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    END_FUNCTION VAR(c_name)
249787ec205ee545b9c08f4fc6d3823cb43d10083afElliott HughesEND_MACRO
25057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
251787ec205ee545b9c08f4fc6d3823cb43d10083afElliott HughesMACRO2(ONE_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
2524360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    DEFINE_FUNCTION VAR(c_name)
2531d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME ebx, ebx  // save all registers as basis for long jump context
25457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    mov %esp, %ecx
25557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    // Outgoing argument set up
2564360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    subl MACRO_LITERAL(8), %esp               // alignment padding
2571d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(8)
2584360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    pushl %fs:THREAD_SELF_OFFSET               // pass Thread::Current()
2593f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
2604360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                                   // pass arg1
2614360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    call CALLVAR(cxx_name)                     // cxx_name(arg1, Thread*)
2624360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    UNREACHABLE
2634360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    END_FUNCTION VAR(c_name)
264787ec205ee545b9c08f4fc6d3823cb43d10083afElliott HughesEND_MACRO
26557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
266787ec205ee545b9c08f4fc6d3823cb43d10083afElliott HughesMACRO2(TWO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
2674360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    DEFINE_FUNCTION VAR(c_name)
2681d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME ebx, ebx  // save all registers as basis for long jump context
26957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    // Outgoing argument set up
2704360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                                   // alignment padding
2714360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    pushl %fs:THREAD_SELF_OFFSET               // pass Thread::Current()
2723f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
2734360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH ecx                                   // pass arg2
2744360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                                   // pass arg1
2754360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    call CALLVAR(cxx_name)                     // cxx_name(arg1, arg2, Thread*)
2764360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    UNREACHABLE
2774360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    END_FUNCTION VAR(c_name)
278787ec205ee545b9c08f4fc6d3823cb43d10083afElliott HughesEND_MACRO
27957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
28057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    /*
28157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     * Called by managed code to create and deliver a NullPointerException.
28257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     */
283468532ea115657709bc32ee498e701a4c71762d4Ian RogersNO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
28457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
28557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    /*
28657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     * Called by managed code to create and deliver an ArithmeticException.
28757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     */
288468532ea115657709bc32ee498e701a4c71762d4Ian RogersNO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode
28957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
29057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    /*
291787ec205ee545b9c08f4fc6d3823cb43d10083afElliott Hughes     * Called by managed code to create and deliver a StackOverflowError.
29257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     */
293468532ea115657709bc32ee498e701a4c71762d4Ian RogersNO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow, artThrowStackOverflowFromCode
29457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
29557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    /*
296787ec205ee545b9c08f4fc6d3823cb43d10083afElliott Hughes     * Called by managed code, saves callee saves and then calls artThrowException
297787ec205ee545b9c08f4fc6d3823cb43d10083afElliott Hughes     * that will place a mock Method* at the bottom of the stack. Arg1 holds the exception.
29857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     */
299468532ea115657709bc32ee498e701a4c71762d4Ian RogersONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception, artDeliverExceptionFromCode
30057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
30157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    /*
30257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     * Called by managed code to create and deliver a NoSuchMethodError.
30357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     */
304468532ea115657709bc32ee498e701a4c71762d4Ian RogersONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method, artThrowNoSuchMethodFromCode
30557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
30657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    /*
307787ec205ee545b9c08f4fc6d3823cb43d10083afElliott Hughes     * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
308787ec205ee545b9c08f4fc6d3823cb43d10083afElliott Hughes     * index, arg2 holds limit.
309787ec205ee545b9c08f4fc6d3823cb43d10083afElliott Hughes     */
310468532ea115657709bc32ee498e701a4c71762d4Ian RogersTWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
311787ec205ee545b9c08f4fc6d3823cb43d10083afElliott Hughes
312787ec205ee545b9c08f4fc6d3823cb43d10083afElliott Hughes    /*
31357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     * All generated callsites for interface invokes and invocation slow paths will load arguments
31457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     * as usual - except instead of loading arg0/r0 with the target Method*, arg0/r0 will contain
3157ea6a170486d81b127e69673cd1020c4db628c93Nicolas Geoffray     * the method_idx.  This wrapper will save arg1-arg3 and call the appropriate C helper.
31657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     * NOTE: "this" is first visible argument of the target, and so can be found in arg1/r1.
31757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     *
31857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     * The helper will attempt to locate the target and return a 64-bit result in r0/r1 consisting
31957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     * of the target Method* in r0 and method->code_ in r1.
32057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     *
3212cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier     * If unsuccessful, the helper will return null/null will bea pending exception in the
32257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     * thread and we branch to another stub to deliver it.
32357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     *
32457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     * On success this wrapper will restore arguments and *jump* to the target, leaving the lr
32557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     * pointing back to the original caller.
32657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers     */
3273031c8da0c5009183f770b005c245f9bf2a4d01bAndreas GampeMACRO1(INVOKE_TRAMPOLINE_BODY, cxx_name)
3281d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME ebx, ebx
3297caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    movl %esp, %edx  // remember SP
330966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
3317caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    // Outgoing argument set up
332aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH edx                      // pass SP
3337caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
3343f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
335aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH ecx                      // pass arg2
336aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH eax                      // pass arg1
3374360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    call CALLVAR(cxx_name)        // cxx_name(arg1, arg2, Thread*, SP)
3387caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    movl %edx, %edi               // save code pointer in EDI
3397ea6a170486d81b127e69673cd1020c4db628c93Nicolas Geoffray    addl MACRO_LITERAL(20), %esp  // Pop arguments skip eax
3407ea6a170486d81b127e69673cd1020c4db628c93Nicolas Geoffray    CFI_ADJUST_CFA_OFFSET(-20)
341966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
342966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Restore FPRs.
343966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd 0(%esp), %xmm0
344966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd 8(%esp), %xmm1
345966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd 16(%esp), %xmm2
346966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd 24(%esp), %xmm3
347966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
348966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Remove space for FPR args.
349966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    addl MACRO_LITERAL(4 * 8), %esp
350966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    CFI_ADJUST_CFA_OFFSET(-4 * 8)
351966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
352bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    POP ecx  // Restore args except eax
353aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    POP edx
354aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    POP ebx
355bbb32c277b800a8ee378c16a3645ab6d4d19aef1Dave Allison    POP ebp  // Restore callee saves
356aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    POP esi
3577caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    // Swap EDI callee save with code pointer.
3587caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    xchgl %edi, (%esp)
3597caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    testl %eax, %eax              // Branch forward if exception pending.
3607caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    jz    1f
3617caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    // Tail call to intended method.
3627caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    ret
3637caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers1:
36420b5c6c9d6fdd0b4192d467086a097a28d7b3a0ajeffhao    addl MACRO_LITERAL(4), %esp   // Pop code pointer off stack
3653f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(-4)
3667caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    DELIVER_PENDING_EXCEPTION
3673031c8da0c5009183f770b005c245f9bf2a4d01bAndreas GampeEND_MACRO
3683031c8da0c5009183f770b005c245f9bf2a4d01bAndreas GampeMACRO2(INVOKE_TRAMPOLINE, c_name, cxx_name)
3694360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    DEFINE_FUNCTION VAR(c_name)
3704360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    INVOKE_TRAMPOLINE_BODY RAW_VAR(cxx_name)
3714360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    END_FUNCTION VAR(c_name)
372787ec205ee545b9c08f4fc6d3823cb43d10083afElliott HughesEND_MACRO
37357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
3748dbb708c7dc05c786329eb5c3fff3194ab6472acLogan ChienINVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck
37557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
3768dbb708c7dc05c786329eb5c3fff3194ab6472acLogan ChienINVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck
3778dbb708c7dc05c786329eb5c3fff3194ab6472acLogan ChienINVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck
3788dbb708c7dc05c786329eb5c3fff3194ab6472acLogan ChienINVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
3798dbb708c7dc05c786329eb5c3fff3194ab6472acLogan ChienINVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
38057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
3815d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    /*
382966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell     * Helper for quick invocation stub to set up XMM registers.
383966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell     * Increments shorty and arg_array and clobbers temp_char.
384966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell     * Branches to finished if it encounters the end of the shorty.
385966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell     */
386966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P MendellMACRO5(LOOP_OVER_SHORTY_LOADING_XMMS, xmm_reg, shorty, arg_array, temp_char, finished)
387966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell1: // LOOP
3884360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    movb (REG_VAR(shorty)), REG_VAR(temp_char)     // temp_char := *shorty
3894360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl MACRO_LITERAL(1), REG_VAR(shorty)         // shorty++
3904360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    cmpb MACRO_LITERAL(0), REG_VAR(temp_char)      // if (temp_char == '\0')
3914360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    je VAR(finished)                               //   goto finished
3924360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    cmpb MACRO_LITERAL(68), REG_VAR(temp_char)     // if (temp_char == 'D')
3934360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    je 2f                                          //   goto FOUND_DOUBLE
3944360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    cmpb MACRO_LITERAL(70), REG_VAR(temp_char)     // if (temp_char == 'F')
3954360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    je 3f                                          //   goto FOUND_FLOAT
3964360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl MACRO_LITERAL(4), REG_VAR(arg_array)      // arg_array++
397966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    //  Handle extra space in arg array taken by a long.
3984360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    cmpb MACRO_LITERAL(74), REG_VAR(temp_char)     // if (temp_char != 'J')
3994360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    jne 1b                                         //   goto LOOP
4004360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl MACRO_LITERAL(4), REG_VAR(arg_array)      // arg_array++
4014360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    jmp 1b                                         // goto LOOP
402966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell2:  // FOUND_DOUBLE
4034360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    movsd (REG_VAR(arg_array)), REG_VAR(xmm_reg)
4044360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl MACRO_LITERAL(8), REG_VAR(arg_array)      // arg_array+=2
405966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    jmp 4f
406966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell3:  // FOUND_FLOAT
4074360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    movss (REG_VAR(arg_array)), REG_VAR(xmm_reg)
4084360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl MACRO_LITERAL(4), REG_VAR(arg_array)      // arg_array++
409966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell4:
410966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P MendellEND_MACRO
411966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
412966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    /*
413966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell     * Helper for quick invocation stub to set up GPR registers.
414966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell     * Increments shorty and arg_array, and returns the current short character in
415966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell     * temp_char. Branches to finished if it encounters the end of the shorty.
416966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell     */
417966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P MendellMACRO4(SKIP_OVER_FLOATS, shorty, arg_array, temp_char, finished)
418966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell1: // LOOP:
4194360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    movb (REG_VAR(shorty)), REG_VAR(temp_char)     // temp_char := *shorty
4204360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl MACRO_LITERAL(1), REG_VAR(shorty)         // shorty++
4214360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    cmpb MACRO_LITERAL(0), REG_VAR(temp_char)      // if (temp_char == '\0')
4224360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    je VAR(finished)                               //   goto finished
4234360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    cmpb MACRO_LITERAL(70), REG_VAR(temp_char)     // if (temp_char == 'F')
4244360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    je 3f                                          //   goto SKIP_FLOAT
4254360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    cmpb MACRO_LITERAL(68), REG_VAR(temp_char)     // if (temp_char == 'D')
4264360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    je 4f                                          //   goto SKIP_DOUBLE
4274360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    jmp 5f                                         // goto end
428966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell3:  // SKIP_FLOAT
4294360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl MACRO_LITERAL(4), REG_VAR(arg_array)      // arg_array++
4304360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    jmp 1b                                         // goto LOOP
431966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell4:  // SKIP_DOUBLE
4324360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl MACRO_LITERAL(8), REG_VAR(arg_array)      // arg_array+=2
4334360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    jmp 1b                                         // goto LOOP
434966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell5:
435966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P MendellEND_MACRO
436966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
437966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell  /*
438966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell     * Quick invocation stub (non-static).
4396474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao     * On entry:
4406474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao     *   [sp] = return address
4416474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao     *   [sp + 4] = method pointer
4422cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier     *   [sp + 8] = argument array or null for no argument methods
4436474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao     *   [sp + 12] = size of argument array in bytes
4446474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao     *   [sp + 16] = (managed) thread pointer
4456474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao     *   [sp + 20] = JValue* result
4460177e53ea521ad58b70c305700dab32f1ac773b7Ian Rogers     *   [sp + 24] = shorty
4475d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao     */
4485d9173014c1ca09f7249a6b07629aa37778b5f8fJeff HaoDEFINE_FUNCTION art_quick_invoke_stub
449966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Save the non-volatiles.
4505d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    PUSH ebp                      // save ebp
4515d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    PUSH ebx                      // save ebx
4524808846b2a8647a448aaa05d561a4f60b190196bNicolas Geoffray    PUSH esi                      // save esi
4534808846b2a8647a448aaa05d561a4f60b190196bNicolas Geoffray    PUSH edi                      // save edi
454966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Set up argument XMM registers.
455966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    mov 24+16(%esp), %esi         // ESI := shorty + 1  ; ie skip return arg character.
456966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    addl LITERAL(1), %esi
457966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    mov 8+16(%esp), %edi          // EDI := arg_array + 4 ; ie skip this pointer.
458966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    addl LITERAL(4), %edi
459966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Clobbers ESI, EDI, EAX.
460966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    LOOP_OVER_SHORTY_LOADING_XMMS xmm0, esi, edi, al, .Lxmm_setup_finished
461966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    LOOP_OVER_SHORTY_LOADING_XMMS xmm1, esi, edi, al, .Lxmm_setup_finished
462966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    LOOP_OVER_SHORTY_LOADING_XMMS xmm2, esi, edi, al, .Lxmm_setup_finished
463966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    LOOP_OVER_SHORTY_LOADING_XMMS xmm3, esi, edi, al, .Lxmm_setup_finished
464966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    .balign 16
465966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell.Lxmm_setup_finished:
4665d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    mov %esp, %ebp                // copy value of stack pointer into base pointer
4673f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_DEF_CFA_REGISTER(ebp)
4684808846b2a8647a448aaa05d561a4f60b190196bNicolas Geoffray    mov 28(%ebp), %ebx            // get arg array size
4694808846b2a8647a448aaa05d561a4f60b190196bNicolas Geoffray    // reserve space for return addr, method*, ebx, ebp, esi, and edi in frame
4704808846b2a8647a448aaa05d561a4f60b190196bNicolas Geoffray    addl LITERAL(36), %ebx
4714808846b2a8647a448aaa05d561a4f60b190196bNicolas Geoffray    // align frame size to 16 bytes
4724808846b2a8647a448aaa05d561a4f60b190196bNicolas Geoffray    andl LITERAL(0xFFFFFFF0), %ebx
4734808846b2a8647a448aaa05d561a4f60b190196bNicolas Geoffray    subl LITERAL(20), %ebx        // remove space for return address, ebx, ebp, esi and edi
4745d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    subl %ebx, %esp               // reserve stack space for argument array
475966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
4762cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    movl LITERAL(0), (%esp)       // store null for method*
477966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
478966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Copy arg array into stack.
479966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl 28(%ebp), %ecx           // ECX = size of args
480966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl 24(%ebp), %esi           // ESI = argument array
481966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    leal 4(%esp), %edi            // EDI = just after Method* in stack arguments
482966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    rep movsb                     // while (ecx--) { *edi++ = *esi++ }
483966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
484966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    mov 40(%ebp), %esi            // ESI := shorty + 1  ; ie skip return arg character.
485966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    addl LITERAL(1), %esi
486966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    mov 24(%ebp), %edi            // EDI := arg_array
487966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    mov 0(%edi), %ecx             // ECX := this pointer
488966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    addl LITERAL(4), %edi         // EDI := arg_array + 4 ; ie skip this pointer.
489966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
490966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Enumerate the possible cases for loading GPRS.
491966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // edx (and maybe ebx):
492966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    SKIP_OVER_FLOATS esi, edi, al, .Lgpr_setup_finished
493966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    cmpb LITERAL(74), %al         // if (al == 'J') goto FOUND_LONG
494966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    je .LfirstLong
495966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Must be an integer value.
496966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl (%edi), %edx
497966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    addl LITERAL(4), %edi         // arg_array++
498966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
499966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Now check ebx
500966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    SKIP_OVER_FLOATS esi, edi, al, .Lgpr_setup_finished
5013e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell    // Must be first word of a long, or an integer. First word of long doesn't
5023e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell    // go into EBX, but can be loaded there anyways, as it is harmless.
503966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl (%edi), %ebx
504966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    jmp .Lgpr_setup_finished
505966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell.LfirstLong:
506966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl (%edi), %edx
507966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl 4(%edi), %ebx
508966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Nothing left to load.
509966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell.Lgpr_setup_finished:
5104808846b2a8647a448aaa05d561a4f60b190196bNicolas Geoffray    mov 20(%ebp), %eax            // move method pointer into eax
511e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    call *ART_METHOD_QUICK_CODE_OFFSET_32(%eax) // call the method
5125d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    mov %ebp, %esp                // restore stack pointer
5133f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_DEF_CFA_REGISTER(esp)
5144808846b2a8647a448aaa05d561a4f60b190196bNicolas Geoffray    POP edi                       // pop edi
5154808846b2a8647a448aaa05d561a4f60b190196bNicolas Geoffray    POP esi                       // pop esi
5165d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    POP ebx                       // pop ebx
5175d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    POP ebp                       // pop ebp
5185d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    mov 20(%esp), %ecx            // get result pointer
5190177e53ea521ad58b70c305700dab32f1ac773b7Ian Rogers    mov %eax, (%ecx)              // store the result assuming its a long, int or Object*
5200177e53ea521ad58b70c305700dab32f1ac773b7Ian Rogers    mov %edx, 4(%ecx)             // store the other half of the result
5210177e53ea521ad58b70c305700dab32f1ac773b7Ian Rogers    mov 24(%esp), %edx            // get the shorty
5220177e53ea521ad58b70c305700dab32f1ac773b7Ian Rogers    cmpb LITERAL(68), (%edx)      // test if result type char == 'D'
5238016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers    je .Lreturn_double_quick
5240177e53ea521ad58b70c305700dab32f1ac773b7Ian Rogers    cmpb LITERAL(70), (%edx)      // test if result type char == 'F'
5258016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers    je .Lreturn_float_quick
5266474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao    ret
5278016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers.Lreturn_double_quick:
5285d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    movsd %xmm0, (%ecx)           // store the floating point result
5295d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    ret
5308016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers.Lreturn_float_quick:
5310177e53ea521ad58b70c305700dab32f1ac773b7Ian Rogers    movss %xmm0, (%ecx)           // store the floating point result
5320177e53ea521ad58b70c305700dab32f1ac773b7Ian Rogers    ret
5335d9173014c1ca09f7249a6b07629aa37778b5f8fJeff HaoEND_FUNCTION art_quick_invoke_stub
5345d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao
535966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell  /*
536966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell     * Quick invocation stub (static).
537966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell     * On entry:
538966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell     *   [sp] = return address
539966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell     *   [sp + 4] = method pointer
5402cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier     *   [sp + 8] = argument array or null for no argument methods
541966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell     *   [sp + 12] = size of argument array in bytes
542966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell     *   [sp + 16] = (managed) thread pointer
543966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell     *   [sp + 20] = JValue* result
544966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell     *   [sp + 24] = shorty
545966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell     */
546966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P MendellDEFINE_FUNCTION art_quick_invoke_static_stub
547966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Save the non-volatiles.
548966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    PUSH ebp                      // save ebp
549966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    PUSH ebx                      // save ebx
550966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    PUSH esi                      // save esi
551966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    PUSH edi                      // save edi
552966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Set up argument XMM registers.
553966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    mov 24+16(%esp), %esi         // ESI := shorty + 1  ; ie skip return arg character.
554966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    addl LITERAL(1), %esi
555966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    mov 8+16(%esp), %edi          // EDI := arg_array
556966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Clobbers ESI, EDI, EAX.
557966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    LOOP_OVER_SHORTY_LOADING_XMMS xmm0, esi, edi, al, .Lxmm_setup_finished2
558966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    LOOP_OVER_SHORTY_LOADING_XMMS xmm1, esi, edi, al, .Lxmm_setup_finished2
559966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    LOOP_OVER_SHORTY_LOADING_XMMS xmm2, esi, edi, al, .Lxmm_setup_finished2
560966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    LOOP_OVER_SHORTY_LOADING_XMMS xmm3, esi, edi, al, .Lxmm_setup_finished2
561966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    .balign 16
562966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell.Lxmm_setup_finished2:
563966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    mov %esp, %ebp                // copy value of stack pointer into base pointer
564966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    CFI_DEF_CFA_REGISTER(ebp)
565966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    mov 28(%ebp), %ebx            // get arg array size
566966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // reserve space for return addr, method*, ebx, ebp, esi, and edi in frame
567966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    addl LITERAL(36), %ebx
568966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // align frame size to 16 bytes
569966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    andl LITERAL(0xFFFFFFF0), %ebx
570966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    subl LITERAL(20), %ebx        // remove space for return address, ebx, ebp, esi and edi
571966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    subl %ebx, %esp               // reserve stack space for argument array
572966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
5732cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    movl LITERAL(0), (%esp)       // store null for method*
574966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
575966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Copy arg array into stack.
576966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl 28(%ebp), %ecx           // ECX = size of args
577966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl 24(%ebp), %esi           // ESI = argument array
578966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    leal 4(%esp), %edi            // EDI = just after Method* in stack arguments
579966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    rep movsb                     // while (ecx--) { *edi++ = *esi++ }
580966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
581966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    mov 40(%ebp), %esi            // ESI := shorty + 1  ; ie skip return arg character.
582966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    addl LITERAL(1), %esi
583966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    mov 24(%ebp), %edi            // EDI := arg_array
584966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
585966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Enumerate the possible cases for loading GPRS.
586966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // ecx (and maybe edx)
587966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    SKIP_OVER_FLOATS esi, edi, al, .Lgpr_setup_finished2
588966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    cmpb LITERAL(74), %al         // if (al == 'J') goto FOUND_LONG
589966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    je .LfirstLong2
590966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Must be an integer value.  Load into ECX.
591966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl (%edi), %ecx
592966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    addl LITERAL(4), %edi         // arg_array++
593966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
594966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Now check edx (and maybe ebx).
595966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    SKIP_OVER_FLOATS esi, edi, al, .Lgpr_setup_finished2
596966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    cmpb LITERAL(74), %al         // if (al == 'J') goto FOUND_LONG
597966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    je .LSecondLong2
598966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Must be an integer.  Load into EDX.
599966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl (%edi), %edx
600966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    addl LITERAL(4), %edi         // arg_array++
601966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
602966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Is there anything for ebx?
603966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    SKIP_OVER_FLOATS esi, edi, al, .Lgpr_setup_finished2
6043e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell    // Must be first word of a long, or an integer. First word of long doesn't
6053e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell    // go into EBX, but can be loaded there anyways, as it is harmless.
606966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl (%edi), %ebx
607966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    jmp .Lgpr_setup_finished2
608966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell.LSecondLong2:
609966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // EDX:EBX is long.  That is all.
610966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl (%edi), %edx
611966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl 4(%edi), %ebx
612966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    jmp .Lgpr_setup_finished2
613966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell.LfirstLong2:
614966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // ECX:EDX is a long
615966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl (%edi), %ecx
616966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl 4(%edi), %edx
617966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    addl LITERAL(8), %edi         // arg_array += 2
618966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
619966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Anything for EBX?
620966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    SKIP_OVER_FLOATS esi, edi, al, .Lgpr_setup_finished2
6213e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell    // Must be first word of a long, or an integer. First word of long doesn't
6223e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell    // go into EBX, but can be loaded there anyways, as it is harmless.
623966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl (%edi), %ebx
624966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    jmp .Lgpr_setup_finished2
625966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Nothing left to load.
626966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell.Lgpr_setup_finished2:
627966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    mov 20(%ebp), %eax            // move method pointer into eax
628e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    call *ART_METHOD_QUICK_CODE_OFFSET_32(%eax) // call the method
629966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    mov %ebp, %esp                // restore stack pointer
630966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    CFI_DEF_CFA_REGISTER(esp)
631966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    POP edi                       // pop edi
632966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    POP esi                       // pop esi
633966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    POP ebx                       // pop ebx
634966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    POP ebp                       // pop ebp
635966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    mov 20(%esp), %ecx            // get result pointer
636966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    mov %eax, (%ecx)              // store the result assuming its a long, int or Object*
637966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    mov %edx, 4(%ecx)             // store the other half of the result
638966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    mov 24(%esp), %edx            // get the shorty
639966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    cmpb LITERAL(68), (%edx)      // test if result type char == 'D'
640966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    je .Lreturn_double_quick2
641966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    cmpb LITERAL(70), (%edx)      // test if result type char == 'F'
642966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    je .Lreturn_float_quick2
643966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    ret
644966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell.Lreturn_double_quick2:
645966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd %xmm0, (%ecx)           // store the floating point result
646966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    ret
647966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell.Lreturn_float_quick2:
648966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movss %xmm0, (%ecx)           // store the floating point result
649966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    ret
650966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P MendellEND_FUNCTION art_quick_invoke_static_stub
651966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
652d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan RogersMACRO3(NO_ARG_DOWNCALL, c_name, cxx_name, return_macro)
6534360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    DEFINE_FUNCTION VAR(c_name)
6541d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx  // save ref containing registers for GC
6557caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    // Outgoing argument set up
6564360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    subl MACRO_LITERAL(12), %esp                // push padding
6571d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(12)
6584360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    pushl %fs:THREAD_SELF_OFFSET                // pass Thread::Current()
6593f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
6604360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    call CALLVAR(cxx_name)                      // cxx_name(Thread*)
6614360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl MACRO_LITERAL(16), %esp                // pop arguments
6623f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(-16)
6634360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME         // restore frame up to return address
6644360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    CALL_MACRO(return_macro)                    // return or deliver exception
6654360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    END_FUNCTION VAR(c_name)
6667caad77632ae121c9f64c488e3f8f710e2c4813dIan RogersEND_MACRO
6677caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers
668d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan RogersMACRO3(ONE_ARG_DOWNCALL, c_name, cxx_name, return_macro)
6694360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    DEFINE_FUNCTION VAR(c_name)
6701d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  ebx, ebx  // save ref containing registers for GC
6717caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    // Outgoing argument set up
6724360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    subl MACRO_LITERAL(8), %esp                  // push padding
6731d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(8)
6744360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    pushl %fs:THREAD_SELF_OFFSET                 // pass Thread::Current()
6753f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
6764360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                                     // pass arg1
6774360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    call CALLVAR(cxx_name)                       // cxx_name(arg1, Thread*)
6784360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl MACRO_LITERAL(16), %esp                 // pop arguments
6793f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(-16)
6804360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME          // restore frame up to return address
6814360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    CALL_MACRO(return_macro)                     // return or deliver exception
6824360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    END_FUNCTION VAR(c_name)
683d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan RogersEND_MACRO
6847caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers
685d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan RogersMACRO3(TWO_ARG_DOWNCALL, c_name, cxx_name, return_macro)
6864360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    DEFINE_FUNCTION VAR(c_name)
6871d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  ebx, ebx  // save ref containing registers for GC
6887caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    // Outgoing argument set up
6894360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                                     // push padding
6904360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    pushl %fs:THREAD_SELF_OFFSET                 // pass Thread::Current()
6913f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
6924360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH ecx                                     // pass arg2
6934360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                                     // pass arg1
6944360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    call CALLVAR(cxx_name)                       // cxx_name(arg1, arg2, Thread*)
6954360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl MACRO_LITERAL(16), %esp                 // pop arguments
6963f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(-16)
6974360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME          // restore frame up to return address
6984360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    CALL_MACRO(return_macro)                     // return or deliver exception
6994360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    END_FUNCTION VAR(c_name)
700d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan RogersEND_MACRO
7017caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers
702d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan RogersMACRO3(THREE_ARG_DOWNCALL, c_name, cxx_name, return_macro)
7034360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    DEFINE_FUNCTION VAR(c_name)
7041d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  ebx, ebx  // save ref containing registers for GC
7057caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    // Outgoing argument set up
7064360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    pushl %fs:THREAD_SELF_OFFSET                 // pass Thread::Current()
7073f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
7084360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH edx                                     // pass arg3
7094360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH ecx                                     // pass arg2
7104360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                                     // pass arg1
7114360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    call CALLVAR(cxx_name)                       // cxx_name(arg1, arg2, arg3, Thread*)
7124360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl MACRO_LITERAL(16), %esp                 // pop arguments
7131d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(-16)
7144360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME          // restore frame up to return address
7154360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    CALL_MACRO(return_macro)                     // return or deliver exception
7164360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    END_FUNCTION VAR(c_name)
717d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan RogersEND_MACRO
718d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers
719848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff HaoMACRO3(FOUR_ARG_DOWNCALL, c_name, cxx_name, return_macro)
7204360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    DEFINE_FUNCTION VAR(c_name)
721a048ca8e0ff6d0e79d070decf9fa2331e2d13824Nicolas Geoffray    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME_PRESERVE_GOT_REG  ebx, ebx  // save ref containing registers for GC
722f969a209c30e3af636342d2fb7851d82a2529bf7Roland Levillain
723848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    // Outgoing argument set up
7244360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    subl MACRO_LITERAL(12), %esp                 // alignment padding
725848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    CFI_ADJUST_CFA_OFFSET(12)
7264360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    pushl %fs:THREAD_SELF_OFFSET                 // pass Thread::Current()
727848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    CFI_ADJUST_CFA_OFFSET(4)
7284360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH ebx                                     // pass arg4
7294360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH edx                                     // pass arg3
7304360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH ecx                                     // pass arg2
7314360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                                     // pass arg1
7324360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    call CALLVAR(cxx_name)                       // cxx_name(arg1, arg2, arg3, arg4, Thread*)
7334360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl MACRO_LITERAL(32), %esp                 // pop arguments
734848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    CFI_ADJUST_CFA_OFFSET(-32)
7354360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME          // restore frame up to return address
7364360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    CALL_MACRO(return_macro)                     // return or deliver exception
7374360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    END_FUNCTION VAR(c_name)
738848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff HaoEND_MACRO
739848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao
74037f05ef45e0393de812d51261dc293240c17294dFred ShihMACRO3(ONE_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro)
7414360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    DEFINE_FUNCTION VAR(c_name)
7424360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  ebx, ebx       // save ref containing registers for GC
74337f05ef45e0393de812d51261dc293240c17294dFred Shih    // Outgoing argument set up
7441d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    mov FRAME_SIZE_REFS_ONLY_CALLEE_SAVE(%esp), %ecx  // get referrer
7454360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                                          // push padding
7464360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    pushl %fs:THREAD_SELF_OFFSET                      // pass Thread::Current()
74737f05ef45e0393de812d51261dc293240c17294dFred Shih    CFI_ADJUST_CFA_OFFSET(4)
7484360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH ecx                                          // pass referrer
7494360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                                          // pass arg1
7504360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    call CALLVAR(cxx_name)                            // cxx_name(arg1, referrer, Thread*)
7514360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl MACRO_LITERAL(16), %esp                      // pop arguments
75237f05ef45e0393de812d51261dc293240c17294dFred Shih    CFI_ADJUST_CFA_OFFSET(-16)
7534360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME               // restore frame up to return address
7544360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    CALL_MACRO(return_macro)                          // return or deliver exception
7554360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    END_FUNCTION VAR(c_name)
75637f05ef45e0393de812d51261dc293240c17294dFred ShihEND_MACRO
75737f05ef45e0393de812d51261dc293240c17294dFred Shih
75837f05ef45e0393de812d51261dc293240c17294dFred ShihMACRO3(TWO_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro)
7594360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    DEFINE_FUNCTION VAR(c_name)
7604360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx        // save ref containing registers for GC
7611d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    // Outgoing argument set up
7621d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    mov FRAME_SIZE_REFS_ONLY_CALLEE_SAVE(%esp), %edx  // get referrer
7634360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    pushl %fs:THREAD_SELF_OFFSET                      // pass Thread::Current()
76437f05ef45e0393de812d51261dc293240c17294dFred Shih    CFI_ADJUST_CFA_OFFSET(4)
7654360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH edx                                          // pass referrer
7664360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH ecx                                          // pass arg2
7674360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                                          // pass arg1
7684360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    call CALLVAR(cxx_name)                            // cxx_name(arg1, arg2, referrer, Thread*)
7694360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl MACRO_LITERAL(16), %esp                      // pop arguments
7701d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(-16)
7714360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME               // restore frame up to return address
7724360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    CALL_MACRO(return_macro)                          // return or deliver exception
7734360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    END_FUNCTION VAR(c_name)
77437f05ef45e0393de812d51261dc293240c17294dFred ShihEND_MACRO
77537f05ef45e0393de812d51261dc293240c17294dFred Shih
7761d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersMACRO3(THREE_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro)
7774360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    DEFINE_FUNCTION VAR(c_name)
7784360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx        // save ref containing registers for GC
7791d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    // Outgoing argument set up
7801d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    mov FRAME_SIZE_REFS_ONLY_CALLEE_SAVE(%esp), %ebx  // get referrer
7814360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    subl MACRO_LITERAL(12), %esp                      // alignment padding
7821d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(12)
7834360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    pushl %fs:THREAD_SELF_OFFSET                      // pass Thread::Current()
7841d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(4)
7854360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH ebx                                          // pass referrer
7864360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH edx                                          // pass arg3
7874360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH ecx                                          // pass arg2
7884360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                                          // pass arg1
7894360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    call CALLVAR(cxx_name)                            // cxx_name(arg1, arg2, arg3, referrer,
7904360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe                                                      //          Thread*)
7914360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl LITERAL(32), %esp                            // pop arguments
7921d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(-32)
7934360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME               // restore frame up to return address
7944360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    CALL_MACRO(return_macro)                          // return or deliver exception
7954360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    END_FUNCTION VAR(c_name)
7961d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersEND_MACRO
79737f05ef45e0393de812d51261dc293240c17294dFred Shih
7984adeab196d160f70b4865fb8be048ddd2ac7ab82Hiroshi YamauchiMACRO0(RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER)
799d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers    testl %eax, %eax               // eax == 0 ?
800d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers    jz  1f                         // if eax == 0 goto 1
801d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers    ret                            // return
802d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers1:                                 // deliver exception on current thread
803d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers    DELIVER_PENDING_EXCEPTION
804d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan RogersEND_MACRO
805d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers
806d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan RogersMACRO0(RETURN_IF_EAX_ZERO)
807d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers    testl %eax, %eax               // eax == 0 ?
808d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers    jnz  1f                        // if eax != 0 goto 1
809d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers    ret                            // return
810d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers1:                                 // deliver exception on current thread
8117caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    DELIVER_PENDING_EXCEPTION
812d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan RogersEND_MACRO
813d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers
814d66a87583bebcd5f89906aeaae9f8fb104ef2ac9jeffhaoMACRO0(RETURN_OR_DELIVER_PENDING_EXCEPTION)
8151d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    cmpl MACRO_LITERAL(0),%fs:THREAD_EXCEPTION_OFFSET // exception field == 0 ?
8164360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    jne 1f                                            // if exception field != 0 goto 1
8174360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    ret                                               // return
8184360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe1:                                                    // deliver exception on current thread
819d66a87583bebcd5f89906aeaae9f8fb104ef2ac9jeffhao    DELIVER_PENDING_EXCEPTION
820d66a87583bebcd5f89906aeaae9f8fb104ef2ac9jeffhaoEND_MACRO
821d66a87583bebcd5f89906aeaae9f8fb104ef2ac9jeffhao
8227410f29b4dae223befac036ea567d7f33351dad1Mathieu Chartier// Generate the allocation entrypoints for each allocator.
8234adeab196d160f70b4865fb8be048ddd2ac7ab82Hiroshi YamauchiGENERATE_ALLOC_ENTRYPOINTS_FOR_EACH_ALLOCATOR
824de95c870993673b512009d94a931cd980df0e6b6lwang
825de95c870993673b512009d94a931cd980df0e6b6lwang// A hand-written override for GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_rosalloc, RosAlloc).
826de95c870993673b512009d94a931cd980df0e6b6lwangDEFINE_FUNCTION art_quick_alloc_object_rosalloc
827de95c870993673b512009d94a931cd980df0e6b6lwang    // Fast path rosalloc allocation.
828de95c870993673b512009d94a931cd980df0e6b6lwang    // eax: uint32_t type_idx/return value, ecx: ArtMethod*
829de95c870993673b512009d94a931cd980df0e6b6lwang    // ebx, edx: free
830de95c870993673b512009d94a931cd980df0e6b6lwang    PUSH edi
831de95c870993673b512009d94a931cd980df0e6b6lwang    movl ART_METHOD_DEX_CACHE_TYPES_OFFSET_32(%ecx), %edx  // Load dex cache resolved types array
832de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // Load the class (edx)
833de95c870993673b512009d94a931cd980df0e6b6lwang    movl 0(%edx, %eax, COMPRESSED_REFERENCE_SIZE), %edx
834de95c870993673b512009d94a931cd980df0e6b6lwang    testl %edx, %edx                                    // Check null class
835de95c870993673b512009d94a931cd980df0e6b6lwang    jz   .Lart_quick_alloc_object_rosalloc_slow_path
836de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // Check class status
837de95c870993673b512009d94a931cd980df0e6b6lwang    cmpl LITERAL(MIRROR_CLASS_STATUS_INITIALIZED), MIRROR_CLASS_STATUS_OFFSET(%edx)
838de95c870993673b512009d94a931cd980df0e6b6lwang    jne  .Lart_quick_alloc_object_rosalloc_slow_path
839de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // No fake dependence needed on x86
840de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // between status and flags load,
841de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // since each load is a load-acquire,
842de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // no loads reordering.
843de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // Check access flags has
844de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // kAccClassIsFinalizable
845de95c870993673b512009d94a931cd980df0e6b6lwang    testl LITERAL(ACCESS_FLAGS_CLASS_IS_FINALIZABLE), MIRROR_CLASS_ACCESS_FLAGS_OFFSET(%edx)
846de95c870993673b512009d94a931cd980df0e6b6lwang    jnz   .Lart_quick_alloc_object_rosalloc_slow_path
847de95c870993673b512009d94a931cd980df0e6b6lwang
848de95c870993673b512009d94a931cd980df0e6b6lwang    movl %fs:THREAD_SELF_OFFSET, %ebx                   // ebx = thread
849de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // Check if the thread local allocation
850de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // stack has room
851de95c870993673b512009d94a931cd980df0e6b6lwang    movl THREAD_LOCAL_ALLOC_STACK_TOP_OFFSET(%ebx), %edi
852de95c870993673b512009d94a931cd980df0e6b6lwang    cmpl THREAD_LOCAL_ALLOC_STACK_END_OFFSET(%ebx), %edi
853de95c870993673b512009d94a931cd980df0e6b6lwang    jae  .Lart_quick_alloc_object_rosalloc_slow_path
854de95c870993673b512009d94a931cd980df0e6b6lwang
855de95c870993673b512009d94a931cd980df0e6b6lwang    movl MIRROR_CLASS_OBJECT_SIZE_OFFSET(%edx), %edi    // Load the object size (edi)
856de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // Check if the size is for a thread
857de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // local allocation
858de95c870993673b512009d94a931cd980df0e6b6lwang    cmpl LITERAL(ROSALLOC_MAX_THREAD_LOCAL_BRACKET_SIZE), %edi
859de95c870993673b512009d94a931cd980df0e6b6lwang    ja   .Lart_quick_alloc_object_rosalloc_slow_path
860de95c870993673b512009d94a931cd980df0e6b6lwang    decl %edi
861de95c870993673b512009d94a931cd980df0e6b6lwang    shrl LITERAL(ROSALLOC_BRACKET_QUANTUM_SIZE_SHIFT), %edi // Calculate the rosalloc bracket index
862de95c870993673b512009d94a931cd980df0e6b6lwang                                                            // from object size.
863de95c870993673b512009d94a931cd980df0e6b6lwang                                                            // Align up the size by the rosalloc
864de95c870993673b512009d94a931cd980df0e6b6lwang                                                            // bracket quantum size and divide
865de95c870993673b512009d94a931cd980df0e6b6lwang                                                            // by the quantum size and subtract
866de95c870993673b512009d94a931cd980df0e6b6lwang                                                            // by 1. This code is a shorter but
867de95c870993673b512009d94a931cd980df0e6b6lwang                                                            // equivalent version.
868de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // Load thread local rosalloc run (ebx)
869de95c870993673b512009d94a931cd980df0e6b6lwang    movl THREAD_ROSALLOC_RUNS_OFFSET(%ebx, %edi, __SIZEOF_POINTER__), %ebx
870de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // Load free_list head (edi),
871de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // this will be the return value.
872de95c870993673b512009d94a931cd980df0e6b6lwang    movl (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_HEAD_OFFSET)(%ebx), %edi
873de95c870993673b512009d94a931cd980df0e6b6lwang    test %edi, %edi
874de95c870993673b512009d94a931cd980df0e6b6lwang    jz   .Lart_quick_alloc_object_rosalloc_slow_path
875de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // Point of no slow path. Won't go to
876de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // the slow path from here on. Ok to
877de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // clobber eax and ecx.
878de95c870993673b512009d94a931cd980df0e6b6lwang    movl %edi, %eax
879de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // Load the next pointer of the head
880de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // and update head of free list with
881de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // next pointer
882de95c870993673b512009d94a931cd980df0e6b6lwang    movl ROSALLOC_SLOT_NEXT_OFFSET(%eax), %edi
883de95c870993673b512009d94a931cd980df0e6b6lwang    movl %edi, (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_HEAD_OFFSET)(%ebx)
884de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // Decrement size of free list by 1
885de95c870993673b512009d94a931cd980df0e6b6lwang    decl (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_SIZE_OFFSET)(%ebx)
886de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // Store the class pointer in the
887de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // header. This also overwrites the
888de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // next pointer. The offsets are
889de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // asserted to match.
890de95c870993673b512009d94a931cd980df0e6b6lwang#if ROSALLOC_SLOT_NEXT_OFFSET != MIRROR_OBJECT_CLASS_OFFSET
891de95c870993673b512009d94a931cd980df0e6b6lwang#error "Class pointer needs to overwrite next pointer."
892de95c870993673b512009d94a931cd980df0e6b6lwang#endif
893de95c870993673b512009d94a931cd980df0e6b6lwang    POISON_HEAP_REF edx
894de95c870993673b512009d94a931cd980df0e6b6lwang    movl %edx, MIRROR_OBJECT_CLASS_OFFSET(%eax)
895de95c870993673b512009d94a931cd980df0e6b6lwang    movl %fs:THREAD_SELF_OFFSET, %ebx                   // ebx = thread
896de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // Push the new object onto the thread
897de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // local allocation stack and
898de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // increment the thread local
899de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // allocation stack top.
900de95c870993673b512009d94a931cd980df0e6b6lwang    movl THREAD_LOCAL_ALLOC_STACK_TOP_OFFSET(%ebx), %edi
901de95c870993673b512009d94a931cd980df0e6b6lwang    movl %eax, (%edi)
902de95c870993673b512009d94a931cd980df0e6b6lwang    addl LITERAL(COMPRESSED_REFERENCE_SIZE), %edi
903de95c870993673b512009d94a931cd980df0e6b6lwang    movl %edi, THREAD_LOCAL_ALLOC_STACK_TOP_OFFSET(%ebx)
904de95c870993673b512009d94a931cd980df0e6b6lwang                                                        // No fence needed for x86.
905de95c870993673b512009d94a931cd980df0e6b6lwang    POP edi
906de95c870993673b512009d94a931cd980df0e6b6lwang    ret
907de95c870993673b512009d94a931cd980df0e6b6lwang.Lart_quick_alloc_object_rosalloc_slow_path:
908de95c870993673b512009d94a931cd980df0e6b6lwang    POP edi
909de95c870993673b512009d94a931cd980df0e6b6lwang    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx // save ref containing registers for GC
910de95c870993673b512009d94a931cd980df0e6b6lwang    // Outgoing argument set up
911de95c870993673b512009d94a931cd980df0e6b6lwang    PUSH eax                      // alignment padding
912de95c870993673b512009d94a931cd980df0e6b6lwang    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
913de95c870993673b512009d94a931cd980df0e6b6lwang    CFI_ADJUST_CFA_OFFSET(4)
914de95c870993673b512009d94a931cd980df0e6b6lwang    PUSH ecx
915de95c870993673b512009d94a931cd980df0e6b6lwang    PUSH eax
916de95c870993673b512009d94a931cd980df0e6b6lwang    call SYMBOL(artAllocObjectFromCodeRosAlloc)  // cxx_name(arg0, arg1, Thread*)
917de95c870993673b512009d94a931cd980df0e6b6lwang    addl LITERAL(16), %esp        // pop arguments
918de95c870993673b512009d94a931cd980df0e6b6lwang    CFI_ADJUST_CFA_OFFSET(-16)
919de95c870993673b512009d94a931cd980df0e6b6lwang    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME          // resotre frame up to return address
920de95c870993673b512009d94a931cd980df0e6b6lwang    RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER      // return or deliver exception
921de95c870993673b512009d94a931cd980df0e6b6lwangEND_FUNCTION art_quick_alloc_object_rosalloc
922de95c870993673b512009d94a931cd980df0e6b6lwang
9233f2d031f639b3b9dd4adbf9e70d23de931a9801dMark MendellGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_tlab, TLAB)
92410d4c08c0ea9df0a85a11e1c77974df24078c0ecHiroshi YamauchiGENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_region_tlab, RegionTLAB)
9254adeab196d160f70b4865fb8be048ddd2ac7ab82Hiroshi Yamauchi
9264adeab196d160f70b4865fb8be048ddd2ac7ab82Hiroshi YamauchiONE_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
9274adeab196d160f70b4865fb8be048ddd2ac7ab82Hiroshi YamauchiONE_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
9284adeab196d160f70b4865fb8be048ddd2ac7ab82Hiroshi YamauchiONE_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
9294adeab196d160f70b4865fb8be048ddd2ac7ab82Hiroshi YamauchiONE_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
930d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers
931832336b3c9eb892045a8de1bb12c9361112ca3c5Ian RogersTWO_ARG_REF_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO
9327caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers
933d9c4fc94fa618617f94e1de9af5f034549100753Ian RogersDEFINE_FUNCTION art_quick_lock_object
934d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    testl %eax, %eax                      // null check object/eax
9358016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers    jz   .Lslow_lock
9368016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers.Lretry_lock:
9371d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    movl MIRROR_OBJECT_LOCK_WORD_OFFSET(%eax), %ecx  // ecx := lock word
938e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    test LITERAL(LOCK_WORD_STATE_MASK), %ecx         // test the 2 high bits.
9398016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers    jne  .Lslow_lock                      // slow path if either of the two high bits are set.
940e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    movl %ecx, %edx                       // save lock word (edx) to keep read barrier bits.
941e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    andl LITERAL(LOCK_WORD_READ_BARRIER_STATE_MASK_TOGGLED), %ecx  // zero the read barrier bits.
942d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    test %ecx, %ecx
9438016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers    jnz  .Lalready_thin                   // lock word contains a thin lock
944e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    // unlocked case - edx: original lock word, eax: obj.
945d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    movl %eax, %ecx                       // remember object in case of retry
946e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    movl %edx, %eax                       // eax: lock word zero except for read barrier bits.
947e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    movl %fs:THREAD_ID_OFFSET, %edx       // load thread id.
948e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    or   %eax, %edx                       // edx: thread id with count of 0 + read barrier bits.
949e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    lock cmpxchg  %edx, MIRROR_OBJECT_LOCK_WORD_OFFSET(%ecx)  // eax: old val, edx: new val.
950e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    jnz  .Llock_cmpxchg_fail              // cmpxchg failed retry
951d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    ret
952e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi.Lalready_thin:  // edx: lock word (with high 2 bits zero and original rb bits), eax: obj.
953e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    movl %fs:THREAD_ID_OFFSET, %ecx       // ecx := thread id
9548ef84afbaeb433adaed98a11902502dd733e5222Serguei Katkov    cmpw %cx, %dx                         // do we hold the lock already?
9558016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers    jne  .Lslow_lock
956e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    movl %edx, %ecx                       // copy the lock word to check count overflow.
957e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    andl LITERAL(LOCK_WORD_READ_BARRIER_STATE_MASK_TOGGLED), %ecx  // zero the read barrier bits.
958e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    addl LITERAL(LOCK_WORD_THIN_LOCK_COUNT_ONE), %ecx  // increment recursion count for overflow check.
959e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    test LITERAL(LOCK_WORD_READ_BARRIER_STATE_MASK), %ecx  // overflowed if either of the upper two bits (28-29) are set.
9608016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers    jne  .Lslow_lock                      // count overflowed so go slow
961e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    movl %eax, %ecx                       // save obj to use eax for cmpxchg.
962e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    movl %edx, %eax                       // copy the lock word as the old val for cmpxchg.
963e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    addl LITERAL(LOCK_WORD_THIN_LOCK_COUNT_ONE), %edx  // increment recursion count again for real.
964e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    // update lockword, cmpxchg necessary for read barrier bits.
965e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    lock cmpxchg  %edx, MIRROR_OBJECT_LOCK_WORD_OFFSET(%ecx)  // eax: old val, edx: new val.
966e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    jnz  .Llock_cmpxchg_fail              // cmpxchg failed retry
967d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    ret
968e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi.Llock_cmpxchg_fail:
969e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    movl  %ecx, %eax                      // restore eax
970e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    jmp  .Lretry_lock
9718016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers.Lslow_lock:
9721d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  ebx, ebx  // save ref containing registers for GC
973d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    // Outgoing argument set up
9744360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    subl LITERAL(8), %esp                 // alignment padding
9751d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(8)
9764360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    pushl %fs:THREAD_SELF_OFFSET          // pass Thread::Current()
9773f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
9784360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                              // pass object
9794360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    call SYMBOL(artLockObjectFromCode)    // artLockObjectFromCode(object, Thread*)
9804360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl LITERAL(16), %esp                // pop arguments
9813f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(-16)
9824360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME   // restore frame up to return address
983d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    RETURN_IF_EAX_ZERO
984d9c4fc94fa618617f94e1de9af5f034549100753Ian RogersEND_FUNCTION art_quick_lock_object
985d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
986fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas GampeDEFINE_FUNCTION art_quick_lock_object_no_inline
987fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  ebx, ebx  // save ref containing registers for GC
988fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    // Outgoing argument set up
989fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    subl LITERAL(8), %esp                 // alignment padding
990fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    CFI_ADJUST_CFA_OFFSET(8)
991fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    pushl %fs:THREAD_SELF_OFFSET          // pass Thread::Current()
992fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    CFI_ADJUST_CFA_OFFSET(4)
993fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    PUSH eax                              // pass object
994fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    call SYMBOL(artLockObjectFromCode)    // artLockObjectFromCode(object, Thread*)
995fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    addl LITERAL(16), %esp                // pop arguments
996fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    CFI_ADJUST_CFA_OFFSET(-16)
997fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME   // restore frame up to return address
998fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    RETURN_IF_EAX_ZERO
999fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas GampeEND_FUNCTION art_quick_lock_object_no_inline
1000fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe
1001fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe
1002d9c4fc94fa618617f94e1de9af5f034549100753Ian RogersDEFINE_FUNCTION art_quick_unlock_object
1003d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    testl %eax, %eax                      // null check object/eax
10048016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers    jz   .Lslow_unlock
1005e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi.Lretry_unlock:
10061d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    movl MIRROR_OBJECT_LOCK_WORD_OFFSET(%eax), %ecx  // ecx := lock word
1007d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    movl %fs:THREAD_ID_OFFSET, %edx       // edx := thread id
1008e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    test LITERAL(LOCK_WORD_STATE_MASK), %ecx
1009e78d4e1a7066d2bc60d265eb27e78b336df941ddSerguei Katkov    jnz  .Lslow_unlock                    // lock word contains a monitor
1010d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    cmpw %cx, %dx                         // does the thread id match?
10118016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers    jne  .Lslow_unlock
1012e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    movl %ecx, %edx                       // copy the lock word to detect new count of 0.
1013e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    andl LITERAL(LOCK_WORD_READ_BARRIER_STATE_MASK_TOGGLED), %edx  // zero the read barrier bits.
1014e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    cmpl LITERAL(LOCK_WORD_THIN_LOCK_COUNT_ONE), %edx
10158016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers    jae  .Lrecursive_thin_unlock
1016e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    // update lockword, cmpxchg necessary for read barrier bits.
1017e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    movl %eax, %edx                       // edx: obj
1018e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    movl %ecx, %eax                       // eax: old lock word.
1019e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    andl LITERAL(LOCK_WORD_READ_BARRIER_STATE_MASK), %ecx  // ecx: new lock word zero except original rb bits.
1020e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi#ifndef USE_READ_BARRIER
1021e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    movl %ecx, MIRROR_OBJECT_LOCK_WORD_OFFSET(%edx)
1022e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi#else
1023e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    lock cmpxchg  %ecx, MIRROR_OBJECT_LOCK_WORD_OFFSET(%edx)  // eax: old val, ecx: new val.
1024e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    jnz  .Lunlock_cmpxchg_fail            // cmpxchg failed retry
1025e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi#endif
1026d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    ret
1027e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi.Lrecursive_thin_unlock:  // ecx: original lock word, eax: obj
1028e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    // update lockword, cmpxchg necessary for read barrier bits.
1029e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    movl %eax, %edx                       // edx: obj
1030e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    movl %ecx, %eax                       // eax: old lock word.
1031e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    subl LITERAL(LOCK_WORD_THIN_LOCK_COUNT_ONE), %ecx  // ecx: new lock word with decremented count.
1032e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi#ifndef USE_READ_BARRIER
1033e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    mov  %ecx, MIRROR_OBJECT_LOCK_WORD_OFFSET(%edx)
1034e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi#else
1035e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    lock cmpxchg  %ecx, MIRROR_OBJECT_LOCK_WORD_OFFSET(%edx)  // eax: old val, ecx: new val.
1036e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    jnz  .Lunlock_cmpxchg_fail            // cmpxchg failed retry
1037e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi#endif
1038d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    ret
1039e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi.Lunlock_cmpxchg_fail:  // edx: obj
1040e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    movl %edx, %eax                       // restore eax
1041e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    jmp  .Lretry_unlock
10428016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers.Lslow_unlock:
10431d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  ebx, ebx  // save ref containing registers for GC
1044d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    // Outgoing argument set up
10454360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    subl LITERAL(8), %esp                 // alignment padding
10461d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(8)
10474360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    pushl %fs:THREAD_SELF_OFFSET          // pass Thread::Current()
10483f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
10494360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                              // pass object
10501d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    call SYMBOL(artUnlockObjectFromCode)  // artUnlockObjectFromCode(object, Thread*)
10514360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl LITERAL(16), %esp                // pop arguments
10523f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(-16)
10534360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME   // restore frame up to return address
1054d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    RETURN_IF_EAX_ZERO
1055d9c4fc94fa618617f94e1de9af5f034549100753Ian RogersEND_FUNCTION art_quick_unlock_object
1056d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
1057fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas GampeDEFINE_FUNCTION art_quick_unlock_object_no_inline
1058fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  ebx, ebx  // save ref containing registers for GC
1059fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    // Outgoing argument set up
1060fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    subl LITERAL(8), %esp                 // alignment padding
1061fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    CFI_ADJUST_CFA_OFFSET(8)
1062fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    pushl %fs:THREAD_SELF_OFFSET          // pass Thread::Current()
1063fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    CFI_ADJUST_CFA_OFFSET(4)
1064fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    PUSH eax                              // pass object
1065fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    call SYMBOL(artUnlockObjectFromCode)  // artUnlockObjectFromCode(object, Thread*)
1066fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    addl LITERAL(16), %esp                // pop arguments
1067fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    CFI_ADJUST_CFA_OFFSET(-16)
1068fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME   // restore frame up to return address
1069fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe    RETURN_IF_EAX_ZERO
1070fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas GampeEND_FUNCTION art_quick_unlock_object_no_inline
1071fc6898769ae1ef91ec3e41c0a273401213cb82cdAndreas Gampe
1072468532ea115657709bc32ee498e701a4c71762d4Ian RogersDEFINE_FUNCTION art_quick_is_assignable
10734360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                              // alignment padding
10744360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH ecx                              // pass arg2 - obj->klass
10754360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                              // pass arg1 - checked class
107629b3841ad8c1c18ee7ddd2d8cab85806b3d62eaaAndreas Gampe    call SYMBOL(artIsAssignableFromCode)  // (Class* klass, Class* ref_klass)
10774360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl LITERAL(12), %esp                // pop arguments
10783f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(-12)
10797caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    ret
1080468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND_FUNCTION art_quick_is_assignable
10817caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers
1082a9a8254c920ce8e22210abfc16c9842ce0aea28fIan RogersDEFINE_FUNCTION art_quick_check_cast
10834360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                              // alignment padding
10844360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH ecx                              // pass arg2 - obj->klass
10854360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                              // pass arg1 - checked class
108629b3841ad8c1c18ee7ddd2d8cab85806b3d62eaaAndreas Gampe    call SYMBOL(artIsAssignableFromCode)  // (Class* klass, Class* ref_klass)
1087a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    testl %eax, %eax
10884360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    jz 1f                                 // jump forward if not assignable
10894360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl LITERAL(12), %esp                // pop arguments
10903f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(-12)
1091a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    ret
10926b90d42316e0370c789dddb5dda48d7403ea378fAndreas Gampe
10934360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    CFI_ADJUST_CFA_OFFSET(12)             // Reset unwind info so following code unwinds.
1094a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers1:
10954360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    POP eax                               // pop arguments
1096a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    POP ecx
1097a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    addl LITERAL(4), %esp
10989f5e1d9b63ef44e05c2cc7b141ef788ecc0084c7Christopher Ferris    CFI_ADJUST_CFA_OFFSET(-4)
10991d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  ebx, ebx  // save all registers as basis for long jump context
1100a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    // Outgoing argument set up
11014360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                              // alignment padding
11024360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    pushl %fs:THREAD_SELF_OFFSET          // pass Thread::Current()
11033f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
11044360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH ecx                              // pass arg2
11054360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                              // pass arg1
11061d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    call SYMBOL(artThrowClassCastException) // (Class* a, Class* b, Thread*)
11074360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    UNREACHABLE
1108a9a8254c920ce8e22210abfc16c9842ce0aea28fIan RogersEND_FUNCTION art_quick_check_cast
1109a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers
11101aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao// Restore reg's value if reg is not the same as exclude_reg, otherwise just adjust stack.
11111aee900d5a0b3a8d78725a7551356bda0d8554e1Man CaoMACRO2(POP_REG_NE, reg, exclude_reg)
11121aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .ifc RAW_VAR(reg), RAW_VAR(exclude_reg)
11131aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao      addl MACRO_LITERAL(4), %esp
11141aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao      CFI_ADJUST_CFA_OFFSET(-4)
11151aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .else
11161aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao      POP RAW_VAR(reg)
11171aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .endif
11181aee900d5a0b3a8d78725a7551356bda0d8554e1Man CaoEND_MACRO
11191aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao
11201aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    /*
11211aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao     * Macro to insert read barrier, only used in art_quick_aput_obj.
11221aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao     * obj_reg and dest_reg are registers, offset is a defined literal such as
11231aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao     * MIRROR_OBJECT_CLASS_OFFSET.
11241aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao     * pop_eax is a boolean flag, indicating if eax is popped after the call.
11251aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao     * TODO: When read barrier has a fast path, add heap unpoisoning support for the fast path.
11261aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao     */
11271aee900d5a0b3a8d78725a7551356bda0d8554e1Man CaoMACRO4(READ_BARRIER, obj_reg, offset, dest_reg, pop_eax)
11281aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao#ifdef USE_READ_BARRIER
11291aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    PUSH eax                        // save registers used in art_quick_aput_obj
11301aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    PUSH ebx
11311aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    PUSH edx
11321aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    PUSH ecx
11331aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    // Outgoing argument set up
11341aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    pushl MACRO_LITERAL((RAW_VAR(offset)))  // pass offset, double parentheses are necessary
11351aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    CFI_ADJUST_CFA_OFFSET(4)
11361aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    PUSH RAW_VAR(obj_reg)           // pass obj_reg
11371aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    PUSH eax                        // pass ref, just pass eax for now since parameter ref is unused
11381aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    call SYMBOL(artReadBarrierSlow) // artReadBarrierSlow(ref, obj_reg, offset)
11391aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    // No need to unpoison return value in eax, artReadBarrierSlow() would do the unpoisoning.
11401aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .ifnc RAW_VAR(dest_reg), eax
11411aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao      movl %eax, REG_VAR(dest_reg)  // save loaded ref in dest_reg
11421aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .endif
11431aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    addl MACRO_LITERAL(12), %esp    // pop arguments
11441aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    CFI_ADJUST_CFA_OFFSET(-12)
11451aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    POP_REG_NE ecx, RAW_VAR(dest_reg) // Restore args except dest_reg
11461aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    POP_REG_NE edx, RAW_VAR(dest_reg)
11471aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    POP_REG_NE ebx, RAW_VAR(dest_reg)
11481aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .ifc RAW_VAR(pop_eax), true
11491aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao      POP_REG_NE eax, RAW_VAR(dest_reg)
11501aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    .endif
11511aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao#else
11521aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    movl RAW_VAR(offset)(REG_VAR(obj_reg)), REG_VAR(dest_reg)
11531aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    UNPOISON_HEAP_REF RAW_VAR(dest_reg)
11541aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao#endif  // USE_READ_BARRIER
11551aee900d5a0b3a8d78725a7551356bda0d8554e1Man CaoEND_MACRO
11561aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao
1157a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    /*
1158a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers     * Entry from managed code for array put operations of objects where the value being stored
1159a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers     * needs to be checked for compatibility.
1160a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers     * eax = array, ecx = index, edx = value
1161a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers     */
1162a9a8254c920ce8e22210abfc16c9842ce0aea28fIan RogersDEFINE_FUNCTION art_quick_aput_obj_with_null_and_bound_check
1163a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    testl %eax, %eax
11643bed41cf3ace3105686f626fed2ac802376852f3Dan Albert    jnz SYMBOL(art_quick_aput_obj_with_bound_check)
11653bed41cf3ace3105686f626fed2ac802376852f3Dan Albert    jmp SYMBOL(art_quick_throw_null_pointer_exception)
1166a9a8254c920ce8e22210abfc16c9842ce0aea28fIan RogersEND_FUNCTION art_quick_aput_obj_with_null_and_bound_check
1167a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers
1168a9a8254c920ce8e22210abfc16c9842ce0aea28fIan RogersDEFINE_FUNCTION art_quick_aput_obj_with_bound_check
11691d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    movl MIRROR_ARRAY_LENGTH_OFFSET(%eax), %ebx
1170a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    cmpl %ebx, %ecx
11713bed41cf3ace3105686f626fed2ac802376852f3Dan Albert    jb SYMBOL(art_quick_aput_obj)
1172a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    mov %ecx, %eax
1173a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    mov %ebx, %ecx
11743bed41cf3ace3105686f626fed2ac802376852f3Dan Albert    jmp SYMBOL(art_quick_throw_array_bounds)
1175a9a8254c920ce8e22210abfc16c9842ce0aea28fIan RogersEND_FUNCTION art_quick_aput_obj_with_bound_check
1176a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers
1177a9a8254c920ce8e22210abfc16c9842ce0aea28fIan RogersDEFINE_FUNCTION art_quick_aput_obj
1178a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    test %edx, %edx              // store of null
11798016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers    jz .Ldo_aput_null
11801aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    READ_BARRIER eax, MIRROR_OBJECT_CLASS_OFFSET, ebx, true
11811aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    READ_BARRIER ebx, MIRROR_CLASS_COMPONENT_TYPE_OFFSET, ebx, true
11821d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    // value's type == array's component type - trivial assignability
11831aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao#if defined(USE_READ_BARRIER)
11841aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    READ_BARRIER edx, MIRROR_OBJECT_CLASS_OFFSET, eax, false
11851aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    cmpl %eax, %ebx
11861aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    POP eax                      // restore eax from the push in the beginning of READ_BARRIER macro
11876306921722283d2b0f8aac01883ad83215d6e864Man Cao    // This asymmetric push/pop saves a push of eax and maintains stack alignment.
11881aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao#elif defined(USE_HEAP_POISONING)
11891aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    PUSH eax                     // save eax
1190bfa5eb6e8d15ea73a36f8df449630f285a91e995Hiroshi Yamauchi    movl MIRROR_OBJECT_CLASS_OFFSET(%edx), %eax
1191bfa5eb6e8d15ea73a36f8df449630f285a91e995Hiroshi Yamauchi    UNPOISON_HEAP_REF eax
1192bfa5eb6e8d15ea73a36f8df449630f285a91e995Hiroshi Yamauchi    cmpl %eax, %ebx
11931aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    POP eax                      // restore eax
1194bfa5eb6e8d15ea73a36f8df449630f285a91e995Hiroshi Yamauchi#else
11951d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    cmpl MIRROR_OBJECT_CLASS_OFFSET(%edx), %ebx
1196bfa5eb6e8d15ea73a36f8df449630f285a91e995Hiroshi Yamauchi#endif
11978016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers    jne .Lcheck_assignability
11988016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers.Ldo_aput:
1199bfa5eb6e8d15ea73a36f8df449630f285a91e995Hiroshi Yamauchi    POISON_HEAP_REF edx
12001d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    movl %edx, MIRROR_OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4)
1201a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    movl %fs:THREAD_CARD_TABLE_OFFSET, %edx
1202a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    shrl LITERAL(7), %eax
1203a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    movb %dl, (%edx, %eax)
1204a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    ret
12058016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers.Ldo_aput_null:
12061d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    movl %edx, MIRROR_OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4)
1207a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    ret
12088016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers.Lcheck_assignability:
12094360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                      // save arguments
1210a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    PUSH ecx
1211a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    PUSH edx
12126306921722283d2b0f8aac01883ad83215d6e864Man Cao#if defined(USE_READ_BARRIER)
12136306921722283d2b0f8aac01883ad83215d6e864Man Cao    subl LITERAL(4), %esp         // alignment padding
12146306921722283d2b0f8aac01883ad83215d6e864Man Cao    CFI_ADJUST_CFA_OFFSET(4)
12156306921722283d2b0f8aac01883ad83215d6e864Man Cao    READ_BARRIER edx, MIRROR_OBJECT_CLASS_OFFSET, eax, true
12166306921722283d2b0f8aac01883ad83215d6e864Man Cao    subl LITERAL(4), %esp         // alignment padding
12176306921722283d2b0f8aac01883ad83215d6e864Man Cao    CFI_ADJUST_CFA_OFFSET(4)
12186306921722283d2b0f8aac01883ad83215d6e864Man Cao    PUSH eax                      // pass arg2 - type of the value to be stored
12196306921722283d2b0f8aac01883ad83215d6e864Man Cao#elif defined(USE_HEAP_POISONING)
12204360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    subl LITERAL(8), %esp         // alignment padding
12213f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(8)
12226306921722283d2b0f8aac01883ad83215d6e864Man Cao    movl MIRROR_OBJECT_CLASS_OFFSET(%edx), %eax
1223bfa5eb6e8d15ea73a36f8df449630f285a91e995Hiroshi Yamauchi    UNPOISON_HEAP_REF eax
12246306921722283d2b0f8aac01883ad83215d6e864Man Cao    PUSH eax                      // pass arg2 - type of the value to be stored
1225bfa5eb6e8d15ea73a36f8df449630f285a91e995Hiroshi Yamauchi#else
12266306921722283d2b0f8aac01883ad83215d6e864Man Cao    subl LITERAL(8), %esp         // alignment padding
12276306921722283d2b0f8aac01883ad83215d6e864Man Cao    CFI_ADJUST_CFA_OFFSET(8)
12281d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    pushl MIRROR_OBJECT_CLASS_OFFSET(%edx)  // pass arg2 - type of the value to be stored
12293f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
12309f5e1d9b63ef44e05c2cc7b141ef788ecc0084c7Christopher Ferris#endif
12312738639bcd30b908d825725169b7497ed047debbMathieu Chartier    PUSH ebx                      // pass arg1 - component type of the array
123229b3841ad8c1c18ee7ddd2d8cab85806b3d62eaaAndreas Gampe    call SYMBOL(artIsAssignableFromCode)  // (Class* a, Class* b)
12332738639bcd30b908d825725169b7497ed047debbMathieu Chartier    addl LITERAL(16), %esp        // pop arguments
12343f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(-16)
1235a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    testl %eax, %eax
12368016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers    jz   .Lthrow_array_store_exception
1237a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    POP  edx
1238a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    POP  ecx
1239a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    POP  eax
1240bfa5eb6e8d15ea73a36f8df449630f285a91e995Hiroshi Yamauchi    POISON_HEAP_REF edx
12411d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    movl %edx, MIRROR_OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4)  // do the aput
1242a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    movl %fs:THREAD_CARD_TABLE_OFFSET, %edx
1243a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    shrl LITERAL(7), %eax
1244a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    movb %dl, (%edx, %eax)
1245a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    ret
12462738639bcd30b908d825725169b7497ed047debbMathieu Chartier    CFI_ADJUST_CFA_OFFSET(12)     // 3 POP after the jz for unwinding.
12478016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers.Lthrow_array_store_exception:
1248a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    POP  edx
1249a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    POP  ecx
1250a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    POP  eax
12511d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME ebx, ebx // save all registers as basis for long jump context
1252a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    // Outgoing argument set up
12531d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    PUSH eax                      // alignment padding
1254a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
12553f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
1256a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    PUSH edx                      // pass arg2 - value
1257a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    PUSH eax                      // pass arg1 - array
12581d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    call SYMBOL(artThrowArrayStoreException) // (array, value, Thread*)
12594360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    UNREACHABLE
1260a9a8254c920ce8e22210abfc16c9842ce0aea28fIan RogersEND_FUNCTION art_quick_aput_obj
1261a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers
12628dbb708c7dc05c786329eb5c3fff3194ab6472acLogan ChienDEFINE_FUNCTION art_quick_memcpy
12631d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_GOT_NOSAVE ebx          // clobbers EBX
1264aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH edx                      // pass arg3
1265aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH ecx                      // pass arg2
1266aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH eax                      // pass arg1
12673f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    call PLT_SYMBOL(memcpy)       // (void*, const void*, size_t)
126855bd45f4ea40b9a0af323f813d07f23d7a8ed397Ian Rogers    addl LITERAL(12), %esp        // pop arguments
12693f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(-12)
12707caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    ret
1271aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian RogersEND_FUNCTION art_quick_memcpy
12727caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers
12738dbb708c7dc05c786329eb5c3fff3194ab6472acLogan ChienNO_ARG_DOWNCALL art_quick_test_suspend, artTestSuspendFromCode, ret
12747caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers
1275468532ea115657709bc32ee498e701a4c71762d4Ian RogersDEFINE_FUNCTION art_quick_d2l
1276966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    subl LITERAL(12), %esp        // alignment padding, room for argument
1277966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    CFI_ADJUST_CFA_OFFSET(12)
1278966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd %xmm0, 0(%esp)          // arg a
1279966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    call SYMBOL(art_d2l)          // (jdouble a)
128041005ddb5576b8630a1084fbb3979ffa602c0599jeffhao    addl LITERAL(12), %esp        // pop arguments
12813f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(-12)
128241005ddb5576b8630a1084fbb3979ffa602c0599jeffhao    ret
1283468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND_FUNCTION art_quick_d2l
128441005ddb5576b8630a1084fbb3979ffa602c0599jeffhao
1285468532ea115657709bc32ee498e701a4c71762d4Ian RogersDEFINE_FUNCTION art_quick_f2l
1286966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    subl LITERAL(12), %esp        // alignment padding
1287966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    CFI_ADJUST_CFA_OFFSET(12)
1288966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movss %xmm0, 0(%esp)          // arg a
1289966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    call SYMBOL(art_f2l)          // (jfloat a)
129041005ddb5576b8630a1084fbb3979ffa602c0599jeffhao    addl LITERAL(12), %esp        // pop arguments
12913f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(-12)
129241005ddb5576b8630a1084fbb3979ffa602c0599jeffhao    ret
1293468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND_FUNCTION art_quick_f2l
129441005ddb5576b8630a1084fbb3979ffa602c0599jeffhao
1295468532ea115657709bc32ee498e701a4c71762d4Ian RogersDEFINE_FUNCTION art_quick_ldiv
12964360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    subl LITERAL(12), %esp        // alignment padding
12973f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(12)
12984360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH ebx                      // pass arg4 b.hi
12994360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH edx                      // pass arg3 b.lo
13004360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH ecx                      // pass arg2 a.hi
13014360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                      // pass arg1 a.lo
13024360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    call SYMBOL(artLdiv)          // (jlong a, jlong b)
13034360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl LITERAL(28), %esp        // pop arguments
13043f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(-28)
130555bd45f4ea40b9a0af323f813d07f23d7a8ed397Ian Rogers    ret
1306468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND_FUNCTION art_quick_ldiv
130755bd45f4ea40b9a0af323f813d07f23d7a8ed397Ian Rogers
1308a9a8254c920ce8e22210abfc16c9842ce0aea28fIan RogersDEFINE_FUNCTION art_quick_lmod
13094360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    subl LITERAL(12), %esp        // alignment padding
13103f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(12)
13114360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH ebx                      // pass arg4 b.hi
13124360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH edx                      // pass arg3 b.lo
13134360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH ecx                      // pass arg2 a.hi
13144360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH eax                      // pass arg1 a.lo
13154360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    call SYMBOL(artLmod)          // (jlong a, jlong b)
13164360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl LITERAL(28), %esp        // pop arguments
13173f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(-28)
131855bd45f4ea40b9a0af323f813d07f23d7a8ed397Ian Rogers    ret
1319a9a8254c920ce8e22210abfc16c9842ce0aea28fIan RogersEND_FUNCTION art_quick_lmod
132055bd45f4ea40b9a0af323f813d07f23d7a8ed397Ian Rogers
1321468532ea115657709bc32ee498e701a4c71762d4Ian RogersDEFINE_FUNCTION art_quick_lmul
13224360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    imul %eax, %ebx               // ebx = a.lo(eax) * b.hi(ebx)
13234360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    imul %edx, %ecx               // ecx = b.lo(edx) * a.hi(ecx)
13244360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    mul  %edx                     // edx:eax = a.lo(eax) * b.lo(edx)
13255793feaaafef40625b010429f3f79d8ee0bdfe28Ian Rogers    add  %ebx, %ecx
13264360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    add  %ecx, %edx               // edx += (a.lo * b.hi) + (b.lo * a.hi)
1327644d5310d7759f6d531a2c4220b1e2cc8f3b72d3jeffhao    ret
1328468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND_FUNCTION art_quick_lmul
1329644d5310d7759f6d531a2c4220b1e2cc8f3b72d3jeffhao
1330468532ea115657709bc32ee498e701a4c71762d4Ian RogersDEFINE_FUNCTION art_quick_lshl
1331644d5310d7759f6d531a2c4220b1e2cc8f3b72d3jeffhao    // ecx:eax << edx
1332141d62275f207bf68c55f583fb206fe586d857cfIan Rogers    xchg %edx, %ecx
1333141d62275f207bf68c55f583fb206fe586d857cfIan Rogers    shld %cl,%eax,%edx
1334141d62275f207bf68c55f583fb206fe586d857cfIan Rogers    shl  %cl,%eax
1335141d62275f207bf68c55f583fb206fe586d857cfIan Rogers    test LITERAL(32), %cl
1336141d62275f207bf68c55f583fb206fe586d857cfIan Rogers    jz  1f
1337141d62275f207bf68c55f583fb206fe586d857cfIan Rogers    mov %eax, %edx
1338141d62275f207bf68c55f583fb206fe586d857cfIan Rogers    xor %eax, %eax
1339141d62275f207bf68c55f583fb206fe586d857cfIan Rogers1:
1340141d62275f207bf68c55f583fb206fe586d857cfIan Rogers    ret
1341468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND_FUNCTION art_quick_lshl
1342141d62275f207bf68c55f583fb206fe586d857cfIan Rogers
1343468532ea115657709bc32ee498e701a4c71762d4Ian RogersDEFINE_FUNCTION art_quick_lshr
1344644d5310d7759f6d531a2c4220b1e2cc8f3b72d3jeffhao    // ecx:eax >> edx
1345141d62275f207bf68c55f583fb206fe586d857cfIan Rogers    xchg %edx, %ecx
1346644d5310d7759f6d531a2c4220b1e2cc8f3b72d3jeffhao    shrd %cl,%edx,%eax
1347644d5310d7759f6d531a2c4220b1e2cc8f3b72d3jeffhao    sar  %cl,%edx
1348141d62275f207bf68c55f583fb206fe586d857cfIan Rogers    test LITERAL(32),%cl
1349141d62275f207bf68c55f583fb206fe586d857cfIan Rogers    jz  1f
13505121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao    mov %edx, %eax
13515121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao    sar LITERAL(31), %edx
1352141d62275f207bf68c55f583fb206fe586d857cfIan Rogers1:
1353141d62275f207bf68c55f583fb206fe586d857cfIan Rogers    ret
1354468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND_FUNCTION art_quick_lshr
1355141d62275f207bf68c55f583fb206fe586d857cfIan Rogers
1356468532ea115657709bc32ee498e701a4c71762d4Ian RogersDEFINE_FUNCTION art_quick_lushr
1357644d5310d7759f6d531a2c4220b1e2cc8f3b72d3jeffhao    // ecx:eax >>> edx
1358141d62275f207bf68c55f583fb206fe586d857cfIan Rogers    xchg %edx, %ecx
1359644d5310d7759f6d531a2c4220b1e2cc8f3b72d3jeffhao    shrd %cl,%edx,%eax
1360644d5310d7759f6d531a2c4220b1e2cc8f3b72d3jeffhao    shr  %cl,%edx
1361644d5310d7759f6d531a2c4220b1e2cc8f3b72d3jeffhao    test LITERAL(32),%cl
1362141d62275f207bf68c55f583fb206fe586d857cfIan Rogers    jz  1f
13635121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao    mov %edx, %eax
13645121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao    xor %edx, %edx
1365141d62275f207bf68c55f583fb206fe586d857cfIan Rogers1:
1366141d62275f207bf68c55f583fb206fe586d857cfIan Rogers    ret
1367468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND_FUNCTION art_quick_lushr
1368141d62275f207bf68c55f583fb206fe586d857cfIan Rogers
13691d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersONE_ARG_REF_DOWNCALL art_quick_get_boolean_static, artGetBooleanStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
13701d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersONE_ARG_REF_DOWNCALL art_quick_get_byte_static, artGetByteStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
13711d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersONE_ARG_REF_DOWNCALL art_quick_get_char_static, artGetCharStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
13721d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersONE_ARG_REF_DOWNCALL art_quick_get_short_static, artGetShortStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
13731d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersONE_ARG_REF_DOWNCALL art_quick_get32_static, artGet32StaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
13741d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersONE_ARG_REF_DOWNCALL art_quick_get64_static, artGet64StaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
13751d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersONE_ARG_REF_DOWNCALL art_quick_get_obj_static, artGetObjStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
137637f05ef45e0393de812d51261dc293240c17294dFred Shih
13771d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersTWO_ARG_REF_DOWNCALL art_quick_get_boolean_instance, artGetBooleanInstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
13781d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersTWO_ARG_REF_DOWNCALL art_quick_get_byte_instance, artGetByteInstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
13791d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersTWO_ARG_REF_DOWNCALL art_quick_get_char_instance, artGetCharInstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
13801d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersTWO_ARG_REF_DOWNCALL art_quick_get_short_instance, artGetShortInstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
13811d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersTWO_ARG_REF_DOWNCALL art_quick_get32_instance, artGet32InstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
13821d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersTWO_ARG_REF_DOWNCALL art_quick_get64_instance, artGet64InstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
13831d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersTWO_ARG_REF_DOWNCALL art_quick_get_obj_instance, artGetObjInstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
138437f05ef45e0393de812d51261dc293240c17294dFred Shih
13851d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersTWO_ARG_REF_DOWNCALL art_quick_set8_static, artSet8StaticFromCode, RETURN_IF_EAX_ZERO
13861d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersTWO_ARG_REF_DOWNCALL art_quick_set16_static, artSet16StaticFromCode, RETURN_IF_EAX_ZERO
13871d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersTWO_ARG_REF_DOWNCALL art_quick_set32_static, artSet32StaticFromCode, RETURN_IF_EAX_ZERO
13881d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersTWO_ARG_REF_DOWNCALL art_quick_set_obj_static, artSetObjStaticFromCode, RETURN_IF_EAX_ZERO
13899dbb23e997f84d7c6c909b246e3faca50a912336jeffhao
13901d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersTHREE_ARG_REF_DOWNCALL art_quick_set8_instance, artSet8InstanceFromCode, RETURN_IF_EAX_ZERO
13911d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersTHREE_ARG_REF_DOWNCALL art_quick_set16_instance, artSet16InstanceFromCode, RETURN_IF_EAX_ZERO
13921d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersTHREE_ARG_REF_DOWNCALL art_quick_set32_instance, artSet32InstanceFromCode, RETURN_IF_EAX_ZERO
13931d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersTHREE_ARG_REF_DOWNCALL art_quick_set_obj_instance, artSetObjInstanceFromCode, RETURN_IF_EAX_ZERO
13941d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers
13951d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers// Call artSet64InstanceFromCode with 4 word size arguments and the referrer.
1396468532ea115657709bc32ee498e701a4c71762d4Ian RogersDEFINE_FUNCTION art_quick_set64_instance
1397e0b46a7513980b5bcb3c3af160a5b3ee077fad2dSerguei Katkov    movd %ebx, %xmm0
13981d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx  // save ref containing registers for GC
1399e0b46a7513980b5bcb3c3af160a5b3ee077fad2dSerguei Katkov    movd %xmm0, %ebx
14001d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    // Outgoing argument set up
14011ff4cd7c1ec698845145edd1e9d0ba767ce45de1jeffhao    subl LITERAL(8), %esp         // alignment padding
14023f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(8)
14039dbb23e997f84d7c6c909b246e3faca50a912336jeffhao    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
14043f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
14051d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    pushl (FRAME_SIZE_REFS_ONLY_CALLEE_SAVE+12)(%esp)  // pass referrer
14061d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(4)
1407aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH ebx                      // pass high half of new_val
1408aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH edx                      // pass low half of new_val
1409aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH ecx                      // pass object
1410aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH eax                      // pass field_idx
14111d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    call SYMBOL(artSet64InstanceFromCode)  // (field_idx, Object*, new_val, referrer, Thread*)
14121ff4cd7c1ec698845145edd1e9d0ba767ce45de1jeffhao    addl LITERAL(32), %esp        // pop arguments
14133f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(-32)
14141d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME     // restore frame up to return address
14159dbb23e997f84d7c6c909b246e3faca50a912336jeffhao    RETURN_IF_EAX_ZERO            // return or deliver exception
1416468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND_FUNCTION art_quick_set64_instance
14179dbb23e997f84d7c6c909b246e3faca50a912336jeffhao
14181d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers// Call artSet64StaticFromCode with 3 word size arguments plus with the referrer in the 2nd position
14191d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers// so that new_val is aligned on even registers were we passing arguments in registers.
14201d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian RogersDEFINE_FUNCTION art_quick_set64_static
1421e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle    // TODO: Implement SETUP_GOT_NOSAVE for got_reg = ecx to avoid moving around the registers.
1422e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle    movd %ebx, %xmm0
14231d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  ebx, ebx  // save ref containing registers for GC
1424e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle    movd %xmm0, %ebx
1425e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle    mov FRAME_SIZE_REFS_ONLY_CALLEE_SAVE(%esp), %ecx  // get referrer
14261ff4cd7c1ec698845145edd1e9d0ba767ce45de1jeffhao    subl LITERAL(12), %esp        // alignment padding
14273f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(12)
14289dbb23e997f84d7c6c909b246e3faca50a912336jeffhao    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
14293f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
1430e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle    PUSH ebx                      // pass high half of new_val
1431e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle    PUSH edx                      // pass low half of new_val
1432e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle    PUSH ecx                      // pass referrer
1433aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH eax                      // pass field_idx
14341d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    call SYMBOL(artSet64StaticFromCode)  // (field_idx, referrer, new_val, Thread*)
14351ff4cd7c1ec698845145edd1e9d0ba767ce45de1jeffhao    addl LITERAL(32), %esp        // pop arguments
14363f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(-32)
14371d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME  // restore frame up to return address
14389dbb23e997f84d7c6c909b246e3faca50a912336jeffhao    RETURN_IF_EAX_ZERO            // return or deliver exception
1439468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND_FUNCTION art_quick_set64_static
14409dbb23e997f84d7c6c909b246e3faca50a912336jeffhao
14418dbb708c7dc05c786329eb5c3fff3194ab6472acLogan ChienDEFINE_FUNCTION art_quick_proxy_invoke_handler
14421d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_WITH_METHOD_IN_EAX
1443aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH esp                      // pass SP
1444d66a87583bebcd5f89906aeaae9f8fb104ef2ac9jeffhao    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
14453f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
1446aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH ecx                      // pass receiver
1447aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH eax                      // pass proxy method
144829b3841ad8c1c18ee7ddd2d8cab85806b3d62eaaAndreas Gampe    call SYMBOL(artQuickProxyInvokeHandler) // (proxy method, receiver, Thread*, SP)
1449af6e67a4816d2593586115b89faa659225363246Ian Rogers    movd %eax, %xmm0              // place return value also into floating point return value
1450af6e67a4816d2593586115b89faa659225363246Ian Rogers    movd %edx, %xmm1
1451af6e67a4816d2593586115b89faa659225363246Ian Rogers    punpckldq %xmm1, %xmm0
14529346ff0cfad6344d0bf4eaa69362dbe1987ac054Mathieu Chartier    addl LITERAL(16 + FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE - FRAME_SIZE_REFS_ONLY_CALLEE_SAVE), %esp
14539346ff0cfad6344d0bf4eaa69362dbe1987ac054Mathieu Chartier    CFI_ADJUST_CFA_OFFSET(-(16 + FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE - FRAME_SIZE_REFS_ONLY_CALLEE_SAVE))
14549346ff0cfad6344d0bf4eaa69362dbe1987ac054Mathieu Chartier    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
14557db619bb2a4e01e8532a04b613745d4926b205d7Ian Rogers    RETURN_OR_DELIVER_PENDING_EXCEPTION    // return or deliver exception
1456aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian RogersEND_FUNCTION art_quick_proxy_invoke_handler
14577db619bb2a4e01e8532a04b613745d4926b205d7Ian Rogers
145888474b416eb257078e590bf9bc7957cee604a186Jeff Hao    /*
1459796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray     * Called to resolve an imt conflict.
1460796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray     * eax is the conflict ArtMethod.
1461796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray     * xmm7 is a hidden argument that holds the target interface method's dex method index.
1462796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray     *
1463796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray     * Note that this stub writes to eax.
1464796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray     * Because of lack of free registers, it also saves and restores edi.
146588474b416eb257078e590bf9bc7957cee604a186Jeff Hao     */
146688474b416eb257078e590bf9bc7957cee604a186Jeff HaoDEFINE_FUNCTION art_quick_imt_conflict_trampoline
1467796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    PUSH EDI
1468796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    movl 8(%esp), %edi // Load referrer
1469796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    movl ART_METHOD_DEX_CACHE_METHODS_OFFSET_32(%edi), %edi   // Load dex cache methods array
1470796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    pushl ART_METHOD_JNI_OFFSET_32(%eax)  // Push ImtConflictTable.
1471796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    CFI_ADJUST_CFA_OFFSET(4)
14728ea18d0f066f63fa4e5d154f14327468bf288e2bNicolas Geoffray    movd %xmm7, %eax              // get target method index stored in xmm7
1473796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    movl 0(%edi, %eax, __SIZEOF_POINTER__), %edi  // Load interface method
1474796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    popl %eax  // Pop ImtConflictTable.
1475796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    CFI_ADJUST_CFA_OFFSET(-4)
1476796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray.Limt_table_iterate:
1477796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    cmpl %edi, 0(%eax)
1478796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    jne .Limt_table_next_entry
147959028d90d51a800bcea8be354d77d7be924da3a0Goran Jakovljevic    // We successfully hit an entry in the table. Load the target method
1480796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    // and jump to it.
1481796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    POP EDI
1482796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    movl __SIZEOF_POINTER__(%eax), %eax
1483796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    jmp *ART_METHOD_QUICK_CODE_OFFSET_32(%eax)
1484796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray.Limt_table_next_entry:
1485796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    // If the entry is null, the interface method is not in the ImtConflictTable.
1486796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    cmpl LITERAL(0), 0(%eax)
1487796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    jz .Lconflict_trampoline
1488796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    // Iterate over the entries of the ImtConflictTable.
1489796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    addl LITERAL(2 * __SIZEOF_POINTER__), %eax
1490796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    jmp .Limt_table_iterate
1491796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray.Lconflict_trampoline:
1492796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    // Call the runtime stub to populate the ImtConflictTable and jump to the
1493796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    // resolved method.
1494796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray    POP EDI
149555978b87877f4774af213b405c9492dc08549912Andreas Gampe    INVOKE_TRAMPOLINE_BODY artInvokeInterfaceTrampoline
149688474b416eb257078e590bf9bc7957cee604a186Jeff HaoEND_FUNCTION art_quick_imt_conflict_trampoline
149788474b416eb257078e590bf9bc7957cee604a186Jeff Hao
1498468532ea115657709bc32ee498e701a4c71762d4Ian RogersDEFINE_FUNCTION art_quick_resolution_trampoline
14991d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME ebx, ebx
150035e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen    movl %esp, %edi
150135e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen    PUSH EDI                      // pass SP. do not just PUSH ESP; that messes up unwinding
1502468532ea115657709bc32ee498e701a4c71762d4Ian Rogers    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
15033f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
1504468532ea115657709bc32ee498e701a4c71762d4Ian Rogers    PUSH ecx                      // pass receiver
1505468532ea115657709bc32ee498e701a4c71762d4Ian Rogers    PUSH eax                      // pass method
150629b3841ad8c1c18ee7ddd2d8cab85806b3d62eaaAndreas Gampe    call SYMBOL(artQuickResolutionTrampoline) // (Method* called, receiver, Thread*, SP)
1507468532ea115657709bc32ee498e701a4c71762d4Ian Rogers    movl %eax, %edi               // remember code pointer in EDI
1508468532ea115657709bc32ee498e701a4c71762d4Ian Rogers    addl LITERAL(16), %esp        // pop arguments
15099f5e1d9b63ef44e05c2cc7b141ef788ecc0084c7Christopher Ferris    CFI_ADJUST_CFA_OFFSET(-16)
15102cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    test %eax, %eax               // if code pointer is null goto deliver pending exception
1511468532ea115657709bc32ee498e701a4c71762d4Ian Rogers    jz 1f
1512966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME_AND_JUMP
1513468532ea115657709bc32ee498e701a4c71762d4Ian Rogers1:
15141d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
1515468532ea115657709bc32ee498e701a4c71762d4Ian Rogers    DELIVER_PENDING_EXCEPTION
1516468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND_FUNCTION art_quick_resolution_trampoline
1517468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
15186f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian RogersDEFINE_FUNCTION art_quick_generic_jni_trampoline
15191d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_WITH_METHOD_IN_EAX
15204360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    movl %esp, %ebp               // save SP at callee-save frame
1521c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    CFI_DEF_CFA_REGISTER(ebp)
1522779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    subl LITERAL(5120), %esp
1523779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    // prepare for artQuickGenericJniTrampoline call
1524779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    // (Thread*,  SP)
1525779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    //  (esp)    4(esp)   <= C calling convention
1526779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    //  fs:...    ebp     <= where they are
1527779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe
1528779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    subl LITERAL(8), %esp         // Padding for 16B alignment.
1529779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    pushl %ebp                    // Pass SP (to ArtMethod).
1530779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    pushl %fs:THREAD_SELF_OFFSET  // Pass Thread::Current().
153129b3841ad8c1c18ee7ddd2d8cab85806b3d62eaaAndreas Gampe    call SYMBOL(artQuickGenericJniTrampoline)  // (Thread*, sp)
1532779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe
1533c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    // The C call will have registered the complete save-frame on success.
1534c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    // The result of the call is:
1535c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    // eax: pointer to native code, 0 on error.
1536c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    // edx: pointer to the bottom of the used area of the alloca, can restore stack till there.
1537779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe
1538c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    // Check for error = 0.
1539779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    test %eax, %eax
1540126d65952a03b3e44d5021208673c01920a982a4Nicolas Geoffray    jz .Lexception_in_native
1541779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe
1542c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    // Release part of the alloca.
1543c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    movl %edx, %esp
1544779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe
1545779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    // On x86 there are no registers passed, so nothing to pop here.
1546779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    // Native call.
1547779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    call *%eax
1548779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe
1549779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    // result sign extension is handled in C code
1550779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    // prepare for artQuickGenericJniEndTrampoline call
1551c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    // (Thread*, result, result_f)
1552c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe    //  (esp)    4(esp)  12(esp)    <= C calling convention
155354accbca0b549b1b1ad3ef09655dad438bc1e104Nicolas Geoffray    //  fs:...  eax:edx   fp0      <= where they are
1554779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe
15554360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    subl LITERAL(20), %esp        // Padding & pass float result.
155654accbca0b549b1b1ad3ef09655dad438bc1e104Nicolas Geoffray    fstpl (%esp)
1557779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    pushl %edx                    // Pass int result.
1558779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    pushl %eax
1559779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    pushl %fs:THREAD_SELF_OFFSET  // Pass Thread::Current().
156029b3841ad8c1c18ee7ddd2d8cab85806b3d62eaaAndreas Gampe    call SYMBOL(artQuickGenericJniEndTrampoline)
1561779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe
1562779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    // Pending exceptions possible.
1563779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    mov %fs:THREAD_EXCEPTION_OFFSET, %ebx
1564779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    testl %ebx, %ebx
1565779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    jnz .Lexception_in_native
1566779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe
1567126d65952a03b3e44d5021208673c01920a982a4Nicolas Geoffray    // Tear down the alloca.
1568126d65952a03b3e44d5021208673c01920a982a4Nicolas Geoffray    movl %ebp, %esp
1569126d65952a03b3e44d5021208673c01920a982a4Nicolas Geoffray    CFI_DEF_CFA_REGISTER(esp)
1570126d65952a03b3e44d5021208673c01920a982a4Nicolas Geoffray
1571126d65952a03b3e44d5021208673c01920a982a4Nicolas Geoffray
1572779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    // Tear down the callee-save frame.
1573966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Remove space for FPR args and EAX
1574966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    addl LITERAL(4 + 4 * 8), %esp
1575966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    CFI_ADJUST_CFA_OFFSET(-(4 + 4 * 8))
1576966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
1577779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    POP ecx
15784360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    addl LITERAL(4), %esp         // Avoid edx, as it may be part of the result.
1579779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    CFI_ADJUST_CFA_OFFSET(-4)
1580779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    POP ebx
1581779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    POP ebp  // Restore callee saves
1582779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    POP esi
1583779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    POP edi
158454accbca0b549b1b1ad3ef09655dad438bc1e104Nicolas Geoffray    // Quick expects the return value to be in xmm0.
1585779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    movd %eax, %xmm0
1586779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    movd %edx, %xmm1
1587779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    punpckldq %xmm1, %xmm0
1588779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    ret
1589779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe.Lexception_in_native:
1590126d65952a03b3e44d5021208673c01920a982a4Nicolas Geoffray    movl %fs:THREAD_TOP_QUICK_FRAME_OFFSET, %esp
1591126d65952a03b3e44d5021208673c01920a982a4Nicolas Geoffray    // Do a call to push a new save-all frame required by the runtime.
1592126d65952a03b3e44d5021208673c01920a982a4Nicolas Geoffray    call .Lexception_call
1593126d65952a03b3e44d5021208673c01920a982a4Nicolas Geoffray.Lexception_call:
1594779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe    DELIVER_PENDING_EXCEPTION
15952da882315a61072664f7ce3c212307342e907207Andreas GampeEND_FUNCTION art_quick_generic_jni_trampoline
15962da882315a61072664f7ce3c212307342e907207Andreas Gampe
15976f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian RogersDEFINE_FUNCTION art_quick_to_interpreter_bridge
15981d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME  ebx, ebx  // save frame
1599aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    mov %esp, %edx                // remember SP
1600aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH eax                      // alignment padding
1601aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH edx                      // pass SP
16027db619bb2a4e01e8532a04b613745d4926b205d7Ian Rogers    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
16033f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
1604aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    PUSH eax                      // pass  method
160529b3841ad8c1c18ee7ddd2d8cab85806b3d62eaaAndreas Gampe    call SYMBOL(artQuickToInterpreterBridge)  // (method, Thread*, SP)
1606949c91fb91f40a4a80b2b492913cf8541008975eVladimir Marko    addl LITERAL(16), %esp        // pop arguments
1607949c91fb91f40a4a80b2b492913cf8541008975eVladimir Marko    CFI_ADJUST_CFA_OFFSET(-16)
1608966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
1609966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Return eax:edx in xmm0 also.
1610966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movd %eax, %xmm0
1611966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movd %edx, %xmm1
1612966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    punpckldq %xmm1, %xmm0
1613966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
1614966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    addl LITERAL(48), %esp        // Remove FPRs and EAX, ECX, EDX, EBX.
1615966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    CFI_ADJUST_CFA_OFFSET(-48)
1616966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
16174360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    POP ebp                       // Restore callee saves
1618966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    POP esi
1619966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    POP edi
1620966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
1621d66a87583bebcd5f89906aeaae9f8fb104ef2ac9jeffhao    RETURN_OR_DELIVER_PENDING_EXCEPTION    // return or deliver exception
1622468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND_FUNCTION art_quick_to_interpreter_bridge
16239dbb23e997f84d7c6c909b246e3faca50a912336jeffhao
16247e4fcb813d6c2657a5b9190a7c10168a2680bc45jeffhao    /*
16257e4fcb813d6c2657a5b9190a7c10168a2680bc45jeffhao     * Routine that intercepts method calls and returns.
16267e4fcb813d6c2657a5b9190a7c10168a2680bc45jeffhao     */
1627468532ea115657709bc32ee498e701a4c71762d4Ian RogersDEFINE_FUNCTION art_quick_instrumentation_entry
16281d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME ebx, edx
162962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    PUSH eax                      // Save eax which will be clobbered by the callee-save method.
16301d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    subl LITERAL(12), %esp        // Align stack.
16311d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(12)
163232b12f8ae491e1acfeaee334e9a30c6c0a232072Sebastien Hertz    pushl FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE-4+16(%esp)  // Pass LR.
16333f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
163462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    pushl %fs:THREAD_SELF_OFFSET  // Pass Thread::Current().
16353f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
163662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    PUSH ecx                      // Pass receiver.
163762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    PUSH eax                      // Pass Method*.
16381d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    call SYMBOL(artInstrumentationMethodEntryFromCode) // (Method*, Object*, Thread*, LR)
16397ac7e32fb84b6a933181d31694d8a2d81ddca6d6Elliott Hughes    addl LITERAL(28), %esp        // Pop arguments upto saved Method*.
16409f5e1d9b63ef44e05c2cc7b141ef788ecc0084c7Christopher Ferris    CFI_ADJUST_CFA_OFFSET(-28)
1641966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl 60(%esp), %edi           // Restore edi.
1642966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl %eax, 60(%esp)           // Place code* over edi, just under return pc.
16437ac7e32fb84b6a933181d31694d8a2d81ddca6d6Elliott Hughes    movl SYMBOL(art_quick_instrumentation_exit)@GOT(%ebx), %ebx
16441d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    // Place instrumentation exit as return pc. ebx holds the GOT computed on entry.
1645966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl %ebx, 64(%esp)
1646966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl 0(%esp), %eax           // Restore eax.
1647966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Restore FPRs (extra 4 bytes of offset due to EAX push at top).
1648966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd 8(%esp), %xmm0
1649966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd 16(%esp), %xmm1
1650966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd 24(%esp), %xmm2
1651966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movsd 32(%esp), %xmm3
1652966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
1653966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // Restore GPRs.
1654966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl 40(%esp), %ecx           // Restore ecx.
1655f551d1bd8da75d14fd858e4a7c9b60612aec5430Sebastien Hertz    movl 44(%esp), %edx           // Restore edx.
1656966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl 48(%esp), %ebx           // Restore ebx.
1657966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl 52(%esp), %ebp           // Restore ebp.
1658966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    movl 56(%esp), %esi           // Restore esi.
1659966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    addl LITERAL(60), %esp        // Wind stack back upto code*.
16609f5e1d9b63ef44e05c2cc7b141ef788ecc0084c7Christopher Ferris    CFI_ADJUST_CFA_OFFSET(-60)
166162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    ret                           // Call method (and pop).
1662468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND_FUNCTION art_quick_instrumentation_entry
166362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
1664468532ea115657709bc32ee498e701a4c71762d4Ian RogersDEFINE_FUNCTION art_quick_instrumentation_exit
166562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    pushl LITERAL(0)              // Push a fake return PC as there will be none on the stack.
16669f5e1d9b63ef44e05c2cc7b141ef788ecc0084c7Christopher Ferris    CFI_ADJUST_CFA_OFFSET(4)
16671d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx
166862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    mov  %esp, %ecx               // Remember SP
166962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    subl LITERAL(8), %esp         // Save float return value.
16703f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(8)
1671fea29016a79f39ac12a4ba4ebdcbc86800c03427Andreas Gampe    movq %xmm0, (%esp)
167262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    PUSH edx                      // Save gpr return value.
167362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    PUSH eax
1674cf2e7b0621dfe7fcacd56555dffabab65d1130e7Jeff Hao    subl LITERAL(16), %esp        // Align stack
1675cf2e7b0621dfe7fcacd56555dffabab65d1130e7Jeff Hao    CFI_ADJUST_CFA_OFFSET(16)
1676fea29016a79f39ac12a4ba4ebdcbc86800c03427Andreas Gampe    movq %xmm0, (%esp)            // Pass float return value.
167762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    PUSH edx                      // Pass gpr return value.
167862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    PUSH eax
167962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    PUSH ecx                      // Pass SP.
168062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    pushl %fs:THREAD_SELF_OFFSET  // Pass Thread::Current.
16813f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
168229b3841ad8c1c18ee7ddd2d8cab85806b3d62eaaAndreas Gampe    call SYMBOL(artInstrumentationMethodExitFromCode)  // (Thread*, SP, gpr_result, fpr_result)
168362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    mov   %eax, %ecx              // Move returned link register.
168462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    addl LITERAL(32), %esp        // Pop arguments.
16853f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(-32)
168662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    movl %edx, %ebx               // Move returned link register for deopt
168762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                  // (ebx is pretending to be our LR).
168862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    POP eax                       // Restore gpr return value.
168962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    POP edx
1690fea29016a79f39ac12a4ba4ebdcbc86800c03427Andreas Gampe    movq (%esp), %xmm0            // Restore fpr return value.
169162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    addl LITERAL(8), %esp
16923f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(-8)
16931d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
169462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    addl LITERAL(4), %esp         // Remove fake return pc.
16959f5e1d9b63ef44e05c2cc7b141ef788ecc0084c7Christopher Ferris    CFI_ADJUST_CFA_OFFSET(-4)
169662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    jmp   *%ecx                   // Return.
1697468532ea115657709bc32ee498e701a4c71762d4Ian RogersEND_FUNCTION art_quick_instrumentation_exit
1698162fd33474038f0de0388338ca007ecf400bb3dfjeffhao
16997e4fcb813d6c2657a5b9190a7c10168a2680bc45jeffhao    /*
170062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers     * Instrumentation has requested that we deoptimize into the interpreter. The deoptimization
170162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers     * will long jump to the upcall with a special exception of -1.
17027e4fcb813d6c2657a5b9190a7c10168a2680bc45jeffhao     */
17038dbb708c7dc05c786329eb5c3fff3194ab6472acLogan ChienDEFINE_FUNCTION art_quick_deoptimize
17049f5e1d9b63ef44e05c2cc7b141ef788ecc0084c7Christopher Ferris    PUSH ebx                      // Entry point for a jump. Fake that we were called.
17051d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME ebx, ebx
17061d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    subl LITERAL(12), %esp        // Align stack.
17071d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    CFI_ADJUST_CFA_OFFSET(12)
170862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    pushl %fs:THREAD_SELF_OFFSET  // Pass Thread::Current().
17093f2d031f639b3b9dd4adbf9e70d23de931a9801dMark Mendell    CFI_ADJUST_CFA_OFFSET(4)
17101d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    call SYMBOL(artDeoptimize)    // artDeoptimize(Thread*)
17114360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    UNREACHABLE
1712aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian RogersEND_FUNCTION art_quick_deoptimize
1713162fd33474038f0de0388338ca007ecf400bb3dfjeffhao
171486e4671975752b112b2e8969ac6652c72c8e86c7jeffhao    /*
17150747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz     * Compiled code has requested that we deoptimize into the interpreter. The deoptimization
1716639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe     * will long jump to the interpreter bridge.
17170747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz     */
17180747466fca310eedea5fc49e37d54f240a0b3c0fSebastien HertzDEFINE_FUNCTION art_quick_deoptimize_from_compiled_code
17190747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME ebx, ebx
17200747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz    subl LITERAL(12), %esp                      // Align stack.
17210747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz    CFI_ADJUST_CFA_OFFSET(12)
17220747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz    pushl %fs:THREAD_SELF_OFFSET                // Pass Thread::Current().
17230747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz    CFI_ADJUST_CFA_OFFSET(4)
17240747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz    call SYMBOL(artDeoptimizeFromCompiledCode)  // artDeoptimizeFromCompiledCode(Thread*)
17250747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz    UNREACHABLE
17260747466fca310eedea5fc49e37d54f240a0b3c0fSebastien HertzEND_FUNCTION art_quick_deoptimize_from_compiled_code
17270747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz
17280747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz    /*
172986e4671975752b112b2e8969ac6652c72c8e86c7jeffhao     * String's compareTo.
173086e4671975752b112b2e8969ac6652c72c8e86c7jeffhao     *
173186e4671975752b112b2e8969ac6652c72c8e86c7jeffhao     * On entry:
173286e4671975752b112b2e8969ac6652c72c8e86c7jeffhao     *    eax:   this string object (known non-null)
173386e4671975752b112b2e8969ac6652c72c8e86c7jeffhao     *    ecx:   comp string object (known non-null)
173486e4671975752b112b2e8969ac6652c72c8e86c7jeffhao     */
17358dbb708c7dc05c786329eb5c3fff3194ab6472acLogan ChienDEFINE_FUNCTION art_quick_string_compareto
17364360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH esi                      // push callee save reg
17374360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    PUSH edi                      // push callee save reg
17381d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    mov MIRROR_STRING_COUNT_OFFSET(%eax), %edx
17391d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    mov MIRROR_STRING_COUNT_OFFSET(%ecx), %ebx
1740848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    lea MIRROR_STRING_VALUE_OFFSET(%eax), %esi
1741848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    lea MIRROR_STRING_VALUE_OFFSET(%ecx), %edi
174286e4671975752b112b2e8969ac6652c72c8e86c7jeffhao    /* Calculate min length and count diff */
174386e4671975752b112b2e8969ac6652c72c8e86c7jeffhao    mov   %edx, %ecx
174486e4671975752b112b2e8969ac6652c72c8e86c7jeffhao    mov   %edx, %eax
174586e4671975752b112b2e8969ac6652c72c8e86c7jeffhao    subl  %ebx, %eax
174686e4671975752b112b2e8969ac6652c72c8e86c7jeffhao    cmovg %ebx, %ecx
174786e4671975752b112b2e8969ac6652c72c8e86c7jeffhao    /*
174886e4671975752b112b2e8969ac6652c72c8e86c7jeffhao     * At this point we have:
174986e4671975752b112b2e8969ac6652c72c8e86c7jeffhao     *   eax: value to return if first part of strings are equal
175086e4671975752b112b2e8969ac6652c72c8e86c7jeffhao     *   ecx: minimum among the lengths of the two strings
175186e4671975752b112b2e8969ac6652c72c8e86c7jeffhao     *   esi: pointer to this string data
175286e4671975752b112b2e8969ac6652c72c8e86c7jeffhao     *   edi: pointer to comp string data
175386e4671975752b112b2e8969ac6652c72c8e86c7jeffhao     */
17544554bfdc2859712a763a12e35a4176914fc7c994Alexei Zavjalov    jecxz .Lkeep_length
175586e4671975752b112b2e8969ac6652c72c8e86c7jeffhao    repe cmpsw                    // find nonmatching chars in [%esi] and [%edi], up to length %ecx
17568016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers    jne .Lnot_equal
17574554bfdc2859712a763a12e35a4176914fc7c994Alexei Zavjalov.Lkeep_length:
1758aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    POP edi                       // pop callee save reg
1759aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    POP esi                       // pop callee save reg
176086e4671975752b112b2e8969ac6652c72c8e86c7jeffhao    ret
176186e4671975752b112b2e8969ac6652c72c8e86c7jeffhao    .balign 16
17628016a12a5f9c2ea70b52e353a0169ba836ee9402Ian Rogers.Lnot_equal:
17631b09b094a85e03f6ef5f687f58bb91c433273ba1Ian Rogers    movzwl  -2(%esi), %eax        // get last compared char from this string
17641b09b094a85e03f6ef5f687f58bb91c433273ba1Ian Rogers    movzwl  -2(%edi), %ecx        // get last compared char from comp string
176586e4671975752b112b2e8969ac6652c72c8e86c7jeffhao    subl  %ecx, %eax              // return the difference
1766aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    POP edi                       // pop callee save reg
1767aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian Rogers    POP esi                       // pop callee save reg
176886e4671975752b112b2e8969ac6652c72c8e86c7jeffhao    ret
1769aeeada47ecd9c6a7f5ea17bb1921d2fdbd394df9Ian RogersEND_FUNCTION art_quick_string_compareto
177086e4671975752b112b2e8969ac6652c72c8e86c7jeffhao
17718ce6b9040747054b444a7fa706503cd257801936Dave Allison// Return from a nested signal:
17728ce6b9040747054b444a7fa706503cd257801936Dave Allison// Entry:
17738ce6b9040747054b444a7fa706503cd257801936Dave Allison//  eax: address of jmp_buf in TLS
17748ce6b9040747054b444a7fa706503cd257801936Dave Allison
17758ce6b9040747054b444a7fa706503cd257801936Dave AllisonDEFINE_FUNCTION art_nested_signal_return
17761d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers    SETUP_GOT_NOSAVE ebx            // sets %ebx for call into PLT
17778ce6b9040747054b444a7fa706503cd257801936Dave Allison    movl LITERAL(1), %ecx
17789f5e1d9b63ef44e05c2cc7b141ef788ecc0084c7Christopher Ferris    PUSH ecx                        // second arg to longjmp (1)
17799f5e1d9b63ef44e05c2cc7b141ef788ecc0084c7Christopher Ferris    PUSH eax                        // first arg to longjmp (jmp_buf)
17808ce6b9040747054b444a7fa706503cd257801936Dave Allison    call PLT_SYMBOL(longjmp)
17814360be281a5f938e1762a1e3ec3b8a949ba05ff3Andreas Gampe    UNREACHABLE
17828ce6b9040747054b444a7fa706503cd257801936Dave AllisonEND_FUNCTION art_nested_signal_return
17838ce6b9040747054b444a7fa706503cd257801936Dave Allison
17847c1559a06041c9c299d5ab514d54b2102f204a84Roland LevillainDEFINE_FUNCTION art_quick_read_barrier_mark
17857c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain    PUSH eax                         // pass arg1 - obj
17867c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain    call SYMBOL(artReadBarrierMark)  // artReadBarrierMark(obj)
17877c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain    addl LITERAL(4), %esp            // pop argument
17887c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain    CFI_ADJUST_CFA_OFFSET(-4)
17897c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain    ret
17907c1559a06041c9c299d5ab514d54b2102f204a84Roland LevillainEND_FUNCTION art_quick_read_barrier_mark
17917c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain
17921aee900d5a0b3a8d78725a7551356bda0d8554e1Man CaoDEFINE_FUNCTION art_quick_read_barrier_slow
17930d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain    PUSH edx                         // pass arg3 - offset
17940d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain    PUSH ecx                         // pass arg2 - obj
17950d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain    PUSH eax                         // pass arg1 - ref
17960d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain    call SYMBOL(artReadBarrierSlow)  // artReadBarrierSlow(ref, obj, offset)
17970d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain    addl LITERAL(12), %esp           // pop arguments
17981aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    CFI_ADJUST_CFA_OFFSET(-12)
17991aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao    ret
18001aee900d5a0b3a8d78725a7551356bda0d8554e1Man CaoEND_FUNCTION art_quick_read_barrier_slow
18011aee900d5a0b3a8d78725a7551356bda0d8554e1Man Cao
18020d5a281c671444bfa75d63caf1427a8c0e6e1177Roland LevillainDEFINE_FUNCTION art_quick_read_barrier_for_root_slow
18030d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain    PUSH eax                                // pass arg1 - root
18040d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain    call SYMBOL(artReadBarrierForRootSlow)  // artReadBarrierForRootSlow(root)
18050d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain    addl LITERAL(4), %esp                   // pop argument
18060d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain    CFI_ADJUST_CFA_OFFSET(-4)
18070d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain    ret
18080d5a281c671444bfa75d63caf1427a8c0e6e1177Roland LevillainEND_FUNCTION art_quick_read_barrier_for_root_slow
18090d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain
1810b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray  /*
1811b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray     * On stack replacement stub.
1812b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray     * On entry:
1813b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray     *   [sp] = return address
1814b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray     *   [sp + 4] = stack to copy
1815b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray     *   [sp + 8] = size of stack
1816b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray     *   [sp + 12] = pc to call
1817b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray     *   [sp + 16] = JValue* result
1818b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray     *   [sp + 20] = shorty
1819b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray     *   [sp + 24] = thread
1820b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray     */
1821b331febbab8e916680faba722cc84b66b84218a3Nicolas GeoffrayDEFINE_FUNCTION art_quick_osr_stub
1822b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    // Save native callee saves.
1823b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    PUSH ebp
1824b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    PUSH ebx
1825b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    PUSH esi
1826b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    PUSH edi
1827b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    mov 4+16(%esp), %esi           // ESI = argument array
1828b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    mov 8+16(%esp), %ecx           // ECX = size of args
1829b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    mov 12+16(%esp), %ebx          // EBX = pc to call
1830b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    mov %esp, %ebp                 // Save stack pointer
1831b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    andl LITERAL(0xFFFFFFF0), %esp // Align stack
1832b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    PUSH ebp                       // Save old stack pointer
1833b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    subl LITERAL(12), %esp         // Align stack
1834b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    movl LITERAL(0), (%esp)        // Store null for ArtMethod* slot
1835b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    call .Losr_entry
1836b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray
1837b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    // Restore stack pointer.
1838b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    addl LITERAL(12), %esp
1839b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    POP ebp
1840b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    mov %ebp, %esp
1841b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray
1842b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    // Restore callee saves.
1843b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    POP edi
1844b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    POP esi
1845b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    POP ebx
1846b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    POP ebp
1847b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    mov 16(%esp), %ecx            // Get JValue result
1848b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    mov %eax, (%ecx)              // Store the result assuming it is a long, int or Object*
1849b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    mov %edx, 4(%ecx)             // Store the other half of the result
1850b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    mov 20(%esp), %edx            // Get the shorty
1851b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    cmpb LITERAL(68), (%edx)      // Test if result type char == 'D'
1852b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    je .Losr_return_double_quick
1853b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    cmpb LITERAL(70), (%edx)      // Test if result type char == 'F'
1854b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    je .Losr_return_float_quick
1855b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    ret
1856b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray.Losr_return_double_quick:
1857b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    movsd %xmm0, (%ecx)           // Store the floating point result
1858b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    ret
1859b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray.Losr_return_float_quick:
1860b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    movss %xmm0, (%ecx)           // Store the floating point result
1861b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    ret
1862b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray.Losr_entry:
1863b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    subl LITERAL(4), %ecx         // Given stack size contains pushed frame pointer, substract it.
1864b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    subl %ecx, %esp
1865b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    mov %esp, %edi                // EDI = beginning of stack
1866b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    rep movsb                     // while (ecx--) { *edi++ = *esi++ }
1867b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    jmp *%ebx
1868b331febbab8e916680faba722cc84b66b84218a3Nicolas GeoffrayEND_FUNCTION art_quick_osr_stub
1869b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray
1870787ec205ee545b9c08f4fc6d3823cb43d10083afElliott Hughes    // TODO: implement these!
18718dbb708c7dc05c786329eb5c3fff3194ab6472acLogan ChienUNIMPLEMENTED art_quick_memcmp16
1872