quick_entrypoints_x86.S revision 891bc286963892ed96134ca1adb7822737af9710
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     */
27MACRO2(SETUP_SAVE_ALL_CALLEE_SAVE_FRAME, got_reg, temp_reg)
28    PUSH edi  // Save callee saves (ebx is saved/restored by the upcall)
29    PUSH esi
30    PUSH ebp
31    subl MACRO_LITERAL(12), %esp  // Grow stack by 3 words.
32    CFI_ADJUST_CFA_OFFSET(12)
33    SETUP_GOT_NOSAVE RAW_VAR(got_reg)
34    // Load Runtime::instance_ from GOT.
35    movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg)), REG_VAR(temp_reg)
36    movl (REG_VAR(temp_reg)), REG_VAR(temp_reg)
37    // Push save all callee-save method.
38    pushl RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET(REG_VAR(temp_reg))
39    CFI_ADJUST_CFA_OFFSET(4)
40    // Store esp as the top quick frame.
41    movl %esp, %fs:THREAD_TOP_QUICK_FRAME_OFFSET
42    // Ugly compile-time check, but we only have the preprocessor.
43    // Last +4: implicit return address pushed on stack when caller made call.
44#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVE != 3*4 + 16 + 4)
45#error "SAVE_ALL_CALLEE_SAVE_FRAME(X86) size not as expected."
46#endif
47END_MACRO
48
49    /*
50     * Macro that sets up the callee save frame to conform with
51     * Runtime::CreateCalleeSaveMethod(kRefsOnly)
52     */
53MACRO2(SETUP_REFS_ONLY_CALLEE_SAVE_FRAME, got_reg, temp_reg)
54    PUSH edi  // Save callee saves (ebx is saved/restored by the upcall)
55    PUSH esi
56    PUSH ebp
57    subl MACRO_LITERAL(12), %esp  // Grow stack by 3 words.
58    CFI_ADJUST_CFA_OFFSET(12)
59    SETUP_GOT_NOSAVE RAW_VAR(got_reg)
60    // Load Runtime::instance_ from GOT.
61    movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg)), REG_VAR(temp_reg)
62    movl (REG_VAR(temp_reg)), REG_VAR(temp_reg)
63    // Push save all callee-save method.
64    pushl RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET(REG_VAR(temp_reg))
65    CFI_ADJUST_CFA_OFFSET(4)
66    // Store esp as the top quick frame.
67    movl %esp, %fs:THREAD_TOP_QUICK_FRAME_OFFSET
68
69    // Ugly compile-time check, but we only have the preprocessor.
70    // Last +4: implicit return address pushed on stack when caller made call.
71#if (FRAME_SIZE_REFS_ONLY_CALLEE_SAVE != 3*4 + 16 + 4)
72#error "REFS_ONLY_CALLEE_SAVE_FRAME(X86) size not as expected."
73#endif
74END_MACRO
75
76MACRO0(RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME)
77    addl MACRO_LITERAL(16), %esp  // Unwind stack up to saved values
78    CFI_ADJUST_CFA_OFFSET(-16)
79    POP ebp  // Restore callee saves (ebx is saved/restored by the upcall)
80    POP esi
81    POP edi
82END_MACRO
83
84    /*
85     * Macro that sets up the callee save frame to conform with
86     * Runtime::CreateCalleeSaveMethod(kRefsAndArgs)
87     */
88MACRO2(SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME, got_reg, temp_reg)
89    PUSH edi  // Save callee saves
90    PUSH esi
91    PUSH ebp
92    PUSH ebx  // Save args
93    PUSH edx
94    PUSH ecx
95    // Create space for FPR args.
96    subl MACRO_LITERAL(4 * 8), %esp
97    CFI_ADJUST_CFA_OFFSET(4 * 8)
98    // Save FPRs.
99    movsd %xmm0, 0(%esp)
100    movsd %xmm1, 8(%esp)
101    movsd %xmm2, 16(%esp)
102    movsd %xmm3, 24(%esp)
103
104    SETUP_GOT_NOSAVE RAW_VAR(got_reg)
105    // Load Runtime::instance_ from GOT.
106    movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg)), REG_VAR(temp_reg)
107    movl (REG_VAR(temp_reg)), REG_VAR(temp_reg)
108    // Push save all callee-save method.
109    pushl RUNTIME_REFS_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET(REG_VAR(temp_reg))
110    CFI_ADJUST_CFA_OFFSET(4)
111    // Store esp as the stop quick frame.
112    movl %esp, %fs:THREAD_TOP_QUICK_FRAME_OFFSET
113
114    // Ugly compile-time check, but we only have the preprocessor.
115    // Last +4: implicit return address pushed on stack when caller made call.
116#if (FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE != 7*4 + 4*8 + 4)
117#error "REFS_AND_ARGS_CALLEE_SAVE_FRAME(X86) size not as expected."
118#endif
119END_MACRO
120
121    /*
122     * Macro that sets up the callee save frame to conform with
123     * Runtime::CreateCalleeSaveMethod(kRefsAndArgs) where the method is passed in EAX.
124     */
125MACRO0(SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_WITH_METHOD_IN_EAX)
126    // Save callee and GPR args, mixed together to agree with core spills bitmap.
127    PUSH edi  // Save callee saves
128    PUSH esi
129    PUSH ebp
130    PUSH ebx  // Save args
131    PUSH edx
132    PUSH ecx
133
134    // Create space for FPR args.
135    subl MACRO_LITERAL(32), %esp
136    CFI_ADJUST_CFA_OFFSET(32)
137
138    // Save FPRs.
139    movsd %xmm0, 0(%esp)
140    movsd %xmm1, 8(%esp)
141    movsd %xmm2, 16(%esp)
142    movsd %xmm3, 24(%esp)
143
144    PUSH eax  // Store the ArtMethod reference at the bottom of the stack.
145    // Store esp as the stop quick frame.
146    movl %esp, %fs:THREAD_TOP_QUICK_FRAME_OFFSET
147END_MACRO
148
149MACRO0(RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME)
150    // Restore FPRs. EAX is still on the stack.
151    movsd 4(%esp), %xmm0
152    movsd 12(%esp), %xmm1
153    movsd 20(%esp), %xmm2
154    movsd 28(%esp), %xmm3
155
156    addl MACRO_LITERAL(36), %esp  // Remove FPRs and EAX.
157    CFI_ADJUST_CFA_OFFSET(-36)
158
159    POP ecx                       // Restore args except eax
160    POP edx
161    POP ebx
162    POP ebp                       // Restore callee saves
163    POP esi
164    POP edi
165END_MACRO
166
167// Restore register and jump to routine
168// Inputs:  EDI contains pointer to code.
169// Notes: Need to pop EAX too (restores Method*)
170MACRO0(RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME_AND_JUMP)
171    POP eax  // Restore Method*
172
173    // Restore FPRs.
174    movsd 0(%esp), %xmm0
175    movsd 8(%esp), %xmm1
176    movsd 16(%esp), %xmm2
177    movsd 24(%esp), %xmm3
178
179    addl MACRO_LITERAL(32), %esp  // Remove FPRs.
180    CFI_ADJUST_CFA_OFFSET(-32)
181
182    POP ecx  // Restore args except eax
183    POP edx
184    POP ebx
185    POP ebp  // Restore callee saves
186    POP esi
187    xchgl 0(%esp),%edi // restore EDI and place code pointer as only value on stack
188    ret
189END_MACRO
190
191    /*
192     * Macro that set calls through to artDeliverPendingExceptionFromCode, where the pending
193     * exception is Thread::Current()->exception_.
194     */
195MACRO0(DELIVER_PENDING_EXCEPTION)
196    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME ebx, ebx  // save callee saves for throw
197    // Outgoing argument set up
198    subl MACRO_LITERAL(12), %esp              // Alignment padding
199    CFI_ADJUST_CFA_OFFSET(12)
200    pushl %fs:THREAD_SELF_OFFSET               // pass Thread::Current()
201    CFI_ADJUST_CFA_OFFSET(4)
202    call SYMBOL(artDeliverPendingExceptionFromCode)  // artDeliverPendingExceptionFromCode(Thread*)
203    UNREACHABLE
204END_MACRO
205
206MACRO2(NO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
207    DEFINE_FUNCTION VAR(c_name)
208    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  ebx, ebx  // save all registers as basis for long jump context
209    // Outgoing argument set up
210    subl MACRO_LITERAL(12), %esp                // alignment padding
211    CFI_ADJUST_CFA_OFFSET(12)
212    pushl %fs:THREAD_SELF_OFFSET                // pass Thread::Current()
213    CFI_ADJUST_CFA_OFFSET(4)
214    call CALLVAR(cxx_name)                      // cxx_name(Thread*)
215    UNREACHABLE
216    END_FUNCTION VAR(c_name)
217END_MACRO
218
219MACRO2(ONE_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
220    DEFINE_FUNCTION VAR(c_name)
221    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME ebx, ebx  // save all registers as basis for long jump context
222    mov %esp, %ecx
223    // Outgoing argument set up
224    subl MACRO_LITERAL(8), %esp               // alignment padding
225    CFI_ADJUST_CFA_OFFSET(8)
226    pushl %fs:THREAD_SELF_OFFSET               // pass Thread::Current()
227    CFI_ADJUST_CFA_OFFSET(4)
228    PUSH eax                                   // pass arg1
229    call CALLVAR(cxx_name)                     // cxx_name(arg1, Thread*)
230    UNREACHABLE
231    END_FUNCTION VAR(c_name)
232END_MACRO
233
234MACRO2(TWO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
235    DEFINE_FUNCTION VAR(c_name)
236    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME ebx, ebx  // save all registers as basis for long jump context
237    // Outgoing argument set up
238    PUSH eax                                   // alignment padding
239    pushl %fs:THREAD_SELF_OFFSET               // pass Thread::Current()
240    CFI_ADJUST_CFA_OFFSET(4)
241    PUSH ecx                                   // pass arg2
242    PUSH eax                                   // pass arg1
243    call CALLVAR(cxx_name)                     // cxx_name(arg1, arg2, Thread*)
244    UNREACHABLE
245    END_FUNCTION VAR(c_name)
246END_MACRO
247
248    /*
249     * Called by managed code to create and deliver a NullPointerException.
250     */
251NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
252
253    /*
254     * Called by managed code to create and deliver an ArithmeticException.
255     */
256NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode
257
258    /*
259     * Called by managed code to create and deliver a StackOverflowError.
260     */
261NO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow, artThrowStackOverflowFromCode
262
263    /*
264     * Called by managed code, saves callee saves and then calls artThrowException
265     * that will place a mock Method* at the bottom of the stack. Arg1 holds the exception.
266     */
267ONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception, artDeliverExceptionFromCode
268
269    /*
270     * Called by managed code to create and deliver a NoSuchMethodError.
271     */
272ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method, artThrowNoSuchMethodFromCode
273
274    /*
275     * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
276     * index, arg2 holds limit.
277     */
278TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
279
280    /*
281     * All generated callsites for interface invokes and invocation slow paths will load arguments
282     * as usual - except instead of loading arg0/r0 with the target Method*, arg0/r0 will contain
283     * the method_idx.  This wrapper will save arg1-arg3 and call the appropriate C helper.
284     * NOTE: "this" is first visible argument of the target, and so can be found in arg1/r1.
285     *
286     * The helper will attempt to locate the target and return a 64-bit result in r0/r1 consisting
287     * of the target Method* in r0 and method->code_ in r1.
288     *
289     * If unsuccessful, the helper will return null/null will bea pending exception in the
290     * thread and we branch to another stub to deliver it.
291     *
292     * On success this wrapper will restore arguments and *jump* to the target, leaving the lr
293     * pointing back to the original caller.
294     */
295MACRO1(INVOKE_TRAMPOLINE_BODY, cxx_name)
296    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME ebx, ebx
297    movl %esp, %edx  // remember SP
298
299    // Outgoing argument set up
300    PUSH edx                      // pass SP
301    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
302    CFI_ADJUST_CFA_OFFSET(4)
303    PUSH ecx                      // pass arg2
304    PUSH eax                      // pass arg1
305    call CALLVAR(cxx_name)        // cxx_name(arg1, arg2, Thread*, SP)
306    movl %edx, %edi               // save code pointer in EDI
307    addl MACRO_LITERAL(20), %esp  // Pop arguments skip eax
308    CFI_ADJUST_CFA_OFFSET(-20)
309
310    // Restore FPRs.
311    movsd 0(%esp), %xmm0
312    movsd 8(%esp), %xmm1
313    movsd 16(%esp), %xmm2
314    movsd 24(%esp), %xmm3
315
316    // Remove space for FPR args.
317    addl MACRO_LITERAL(4 * 8), %esp
318    CFI_ADJUST_CFA_OFFSET(-4 * 8)
319
320    POP ecx  // Restore args except eax
321    POP edx
322    POP ebx
323    POP ebp  // Restore callee saves
324    POP esi
325    // Swap EDI callee save with code pointer.
326    xchgl %edi, (%esp)
327    testl %eax, %eax              // Branch forward if exception pending.
328    jz    1f
329    // Tail call to intended method.
330    ret
3311:
332    addl MACRO_LITERAL(4), %esp   // Pop code pointer off stack
333    CFI_ADJUST_CFA_OFFSET(-4)
334    DELIVER_PENDING_EXCEPTION
335END_MACRO
336MACRO2(INVOKE_TRAMPOLINE, c_name, cxx_name)
337    DEFINE_FUNCTION VAR(c_name)
338    INVOKE_TRAMPOLINE_BODY RAW_VAR(cxx_name)
339    END_FUNCTION VAR(c_name)
340END_MACRO
341
342INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck
343
344INVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck
345INVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck
346INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
347INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
348
349    /*
350     * Helper for quick invocation stub to set up XMM registers.
351     * Increments shorty and arg_array and clobbers temp_char.
352     * Branches to finished if it encounters the end of the shorty.
353     */
354MACRO5(LOOP_OVER_SHORTY_LOADING_XMMS, xmm_reg, shorty, arg_array, temp_char, finished)
3551: // LOOP
356    movb (REG_VAR(shorty)), REG_VAR(temp_char)     // temp_char := *shorty
357    addl MACRO_LITERAL(1), REG_VAR(shorty)         // shorty++
358    cmpb MACRO_LITERAL(0), REG_VAR(temp_char)      // if (temp_char == '\0')
359    je VAR(finished)                               //   goto finished
360    cmpb MACRO_LITERAL(68), REG_VAR(temp_char)     // if (temp_char == 'D')
361    je 2f                                          //   goto FOUND_DOUBLE
362    cmpb MACRO_LITERAL(70), REG_VAR(temp_char)     // if (temp_char == 'F')
363    je 3f                                          //   goto FOUND_FLOAT
364    addl MACRO_LITERAL(4), REG_VAR(arg_array)      // arg_array++
365    //  Handle extra space in arg array taken by a long.
366    cmpb MACRO_LITERAL(74), REG_VAR(temp_char)     // if (temp_char != 'J')
367    jne 1b                                         //   goto LOOP
368    addl MACRO_LITERAL(4), REG_VAR(arg_array)      // arg_array++
369    jmp 1b                                         // goto LOOP
3702:  // FOUND_DOUBLE
371    movsd (REG_VAR(arg_array)), REG_VAR(xmm_reg)
372    addl MACRO_LITERAL(8), REG_VAR(arg_array)      // arg_array+=2
373    jmp 4f
3743:  // FOUND_FLOAT
375    movss (REG_VAR(arg_array)), REG_VAR(xmm_reg)
376    addl MACRO_LITERAL(4), REG_VAR(arg_array)      // arg_array++
3774:
378END_MACRO
379
380    /*
381     * Helper for quick invocation stub to set up GPR registers.
382     * Increments shorty and arg_array, and returns the current short character in
383     * temp_char. Branches to finished if it encounters the end of the shorty.
384     */
385MACRO4(SKIP_OVER_FLOATS, shorty, arg_array, temp_char, finished)
3861: // LOOP:
387    movb (REG_VAR(shorty)), REG_VAR(temp_char)     // temp_char := *shorty
388    addl MACRO_LITERAL(1), REG_VAR(shorty)         // shorty++
389    cmpb MACRO_LITERAL(0), REG_VAR(temp_char)      // if (temp_char == '\0')
390    je VAR(finished)                               //   goto finished
391    cmpb MACRO_LITERAL(70), REG_VAR(temp_char)     // if (temp_char == 'F')
392    je 3f                                          //   goto SKIP_FLOAT
393    cmpb MACRO_LITERAL(68), REG_VAR(temp_char)     // if (temp_char == 'D')
394    je 4f                                          //   goto SKIP_DOUBLE
395    jmp 5f                                         // goto end
3963:  // SKIP_FLOAT
397    addl MACRO_LITERAL(4), REG_VAR(arg_array)      // arg_array++
398    jmp 1b                                         // goto LOOP
3994:  // SKIP_DOUBLE
400    addl MACRO_LITERAL(8), REG_VAR(arg_array)      // arg_array+=2
401    jmp 1b                                         // goto LOOP
4025:
403END_MACRO
404
405  /*
406     * Quick invocation stub (non-static).
407     * On entry:
408     *   [sp] = return address
409     *   [sp + 4] = method pointer
410     *   [sp + 8] = argument array or null for no argument methods
411     *   [sp + 12] = size of argument array in bytes
412     *   [sp + 16] = (managed) thread pointer
413     *   [sp + 20] = JValue* result
414     *   [sp + 24] = shorty
415     */
416DEFINE_FUNCTION art_quick_invoke_stub
417    // Save the non-volatiles.
418    PUSH ebp                      // save ebp
419    PUSH ebx                      // save ebx
420    PUSH esi                      // save esi
421    PUSH edi                      // save edi
422    // Set up argument XMM registers.
423    mov 24+16(%esp), %esi         // ESI := shorty + 1  ; ie skip return arg character.
424    addl LITERAL(1), %esi
425    mov 8+16(%esp), %edi          // EDI := arg_array + 4 ; ie skip this pointer.
426    addl LITERAL(4), %edi
427    // Clobbers ESI, EDI, EAX.
428    LOOP_OVER_SHORTY_LOADING_XMMS xmm0, esi, edi, al, .Lxmm_setup_finished
429    LOOP_OVER_SHORTY_LOADING_XMMS xmm1, esi, edi, al, .Lxmm_setup_finished
430    LOOP_OVER_SHORTY_LOADING_XMMS xmm2, esi, edi, al, .Lxmm_setup_finished
431    LOOP_OVER_SHORTY_LOADING_XMMS xmm3, esi, edi, al, .Lxmm_setup_finished
432    .balign 16
433.Lxmm_setup_finished:
434    mov %esp, %ebp                // copy value of stack pointer into base pointer
435    CFI_DEF_CFA_REGISTER(ebp)
436    mov 28(%ebp), %ebx            // get arg array size
437    // reserve space for return addr, method*, ebx, ebp, esi, and edi in frame
438    addl LITERAL(36), %ebx
439    // align frame size to 16 bytes
440    andl LITERAL(0xFFFFFFF0), %ebx
441    subl LITERAL(20), %ebx        // remove space for return address, ebx, ebp, esi and edi
442    subl %ebx, %esp               // reserve stack space for argument array
443
444    movl LITERAL(0), (%esp)       // store null for method*
445
446    // Copy arg array into stack.
447    movl 28(%ebp), %ecx           // ECX = size of args
448    movl 24(%ebp), %esi           // ESI = argument array
449    leal 4(%esp), %edi            // EDI = just after Method* in stack arguments
450    rep movsb                     // while (ecx--) { *edi++ = *esi++ }
451
452    mov 40(%ebp), %esi            // ESI := shorty + 1  ; ie skip return arg character.
453    addl LITERAL(1), %esi
454    mov 24(%ebp), %edi            // EDI := arg_array
455    mov 0(%edi), %ecx             // ECX := this pointer
456    addl LITERAL(4), %edi         // EDI := arg_array + 4 ; ie skip this pointer.
457
458    // Enumerate the possible cases for loading GPRS.
459    // edx (and maybe ebx):
460    SKIP_OVER_FLOATS esi, edi, al, .Lgpr_setup_finished
461    cmpb LITERAL(74), %al         // if (al == 'J') goto FOUND_LONG
462    je .LfirstLong
463    // Must be an integer value.
464    movl (%edi), %edx
465    addl LITERAL(4), %edi         // arg_array++
466
467    // Now check ebx
468    SKIP_OVER_FLOATS esi, edi, al, .Lgpr_setup_finished
469    // Must be first word of a long, or an integer. First word of long doesn't
470    // go into EBX, but can be loaded there anyways, as it is harmless.
471    movl (%edi), %ebx
472    jmp .Lgpr_setup_finished
473.LfirstLong:
474    movl (%edi), %edx
475    movl 4(%edi), %ebx
476    // Nothing left to load.
477.Lgpr_setup_finished:
478    mov 20(%ebp), %eax            // move method pointer into eax
479    call *ART_METHOD_QUICK_CODE_OFFSET_32(%eax) // call the method
480    mov %ebp, %esp                // restore stack pointer
481    CFI_DEF_CFA_REGISTER(esp)
482    POP edi                       // pop edi
483    POP esi                       // pop esi
484    POP ebx                       // pop ebx
485    POP ebp                       // pop ebp
486    mov 20(%esp), %ecx            // get result pointer
487    mov %eax, (%ecx)              // store the result assuming its a long, int or Object*
488    mov %edx, 4(%ecx)             // store the other half of the result
489    mov 24(%esp), %edx            // get the shorty
490    cmpb LITERAL(68), (%edx)      // test if result type char == 'D'
491    je .Lreturn_double_quick
492    cmpb LITERAL(70), (%edx)      // test if result type char == 'F'
493    je .Lreturn_float_quick
494    ret
495.Lreturn_double_quick:
496    movsd %xmm0, (%ecx)           // store the floating point result
497    ret
498.Lreturn_float_quick:
499    movss %xmm0, (%ecx)           // store the floating point result
500    ret
501END_FUNCTION art_quick_invoke_stub
502
503  /*
504     * Quick invocation stub (static).
505     * On entry:
506     *   [sp] = return address
507     *   [sp + 4] = method pointer
508     *   [sp + 8] = argument array or null for no argument methods
509     *   [sp + 12] = size of argument array in bytes
510     *   [sp + 16] = (managed) thread pointer
511     *   [sp + 20] = JValue* result
512     *   [sp + 24] = shorty
513     */
514DEFINE_FUNCTION art_quick_invoke_static_stub
515    // Save the non-volatiles.
516    PUSH ebp                      // save ebp
517    PUSH ebx                      // save ebx
518    PUSH esi                      // save esi
519    PUSH edi                      // save edi
520    // Set up argument XMM registers.
521    mov 24+16(%esp), %esi         // ESI := shorty + 1  ; ie skip return arg character.
522    addl LITERAL(1), %esi
523    mov 8+16(%esp), %edi          // EDI := arg_array
524    // Clobbers ESI, EDI, EAX.
525    LOOP_OVER_SHORTY_LOADING_XMMS xmm0, esi, edi, al, .Lxmm_setup_finished2
526    LOOP_OVER_SHORTY_LOADING_XMMS xmm1, esi, edi, al, .Lxmm_setup_finished2
527    LOOP_OVER_SHORTY_LOADING_XMMS xmm2, esi, edi, al, .Lxmm_setup_finished2
528    LOOP_OVER_SHORTY_LOADING_XMMS xmm3, esi, edi, al, .Lxmm_setup_finished2
529    .balign 16
530.Lxmm_setup_finished2:
531    mov %esp, %ebp                // copy value of stack pointer into base pointer
532    CFI_DEF_CFA_REGISTER(ebp)
533    mov 28(%ebp), %ebx            // get arg array size
534    // reserve space for return addr, method*, ebx, ebp, esi, and edi in frame
535    addl LITERAL(36), %ebx
536    // align frame size to 16 bytes
537    andl LITERAL(0xFFFFFFF0), %ebx
538    subl LITERAL(20), %ebx        // remove space for return address, ebx, ebp, esi and edi
539    subl %ebx, %esp               // reserve stack space for argument array
540
541    movl LITERAL(0), (%esp)       // store null for method*
542
543    // Copy arg array into stack.
544    movl 28(%ebp), %ecx           // ECX = size of args
545    movl 24(%ebp), %esi           // ESI = argument array
546    leal 4(%esp), %edi            // EDI = just after Method* in stack arguments
547    rep movsb                     // while (ecx--) { *edi++ = *esi++ }
548
549    mov 40(%ebp), %esi            // ESI := shorty + 1  ; ie skip return arg character.
550    addl LITERAL(1), %esi
551    mov 24(%ebp), %edi            // EDI := arg_array
552
553    // Enumerate the possible cases for loading GPRS.
554    // ecx (and maybe edx)
555    SKIP_OVER_FLOATS esi, edi, al, .Lgpr_setup_finished2
556    cmpb LITERAL(74), %al         // if (al == 'J') goto FOUND_LONG
557    je .LfirstLong2
558    // Must be an integer value.  Load into ECX.
559    movl (%edi), %ecx
560    addl LITERAL(4), %edi         // arg_array++
561
562    // Now check edx (and maybe ebx).
563    SKIP_OVER_FLOATS esi, edi, al, .Lgpr_setup_finished2
564    cmpb LITERAL(74), %al         // if (al == 'J') goto FOUND_LONG
565    je .LSecondLong2
566    // Must be an integer.  Load into EDX.
567    movl (%edi), %edx
568    addl LITERAL(4), %edi         // arg_array++
569
570    // Is there anything for ebx?
571    SKIP_OVER_FLOATS esi, edi, al, .Lgpr_setup_finished2
572    // Must be first word of a long, or an integer. First word of long doesn't
573    // go into EBX, but can be loaded there anyways, as it is harmless.
574    movl (%edi), %ebx
575    jmp .Lgpr_setup_finished2
576.LSecondLong2:
577    // EDX:EBX is long.  That is all.
578    movl (%edi), %edx
579    movl 4(%edi), %ebx
580    jmp .Lgpr_setup_finished2
581.LfirstLong2:
582    // ECX:EDX is a long
583    movl (%edi), %ecx
584    movl 4(%edi), %edx
585    addl LITERAL(8), %edi         // arg_array += 2
586
587    // Anything for EBX?
588    SKIP_OVER_FLOATS esi, edi, al, .Lgpr_setup_finished2
589    // Must be first word of a long, or an integer. First word of long doesn't
590    // go into EBX, but can be loaded there anyways, as it is harmless.
591    movl (%edi), %ebx
592    jmp .Lgpr_setup_finished2
593    // Nothing left to load.
594.Lgpr_setup_finished2:
595    mov 20(%ebp), %eax            // move method pointer into eax
596    call *ART_METHOD_QUICK_CODE_OFFSET_32(%eax) // call the method
597    mov %ebp, %esp                // restore stack pointer
598    CFI_DEF_CFA_REGISTER(esp)
599    POP edi                       // pop edi
600    POP esi                       // pop esi
601    POP ebx                       // pop ebx
602    POP ebp                       // pop ebp
603    mov 20(%esp), %ecx            // get result pointer
604    mov %eax, (%ecx)              // store the result assuming its a long, int or Object*
605    mov %edx, 4(%ecx)             // store the other half of the result
606    mov 24(%esp), %edx            // get the shorty
607    cmpb LITERAL(68), (%edx)      // test if result type char == 'D'
608    je .Lreturn_double_quick2
609    cmpb LITERAL(70), (%edx)      // test if result type char == 'F'
610    je .Lreturn_float_quick2
611    ret
612.Lreturn_double_quick2:
613    movsd %xmm0, (%ecx)           // store the floating point result
614    ret
615.Lreturn_float_quick2:
616    movss %xmm0, (%ecx)           // store the floating point result
617    ret
618END_FUNCTION art_quick_invoke_static_stub
619
620MACRO3(NO_ARG_DOWNCALL, c_name, cxx_name, return_macro)
621    DEFINE_FUNCTION VAR(c_name)
622    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx  // save ref containing registers for GC
623    // Outgoing argument set up
624    subl MACRO_LITERAL(12), %esp                // push padding
625    CFI_ADJUST_CFA_OFFSET(12)
626    pushl %fs:THREAD_SELF_OFFSET                // pass Thread::Current()
627    CFI_ADJUST_CFA_OFFSET(4)
628    call CALLVAR(cxx_name)                      // cxx_name(Thread*)
629    addl MACRO_LITERAL(16), %esp                // pop arguments
630    CFI_ADJUST_CFA_OFFSET(-16)
631    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME         // restore frame up to return address
632    CALL_MACRO(return_macro)                    // return or deliver exception
633    END_FUNCTION VAR(c_name)
634END_MACRO
635
636MACRO3(ONE_ARG_DOWNCALL, c_name, cxx_name, return_macro)
637    DEFINE_FUNCTION VAR(c_name)
638    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  ebx, ebx  // save ref containing registers for GC
639    // Outgoing argument set up
640    subl MACRO_LITERAL(8), %esp                  // push padding
641    CFI_ADJUST_CFA_OFFSET(8)
642    pushl %fs:THREAD_SELF_OFFSET                 // pass Thread::Current()
643    CFI_ADJUST_CFA_OFFSET(4)
644    PUSH eax                                     // pass arg1
645    call CALLVAR(cxx_name)                       // cxx_name(arg1, Thread*)
646    addl MACRO_LITERAL(16), %esp                 // pop arguments
647    CFI_ADJUST_CFA_OFFSET(-16)
648    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME          // restore frame up to return address
649    CALL_MACRO(return_macro)                     // return or deliver exception
650    END_FUNCTION VAR(c_name)
651END_MACRO
652
653MACRO3(TWO_ARG_DOWNCALL, c_name, cxx_name, return_macro)
654    DEFINE_FUNCTION VAR(c_name)
655    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  ebx, ebx  // save ref containing registers for GC
656    // Outgoing argument set up
657    PUSH eax                                     // push padding
658    pushl %fs:THREAD_SELF_OFFSET                 // pass Thread::Current()
659    CFI_ADJUST_CFA_OFFSET(4)
660    PUSH ecx                                     // pass arg2
661    PUSH eax                                     // pass arg1
662    call CALLVAR(cxx_name)                       // cxx_name(arg1, arg2, Thread*)
663    addl MACRO_LITERAL(16), %esp                 // pop arguments
664    CFI_ADJUST_CFA_OFFSET(-16)
665    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME          // restore frame up to return address
666    CALL_MACRO(return_macro)                     // return or deliver exception
667    END_FUNCTION VAR(c_name)
668END_MACRO
669
670MACRO3(THREE_ARG_DOWNCALL, c_name, cxx_name, return_macro)
671    DEFINE_FUNCTION VAR(c_name)
672    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  ebx, ebx  // save ref containing registers for GC
673    // Outgoing argument set up
674    pushl %fs:THREAD_SELF_OFFSET                 // pass Thread::Current()
675    CFI_ADJUST_CFA_OFFSET(4)
676    PUSH edx                                     // pass arg3
677    PUSH ecx                                     // pass arg2
678    PUSH eax                                     // pass arg1
679    call CALLVAR(cxx_name)                       // cxx_name(arg1, arg2, arg3, Thread*)
680    addl MACRO_LITERAL(16), %esp                 // pop arguments
681    CFI_ADJUST_CFA_OFFSET(-16)
682    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME          // restore frame up to return address
683    CALL_MACRO(return_macro)                     // return or deliver exception
684    END_FUNCTION VAR(c_name)
685END_MACRO
686
687MACRO3(FOUR_ARG_DOWNCALL, c_name, cxx_name, return_macro)
688    DEFINE_FUNCTION VAR(c_name)
689    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  ebx, ebx  // save ref containing registers for GC
690    // Outgoing argument set up
691    subl MACRO_LITERAL(12), %esp                 // alignment padding
692    CFI_ADJUST_CFA_OFFSET(12)
693    pushl %fs:THREAD_SELF_OFFSET                 // pass Thread::Current()
694    CFI_ADJUST_CFA_OFFSET(4)
695    PUSH ebx                                     // pass arg4
696    PUSH edx                                     // pass arg3
697    PUSH ecx                                     // pass arg2
698    PUSH eax                                     // pass arg1
699    call CALLVAR(cxx_name)                       // cxx_name(arg1, arg2, arg3, arg4, Thread*)
700    addl MACRO_LITERAL(32), %esp                 // pop arguments
701    CFI_ADJUST_CFA_OFFSET(-32)
702    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME          // restore frame up to return address
703    CALL_MACRO(return_macro)                     // return or deliver exception
704    END_FUNCTION VAR(c_name)
705END_MACRO
706
707MACRO3(ONE_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro)
708    DEFINE_FUNCTION VAR(c_name)
709    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  ebx, ebx       // save ref containing registers for GC
710    // Outgoing argument set up
711    mov FRAME_SIZE_REFS_ONLY_CALLEE_SAVE(%esp), %ecx  // get referrer
712    PUSH eax                                          // push padding
713    pushl %fs:THREAD_SELF_OFFSET                      // pass Thread::Current()
714    CFI_ADJUST_CFA_OFFSET(4)
715    PUSH ecx                                          // pass referrer
716    PUSH eax                                          // pass arg1
717    call CALLVAR(cxx_name)                            // cxx_name(arg1, referrer, Thread*)
718    addl MACRO_LITERAL(16), %esp                      // pop arguments
719    CFI_ADJUST_CFA_OFFSET(-16)
720    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME               // restore frame up to return address
721    CALL_MACRO(return_macro)                          // return or deliver exception
722    END_FUNCTION VAR(c_name)
723END_MACRO
724
725MACRO3(TWO_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro)
726    DEFINE_FUNCTION VAR(c_name)
727    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx        // save ref containing registers for GC
728    // Outgoing argument set up
729    mov FRAME_SIZE_REFS_ONLY_CALLEE_SAVE(%esp), %edx  // get referrer
730    pushl %fs:THREAD_SELF_OFFSET                      // pass Thread::Current()
731    CFI_ADJUST_CFA_OFFSET(4)
732    PUSH edx                                          // pass referrer
733    PUSH ecx                                          // pass arg2
734    PUSH eax                                          // pass arg1
735    call CALLVAR(cxx_name)                            // cxx_name(arg1, arg2, referrer, Thread*)
736    addl MACRO_LITERAL(16), %esp                      // pop arguments
737    CFI_ADJUST_CFA_OFFSET(-16)
738    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME               // restore frame up to return address
739    CALL_MACRO(return_macro)                          // return or deliver exception
740    END_FUNCTION VAR(c_name)
741END_MACRO
742
743MACRO3(THREE_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro)
744    DEFINE_FUNCTION VAR(c_name)
745    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx        // save ref containing registers for GC
746    // Outgoing argument set up
747    mov FRAME_SIZE_REFS_ONLY_CALLEE_SAVE(%esp), %ebx  // get referrer
748    subl MACRO_LITERAL(12), %esp                      // alignment padding
749    CFI_ADJUST_CFA_OFFSET(12)
750    pushl %fs:THREAD_SELF_OFFSET                      // pass Thread::Current()
751    CFI_ADJUST_CFA_OFFSET(4)
752    PUSH ebx                                          // pass referrer
753    PUSH edx                                          // pass arg3
754    PUSH ecx                                          // pass arg2
755    PUSH eax                                          // pass arg1
756    call CALLVAR(cxx_name)                            // cxx_name(arg1, arg2, arg3, referrer,
757                                                      //          Thread*)
758    addl LITERAL(32), %esp                            // pop arguments
759    CFI_ADJUST_CFA_OFFSET(-32)
760    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME               // restore frame up to return address
761    CALL_MACRO(return_macro)                          // return or deliver exception
762    END_FUNCTION VAR(c_name)
763END_MACRO
764
765MACRO0(RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER)
766    testl %eax, %eax               // eax == 0 ?
767    jz  1f                         // if eax == 0 goto 1
768    ret                            // return
7691:                                 // deliver exception on current thread
770    DELIVER_PENDING_EXCEPTION
771END_MACRO
772
773MACRO0(RETURN_IF_EAX_ZERO)
774    testl %eax, %eax               // eax == 0 ?
775    jnz  1f                        // if eax != 0 goto 1
776    ret                            // return
7771:                                 // deliver exception on current thread
778    DELIVER_PENDING_EXCEPTION
779END_MACRO
780
781MACRO0(RETURN_OR_DELIVER_PENDING_EXCEPTION)
782    cmpl MACRO_LITERAL(0),%fs:THREAD_EXCEPTION_OFFSET // exception field == 0 ?
783    jne 1f                                            // if exception field != 0 goto 1
784    ret                                               // return
7851:                                                    // deliver exception on current thread
786    DELIVER_PENDING_EXCEPTION
787END_MACRO
788
789// Generate the allocation entrypoints for each allocator.
790GENERATE_ALLOC_ENTRYPOINTS_FOR_EACH_ALLOCATOR
791
792// A hand-written override for GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_rosalloc, RosAlloc).
793DEFINE_FUNCTION art_quick_alloc_object_rosalloc
794    // Fast path rosalloc allocation.
795    // eax: uint32_t type_idx/return value, ecx: ArtMethod*
796    // ebx, edx: free
797    PUSH edi
798    movl ART_METHOD_DEX_CACHE_TYPES_OFFSET_32(%ecx), %edx  // Load dex cache resolved types array
799                                                        // Load the class (edx)
800    movl 0(%edx, %eax, COMPRESSED_REFERENCE_SIZE), %edx
801    testl %edx, %edx                                    // Check null class
802    jz   .Lart_quick_alloc_object_rosalloc_slow_path
803                                                        // Check class status
804    cmpl LITERAL(MIRROR_CLASS_STATUS_INITIALIZED), MIRROR_CLASS_STATUS_OFFSET(%edx)
805    jne  .Lart_quick_alloc_object_rosalloc_slow_path
806                                                        // No fake dependence needed on x86
807                                                        // between status and flags load,
808                                                        // since each load is a load-acquire,
809                                                        // no loads reordering.
810                                                        // Check access flags has
811                                                        // kAccClassIsFinalizable
812    testl LITERAL(ACCESS_FLAGS_CLASS_IS_FINALIZABLE), MIRROR_CLASS_ACCESS_FLAGS_OFFSET(%edx)
813    jnz   .Lart_quick_alloc_object_rosalloc_slow_path
814
815    movl %fs:THREAD_SELF_OFFSET, %ebx                   // ebx = thread
816                                                        // Check if the thread local allocation
817                                                        // stack has room
818    movl THREAD_LOCAL_ALLOC_STACK_TOP_OFFSET(%ebx), %edi
819    cmpl THREAD_LOCAL_ALLOC_STACK_END_OFFSET(%ebx), %edi
820    jae  .Lart_quick_alloc_object_rosalloc_slow_path
821
822    movl MIRROR_CLASS_OBJECT_SIZE_OFFSET(%edx), %edi    // Load the object size (edi)
823                                                        // Check if the size is for a thread
824                                                        // local allocation
825    cmpl LITERAL(ROSALLOC_MAX_THREAD_LOCAL_BRACKET_SIZE), %edi
826    ja   .Lart_quick_alloc_object_rosalloc_slow_path
827    decl %edi
828    shrl LITERAL(ROSALLOC_BRACKET_QUANTUM_SIZE_SHIFT), %edi // Calculate the rosalloc bracket index
829                                                            // from object size.
830                                                            // Align up the size by the rosalloc
831                                                            // bracket quantum size and divide
832                                                            // by the quantum size and subtract
833                                                            // by 1. This code is a shorter but
834                                                            // equivalent version.
835                                                        // Load thread local rosalloc run (ebx)
836    movl THREAD_ROSALLOC_RUNS_OFFSET(%ebx, %edi, __SIZEOF_POINTER__), %ebx
837                                                        // Load free_list head (edi),
838                                                        // this will be the return value.
839    movl (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_HEAD_OFFSET)(%ebx), %edi
840    test %edi, %edi
841    jz   .Lart_quick_alloc_object_rosalloc_slow_path
842                                                        // Point of no slow path. Won't go to
843                                                        // the slow path from here on. Ok to
844                                                        // clobber eax and ecx.
845    movl %edi, %eax
846                                                        // Load the next pointer of the head
847                                                        // and update head of free list with
848                                                        // next pointer
849    movl ROSALLOC_SLOT_NEXT_OFFSET(%eax), %edi
850    movl %edi, (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_HEAD_OFFSET)(%ebx)
851                                                        // Decrement size of free list by 1
852    decl (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_SIZE_OFFSET)(%ebx)
853                                                        // Store the class pointer in the
854                                                        // header. This also overwrites the
855                                                        // next pointer. The offsets are
856                                                        // asserted to match.
857#if ROSALLOC_SLOT_NEXT_OFFSET != MIRROR_OBJECT_CLASS_OFFSET
858#error "Class pointer needs to overwrite next pointer."
859#endif
860    POISON_HEAP_REF edx
861    movl %edx, MIRROR_OBJECT_CLASS_OFFSET(%eax)
862    movl %fs:THREAD_SELF_OFFSET, %ebx                   // ebx = thread
863                                                        // Push the new object onto the thread
864                                                        // local allocation stack and
865                                                        // increment the thread local
866                                                        // allocation stack top.
867    movl THREAD_LOCAL_ALLOC_STACK_TOP_OFFSET(%ebx), %edi
868    movl %eax, (%edi)
869    addl LITERAL(COMPRESSED_REFERENCE_SIZE), %edi
870    movl %edi, THREAD_LOCAL_ALLOC_STACK_TOP_OFFSET(%ebx)
871                                                        // No fence needed for x86.
872    POP edi
873    ret
874.Lart_quick_alloc_object_rosalloc_slow_path:
875    POP edi
876    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx // save ref containing registers for GC
877    // Outgoing argument set up
878    PUSH eax                      // alignment padding
879    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
880    CFI_ADJUST_CFA_OFFSET(4)
881    PUSH ecx
882    PUSH eax
883    call SYMBOL(artAllocObjectFromCodeRosAlloc)  // cxx_name(arg0, arg1, Thread*)
884    addl LITERAL(16), %esp        // pop arguments
885    CFI_ADJUST_CFA_OFFSET(-16)
886    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME          // resotre frame up to return address
887    RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER      // return or deliver exception
888END_FUNCTION art_quick_alloc_object_rosalloc
889
890
891GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_tlab, TLAB)
892
893ONE_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
894ONE_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
895ONE_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
896ONE_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
897
898TWO_ARG_REF_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO
899
900DEFINE_FUNCTION art_quick_lock_object
901    testl %eax, %eax                      // null check object/eax
902    jz   .Lslow_lock
903.Lretry_lock:
904    movl MIRROR_OBJECT_LOCK_WORD_OFFSET(%eax), %ecx  // ecx := lock word
905    test LITERAL(LOCK_WORD_STATE_MASK), %ecx         // test the 2 high bits.
906    jne  .Lslow_lock                      // slow path if either of the two high bits are set.
907    movl %ecx, %edx                       // save lock word (edx) to keep read barrier bits.
908    andl LITERAL(LOCK_WORD_READ_BARRIER_STATE_MASK_TOGGLED), %ecx  // zero the read barrier bits.
909    test %ecx, %ecx
910    jnz  .Lalready_thin                   // lock word contains a thin lock
911    // unlocked case - edx: original lock word, eax: obj.
912    movl %eax, %ecx                       // remember object in case of retry
913    movl %edx, %eax                       // eax: lock word zero except for read barrier bits.
914    movl %fs:THREAD_ID_OFFSET, %edx       // load thread id.
915    or   %eax, %edx                       // edx: thread id with count of 0 + read barrier bits.
916    lock cmpxchg  %edx, MIRROR_OBJECT_LOCK_WORD_OFFSET(%ecx)  // eax: old val, edx: new val.
917    jnz  .Llock_cmpxchg_fail              // cmpxchg failed retry
918    ret
919.Lalready_thin:  // edx: lock word (with high 2 bits zero and original rb bits), eax: obj.
920    movl %fs:THREAD_ID_OFFSET, %ecx       // ecx := thread id
921    cmpw %cx, %dx                         // do we hold the lock already?
922    jne  .Lslow_lock
923    movl %edx, %ecx                       // copy the lock word to check count overflow.
924    andl LITERAL(LOCK_WORD_READ_BARRIER_STATE_MASK_TOGGLED), %ecx  // zero the read barrier bits.
925    addl LITERAL(LOCK_WORD_THIN_LOCK_COUNT_ONE), %ecx  // increment recursion count for overflow check.
926    test LITERAL(LOCK_WORD_READ_BARRIER_STATE_MASK), %ecx  // overflowed if either of the upper two bits (28-29) are set.
927    jne  .Lslow_lock                      // count overflowed so go slow
928    movl %eax, %ecx                       // save obj to use eax for cmpxchg.
929    movl %edx, %eax                       // copy the lock word as the old val for cmpxchg.
930    addl LITERAL(LOCK_WORD_THIN_LOCK_COUNT_ONE), %edx  // increment recursion count again for real.
931    // update lockword, cmpxchg necessary for read barrier bits.
932    lock cmpxchg  %edx, MIRROR_OBJECT_LOCK_WORD_OFFSET(%ecx)  // eax: old val, edx: new val.
933    jnz  .Llock_cmpxchg_fail              // cmpxchg failed retry
934    ret
935.Llock_cmpxchg_fail:
936    movl  %ecx, %eax                      // restore eax
937    jmp  .Lretry_lock
938.Lslow_lock:
939    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  ebx, ebx  // save ref containing registers for GC
940    // Outgoing argument set up
941    subl LITERAL(8), %esp                 // alignment padding
942    CFI_ADJUST_CFA_OFFSET(8)
943    pushl %fs:THREAD_SELF_OFFSET          // pass Thread::Current()
944    CFI_ADJUST_CFA_OFFSET(4)
945    PUSH eax                              // pass object
946    call SYMBOL(artLockObjectFromCode)    // artLockObjectFromCode(object, Thread*)
947    addl LITERAL(16), %esp                // pop arguments
948    CFI_ADJUST_CFA_OFFSET(-16)
949    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME   // restore frame up to return address
950    RETURN_IF_EAX_ZERO
951END_FUNCTION art_quick_lock_object
952
953DEFINE_FUNCTION art_quick_unlock_object
954    testl %eax, %eax                      // null check object/eax
955    jz   .Lslow_unlock
956.Lretry_unlock:
957    movl MIRROR_OBJECT_LOCK_WORD_OFFSET(%eax), %ecx  // ecx := lock word
958    movl %fs:THREAD_ID_OFFSET, %edx       // edx := thread id
959    test LITERAL(LOCK_WORD_STATE_MASK), %ecx
960    jnz  .Lslow_unlock                    // lock word contains a monitor
961    cmpw %cx, %dx                         // does the thread id match?
962    jne  .Lslow_unlock
963    movl %ecx, %edx                       // copy the lock word to detect new count of 0.
964    andl LITERAL(LOCK_WORD_READ_BARRIER_STATE_MASK_TOGGLED), %edx  // zero the read barrier bits.
965    cmpl LITERAL(LOCK_WORD_THIN_LOCK_COUNT_ONE), %edx
966    jae  .Lrecursive_thin_unlock
967    // update lockword, cmpxchg necessary for read barrier bits.
968    movl %eax, %edx                       // edx: obj
969    movl %ecx, %eax                       // eax: old lock word.
970    andl LITERAL(LOCK_WORD_READ_BARRIER_STATE_MASK), %ecx  // ecx: new lock word zero except original rb bits.
971#ifndef USE_READ_BARRIER
972    movl %ecx, MIRROR_OBJECT_LOCK_WORD_OFFSET(%edx)
973#else
974    lock cmpxchg  %ecx, MIRROR_OBJECT_LOCK_WORD_OFFSET(%edx)  // eax: old val, ecx: new val.
975    jnz  .Lunlock_cmpxchg_fail            // cmpxchg failed retry
976#endif
977    ret
978.Lrecursive_thin_unlock:  // ecx: original lock word, eax: obj
979    // update lockword, cmpxchg necessary for read barrier bits.
980    movl %eax, %edx                       // edx: obj
981    movl %ecx, %eax                       // eax: old lock word.
982    subl LITERAL(LOCK_WORD_THIN_LOCK_COUNT_ONE), %ecx  // ecx: new lock word with decremented count.
983#ifndef USE_READ_BARRIER
984    mov  %ecx, MIRROR_OBJECT_LOCK_WORD_OFFSET(%edx)
985#else
986    lock cmpxchg  %ecx, MIRROR_OBJECT_LOCK_WORD_OFFSET(%edx)  // eax: old val, ecx: new val.
987    jnz  .Lunlock_cmpxchg_fail            // cmpxchg failed retry
988#endif
989    ret
990.Lunlock_cmpxchg_fail:  // edx: obj
991    movl %edx, %eax                       // restore eax
992    jmp  .Lretry_unlock
993.Lslow_unlock:
994    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  ebx, ebx  // save ref containing registers for GC
995    // Outgoing argument set up
996    subl LITERAL(8), %esp                 // alignment padding
997    CFI_ADJUST_CFA_OFFSET(8)
998    pushl %fs:THREAD_SELF_OFFSET          // pass Thread::Current()
999    CFI_ADJUST_CFA_OFFSET(4)
1000    PUSH eax                              // pass object
1001    call SYMBOL(artUnlockObjectFromCode)  // artUnlockObjectFromCode(object, Thread*)
1002    addl LITERAL(16), %esp                // pop arguments
1003    CFI_ADJUST_CFA_OFFSET(-16)
1004    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME   // restore frame up to return address
1005    RETURN_IF_EAX_ZERO
1006END_FUNCTION art_quick_unlock_object
1007
1008DEFINE_FUNCTION art_quick_is_assignable
1009    PUSH eax                              // alignment padding
1010    PUSH ecx                              // pass arg2 - obj->klass
1011    PUSH eax                              // pass arg1 - checked class
1012    call SYMBOL(artIsAssignableFromCode)  // (Class* klass, Class* ref_klass)
1013    addl LITERAL(12), %esp                // pop arguments
1014    CFI_ADJUST_CFA_OFFSET(-12)
1015    ret
1016END_FUNCTION art_quick_is_assignable
1017
1018DEFINE_FUNCTION art_quick_check_cast
1019    PUSH eax                              // alignment padding
1020    PUSH ecx                              // pass arg2 - obj->klass
1021    PUSH eax                              // pass arg1 - checked class
1022    call SYMBOL(artIsAssignableFromCode)  // (Class* klass, Class* ref_klass)
1023    testl %eax, %eax
1024    jz 1f                                 // jump forward if not assignable
1025    addl LITERAL(12), %esp                // pop arguments
1026    CFI_ADJUST_CFA_OFFSET(-12)
1027    ret
1028
1029    CFI_ADJUST_CFA_OFFSET(12)             // Reset unwind info so following code unwinds.
10301:
1031    POP eax                               // pop arguments
1032    POP ecx
1033    addl LITERAL(4), %esp
1034    CFI_ADJUST_CFA_OFFSET(-4)
1035    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  ebx, ebx  // save all registers as basis for long jump context
1036    // Outgoing argument set up
1037    PUSH eax                              // alignment padding
1038    pushl %fs:THREAD_SELF_OFFSET          // pass Thread::Current()
1039    CFI_ADJUST_CFA_OFFSET(4)
1040    PUSH ecx                              // pass arg2
1041    PUSH eax                              // pass arg1
1042    call SYMBOL(artThrowClassCastException) // (Class* a, Class* b, Thread*)
1043    UNREACHABLE
1044END_FUNCTION art_quick_check_cast
1045
1046// Restore reg's value if reg is not the same as exclude_reg, otherwise just adjust stack.
1047MACRO2(POP_REG_NE, reg, exclude_reg)
1048    .ifc RAW_VAR(reg), RAW_VAR(exclude_reg)
1049      addl MACRO_LITERAL(4), %esp
1050      CFI_ADJUST_CFA_OFFSET(-4)
1051    .else
1052      POP RAW_VAR(reg)
1053    .endif
1054END_MACRO
1055
1056    /*
1057     * Macro to insert read barrier, only used in art_quick_aput_obj.
1058     * obj_reg and dest_reg are registers, offset is a defined literal such as
1059     * MIRROR_OBJECT_CLASS_OFFSET.
1060     * pop_eax is a boolean flag, indicating if eax is popped after the call.
1061     * TODO: When read barrier has a fast path, add heap unpoisoning support for the fast path.
1062     */
1063MACRO4(READ_BARRIER, obj_reg, offset, dest_reg, pop_eax)
1064#ifdef USE_READ_BARRIER
1065    PUSH eax                        // save registers used in art_quick_aput_obj
1066    PUSH ebx
1067    PUSH edx
1068    PUSH ecx
1069    // Outgoing argument set up
1070    pushl MACRO_LITERAL((RAW_VAR(offset)))  // pass offset, double parentheses are necessary
1071    CFI_ADJUST_CFA_OFFSET(4)
1072    PUSH RAW_VAR(obj_reg)           // pass obj_reg
1073    PUSH eax                        // pass ref, just pass eax for now since parameter ref is unused
1074    call SYMBOL(artReadBarrierSlow) // artReadBarrierSlow(ref, obj_reg, offset)
1075    // No need to unpoison return value in eax, artReadBarrierSlow() would do the unpoisoning.
1076    .ifnc RAW_VAR(dest_reg), eax
1077      movl %eax, REG_VAR(dest_reg)  // save loaded ref in dest_reg
1078    .endif
1079    addl MACRO_LITERAL(12), %esp    // pop arguments
1080    CFI_ADJUST_CFA_OFFSET(-12)
1081    POP_REG_NE ecx, RAW_VAR(dest_reg) // Restore args except dest_reg
1082    POP_REG_NE edx, RAW_VAR(dest_reg)
1083    POP_REG_NE ebx, RAW_VAR(dest_reg)
1084    .ifc RAW_VAR(pop_eax), true
1085      POP_REG_NE eax, RAW_VAR(dest_reg)
1086    .endif
1087#else
1088    movl RAW_VAR(offset)(REG_VAR(obj_reg)), REG_VAR(dest_reg)
1089    UNPOISON_HEAP_REF RAW_VAR(dest_reg)
1090#endif  // USE_READ_BARRIER
1091END_MACRO
1092
1093    /*
1094     * Entry from managed code for array put operations of objects where the value being stored
1095     * needs to be checked for compatibility.
1096     * eax = array, ecx = index, edx = value
1097     */
1098DEFINE_FUNCTION art_quick_aput_obj_with_null_and_bound_check
1099    testl %eax, %eax
1100    jnz SYMBOL(art_quick_aput_obj_with_bound_check)
1101    jmp SYMBOL(art_quick_throw_null_pointer_exception)
1102END_FUNCTION art_quick_aput_obj_with_null_and_bound_check
1103
1104DEFINE_FUNCTION art_quick_aput_obj_with_bound_check
1105    movl MIRROR_ARRAY_LENGTH_OFFSET(%eax), %ebx
1106    cmpl %ebx, %ecx
1107    jb SYMBOL(art_quick_aput_obj)
1108    mov %ecx, %eax
1109    mov %ebx, %ecx
1110    jmp SYMBOL(art_quick_throw_array_bounds)
1111END_FUNCTION art_quick_aput_obj_with_bound_check
1112
1113DEFINE_FUNCTION art_quick_aput_obj
1114    test %edx, %edx              // store of null
1115    jz .Ldo_aput_null
1116    READ_BARRIER eax, MIRROR_OBJECT_CLASS_OFFSET, ebx, true
1117    READ_BARRIER ebx, MIRROR_CLASS_COMPONENT_TYPE_OFFSET, ebx, true
1118    // value's type == array's component type - trivial assignability
1119#if defined(USE_READ_BARRIER)
1120    READ_BARRIER edx, MIRROR_OBJECT_CLASS_OFFSET, eax, false
1121    cmpl %eax, %ebx
1122    POP eax                      // restore eax from the push in the beginning of READ_BARRIER macro
1123    // This asymmetric push/pop saves a push of eax and maintains stack alignment.
1124#elif defined(USE_HEAP_POISONING)
1125    PUSH eax                     // save eax
1126    movl MIRROR_OBJECT_CLASS_OFFSET(%edx), %eax
1127    UNPOISON_HEAP_REF eax
1128    cmpl %eax, %ebx
1129    POP eax                      // restore eax
1130#else
1131    cmpl MIRROR_OBJECT_CLASS_OFFSET(%edx), %ebx
1132#endif
1133    jne .Lcheck_assignability
1134.Ldo_aput:
1135    POISON_HEAP_REF edx
1136    movl %edx, MIRROR_OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4)
1137    movl %fs:THREAD_CARD_TABLE_OFFSET, %edx
1138    shrl LITERAL(7), %eax
1139    movb %dl, (%edx, %eax)
1140    ret
1141.Ldo_aput_null:
1142    movl %edx, MIRROR_OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4)
1143    ret
1144.Lcheck_assignability:
1145    PUSH eax                      // save arguments
1146    PUSH ecx
1147    PUSH edx
1148#if defined(USE_READ_BARRIER)
1149    subl LITERAL(4), %esp         // alignment padding
1150    CFI_ADJUST_CFA_OFFSET(4)
1151    READ_BARRIER edx, MIRROR_OBJECT_CLASS_OFFSET, eax, true
1152    subl LITERAL(4), %esp         // alignment padding
1153    CFI_ADJUST_CFA_OFFSET(4)
1154    PUSH eax                      // pass arg2 - type of the value to be stored
1155#elif defined(USE_HEAP_POISONING)
1156    subl LITERAL(8), %esp         // alignment padding
1157    CFI_ADJUST_CFA_OFFSET(8)
1158    movl MIRROR_OBJECT_CLASS_OFFSET(%edx), %eax
1159    UNPOISON_HEAP_REF eax
1160    PUSH eax                      // pass arg2 - type of the value to be stored
1161#else
1162    subl LITERAL(8), %esp         // alignment padding
1163    CFI_ADJUST_CFA_OFFSET(8)
1164    pushl MIRROR_OBJECT_CLASS_OFFSET(%edx)  // pass arg2 - type of the value to be stored
1165    CFI_ADJUST_CFA_OFFSET(4)
1166#endif
1167    PUSH ebx                      // pass arg1 - component type of the array
1168    call SYMBOL(artIsAssignableFromCode)  // (Class* a, Class* b)
1169    addl LITERAL(16), %esp        // pop arguments
1170    CFI_ADJUST_CFA_OFFSET(-16)
1171    testl %eax, %eax
1172    jz   .Lthrow_array_store_exception
1173    POP  edx
1174    POP  ecx
1175    POP  eax
1176    POISON_HEAP_REF edx
1177    movl %edx, MIRROR_OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4)  // do the aput
1178    movl %fs:THREAD_CARD_TABLE_OFFSET, %edx
1179    shrl LITERAL(7), %eax
1180    movb %dl, (%edx, %eax)
1181    ret
1182    CFI_ADJUST_CFA_OFFSET(12)     // 3 POP after the jz for unwinding.
1183.Lthrow_array_store_exception:
1184    POP  edx
1185    POP  ecx
1186    POP  eax
1187    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME ebx, ebx // save all registers as basis for long jump context
1188    // Outgoing argument set up
1189    PUSH eax                      // alignment padding
1190    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
1191    CFI_ADJUST_CFA_OFFSET(4)
1192    PUSH edx                      // pass arg2 - value
1193    PUSH eax                      // pass arg1 - array
1194    call SYMBOL(artThrowArrayStoreException) // (array, value, Thread*)
1195    UNREACHABLE
1196END_FUNCTION art_quick_aput_obj
1197
1198DEFINE_FUNCTION art_quick_memcpy
1199    SETUP_GOT_NOSAVE ebx          // clobbers EBX
1200    PUSH edx                      // pass arg3
1201    PUSH ecx                      // pass arg2
1202    PUSH eax                      // pass arg1
1203    call PLT_SYMBOL(memcpy)       // (void*, const void*, size_t)
1204    addl LITERAL(12), %esp        // pop arguments
1205    CFI_ADJUST_CFA_OFFSET(-12)
1206    ret
1207END_FUNCTION art_quick_memcpy
1208
1209NO_ARG_DOWNCALL art_quick_test_suspend, artTestSuspendFromCode, ret
1210
1211DEFINE_FUNCTION art_quick_d2l
1212    subl LITERAL(12), %esp        // alignment padding, room for argument
1213    CFI_ADJUST_CFA_OFFSET(12)
1214    movsd %xmm0, 0(%esp)          // arg a
1215    call SYMBOL(art_d2l)          // (jdouble a)
1216    addl LITERAL(12), %esp        // pop arguments
1217    CFI_ADJUST_CFA_OFFSET(-12)
1218    ret
1219END_FUNCTION art_quick_d2l
1220
1221DEFINE_FUNCTION art_quick_f2l
1222    subl LITERAL(12), %esp        // alignment padding
1223    CFI_ADJUST_CFA_OFFSET(12)
1224    movss %xmm0, 0(%esp)          // arg a
1225    call SYMBOL(art_f2l)          // (jfloat a)
1226    addl LITERAL(12), %esp        // pop arguments
1227    CFI_ADJUST_CFA_OFFSET(-12)
1228    ret
1229END_FUNCTION art_quick_f2l
1230
1231DEFINE_FUNCTION art_quick_ldiv
1232    subl LITERAL(12), %esp        // alignment padding
1233    CFI_ADJUST_CFA_OFFSET(12)
1234    PUSH ebx                      // pass arg4 b.hi
1235    PUSH edx                      // pass arg3 b.lo
1236    PUSH ecx                      // pass arg2 a.hi
1237    PUSH eax                      // pass arg1 a.lo
1238    call SYMBOL(artLdiv)          // (jlong a, jlong b)
1239    addl LITERAL(28), %esp        // pop arguments
1240    CFI_ADJUST_CFA_OFFSET(-28)
1241    ret
1242END_FUNCTION art_quick_ldiv
1243
1244DEFINE_FUNCTION art_quick_lmod
1245    subl LITERAL(12), %esp        // alignment padding
1246    CFI_ADJUST_CFA_OFFSET(12)
1247    PUSH ebx                      // pass arg4 b.hi
1248    PUSH edx                      // pass arg3 b.lo
1249    PUSH ecx                      // pass arg2 a.hi
1250    PUSH eax                      // pass arg1 a.lo
1251    call SYMBOL(artLmod)          // (jlong a, jlong b)
1252    addl LITERAL(28), %esp        // pop arguments
1253    CFI_ADJUST_CFA_OFFSET(-28)
1254    ret
1255END_FUNCTION art_quick_lmod
1256
1257DEFINE_FUNCTION art_quick_lmul
1258    imul %eax, %ebx               // ebx = a.lo(eax) * b.hi(ebx)
1259    imul %edx, %ecx               // ecx = b.lo(edx) * a.hi(ecx)
1260    mul  %edx                     // edx:eax = a.lo(eax) * b.lo(edx)
1261    add  %ebx, %ecx
1262    add  %ecx, %edx               // edx += (a.lo * b.hi) + (b.lo * a.hi)
1263    ret
1264END_FUNCTION art_quick_lmul
1265
1266DEFINE_FUNCTION art_quick_lshl
1267    // ecx:eax << edx
1268    xchg %edx, %ecx
1269    shld %cl,%eax,%edx
1270    shl  %cl,%eax
1271    test LITERAL(32), %cl
1272    jz  1f
1273    mov %eax, %edx
1274    xor %eax, %eax
12751:
1276    ret
1277END_FUNCTION art_quick_lshl
1278
1279DEFINE_FUNCTION art_quick_lshr
1280    // ecx:eax >> edx
1281    xchg %edx, %ecx
1282    shrd %cl,%edx,%eax
1283    sar  %cl,%edx
1284    test LITERAL(32),%cl
1285    jz  1f
1286    mov %edx, %eax
1287    sar LITERAL(31), %edx
12881:
1289    ret
1290END_FUNCTION art_quick_lshr
1291
1292DEFINE_FUNCTION art_quick_lushr
1293    // ecx:eax >>> edx
1294    xchg %edx, %ecx
1295    shrd %cl,%edx,%eax
1296    shr  %cl,%edx
1297    test LITERAL(32),%cl
1298    jz  1f
1299    mov %edx, %eax
1300    xor %edx, %edx
13011:
1302    ret
1303END_FUNCTION art_quick_lushr
1304
1305ONE_ARG_REF_DOWNCALL art_quick_get_boolean_static, artGetBooleanStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1306ONE_ARG_REF_DOWNCALL art_quick_get_byte_static, artGetByteStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1307ONE_ARG_REF_DOWNCALL art_quick_get_char_static, artGetCharStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1308ONE_ARG_REF_DOWNCALL art_quick_get_short_static, artGetShortStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1309ONE_ARG_REF_DOWNCALL art_quick_get32_static, artGet32StaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1310ONE_ARG_REF_DOWNCALL art_quick_get64_static, artGet64StaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1311ONE_ARG_REF_DOWNCALL art_quick_get_obj_static, artGetObjStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1312
1313TWO_ARG_REF_DOWNCALL art_quick_get_boolean_instance, artGetBooleanInstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1314TWO_ARG_REF_DOWNCALL art_quick_get_byte_instance, artGetByteInstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1315TWO_ARG_REF_DOWNCALL art_quick_get_char_instance, artGetCharInstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1316TWO_ARG_REF_DOWNCALL art_quick_get_short_instance, artGetShortInstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1317TWO_ARG_REF_DOWNCALL art_quick_get32_instance, artGet32InstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1318TWO_ARG_REF_DOWNCALL art_quick_get64_instance, artGet64InstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1319TWO_ARG_REF_DOWNCALL art_quick_get_obj_instance, artGetObjInstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
1320
1321TWO_ARG_REF_DOWNCALL art_quick_set8_static, artSet8StaticFromCode, RETURN_IF_EAX_ZERO
1322TWO_ARG_REF_DOWNCALL art_quick_set16_static, artSet16StaticFromCode, RETURN_IF_EAX_ZERO
1323TWO_ARG_REF_DOWNCALL art_quick_set32_static, artSet32StaticFromCode, RETURN_IF_EAX_ZERO
1324TWO_ARG_REF_DOWNCALL art_quick_set_obj_static, artSetObjStaticFromCode, RETURN_IF_EAX_ZERO
1325
1326THREE_ARG_REF_DOWNCALL art_quick_set8_instance, artSet8InstanceFromCode, RETURN_IF_EAX_ZERO
1327THREE_ARG_REF_DOWNCALL art_quick_set16_instance, artSet16InstanceFromCode, RETURN_IF_EAX_ZERO
1328THREE_ARG_REF_DOWNCALL art_quick_set32_instance, artSet32InstanceFromCode, RETURN_IF_EAX_ZERO
1329THREE_ARG_REF_DOWNCALL art_quick_set_obj_instance, artSetObjInstanceFromCode, RETURN_IF_EAX_ZERO
1330
1331// Call artSet64InstanceFromCode with 4 word size arguments and the referrer.
1332DEFINE_FUNCTION art_quick_set64_instance
1333    movd %ebx, %xmm0
1334    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx  // save ref containing registers for GC
1335    movd %xmm0, %ebx
1336    // Outgoing argument set up
1337    subl LITERAL(8), %esp         // alignment padding
1338    CFI_ADJUST_CFA_OFFSET(8)
1339    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
1340    CFI_ADJUST_CFA_OFFSET(4)
1341    pushl (FRAME_SIZE_REFS_ONLY_CALLEE_SAVE+12)(%esp)  // pass referrer
1342    CFI_ADJUST_CFA_OFFSET(4)
1343    PUSH ebx                      // pass high half of new_val
1344    PUSH edx                      // pass low half of new_val
1345    PUSH ecx                      // pass object
1346    PUSH eax                      // pass field_idx
1347    call SYMBOL(artSet64InstanceFromCode)  // (field_idx, Object*, new_val, referrer, Thread*)
1348    addl LITERAL(32), %esp        // pop arguments
1349    CFI_ADJUST_CFA_OFFSET(-32)
1350    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME     // restore frame up to return address
1351    RETURN_IF_EAX_ZERO            // return or deliver exception
1352END_FUNCTION art_quick_set64_instance
1353
1354// Call artSet64StaticFromCode with 3 word size arguments plus with the referrer in the 2nd position
1355// so that new_val is aligned on even registers were we passing arguments in registers.
1356DEFINE_FUNCTION art_quick_set64_static
1357    // TODO: Implement SETUP_GOT_NOSAVE for got_reg = ecx to avoid moving around the registers.
1358    movd %ebx, %xmm0
1359    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  ebx, ebx  // save ref containing registers for GC
1360    movd %xmm0, %ebx
1361    mov FRAME_SIZE_REFS_ONLY_CALLEE_SAVE(%esp), %ecx  // get referrer
1362    subl LITERAL(12), %esp        // alignment padding
1363    CFI_ADJUST_CFA_OFFSET(12)
1364    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
1365    CFI_ADJUST_CFA_OFFSET(4)
1366    PUSH ebx                      // pass high half of new_val
1367    PUSH edx                      // pass low half of new_val
1368    PUSH ecx                      // pass referrer
1369    PUSH eax                      // pass field_idx
1370    call SYMBOL(artSet64StaticFromCode)  // (field_idx, referrer, new_val, Thread*)
1371    addl LITERAL(32), %esp        // pop arguments
1372    CFI_ADJUST_CFA_OFFSET(-32)
1373    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME  // restore frame up to return address
1374    RETURN_IF_EAX_ZERO            // return or deliver exception
1375END_FUNCTION art_quick_set64_static
1376
1377DEFINE_FUNCTION art_quick_proxy_invoke_handler
1378    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_WITH_METHOD_IN_EAX
1379    PUSH esp                      // pass SP
1380    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
1381    CFI_ADJUST_CFA_OFFSET(4)
1382    PUSH ecx                      // pass receiver
1383    PUSH eax                      // pass proxy method
1384    call SYMBOL(artQuickProxyInvokeHandler) // (proxy method, receiver, Thread*, SP)
1385    movd %eax, %xmm0              // place return value also into floating point return value
1386    movd %edx, %xmm1
1387    punpckldq %xmm1, %xmm0
1388    addl LITERAL(16 + FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE - FRAME_SIZE_REFS_ONLY_CALLEE_SAVE), %esp
1389    CFI_ADJUST_CFA_OFFSET(-(16 + FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE - FRAME_SIZE_REFS_ONLY_CALLEE_SAVE))
1390    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
1391    RETURN_OR_DELIVER_PENDING_EXCEPTION    // return or deliver exception
1392END_FUNCTION art_quick_proxy_invoke_handler
1393
1394    /*
1395     * Called to resolve an imt conflict. xmm7 is a hidden argument that holds the target method's
1396     * dex method index.
1397     */
1398DEFINE_FUNCTION art_quick_imt_conflict_trampoline
1399    movd %xmm7, %eax              // get target method index stored in xmm7
1400    INVOKE_TRAMPOLINE_BODY artInvokeInterfaceTrampoline
1401END_FUNCTION art_quick_imt_conflict_trampoline
1402
1403DEFINE_FUNCTION art_quick_resolution_trampoline
1404    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME ebx, ebx
1405    movl %esp, %edi
1406    PUSH EDI                      // pass SP. do not just PUSH ESP; that messes up unwinding
1407    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
1408    CFI_ADJUST_CFA_OFFSET(4)
1409    PUSH ecx                      // pass receiver
1410    PUSH eax                      // pass method
1411    call SYMBOL(artQuickResolutionTrampoline) // (Method* called, receiver, Thread*, SP)
1412    movl %eax, %edi               // remember code pointer in EDI
1413    addl LITERAL(16), %esp        // pop arguments
1414    CFI_ADJUST_CFA_OFFSET(-16)
1415    test %eax, %eax               // if code pointer is null goto deliver pending exception
1416    jz 1f
1417    RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME_AND_JUMP
14181:
1419    RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
1420    DELIVER_PENDING_EXCEPTION
1421END_FUNCTION art_quick_resolution_trampoline
1422
1423DEFINE_FUNCTION art_quick_generic_jni_trampoline
1424    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_WITH_METHOD_IN_EAX
1425    movl %esp, %ebp               // save SP at callee-save frame
1426    CFI_DEF_CFA_REGISTER(ebp)
1427    subl LITERAL(5120), %esp
1428    // prepare for artQuickGenericJniTrampoline call
1429    // (Thread*,  SP)
1430    //  (esp)    4(esp)   <= C calling convention
1431    //  fs:...    ebp     <= where they are
1432
1433    subl LITERAL(8), %esp         // Padding for 16B alignment.
1434    pushl %ebp                    // Pass SP (to ArtMethod).
1435    pushl %fs:THREAD_SELF_OFFSET  // Pass Thread::Current().
1436    call SYMBOL(artQuickGenericJniTrampoline)  // (Thread*, sp)
1437
1438    // The C call will have registered the complete save-frame on success.
1439    // The result of the call is:
1440    // eax: pointer to native code, 0 on error.
1441    // edx: pointer to the bottom of the used area of the alloca, can restore stack till there.
1442
1443    // Check for error = 0.
1444    test %eax, %eax
1445    jz .Lexception_in_native
1446
1447    // Release part of the alloca.
1448    movl %edx, %esp
1449
1450    // On x86 there are no registers passed, so nothing to pop here.
1451    // Native call.
1452    call *%eax
1453
1454    // result sign extension is handled in C code
1455    // prepare for artQuickGenericJniEndTrampoline call
1456    // (Thread*, result, result_f)
1457    //  (esp)    4(esp)  12(esp)    <= C calling convention
1458    //  fs:...  eax:edx   fp0      <= where they are
1459
1460    subl LITERAL(20), %esp        // Padding & pass float result.
1461    fstpl (%esp)
1462    pushl %edx                    // Pass int result.
1463    pushl %eax
1464    pushl %fs:THREAD_SELF_OFFSET  // Pass Thread::Current().
1465    call SYMBOL(artQuickGenericJniEndTrampoline)
1466
1467    // Pending exceptions possible.
1468    mov %fs:THREAD_EXCEPTION_OFFSET, %ebx
1469    testl %ebx, %ebx
1470    jnz .Lexception_in_native
1471
1472    // Tear down the alloca.
1473    movl %ebp, %esp
1474    CFI_DEF_CFA_REGISTER(esp)
1475
1476
1477    // Tear down the callee-save frame.
1478    // Remove space for FPR args and EAX
1479    addl LITERAL(4 + 4 * 8), %esp
1480    CFI_ADJUST_CFA_OFFSET(-(4 + 4 * 8))
1481
1482    POP ecx
1483    addl LITERAL(4), %esp         // Avoid edx, as it may be part of the result.
1484    CFI_ADJUST_CFA_OFFSET(-4)
1485    POP ebx
1486    POP ebp  // Restore callee saves
1487    POP esi
1488    POP edi
1489    // Quick expects the return value to be in xmm0.
1490    movd %eax, %xmm0
1491    movd %edx, %xmm1
1492    punpckldq %xmm1, %xmm0
1493    ret
1494.Lexception_in_native:
1495    movl %fs:THREAD_TOP_QUICK_FRAME_OFFSET, %esp
1496    // Do a call to push a new save-all frame required by the runtime.
1497    call .Lexception_call
1498.Lexception_call:
1499    DELIVER_PENDING_EXCEPTION
1500END_FUNCTION art_quick_generic_jni_trampoline
1501
1502DEFINE_FUNCTION art_quick_to_interpreter_bridge
1503    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME  ebx, ebx  // save frame
1504    mov %esp, %edx                // remember SP
1505    PUSH eax                      // alignment padding
1506    PUSH edx                      // pass SP
1507    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
1508    CFI_ADJUST_CFA_OFFSET(4)
1509    PUSH eax                      // pass  method
1510    call SYMBOL(artQuickToInterpreterBridge)  // (method, Thread*, SP)
1511    addl LITERAL(16), %esp        // pop arguments
1512    CFI_ADJUST_CFA_OFFSET(-16)
1513
1514    // Return eax:edx in xmm0 also.
1515    movd %eax, %xmm0
1516    movd %edx, %xmm1
1517    punpckldq %xmm1, %xmm0
1518
1519    addl LITERAL(48), %esp        // Remove FPRs and EAX, ECX, EDX, EBX.
1520    CFI_ADJUST_CFA_OFFSET(-48)
1521
1522    POP ebp                       // Restore callee saves
1523    POP esi
1524    POP edi
1525
1526    RETURN_OR_DELIVER_PENDING_EXCEPTION    // return or deliver exception
1527END_FUNCTION art_quick_to_interpreter_bridge
1528
1529    /*
1530     * Routine that intercepts method calls and returns.
1531     */
1532DEFINE_FUNCTION art_quick_instrumentation_entry
1533    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME ebx, edx
1534    PUSH eax                      // Save eax which will be clobbered by the callee-save method.
1535    subl LITERAL(12), %esp        // Align stack.
1536    CFI_ADJUST_CFA_OFFSET(12)
1537    pushl FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE-4+16(%esp)  // Pass LR.
1538    CFI_ADJUST_CFA_OFFSET(4)
1539    pushl %fs:THREAD_SELF_OFFSET  // Pass Thread::Current().
1540    CFI_ADJUST_CFA_OFFSET(4)
1541    PUSH ecx                      // Pass receiver.
1542    PUSH eax                      // Pass Method*.
1543    call SYMBOL(artInstrumentationMethodEntryFromCode) // (Method*, Object*, Thread*, LR)
1544    addl LITERAL(28), %esp        // Pop arguments upto saved Method*.
1545    CFI_ADJUST_CFA_OFFSET(-28)
1546    movl 60(%esp), %edi           // Restore edi.
1547    movl %eax, 60(%esp)           // Place code* over edi, just under return pc.
1548    movl SYMBOL(art_quick_instrumentation_exit)@GOT(%ebx), %ebx
1549    // Place instrumentation exit as return pc. ebx holds the GOT computed on entry.
1550    movl %ebx, 64(%esp)
1551    movl 0(%esp), %eax           // Restore eax.
1552    // Restore FPRs (extra 4 bytes of offset due to EAX push at top).
1553    movsd 8(%esp), %xmm0
1554    movsd 16(%esp), %xmm1
1555    movsd 24(%esp), %xmm2
1556    movsd 32(%esp), %xmm3
1557
1558    // Restore GPRs.
1559    movl 40(%esp), %ecx           // Restore ecx.
1560    movl 44(%esp), %edx           // Restore edx.
1561    movl 48(%esp), %ebx           // Restore ebx.
1562    movl 52(%esp), %ebp           // Restore ebp.
1563    movl 56(%esp), %esi           // Restore esi.
1564    addl LITERAL(60), %esp        // Wind stack back upto code*.
1565    CFI_ADJUST_CFA_OFFSET(-60)
1566    ret                           // Call method (and pop).
1567END_FUNCTION art_quick_instrumentation_entry
1568
1569DEFINE_FUNCTION art_quick_instrumentation_exit
1570    pushl LITERAL(0)              // Push a fake return PC as there will be none on the stack.
1571    CFI_ADJUST_CFA_OFFSET(4)
1572    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx
1573    mov  %esp, %ecx               // Remember SP
1574    subl LITERAL(8), %esp         // Save float return value.
1575    CFI_ADJUST_CFA_OFFSET(8)
1576    movq %xmm0, (%esp)
1577    PUSH edx                      // Save gpr return value.
1578    PUSH eax
1579    subl LITERAL(16), %esp        // Align stack
1580    CFI_ADJUST_CFA_OFFSET(16)
1581    movq %xmm0, (%esp)            // Pass float return value.
1582    PUSH edx                      // Pass gpr return value.
1583    PUSH eax
1584    PUSH ecx                      // Pass SP.
1585    pushl %fs:THREAD_SELF_OFFSET  // Pass Thread::Current.
1586    CFI_ADJUST_CFA_OFFSET(4)
1587    call SYMBOL(artInstrumentationMethodExitFromCode)  // (Thread*, SP, gpr_result, fpr_result)
1588    mov   %eax, %ecx              // Move returned link register.
1589    addl LITERAL(32), %esp        // Pop arguments.
1590    CFI_ADJUST_CFA_OFFSET(-32)
1591    movl %edx, %ebx               // Move returned link register for deopt
1592                                  // (ebx is pretending to be our LR).
1593    POP eax                       // Restore gpr return value.
1594    POP edx
1595    movq (%esp), %xmm0            // Restore fpr return value.
1596    addl LITERAL(8), %esp
1597    CFI_ADJUST_CFA_OFFSET(-8)
1598    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
1599    addl LITERAL(4), %esp         // Remove fake return pc.
1600    CFI_ADJUST_CFA_OFFSET(-4)
1601    jmp   *%ecx                   // Return.
1602END_FUNCTION art_quick_instrumentation_exit
1603
1604    /*
1605     * Instrumentation has requested that we deoptimize into the interpreter. The deoptimization
1606     * will long jump to the upcall with a special exception of -1.
1607     */
1608DEFINE_FUNCTION art_quick_deoptimize
1609    PUSH ebx                      // Entry point for a jump. Fake that we were called.
1610    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME ebx, ebx
1611    subl LITERAL(12), %esp        // Align stack.
1612    CFI_ADJUST_CFA_OFFSET(12)
1613    pushl %fs:THREAD_SELF_OFFSET  // Pass Thread::Current().
1614    CFI_ADJUST_CFA_OFFSET(4)
1615    call SYMBOL(artDeoptimize)    // artDeoptimize(Thread*)
1616    UNREACHABLE
1617END_FUNCTION art_quick_deoptimize
1618
1619    /*
1620     * Compiled code has requested that we deoptimize into the interpreter. The deoptimization
1621     * will long jump to the interpreter bridge.
1622     */
1623DEFINE_FUNCTION art_quick_deoptimize_from_compiled_code
1624    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME ebx, ebx
1625    subl LITERAL(12), %esp                      // Align stack.
1626    CFI_ADJUST_CFA_OFFSET(12)
1627    pushl %fs:THREAD_SELF_OFFSET                // Pass Thread::Current().
1628    CFI_ADJUST_CFA_OFFSET(4)
1629    call SYMBOL(artDeoptimizeFromCompiledCode)  // artDeoptimizeFromCompiledCode(Thread*)
1630    UNREACHABLE
1631END_FUNCTION art_quick_deoptimize_from_compiled_code
1632
1633    /*
1634     * String's compareTo.
1635     *
1636     * On entry:
1637     *    eax:   this string object (known non-null)
1638     *    ecx:   comp string object (known non-null)
1639     */
1640DEFINE_FUNCTION art_quick_string_compareto
1641    PUSH esi                      // push callee save reg
1642    PUSH edi                      // push callee save reg
1643    mov MIRROR_STRING_COUNT_OFFSET(%eax), %edx
1644    mov MIRROR_STRING_COUNT_OFFSET(%ecx), %ebx
1645    lea MIRROR_STRING_VALUE_OFFSET(%eax), %esi
1646    lea MIRROR_STRING_VALUE_OFFSET(%ecx), %edi
1647    /* Calculate min length and count diff */
1648    mov   %edx, %ecx
1649    mov   %edx, %eax
1650    subl  %ebx, %eax
1651    cmovg %ebx, %ecx
1652    /*
1653     * At this point we have:
1654     *   eax: value to return if first part of strings are equal
1655     *   ecx: minimum among the lengths of the two strings
1656     *   esi: pointer to this string data
1657     *   edi: pointer to comp string data
1658     */
1659    jecxz .Lkeep_length
1660    repe cmpsw                    // find nonmatching chars in [%esi] and [%edi], up to length %ecx
1661    jne .Lnot_equal
1662.Lkeep_length:
1663    POP edi                       // pop callee save reg
1664    POP esi                       // pop callee save reg
1665    ret
1666    .balign 16
1667.Lnot_equal:
1668    movzwl  -2(%esi), %eax        // get last compared char from this string
1669    movzwl  -2(%edi), %ecx        // get last compared char from comp string
1670    subl  %ecx, %eax              // return the difference
1671    POP edi                       // pop callee save reg
1672    POP esi                       // pop callee save reg
1673    ret
1674END_FUNCTION art_quick_string_compareto
1675
1676// Return from a nested signal:
1677// Entry:
1678//  eax: address of jmp_buf in TLS
1679
1680DEFINE_FUNCTION art_nested_signal_return
1681    SETUP_GOT_NOSAVE ebx            // sets %ebx for call into PLT
1682    movl LITERAL(1), %ecx
1683    PUSH ecx                        // second arg to longjmp (1)
1684    PUSH eax                        // first arg to longjmp (jmp_buf)
1685    call PLT_SYMBOL(longjmp)
1686    UNREACHABLE
1687END_FUNCTION art_nested_signal_return
1688
1689DEFINE_FUNCTION art_quick_read_barrier_mark
1690    PUSH eax                         // pass arg1 - obj
1691    call SYMBOL(artReadBarrierMark)  // artReadBarrierMark(obj)
1692    addl LITERAL(4), %esp            // pop argument
1693    CFI_ADJUST_CFA_OFFSET(-4)
1694    ret
1695END_FUNCTION art_quick_read_barrier_mark
1696
1697DEFINE_FUNCTION art_quick_read_barrier_slow
1698    PUSH edx                         // pass arg3 - offset
1699    PUSH ecx                         // pass arg2 - obj
1700    PUSH eax                         // pass arg1 - ref
1701    call SYMBOL(artReadBarrierSlow)  // artReadBarrierSlow(ref, obj, offset)
1702    addl LITERAL(12), %esp           // pop arguments
1703    CFI_ADJUST_CFA_OFFSET(-12)
1704    ret
1705END_FUNCTION art_quick_read_barrier_slow
1706
1707DEFINE_FUNCTION art_quick_read_barrier_for_root_slow
1708    PUSH eax                                // pass arg1 - root
1709    call SYMBOL(artReadBarrierForRootSlow)  // artReadBarrierForRootSlow(root)
1710    addl LITERAL(4), %esp                   // pop argument
1711    CFI_ADJUST_CFA_OFFSET(-4)
1712    ret
1713END_FUNCTION art_quick_read_barrier_for_root_slow
1714
1715  /*
1716     * On stack replacement stub.
1717     * On entry:
1718     *   [sp] = return address
1719     *   [sp + 4] = stack to copy
1720     *   [sp + 8] = size of stack
1721     *   [sp + 12] = pc to call
1722     *   [sp + 16] = JValue* result
1723     *   [sp + 20] = shorty
1724     *   [sp + 24] = thread
1725     */
1726DEFINE_FUNCTION art_quick_osr_stub
1727    // Save native callee saves.
1728    PUSH ebp
1729    PUSH ebx
1730    PUSH esi
1731    PUSH edi
1732    mov 4+16(%esp), %esi           // ESI = argument array
1733    mov 8+16(%esp), %ecx           // ECX = size of args
1734    mov 12+16(%esp), %ebx          // EBX = pc to call
1735    mov %esp, %ebp                 // Save stack pointer
1736    andl LITERAL(0xFFFFFFF0), %esp // Align stack
1737    PUSH ebp                       // Save old stack pointer
1738    subl LITERAL(12), %esp         // Align stack
1739    movl LITERAL(0), (%esp)        // Store null for ArtMethod* slot
1740    call .Losr_entry
1741
1742    // Restore stack pointer.
1743    addl LITERAL(12), %esp
1744    POP ebp
1745    mov %ebp, %esp
1746
1747    // Restore callee saves.
1748    POP edi
1749    POP esi
1750    POP ebx
1751    POP ebp
1752    mov 16(%esp), %ecx            // Get JValue result
1753    mov %eax, (%ecx)              // Store the result assuming it is a long, int or Object*
1754    mov %edx, 4(%ecx)             // Store the other half of the result
1755    mov 20(%esp), %edx            // Get the shorty
1756    cmpb LITERAL(68), (%edx)      // Test if result type char == 'D'
1757    je .Losr_return_double_quick
1758    cmpb LITERAL(70), (%edx)      // Test if result type char == 'F'
1759    je .Losr_return_float_quick
1760    ret
1761.Losr_return_double_quick:
1762    movsd %xmm0, (%ecx)           // Store the floating point result
1763    ret
1764.Losr_return_float_quick:
1765    movss %xmm0, (%ecx)           // Store the floating point result
1766    ret
1767.Losr_entry:
1768    subl LITERAL(4), %ecx         // Given stack size contains pushed frame pointer, substract it.
1769    subl %ecx, %esp
1770    mov %esp, %edi                // EDI = beginning of stack
1771    rep movsb                     // while (ecx--) { *edi++ = *esi++ }
1772    jmp *%ebx
1773END_FUNCTION art_quick_osr_stub
1774
1775    // TODO: implement these!
1776UNIMPLEMENTED art_quick_memcmp16
1777