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