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