quick_entrypoints_x86.S revision a9abe872ad5ad6128d6f3fb018b6447962303ecc
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "asm_support_x86.S"
18
19#include "arch/quick_alloc_entrypoints.S"
20
21// For x86, the CFA is esp+4, the address above the pushed return address on the stack.
22
23    /*
24     * Macro that sets up the callee save frame to conform with
25     * Runtime::CreateCalleeSaveMethod(kSaveAll)
26     */
27MACRO0(SETUP_SAVE_ALL_CALLEE_SAVE_FRAME)
28    PUSH edi  // Save callee saves (ebx is saved/restored by the upcall)
29    PUSH esi
30    PUSH ebp
31    subl  MACRO_LITERAL(16), %esp  // Grow stack by 4 words, bottom word will hold Method*
32    .cfi_adjust_cfa_offset 16
33END_MACRO
34
35    /*
36     * Macro that sets up the callee save frame to conform with
37     * Runtime::CreateCalleeSaveMethod(kRefsOnly)
38     */
39MACRO0(SETUP_REF_ONLY_CALLEE_SAVE_FRAME)
40    PUSH edi  // Save callee saves (ebx is saved/restored by the upcall)
41    PUSH esi
42    PUSH ebp
43    subl  MACRO_LITERAL(16), %esp  // Grow stack by 4 words, bottom word will hold Method*
44    .cfi_adjust_cfa_offset 16
45END_MACRO
46
47MACRO0(RESTORE_REF_ONLY_CALLEE_SAVE_FRAME)
48    addl MACRO_LITERAL(16), %esp  // Unwind stack up to return address
49    POP ebp  // Restore callee saves (ebx is saved/restored by the upcall)
50    POP esi
51    POP edi
52    .cfi_adjust_cfa_offset -28
53END_MACRO
54
55    /*
56     * Macro that sets up the callee save frame to conform with
57     * Runtime::CreateCalleeSaveMethod(kRefsAndArgs)
58     */
59MACRO0(SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME)
60    PUSH edi  // Save callee saves
61    PUSH esi
62    PUSH ebp
63    PUSH ebx  // Save args
64    PUSH edx
65    PUSH ecx
66    PUSH eax   // Align stack, eax will be clobbered by Method*
67END_MACRO
68
69MACRO0(RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME)
70    addl MACRO_LITERAL(4), %esp  // Remove padding
71    .cfi_adjust_cfa_offset -4
72    POP ecx  // Restore args except eax
73    POP edx
74    POP ebx
75    POP ebp  // Restore callee saves
76    POP esi
77    POP edi
78END_MACRO
79
80    /*
81     * Macro that set calls through to artDeliverPendingExceptionFromCode, where the pending
82     * exception is Thread::Current()->exception_.
83     */
84MACRO0(DELIVER_PENDING_EXCEPTION)
85    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME         // save callee saves for throw
86    mov %esp, %ecx
87    // Outgoing argument set up
88    subl  MACRO_LITERAL(8), %esp             // Alignment padding
89    .cfi_adjust_cfa_offset 8
90    PUSH ecx                                 // pass SP
91    pushl %fs:THREAD_SELF_OFFSET             // pass Thread::Current()
92    .cfi_adjust_cfa_offset 4
93    SETUP_GOT_NOSAVE                         // clobbers ebx (harmless here)
94    call SYMBOL(artDeliverPendingExceptionFromCode)@PLT  // artDeliverPendingExceptionFromCode(Thread*, SP)
95    int3                                     // unreached
96END_MACRO
97
98MACRO2(NO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
99    DEFINE_FUNCTION VAR(c_name, 0)
100    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
101    mov %esp, %ecx
102    // Outgoing argument set up
103    subl  MACRO_LITERAL(8), %esp  // alignment padding
104    .cfi_adjust_cfa_offset 8
105    PUSH ecx                      // pass SP
106    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
107    .cfi_adjust_cfa_offset 4
108    SETUP_GOT_NOSAVE              // clobbers ebx (harmless here)
109    call VAR(cxx_name, 1)@PLT     // cxx_name(Thread*, SP)
110    int3                          // unreached
111    END_FUNCTION VAR(c_name, 0)
112END_MACRO
113
114MACRO2(ONE_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
115    DEFINE_FUNCTION VAR(c_name, 0)
116    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
117    mov %esp, %ecx
118    // Outgoing argument set up
119    PUSH eax                      // alignment padding
120    PUSH ecx                      // pass SP
121    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
122    .cfi_adjust_cfa_offset 4
123    PUSH eax                      // pass arg1
124    SETUP_GOT_NOSAVE              // clobbers ebx (harmless here)
125    call VAR(cxx_name, 1)@PLT     // cxx_name(arg1, Thread*, SP)
126    int3                          // unreached
127    END_FUNCTION VAR(c_name, 0)
128END_MACRO
129
130MACRO2(TWO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
131    DEFINE_FUNCTION VAR(c_name, 0)
132    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
133    mov %esp, %edx
134    // Outgoing argument set up
135    PUSH edx                      // pass SP
136    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
137    .cfi_adjust_cfa_offset 4
138    PUSH ecx                      // pass arg2
139    PUSH eax                      // pass arg1
140    SETUP_GOT_NOSAVE              // clobbers ebx (harmless here)
141    call VAR(cxx_name, 1)@PLT     // cxx_name(arg1, arg2, Thread*, SP)
142    int3                          // unreached
143    END_FUNCTION VAR(c_name, 0)
144END_MACRO
145
146    /*
147     * Called by managed code to create and deliver a NullPointerException.
148     */
149NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
150
151    /*
152     * Called by managed code to create and deliver an ArithmeticException.
153     */
154NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode
155
156    /*
157     * Called by managed code to create and deliver a StackOverflowError.
158     */
159NO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow, artThrowStackOverflowFromCode
160
161    /*
162     * Called by managed code, saves callee saves and then calls artThrowException
163     * that will place a mock Method* at the bottom of the stack. Arg1 holds the exception.
164     */
165ONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception, artDeliverExceptionFromCode
166
167    /*
168     * Called by managed code to create and deliver a NoSuchMethodError.
169     */
170ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method, artThrowNoSuchMethodFromCode
171
172    /*
173     * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
174     * index, arg2 holds limit.
175     */
176TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
177
178    /*
179     * All generated callsites for interface invokes and invocation slow paths will load arguments
180     * as usual - except instead of loading arg0/r0 with the target Method*, arg0/r0 will contain
181     * the method_idx.  This wrapper will save arg1-arg3, load the caller's Method*, align the
182     * stack and call the appropriate C helper.
183     * NOTE: "this" is first visible argument of the target, and so can be found in arg1/r1.
184     *
185     * The helper will attempt to locate the target and return a 64-bit result in r0/r1 consisting
186     * of the target Method* in r0 and method->code_ in r1.
187     *
188     * If unsuccessful, the helper will return NULL/NULL. There will bea pending exception in the
189     * thread and we branch to another stub to deliver it.
190     *
191     * On success this wrapper will restore arguments and *jump* to the target, leaving the lr
192     * pointing back to the original caller.
193     */
194MACRO2(INVOKE_TRAMPOLINE, c_name, cxx_name)
195    DEFINE_FUNCTION VAR(c_name, 0)
196    // Set up the callee save frame to conform with Runtime::CreateCalleeSaveMethod(kRefsAndArgs)
197    // return address
198    PUSH edi
199    PUSH esi
200    PUSH ebp
201    PUSH ebx  // Save args
202    PUSH edx
203    PUSH ecx
204    PUSH eax    // <-- callee save Method* to go here
205    movl %esp, %edx  // remember SP
206    // Outgoing argument set up
207    SETUP_GOT_NOSAVE
208    subl MACRO_LITERAL(12), %esp  // alignment padding
209    .cfi_adjust_cfa_offset 12
210    PUSH edx                      // pass SP
211    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
212    .cfi_adjust_cfa_offset 4
213    pushl 32(%edx)                // pass caller Method*
214    .cfi_adjust_cfa_offset 4
215    PUSH ecx                      // pass arg2
216    PUSH eax                      // pass arg1
217    call VAR(cxx_name, 1)@PLT     // cxx_name(arg1, arg2, arg3, Thread*, SP)
218    movl %edx, %edi               // save code pointer in EDI
219    addl MACRO_LITERAL(36), %esp  // Pop arguments skip eax
220    .cfi_adjust_cfa_offset -36
221    POP ecx  // Restore args except eax
222    POP edx
223    POP ebx
224    POP ebp  // Restore callee saves
225    POP esi
226    // Swap EDI callee save with code pointer.
227    xchgl %edi, (%esp)
228    testl %eax, %eax              // Branch forward if exception pending.
229    jz    1f
230    // Tail call to intended method.
231    ret
2321:
233    addl MACRO_LITERAL(4), %esp   // Pop code pointer off stack
234    .cfi_adjust_cfa_offset -4
235    DELIVER_PENDING_EXCEPTION
236    END_FUNCTION VAR(c_name, 0)
237END_MACRO
238
239INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline, artInvokeInterfaceTrampoline
240INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck
241
242INVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck
243INVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck
244INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
245INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
246
247    /*
248     * Quick invocation stub.
249     * On entry:
250     *   [sp] = return address
251     *   [sp + 4] = method pointer
252     *   [sp + 8] = argument array or NULL for no argument methods
253     *   [sp + 12] = size of argument array in bytes
254     *   [sp + 16] = (managed) thread pointer
255     *   [sp + 20] = JValue* result
256     *   [sp + 24] = result type char
257     */
258DEFINE_FUNCTION art_quick_invoke_stub
259    PUSH ebp                      // save ebp
260    PUSH ebx                      // save ebx
261    mov %esp, %ebp                // copy value of stack pointer into base pointer
262    .cfi_def_cfa_register ebp
263    mov 20(%ebp), %ebx            // get arg array size
264    addl LITERAL(28), %ebx        // reserve space for return addr, method*, ebx, and ebp in frame
265    andl LITERAL(0xFFFFFFF0), %ebx    // align frame size to 16 bytes
266    subl LITERAL(12), %ebx        // remove space for return address, ebx, and ebp
267    subl %ebx, %esp               // reserve stack space for argument array
268    SETUP_GOT_NOSAVE              // clobbers ebx (harmless here)
269    lea  4(%esp), %eax            // use stack pointer + method ptr as dest for memcpy
270    pushl 20(%ebp)                // push size of region to memcpy
271    pushl 16(%ebp)                // push arg array as source of memcpy
272    pushl %eax                    // push stack pointer as destination of memcpy
273    call SYMBOL(memcpy)@PLT       // (void*, const void*, size_t)
274    addl LITERAL(12), %esp        // pop arguments to memcpy
275    movl LITERAL(0), (%esp)       // store NULL for method*
276    mov 12(%ebp), %eax            // move method pointer into eax
277    mov 4(%esp), %ecx             // copy arg1 into ecx
278    mov 8(%esp), %edx             // copy arg2 into edx
279    mov 12(%esp), %ebx            // copy arg3 into ebx
280    call *METHOD_CODE_OFFSET(%eax) // call the method
281    mov %ebp, %esp                // restore stack pointer
282    .cfi_def_cfa_register esp
283    POP ebx                       // pop ebx
284    POP ebp                       // pop ebp
285    mov 20(%esp), %ecx            // get result pointer
286    cmpl LITERAL(68), 24(%esp)    // test if result type char == 'D'
287    je return_double_quick
288    cmpl LITERAL(70), 24(%esp)    // test if result type char == 'F'
289    je return_float_quick
290    mov %eax, (%ecx)              // store the result
291    mov %edx, 4(%ecx)             // store the other half of the result
292    ret
293return_double_quick:
294return_float_quick:
295    movsd %xmm0, (%ecx)           // store the floating point result
296    ret
297END_FUNCTION art_quick_invoke_stub
298
299MACRO3(NO_ARG_DOWNCALL, c_name, cxx_name, return_macro)
300    DEFINE_FUNCTION VAR(c_name, 0)
301    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save ref containing registers for GC
302    mov %esp, %edx                // remember SP
303    SETUP_GOT_NOSAVE              // clobbers ebx (harmless here)
304    // Outgoing argument set up
305    subl MACRO_LITERAL(8), %esp   // push padding
306    .cfi_adjust_cfa_offset 8
307    PUSH edx                      // pass SP
308    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
309    .cfi_adjust_cfa_offset 4
310    call VAR(cxx_name, 1)@PLT     // cxx_name(Thread*, SP)
311    addl MACRO_LITERAL(16), %esp  // pop arguments
312    .cfi_adjust_cfa_offset -16
313    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME  // restore frame up to return address
314    CALL_MACRO(return_macro, 2)   // return or deliver exception
315    END_FUNCTION VAR(c_name, 0)
316END_MACRO
317
318MACRO3(ONE_ARG_DOWNCALL, c_name, cxx_name, return_macro)
319    DEFINE_FUNCTION VAR(c_name, 0)
320    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save ref containing registers for GC
321    mov %esp, %edx                // remember SP
322    SETUP_GOT_NOSAVE              // clobbers EBX
323    // Outgoing argument set up
324    PUSH eax                      // push padding
325    PUSH edx                      // pass SP
326    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
327    .cfi_adjust_cfa_offset 4
328    PUSH eax                      // pass arg1
329    call VAR(cxx_name, 1)@PLT     // cxx_name(arg1, Thread*, SP)
330    addl MACRO_LITERAL(16), %esp  // pop arguments
331    .cfi_adjust_cfa_offset -16
332    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME  // restore frame up to return address
333    CALL_MACRO(return_macro, 2)   // return or deliver exception
334    END_FUNCTION VAR(c_name, 0)
335END_MACRO
336
337MACRO3(TWO_ARG_DOWNCALL, c_name, cxx_name, return_macro)
338    DEFINE_FUNCTION VAR(c_name, 0)
339    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save ref containing registers for GC
340    mov %esp, %edx                // remember SP
341    SETUP_GOT_NOSAVE              // clobbers EBX
342    // Outgoing argument set up
343    PUSH edx                      // pass SP
344    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
345    .cfi_adjust_cfa_offset 4
346    PUSH ecx                      // pass arg2
347    PUSH eax                      // pass arg1
348    call VAR(cxx_name, 1)@PLT     // cxx_name(arg1, arg2, Thread*, SP)
349    addl MACRO_LITERAL(16), %esp  // pop arguments
350    .cfi_adjust_cfa_offset -16
351    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME  // restore frame up to return address
352    CALL_MACRO(return_macro, 2)   // return or deliver exception
353    END_FUNCTION VAR(c_name, 0)
354END_MACRO
355
356MACRO3(THREE_ARG_DOWNCALL, c_name, cxx_name, return_macro)
357    DEFINE_FUNCTION VAR(c_name, 0)
358    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save ref containing registers for GC
359    mov %esp, %ebx                // remember SP
360    // Outgoing argument set up
361    subl MACRO_LITERAL(12), %esp  // alignment padding
362    .cfi_adjust_cfa_offset 12
363    PUSH ebx                      // pass SP
364    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
365    .cfi_adjust_cfa_offset 4
366    PUSH edx                      // pass arg3
367    PUSH ecx                      // pass arg2
368    PUSH eax                      // pass arg1
369    SETUP_GOT_NOSAVE              // clobbers EBX
370    call VAR(cxx_name, 1)@PLT     // cxx_name(arg1, arg2, arg3, Thread*, SP)
371    addl MACRO_LITERAL(32), %esp  // pop arguments
372    .cfi_adjust_cfa_offset -32
373    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME  // restore frame up to return address
374    CALL_MACRO(return_macro, 2)   // return or deliver exception
375    END_FUNCTION VAR(c_name, 0)
376END_MACRO
377
378MACRO0(RETURN_IF_RESULT_IS_NON_ZERO)
379    testl %eax, %eax               // eax == 0 ?
380    jz  1f                         // if eax == 0 goto 1
381    ret                            // return
3821:                                 // deliver exception on current thread
383    DELIVER_PENDING_EXCEPTION
384END_MACRO
385
386MACRO0(RETURN_IF_EAX_ZERO)
387    testl %eax, %eax               // eax == 0 ?
388    jnz  1f                        // if eax != 0 goto 1
389    ret                            // return
3901:                                 // deliver exception on current thread
391    DELIVER_PENDING_EXCEPTION
392END_MACRO
393
394MACRO0(RETURN_OR_DELIVER_PENDING_EXCEPTION)
395    mov %fs:THREAD_EXCEPTION_OFFSET, %ebx // get exception field
396    testl %ebx, %ebx               // ebx == 0 ?
397    jnz 1f                         // if ebx != 0 goto 1
398    ret                            // return
3991:                                 // deliver exception on current thread
400    DELIVER_PENDING_EXCEPTION
401END_MACRO
402
403// Generate the allocation entrypoints for each allocator.
404GENERATE_ALL_ALLOC_ENTRYPOINTS
405
406TWO_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO
407TWO_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO
408TWO_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO
409TWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO
410
411TWO_ARG_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO
412
413DEFINE_FUNCTION art_quick_lock_object
414    testl %eax, %eax                      // null check object/eax
415    jz   slow_lock
416retry_lock:
417    movl LOCK_WORD_OFFSET(%eax), %ecx     // ecx := lock word
418    test LITERAL(0xC0000000), %ecx        // test the 2 high bits.
419    jne  slow_lock                        // slow path if either of the two high bits are set.
420    movl %fs:THREAD_ID_OFFSET, %edx       // edx := thread id
421    test %ecx, %ecx
422    jnz  already_thin                     // lock word contains a thin lock
423    // unlocked case - %edx holds thread id with count of 0
424    movl %eax, %ecx                       // remember object in case of retry
425    xor  %eax, %eax                       // eax == 0 for comparison with lock word in cmpxchg
426    lock cmpxchg  %edx, LOCK_WORD_OFFSET(%ecx)
427    jnz  cmpxchg_fail                     // cmpxchg failed retry
428    ret
429cmpxchg_fail:
430    movl  %ecx, %eax                       // restore eax
431    jmp  retry_lock
432already_thin:
433    cmpw %ax, %dx                         // do we hold the lock already?
434    jne  slow_lock
435    addl LITERAL(65536), %eax             // increment recursion count
436    test LITERAL(0xC0000000), %eax        // overflowed if either of top two bits are set
437    jne  slow_lock                        // count overflowed so go slow
438    movl %eax, LOCK_WORD_OFFSET(%ecx)     // update lockword, cmpxchg not necessary as we hold lock
439    ret
440slow_lock:
441    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save ref containing registers for GC
442    mov %esp, %edx                // remember SP
443    SETUP_GOT_NOSAVE              // clobbers EBX
444    // Outgoing argument set up
445    PUSH eax                      // push padding
446    PUSH edx                      // pass SP
447    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
448    .cfi_adjust_cfa_offset 4
449    PUSH eax                      // pass object
450    call artLockObjectFromCode@PLT  // artLockObjectFromCode(object, Thread*, SP)
451    addl MACRO_LITERAL(16), %esp  // pop arguments
452    .cfi_adjust_cfa_offset -16
453    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME  // restore frame up to return address
454    RETURN_IF_EAX_ZERO
455END_FUNCTION art_quick_lock_object
456
457DEFINE_FUNCTION art_quick_unlock_object
458    testl %eax, %eax                      // null check object/eax
459    jz   slow_unlock
460    movl LOCK_WORD_OFFSET(%eax), %ecx     // ecx := lock word
461    movl %fs:THREAD_ID_OFFSET, %edx       // edx := thread id
462    test %ecx, %ecx
463    jb   slow_unlock                      // lock word contains a monitor
464    cmpw %cx, %dx                         // does the thread id match?
465    jne  slow_unlock
466    cmpl LITERAL(65536), %ecx
467    jae  recursive_thin_unlock
468    movl LITERAL(0), LOCK_WORD_OFFSET(%eax)
469    ret
470recursive_thin_unlock:
471    subl LITERAL(65536), %ecx
472    mov  %ecx, LOCK_WORD_OFFSET(%eax)
473    ret
474slow_unlock:
475    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save ref containing registers for GC
476    mov %esp, %edx                // remember SP
477    SETUP_GOT_NOSAVE              // clobbers EBX
478    // Outgoing argument set up
479    PUSH eax                      // push padding
480    PUSH edx                      // pass SP
481    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
482    .cfi_adjust_cfa_offset 4
483    PUSH eax                      // pass object
484    call artUnlockObjectFromCode@PLT  // artUnlockObjectFromCode(object, Thread*, SP)
485    addl MACRO_LITERAL(16), %esp  // pop arguments
486    .cfi_adjust_cfa_offset -16
487    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME  // restore frame up to return address
488    RETURN_IF_EAX_ZERO
489END_FUNCTION art_quick_unlock_object
490
491DEFINE_FUNCTION art_quick_is_assignable
492    SETUP_GOT_NOSAVE             // clobbers EBX
493    PUSH eax                     // alignment padding
494    PUSH ecx                     // pass arg2 - obj->klass
495    PUSH eax                     // pass arg1 - checked class
496    call SYMBOL(artIsAssignableFromCode)@PLT  // (Class* klass, Class* ref_klass)
497    addl LITERAL(12), %esp        // pop arguments
498    .cfi_adjust_cfa_offset -12
499    ret
500END_FUNCTION art_quick_is_assignable
501
502DEFINE_FUNCTION art_quick_check_cast
503    SETUP_GOT_NOSAVE             // clobbers EBX
504    PUSH eax                     // alignment padding
505    PUSH ecx                     // pass arg2 - obj->klass
506    PUSH eax                     // pass arg1 - checked class
507    call SYMBOL(artIsAssignableFromCode)@PLT  // (Class* klass, Class* ref_klass)
508    testl %eax, %eax
509    jz 1f                         // jump forward if not assignable
510    addl LITERAL(12), %esp        // pop arguments
511    .cfi_adjust_cfa_offset -12
512    ret
5131:
514    POP eax                       // pop arguments
515    POP ecx
516    addl LITERAL(4), %esp
517    .cfi_adjust_cfa_offset -12
518    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
519    mov %esp, %edx
520    // Outgoing argument set up
521    PUSH edx                      // pass SP
522    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
523    .cfi_adjust_cfa_offset 4
524    PUSH ecx                      // pass arg2
525    PUSH eax                      // pass arg1
526    call SYMBOL(artThrowClassCastException)@PLT // (Class* a, Class* b, Thread*, SP)
527    int3                          // unreached
528END_FUNCTION art_quick_check_cast
529
530    /*
531     * Entry from managed code for array put operations of objects where the value being stored
532     * needs to be checked for compatibility.
533     * eax = array, ecx = index, edx = value
534     */
535DEFINE_FUNCTION art_quick_aput_obj_with_null_and_bound_check
536    testl %eax, %eax
537    jnz art_quick_aput_obj_with_bound_check
538    jmp art_quick_throw_null_pointer_exception
539END_FUNCTION art_quick_aput_obj_with_null_and_bound_check
540
541DEFINE_FUNCTION art_quick_aput_obj_with_bound_check
542    movl ARRAY_LENGTH_OFFSET(%eax), %ebx
543    cmpl %ebx, %ecx
544    jb art_quick_aput_obj
545    mov %ecx, %eax
546    mov %ebx, %ecx
547    jmp art_quick_throw_array_bounds
548END_FUNCTION art_quick_aput_obj_with_bound_check
549
550DEFINE_FUNCTION art_quick_aput_obj
551    test %edx, %edx              // store of null
552    jz do_aput_null
553    movl CLASS_OFFSET(%eax), %ebx
554    movl CLASS_COMPONENT_TYPE_OFFSET(%ebx), %ebx
555    cmpl CLASS_OFFSET(%edx), %ebx // value's type == array's component type - trivial assignability
556    jne check_assignability
557do_aput:
558    movl %edx, OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4)
559    movl %fs:THREAD_CARD_TABLE_OFFSET, %edx
560    shrl LITERAL(7), %eax
561    movb %dl, (%edx, %eax)
562    ret
563do_aput_null:
564    movl %edx, OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4)
565    ret
566check_assignability:
567    PUSH eax                     // save arguments
568    PUSH ecx
569    PUSH edx
570    subl LITERAL(8), %esp        // alignment padding
571    .cfi_adjust_cfa_offset 8
572    pushl CLASS_OFFSET(%edx)     // pass arg2 - type of the value to be stored
573    .cfi_adjust_cfa_offset 4
574    PUSH ebx                     // pass arg1 - component type of the array
575    SETUP_GOT_NOSAVE             // clobbers EBX
576    call SYMBOL(artIsAssignableFromCode)@PLT  // (Class* a, Class* b)
577    addl LITERAL(16), %esp       // pop arguments
578    .cfi_adjust_cfa_offset -16
579    testl %eax, %eax
580    jz   throw_array_store_exception
581    POP  edx
582    POP  ecx
583    POP  eax
584    movl %edx, OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4)  // do the aput
585    movl %fs:THREAD_CARD_TABLE_OFFSET, %edx
586    shrl LITERAL(7), %eax
587    movb %dl, (%edx, %eax)
588    ret
589throw_array_store_exception:
590    POP  edx
591    POP  ecx
592    POP  eax
593    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
594    mov %esp, %ecx
595    // Outgoing argument set up
596    PUSH ecx                      // pass SP
597    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
598    .cfi_adjust_cfa_offset 4
599    PUSH edx                      // pass arg2 - value
600    PUSH eax                      // pass arg1 - array
601    call SYMBOL(artThrowArrayStoreException)@PLT // (array, value, Thread*, SP)
602    int3                          // unreached
603END_FUNCTION art_quick_aput_obj
604
605DEFINE_FUNCTION art_quick_memcpy
606    SETUP_GOT_NOSAVE              // clobbers EBX
607    PUSH edx                      // pass arg3
608    PUSH ecx                      // pass arg2
609    PUSH eax                      // pass arg1
610    call SYMBOL(memcpy)@PLT       // (void*, const void*, size_t)
611    addl LITERAL(12), %esp        // pop arguments
612    .cfi_adjust_cfa_offset -12
613    ret
614END_FUNCTION art_quick_memcpy
615
616NO_ARG_DOWNCALL art_quick_test_suspend, artTestSuspendFromCode, ret
617
618DEFINE_FUNCTION art_quick_fmod
619    subl LITERAL(12), %esp        // alignment padding
620    .cfi_adjust_cfa_offset 12
621    PUSH ebx                      // pass arg4 b.hi
622    PUSH edx                      // pass arg3 b.lo
623    PUSH ecx                      // pass arg2 a.hi
624    PUSH eax                      // pass arg1 a.lo
625    SETUP_GOT_NOSAVE              // clobbers EBX
626    call SYMBOL(fmod)@PLT         // (jdouble a, jdouble b)
627    fstpl (%esp)                  // pop return value off fp stack
628    movsd (%esp), %xmm0           // place into %xmm0
629    addl LITERAL(28), %esp        // pop arguments
630    .cfi_adjust_cfa_offset -28
631    ret
632END_FUNCTION art_quick_fmod
633
634DEFINE_FUNCTION art_quick_fmodf
635    PUSH eax                      // alignment padding
636    PUSH ecx                      // pass arg2 b
637    PUSH eax                      // pass arg1 a
638    SETUP_GOT_NOSAVE              // clobbers EBX
639    call SYMBOL(fmodf)@PLT        // (jfloat a, jfloat b)
640    fstps (%esp)                  // pop return value off fp stack
641    movss (%esp), %xmm0           // place into %xmm0
642    addl LITERAL(12), %esp        // pop arguments
643    .cfi_adjust_cfa_offset -12
644    ret
645END_FUNCTION art_quick_fmodf
646
647DEFINE_FUNCTION art_quick_l2d
648    PUSH ecx                      // push arg2 a.hi
649    PUSH eax                      // push arg1 a.lo
650    fildll (%esp)                 // load as integer and push into st0
651    fstpl (%esp)                  // pop value off fp stack as double
652    movsd (%esp), %xmm0           // place into %xmm0
653    addl LITERAL(8), %esp         // pop arguments
654    .cfi_adjust_cfa_offset -8
655    ret
656END_FUNCTION art_quick_l2d
657
658DEFINE_FUNCTION art_quick_l2f
659    PUSH ecx                      // push arg2 a.hi
660    PUSH eax                      // push arg1 a.lo
661    fildll (%esp)                 // load as integer and push into st0
662    fstps (%esp)                  // pop value off fp stack as a single
663    movss (%esp), %xmm0           // place into %xmm0
664    addl LITERAL(8), %esp         // pop argument
665    .cfi_adjust_cfa_offset -8
666    ret
667END_FUNCTION art_quick_l2f
668
669DEFINE_FUNCTION art_quick_d2l
670    PUSH eax                      // alignment padding
671    PUSH ecx                      // pass arg2 a.hi
672    PUSH eax                      // pass arg1 a.lo
673    SETUP_GOT_NOSAVE              // clobbers EBX
674    call SYMBOL(art_d2l)@PLT      // (jdouble a)
675    addl LITERAL(12), %esp        // pop arguments
676    .cfi_adjust_cfa_offset -12
677    ret
678END_FUNCTION art_quick_d2l
679
680DEFINE_FUNCTION art_quick_f2l
681    subl LITERAL(8), %esp         // alignment padding
682    .cfi_adjust_cfa_offset 8
683    SETUP_GOT_NOSAVE              // clobbers EBX
684    PUSH eax                      // pass arg1 a
685    call SYMBOL(art_f2l)@PLT      // (jfloat a)
686    addl LITERAL(12), %esp        // pop arguments
687    .cfi_adjust_cfa_offset -12
688    ret
689END_FUNCTION art_quick_f2l
690
691DEFINE_FUNCTION art_quick_idivmod
692    cmpl LITERAL(0x80000000), %eax
693    je check_arg2  // special case
694args_ok:
695    cdq         // edx:eax = sign extend eax
696    idiv %ecx   // (edx,eax) = (edx:eax % ecx, edx:eax / ecx)
697    ret
698check_arg2:
699    cmpl LITERAL(-1), %ecx
700    jne args_ok
701    xorl %edx, %edx
702    ret         // eax already holds min int
703END_FUNCTION art_quick_idivmod
704
705DEFINE_FUNCTION art_quick_ldiv
706    subl LITERAL(12), %esp       // alignment padding
707    .cfi_adjust_cfa_offset 12
708    PUSH ebx                     // pass arg4 b.hi
709    PUSH edx                     // pass arg3 b.lo
710    PUSH ecx                     // pass arg2 a.hi
711    PUSH eax                     // pass arg1 a.lo
712    SETUP_GOT_NOSAVE             // clobbers EBX
713    call SYMBOL(artLdiv)@PLT     // (jlong a, jlong b)
714    addl LITERAL(28), %esp       // pop arguments
715    .cfi_adjust_cfa_offset -28
716    ret
717END_FUNCTION art_quick_ldiv
718
719DEFINE_FUNCTION art_quick_lmod
720    subl LITERAL(12), %esp       // alignment padding
721    .cfi_adjust_cfa_offset 12
722    PUSH ebx                     // pass arg4 b.hi
723    PUSH edx                     // pass arg3 b.lo
724    PUSH ecx                     // pass arg2 a.hi
725    PUSH eax                     // pass arg1 a.lo
726    SETUP_GOT_NOSAVE             // clobbers EBX
727    call SYMBOL(artLmod)@PLT     // (jlong a, jlong b)
728    addl LITERAL(28), %esp       // pop arguments
729    .cfi_adjust_cfa_offset -28
730    ret
731END_FUNCTION art_quick_lmod
732
733DEFINE_FUNCTION art_quick_lmul
734    imul %eax, %ebx              // ebx = a.lo(eax) * b.hi(ebx)
735    imul %edx, %ecx              // ecx = b.lo(edx) * a.hi(ecx)
736    mul  %edx                    // edx:eax = a.lo(eax) * b.lo(edx)
737    add  %ebx, %ecx
738    add  %ecx, %edx              // edx += (a.lo * b.hi) + (b.lo * a.hi)
739    ret
740END_FUNCTION art_quick_lmul
741
742DEFINE_FUNCTION art_quick_lshl
743    // ecx:eax << edx
744    xchg %edx, %ecx
745    shld %cl,%eax,%edx
746    shl  %cl,%eax
747    test LITERAL(32), %cl
748    jz  1f
749    mov %eax, %edx
750    xor %eax, %eax
7511:
752    ret
753END_FUNCTION art_quick_lshl
754
755DEFINE_FUNCTION art_quick_lshr
756    // ecx:eax >> edx
757    xchg %edx, %ecx
758    shrd %cl,%edx,%eax
759    sar  %cl,%edx
760    test LITERAL(32),%cl
761    jz  1f
762    mov %edx, %eax
763    sar LITERAL(31), %edx
7641:
765    ret
766END_FUNCTION art_quick_lshr
767
768DEFINE_FUNCTION art_quick_lushr
769    // ecx:eax >>> edx
770    xchg %edx, %ecx
771    shrd %cl,%edx,%eax
772    shr  %cl,%edx
773    test LITERAL(32),%cl
774    jz  1f
775    mov %edx, %eax
776    xor %edx, %edx
7771:
778    ret
779END_FUNCTION art_quick_lushr
780
781DEFINE_FUNCTION art_quick_set32_instance
782    SETUP_REF_ONLY_CALLEE_SAVE_FRAME       // save ref containing registers for GC
783    mov %esp, %ebx                // remember SP
784    subl LITERAL(8), %esp         // alignment padding
785    .cfi_adjust_cfa_offset 8
786    PUSH ebx                      // pass SP
787    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
788    .cfi_adjust_cfa_offset 4
789    mov 32(%ebx), %ebx            // get referrer
790    PUSH ebx                      // pass referrer
791    PUSH edx                      // pass new_val
792    PUSH ecx                      // pass object
793    PUSH eax                      // pass field_idx
794    SETUP_GOT_NOSAVE              // clobbers EBX
795    call SYMBOL(artSet32InstanceFromCode)@PLT  // (field_idx, Object*, new_val, referrer, Thread*, SP)
796    addl LITERAL(32), %esp        // pop arguments
797    .cfi_adjust_cfa_offset -32
798    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME     // restore frame up to return address
799    RETURN_IF_EAX_ZERO            // return or deliver exception
800END_FUNCTION art_quick_set32_instance
801
802DEFINE_FUNCTION art_quick_set64_instance
803    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save ref containing registers for GC
804    subl LITERAL(8), %esp         // alignment padding
805    .cfi_adjust_cfa_offset 8
806    PUSH esp                      // pass SP-8
807    addl LITERAL(8), (%esp)       // fix SP on stack by adding 8
808    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
809    .cfi_adjust_cfa_offset 4
810    PUSH ebx                      // pass high half of new_val
811    PUSH edx                      // pass low half of new_val
812    PUSH ecx                      // pass object
813    PUSH eax                      // pass field_idx
814    SETUP_GOT_NOSAVE              // clobbers EBX
815    call SYMBOL(artSet64InstanceFromCode)@PLT  // (field_idx, Object*, new_val, Thread*, SP)
816    addl LITERAL(32), %esp        // pop arguments
817    .cfi_adjust_cfa_offset -32
818    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME  // restore frame up to return address
819    RETURN_IF_EAX_ZERO            // return or deliver exception
820END_FUNCTION art_quick_set64_instance
821
822DEFINE_FUNCTION art_quick_set_obj_instance
823    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save ref containing registers for GC
824    mov %esp, %ebx                // remember SP
825    subl LITERAL(8), %esp         // alignment padding
826    .cfi_adjust_cfa_offset 8
827    PUSH ebx                      // pass SP
828    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
829    .cfi_adjust_cfa_offset 4
830    mov 32(%ebx), %ebx            // get referrer
831    PUSH ebx                      // pass referrer
832    PUSH edx                      // pass new_val
833    PUSH ecx                      // pass object
834    PUSH eax                      // pass field_idx
835    SETUP_GOT_NOSAVE              // clobbers EBX
836    call SYMBOL(artSetObjInstanceFromCode)@PLT // (field_idx, Object*, new_val, referrer, Thread*, SP)
837    addl LITERAL(32), %esp        // pop arguments
838    .cfi_adjust_cfa_offset -32
839    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME     // restore frame up to return address
840    RETURN_IF_EAX_ZERO            // return or deliver exception
841END_FUNCTION art_quick_set_obj_instance
842
843DEFINE_FUNCTION art_quick_get32_instance
844    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save ref containing registers for GC
845    mov %esp, %ebx                // remember SP
846    mov 32(%esp), %edx            // get referrer
847    subl LITERAL(12), %esp        // alignment padding
848    .cfi_adjust_cfa_offset 12
849    PUSH ebx                      // pass SP
850    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
851    .cfi_adjust_cfa_offset 4
852    PUSH edx                      // pass referrer
853    PUSH ecx                      // pass object
854    PUSH eax                      // pass field_idx
855    SETUP_GOT_NOSAVE              // clobbers EBX
856    call SYMBOL(artGet32InstanceFromCode)@PLT  // (field_idx, Object*, referrer, Thread*, SP)
857    addl LITERAL(32), %esp        // pop arguments
858    .cfi_adjust_cfa_offset -32
859    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME     // restore frame up to return address
860    RETURN_OR_DELIVER_PENDING_EXCEPTION    // return or deliver exception
861END_FUNCTION art_quick_get32_instance
862
863DEFINE_FUNCTION art_quick_get64_instance
864    SETUP_REF_ONLY_CALLEE_SAVE_FRAME       // save ref containing registers for GC
865    mov %esp, %ebx                // remember SP
866    mov 32(%esp), %edx            // get referrer
867    subl LITERAL(12), %esp        // alignment padding
868    .cfi_adjust_cfa_offset 12
869    PUSH ebx                      // pass SP
870    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
871    .cfi_adjust_cfa_offset 4
872    PUSH edx                      // pass referrer
873    PUSH ecx                      // pass object
874    PUSH eax                      // pass field_idx
875    SETUP_GOT_NOSAVE              // clobbers EBX
876    call SYMBOL(artGet64InstanceFromCode)@PLT  // (field_idx, Object*, referrer, Thread*, SP)
877    addl LITERAL(32), %esp        // pop arguments
878    .cfi_adjust_cfa_offset -32
879    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME     // restore frame up to return address
880    RETURN_OR_DELIVER_PENDING_EXCEPTION    // return or deliver exception
881END_FUNCTION art_quick_get64_instance
882
883DEFINE_FUNCTION art_quick_get_obj_instance
884    SETUP_REF_ONLY_CALLEE_SAVE_FRAME       // save ref containing registers for GC
885    mov %esp, %ebx                // remember SP
886    mov 32(%esp), %edx            // get referrer
887    subl LITERAL(12), %esp        // alignment padding
888    .cfi_adjust_cfa_offset 12
889    PUSH ebx                      // pass SP
890    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
891    .cfi_adjust_cfa_offset 4
892    PUSH edx                      // pass referrer
893    PUSH ecx                      // pass object
894    PUSH eax                      // pass field_idx
895    SETUP_GOT_NOSAVE              // clobbers EBX
896    call SYMBOL(artGetObjInstanceFromCode)@PLT // (field_idx, Object*, referrer, Thread*, SP)
897    addl LITERAL(32), %esp        // pop arguments
898    .cfi_adjust_cfa_offset -32
899    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME     // restore frame up to return address
900    RETURN_OR_DELIVER_PENDING_EXCEPTION    // return or deliver exception
901END_FUNCTION art_quick_get_obj_instance
902
903DEFINE_FUNCTION art_quick_set32_static
904    SETUP_REF_ONLY_CALLEE_SAVE_FRAME       // save ref containing registers for GC
905    mov %esp, %ebx                // remember SP
906    mov 32(%esp), %edx            // get referrer
907    subl LITERAL(12), %esp        // alignment padding
908    .cfi_adjust_cfa_offset 12
909    PUSH ebx                      // pass SP
910    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
911    .cfi_adjust_cfa_offset 4
912    PUSH edx                      // pass referrer
913    PUSH ecx                      // pass new_val
914    PUSH eax                      // pass field_idx
915    SETUP_GOT_NOSAVE              // clobbers EBX
916    call SYMBOL(artSet32StaticFromCode)@PLT  // (field_idx, new_val, referrer, Thread*, SP)
917    addl LITERAL(32), %esp        // pop arguments
918    .cfi_adjust_cfa_offset -32
919    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME     // restore frame up to return address
920    RETURN_IF_EAX_ZERO            // return or deliver exception
921END_FUNCTION art_quick_set32_static
922
923DEFINE_FUNCTION art_quick_set64_static
924    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save ref containing registers for GC
925    mov %esp, %ebx                // remember SP
926    subl LITERAL(8), %esp         // alignment padding
927    .cfi_adjust_cfa_offset 8
928    PUSH ebx                      // pass SP
929    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
930    .cfi_adjust_cfa_offset 4
931    mov 32(%ebx), %ebx            // get referrer
932    PUSH edx                      // pass high half of new_val
933    PUSH ecx                      // pass low half of new_val
934    PUSH ebx                      // pass referrer
935    PUSH eax                      // pass field_idx
936    SETUP_GOT_NOSAVE              // clobbers EBX
937    call SYMBOL(artSet64StaticFromCode)@PLT  // (field_idx, referrer, new_val, Thread*, SP)
938    addl LITERAL(32), %esp        // pop arguments
939    .cfi_adjust_cfa_offset -32
940    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME  // restore frame up to return address
941    RETURN_IF_EAX_ZERO            // return or deliver exception
942END_FUNCTION art_quick_set64_static
943
944DEFINE_FUNCTION art_quick_set_obj_static
945    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save ref containing registers for GC
946    mov %esp, %ebx                // remember SP
947    mov 32(%esp), %edx            // get referrer
948    subl LITERAL(12), %esp        // alignment padding
949    .cfi_adjust_cfa_offset 12
950    PUSH ebx                      // pass SP
951    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
952    .cfi_adjust_cfa_offset 4
953    PUSH edx                      // pass referrer
954    PUSH ecx                      // pass new_val
955    PUSH eax                      // pass field_idx
956    SETUP_GOT_NOSAVE              // clobbers EBX
957    call SYMBOL(artSetObjStaticFromCode)@PLT  // (field_idx, new_val, referrer, Thread*, SP)
958    addl LITERAL(32), %esp        // pop arguments
959    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME  // restore frame up to return address
960    RETURN_IF_EAX_ZERO            // return or deliver exception
961END_FUNCTION art_quick_set_obj_static
962
963DEFINE_FUNCTION art_quick_get32_static
964    SETUP_REF_ONLY_CALLEE_SAVE_FRAME       // save ref containing registers for GC
965    mov %esp, %edx                // remember SP
966    mov 32(%esp), %ecx            // get referrer
967    PUSH edx                      // pass SP
968    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
969    .cfi_adjust_cfa_offset 4
970    PUSH ecx                      // pass referrer
971    PUSH eax                      // pass field_idx
972    SETUP_GOT_NOSAVE              // clobbers EBX
973    call SYMBOL(artGet32StaticFromCode)@PLT    // (field_idx, referrer, Thread*, SP)
974    addl LITERAL(16), %esp        // pop arguments
975    .cfi_adjust_cfa_offset -16
976    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME     // restore frame up to return address
977    RETURN_OR_DELIVER_PENDING_EXCEPTION    // return or deliver exception
978END_FUNCTION art_quick_get32_static
979
980DEFINE_FUNCTION art_quick_get64_static
981    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // save ref containing registers for GC
982    mov %esp, %edx                // remember SP
983    mov 32(%esp), %ecx            // get referrer
984    PUSH edx                      // pass SP
985    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
986    .cfi_adjust_cfa_offset 4
987    PUSH ecx                      // pass referrer
988    PUSH eax                      // pass field_idx
989    SETUP_GOT_NOSAVE              // clobbers EBX
990    call SYMBOL(artGet64StaticFromCode)@PLT    // (field_idx, referrer, Thread*, SP)
991    addl LITERAL(16), %esp        // pop arguments
992    .cfi_adjust_cfa_offset -16
993    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME     // restore frame up to return address
994    RETURN_OR_DELIVER_PENDING_EXCEPTION    // return or deliver exception
995END_FUNCTION art_quick_get64_static
996
997DEFINE_FUNCTION art_quick_get_obj_static
998    SETUP_REF_ONLY_CALLEE_SAVE_FRAME       // save ref containing registers for GC
999    mov %esp, %edx                // remember SP
1000    mov 32(%esp), %ecx            // get referrer
1001    PUSH edx                      // pass SP
1002    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
1003    .cfi_adjust_cfa_offset 4
1004    PUSH ecx                      // pass referrer
1005    PUSH eax                      // pass field_idx
1006    SETUP_GOT_NOSAVE              // clobbers EBX
1007    call SYMBOL(artGetObjStaticFromCode)@PLT   // (field_idx, referrer, Thread*, SP)
1008    addl LITERAL(16), %esp        // pop arguments
1009    .cfi_adjust_cfa_offset -16
1010    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME     // restore frame up to return address
1011    RETURN_OR_DELIVER_PENDING_EXCEPTION    // return or deliver exception
1012END_FUNCTION art_quick_get_obj_static
1013
1014DEFINE_FUNCTION art_quick_proxy_invoke_handler
1015    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME   // save frame and Method*
1016    PUSH esp                      // pass SP
1017    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
1018    .cfi_adjust_cfa_offset 4
1019    PUSH ecx                      // pass receiver
1020    PUSH eax                      // pass proxy method
1021    SETUP_GOT_NOSAVE              // clobbers EBX
1022    call SYMBOL(artQuickProxyInvokeHandler)@PLT // (proxy method, receiver, Thread*, SP)
1023    movd %eax, %xmm0              // place return value also into floating point return value
1024    movd %edx, %xmm1
1025    punpckldq %xmm1, %xmm0
1026    addl LITERAL(44), %esp        // pop arguments
1027    .cfi_adjust_cfa_offset -44
1028    RETURN_OR_DELIVER_PENDING_EXCEPTION    // return or deliver exception
1029END_FUNCTION art_quick_proxy_invoke_handler
1030
1031    /*
1032     * Called to resolve an imt conflict. xmm0 is a hidden argument that holds the target method's
1033     * dex method index.
1034     */
1035DEFINE_FUNCTION art_quick_imt_conflict_trampoline
1036    PUSH ecx
1037    movl 8(%esp), %eax            // load caller Method*
1038    movl METHOD_DEX_CACHE_METHODS_OFFSET(%eax), %eax  // load dex_cache_resolved_methods
1039    movd %xmm0, %ecx              // get target method index stored in xmm0
1040    movl OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4), %eax  // load the target method
1041    POP ecx
1042    jmp art_quick_invoke_interface_trampoline
1043END_FUNCTION art_quick_imt_conflict_trampoline
1044
1045DEFINE_FUNCTION art_quick_resolution_trampoline
1046    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
1047    PUSH esp                      // pass SP
1048    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
1049    .cfi_adjust_cfa_offset 4
1050    PUSH ecx                      // pass receiver
1051    PUSH eax                      // pass method
1052    SETUP_GOT_NOSAVE              // clobbers EBX
1053    call SYMBOL(artQuickResolutionTrampoline)@PLT // (Method* called, receiver, Thread*, SP)
1054    movl %eax, %edi               // remember code pointer in EDI
1055    addl LITERAL(16), %esp        // pop arguments
1056    test %eax, %eax               // if code pointer is NULL goto deliver pending exception
1057    jz 1f
1058    POP eax                       // called method
1059    POP ecx                       // restore args
1060    POP edx
1061    POP ebx
1062    POP ebp                       // restore callee saves except EDI
1063    POP esi
1064    xchgl 0(%esp),%edi            // restore EDI and place code pointer as only value on stack
1065    ret                           // tail call into method
10661:
1067    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
1068    DELIVER_PENDING_EXCEPTION
1069END_FUNCTION art_quick_resolution_trampoline
1070
1071DEFINE_FUNCTION art_quick_to_interpreter_bridge
1072    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME   // save frame
1073    mov %esp, %edx                // remember SP
1074    PUSH eax                      // alignment padding
1075    PUSH edx                      // pass SP
1076    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
1077    .cfi_adjust_cfa_offset 4
1078    PUSH eax                      // pass  method
1079    SETUP_GOT_NOSAVE              // clobbers EBX
1080    call SYMBOL(artQuickToInterpreterBridge)@PLT  // (method, Thread*, SP)
1081    movd %eax, %xmm0              // place return value also into floating point return value
1082    movd %edx, %xmm1
1083    punpckldq %xmm1, %xmm0
1084    addl LITERAL(16), %esp        // pop arguments
1085    .cfi_adjust_cfa_offset -16
1086    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
1087    RETURN_OR_DELIVER_PENDING_EXCEPTION    // return or deliver exception
1088END_FUNCTION art_quick_to_interpreter_bridge
1089
1090    /*
1091     * Routine that intercepts method calls and returns.
1092     */
1093DEFINE_FUNCTION art_quick_instrumentation_entry
1094    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
1095    movl  %esp, %edx              // Save SP.
1096    PUSH eax                      // Save eax which will be clobbered by the callee-save method.
1097    subl LITERAL(8), %esp         // Align stack.
1098    .cfi_adjust_cfa_offset 8
1099    pushl 40(%esp)                // Pass LR.
1100    .cfi_adjust_cfa_offset 4
1101    PUSH edx                      // Pass SP.
1102    pushl %fs:THREAD_SELF_OFFSET  // Pass Thread::Current().
1103    .cfi_adjust_cfa_offset 4
1104    PUSH ecx                      // Pass receiver.
1105    PUSH eax                      // Pass Method*.
1106    SETUP_GOT_NOSAVE              // clobbers EBX
1107    call  SYMBOL(artInstrumentationMethodEntryFromCode)@PLT // (Method*, Object*, Thread*, SP, LR)
1108    addl  LITERAL(28), %esp       // Pop arguments upto saved Method*.
1109    movl 28(%esp), %edi           // Restore edi.
1110    movl %eax, 28(%esp)           // Place code* over edi, just under return pc.
1111    movl LITERAL(SYMBOL(art_quick_instrumentation_exit)@PLT), 32(%esp)
1112                                  // Place instrumentation exit as return pc.
1113    movl (%esp), %eax             // Restore eax.
1114    movl 8(%esp), %ecx            // Restore ecx.
1115    movl 12(%esp), %edx           // Restore edx.
1116    movl 16(%esp), %ebx           // Restore ebx.
1117    movl 20(%esp), %ebp           // Restore ebp.
1118    movl 24(%esp), %esi           // Restore esi.
1119    addl LITERAL(28), %esp        // Wind stack back upto code*.
1120    ret                           // Call method (and pop).
1121END_FUNCTION art_quick_instrumentation_entry
1122
1123DEFINE_FUNCTION art_quick_instrumentation_exit
1124    pushl LITERAL(0)              // Push a fake return PC as there will be none on the stack.
1125    SETUP_REF_ONLY_CALLEE_SAVE_FRAME
1126    mov  %esp, %ecx               // Remember SP
1127    subl LITERAL(8), %esp         // Save float return value.
1128    .cfi_adjust_cfa_offset 8
1129    movd %xmm0, (%esp)
1130    PUSH edx                      // Save gpr return value.
1131    PUSH eax
1132    subl LITERAL(8), %esp         // Align stack
1133    movd %xmm0, (%esp)
1134    subl LITERAL(8), %esp         // Pass float return value.
1135    .cfi_adjust_cfa_offset 8
1136    movd %xmm0, (%esp)
1137    PUSH edx                      // Pass gpr return value.
1138    PUSH eax
1139    PUSH ecx                      // Pass SP.
1140    pushl %fs:THREAD_SELF_OFFSET  // Pass Thread::Current.
1141    .cfi_adjust_cfa_offset 4
1142    SETUP_GOT_NOSAVE              // clobbers EBX
1143    call  SYMBOL(artInstrumentationMethodExitFromCode)@PLT  // (Thread*, SP, gpr_result, fpr_result)
1144    mov   %eax, %ecx              // Move returned link register.
1145    addl LITERAL(32), %esp        // Pop arguments.
1146    .cfi_adjust_cfa_offset -32
1147    movl %edx, %ebx               // Move returned link register for deopt
1148                                  // (ebx is pretending to be our LR).
1149    POP eax                       // Restore gpr return value.
1150    POP edx
1151    movd (%esp), %xmm0            // Restore fpr return value.
1152    addl LITERAL(8), %esp
1153    .cfi_adjust_cfa_offset -8
1154    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
1155    addl LITERAL(4), %esp         // Remove fake return pc.
1156    jmp   *%ecx                   // Return.
1157END_FUNCTION art_quick_instrumentation_exit
1158
1159    /*
1160     * Instrumentation has requested that we deoptimize into the interpreter. The deoptimization
1161     * will long jump to the upcall with a special exception of -1.
1162     */
1163DEFINE_FUNCTION art_quick_deoptimize
1164    pushl %ebx                    // Fake that we were called.
1165    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
1166    mov  %esp, %ecx               // Remember SP.
1167    subl LITERAL(8), %esp         // Align stack.
1168    .cfi_adjust_cfa_offset 8
1169    PUSH ecx                      // Pass SP.
1170    pushl %fs:THREAD_SELF_OFFSET  // Pass Thread::Current().
1171    .cfi_adjust_cfa_offset 4
1172    SETUP_GOT_NOSAVE              // clobbers EBX
1173    call SYMBOL(artDeoptimize)@PLT    // artDeoptimize(Thread*, SP)
1174    int3                          // Unreachable.
1175END_FUNCTION art_quick_deoptimize
1176
1177    /*
1178     * String's indexOf.
1179     *
1180     * On entry:
1181     *    eax:   string object (known non-null)
1182     *    ecx:   char to match (known <= 0xFFFF)
1183     *    edx:   Starting offset in string data
1184     */
1185DEFINE_FUNCTION art_quick_indexof
1186    PUSH edi                      // push callee save reg
1187    mov STRING_COUNT_OFFSET(%eax), %ebx
1188    mov STRING_VALUE_OFFSET(%eax), %edi
1189    mov STRING_OFFSET_OFFSET(%eax), %eax
1190    testl %edx, %edx              // check if start < 0
1191    jl   clamp_min
1192clamp_done:
1193    cmpl %ebx, %edx               // check if start >= count
1194    jge  not_found
1195    lea  STRING_DATA_OFFSET(%edi, %eax, 2), %edi  // build a pointer to the start of string data
1196    mov  %edi, %eax               // save a copy in eax to later compute result
1197    lea  (%edi, %edx, 2), %edi    // build pointer to start of data to compare
1198    subl  %edx, %ebx              // compute iteration count
1199    /*
1200     * At this point we have:
1201     *   eax: original start of string data
1202     *   ecx: char to compare
1203     *   ebx: length to compare
1204     *   edi: start of data to test
1205     */
1206    mov  %eax, %edx
1207    mov  %ecx, %eax               // put char to match in %eax
1208    mov  %ebx, %ecx               // put length to compare in %ecx
1209    repne scasw                   // find %ax, starting at [%edi], up to length %ecx
1210    jne  not_found
1211    subl %edx, %edi
1212    sar  LITERAL(1), %edi
1213    decl %edi                     // index = ((curr_ptr - orig_ptr) / 2) - 1
1214    mov  %edi, %eax
1215    POP edi                       // pop callee save reg
1216    ret
1217    .balign 16
1218not_found:
1219    mov  LITERAL(-1), %eax        // return -1 (not found)
1220    POP edi                       // pop callee save reg
1221    ret
1222clamp_min:
1223    xor  %edx, %edx               // clamp start to 0
1224    jmp  clamp_done
1225END_FUNCTION art_quick_indexof
1226
1227    /*
1228     * String's compareTo.
1229     *
1230     * On entry:
1231     *    eax:   this string object (known non-null)
1232     *    ecx:   comp string object (known non-null)
1233     */
1234DEFINE_FUNCTION art_quick_string_compareto
1235    PUSH esi                    // push callee save reg
1236    PUSH edi                    // push callee save reg
1237    mov STRING_COUNT_OFFSET(%eax), %edx
1238    mov STRING_COUNT_OFFSET(%ecx), %ebx
1239    mov STRING_VALUE_OFFSET(%eax), %esi
1240    mov STRING_VALUE_OFFSET(%ecx), %edi
1241    mov STRING_OFFSET_OFFSET(%eax), %eax
1242    mov STRING_OFFSET_OFFSET(%ecx), %ecx
1243    /* Build pointers to the start of string data */
1244    lea  STRING_DATA_OFFSET(%esi, %eax, 2), %esi
1245    lea  STRING_DATA_OFFSET(%edi, %ecx, 2), %edi
1246    /* Calculate min length and count diff */
1247    mov   %edx, %ecx
1248    mov   %edx, %eax
1249    subl  %ebx, %eax
1250    cmovg %ebx, %ecx
1251    /*
1252     * At this point we have:
1253     *   eax: value to return if first part of strings are equal
1254     *   ecx: minimum among the lengths of the two strings
1255     *   esi: pointer to this string data
1256     *   edi: pointer to comp string data
1257     */
1258    repe cmpsw                    // find nonmatching chars in [%esi] and [%edi], up to length %ecx
1259    jne not_equal
1260    POP edi                       // pop callee save reg
1261    POP esi                       // pop callee save reg
1262    ret
1263    .balign 16
1264not_equal:
1265    movzwl  -2(%esi), %eax        // get last compared char from this string
1266    movzwl  -2(%edi), %ecx        // get last compared char from comp string
1267    subl  %ecx, %eax              // return the difference
1268    POP edi                       // pop callee save reg
1269    POP esi                       // pop callee save reg
1270    ret
1271END_FUNCTION art_quick_string_compareto
1272
1273    // TODO: implement these!
1274UNIMPLEMENTED art_quick_memcmp16
1275