quick_entrypoints_x86.S revision 3f2d031f639b3b9dd4adbf9e70d23de931a9801d
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] = result type char 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_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 cmpl LITERAL(68), 24(%esp) // test if result type char == 'D' 285 je return_double_quick 286 cmpl LITERAL(70), 24(%esp) // test if result type char == 'F' 287 je return_float_quick 288 mov %eax, (%ecx) // store the result 289 mov %edx, 4(%ecx) // store the other half of the result 290 ret 291return_double_quick: 292return_float_quick: 293 movsd %xmm0, (%ecx) // store the floating point result 294 ret 295END_FUNCTION art_quick_invoke_stub 296 297MACRO3(NO_ARG_DOWNCALL, c_name, cxx_name, return_macro) 298 DEFINE_FUNCTION VAR(c_name, 0) 299 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 300 mov %esp, %edx // remember SP 301 SETUP_GOT_NOSAVE // clobbers ebx (harmless here) 302 // Outgoing argument set up 303 subl MACRO_LITERAL(8), %esp // push padding 304 CFI_ADJUST_CFA_OFFSET(8) 305 PUSH edx // pass SP 306 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 307 CFI_ADJUST_CFA_OFFSET(4) 308 call PLT_VAR(cxx_name, 1) // cxx_name(Thread*, SP) 309 addl MACRO_LITERAL(16), %esp // pop arguments 310 CFI_ADJUST_CFA_OFFSET(-16) 311 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 312 CALL_MACRO(return_macro, 2) // return or deliver exception 313 END_FUNCTION VAR(c_name, 0) 314END_MACRO 315 316MACRO3(ONE_ARG_DOWNCALL, c_name, cxx_name, return_macro) 317 DEFINE_FUNCTION VAR(c_name, 0) 318 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 319 mov %esp, %edx // remember SP 320 SETUP_GOT_NOSAVE // clobbers EBX 321 // Outgoing argument set up 322 PUSH eax // push padding 323 PUSH edx // pass SP 324 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 325 CFI_ADJUST_CFA_OFFSET(4) 326 PUSH eax // pass arg1 327 call PLT_VAR(cxx_name, 1) // cxx_name(arg1, Thread*, SP) 328 addl MACRO_LITERAL(16), %esp // pop arguments 329 CFI_ADJUST_CFA_OFFSET(-16) 330 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 331 CALL_MACRO(return_macro, 2) // return or deliver exception 332 END_FUNCTION VAR(c_name, 0) 333END_MACRO 334 335MACRO3(TWO_ARG_DOWNCALL, c_name, cxx_name, return_macro) 336 DEFINE_FUNCTION VAR(c_name, 0) 337 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 338 mov %esp, %edx // remember SP 339 SETUP_GOT_NOSAVE // clobbers EBX 340 // Outgoing argument set up 341 PUSH edx // pass SP 342 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 343 CFI_ADJUST_CFA_OFFSET(4) 344 PUSH ecx // pass arg2 345 PUSH eax // pass arg1 346 call PLT_VAR(cxx_name, 1) // cxx_name(arg1, arg2, Thread*, SP) 347 addl MACRO_LITERAL(16), %esp // pop arguments 348 CFI_ADJUST_CFA_OFFSET(-16) 349 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 350 CALL_MACRO(return_macro, 2) // return or deliver exception 351 END_FUNCTION VAR(c_name, 0) 352END_MACRO 353 354MACRO3(THREE_ARG_DOWNCALL, c_name, cxx_name, return_macro) 355 DEFINE_FUNCTION VAR(c_name, 0) 356 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 357 mov %esp, %ebx // remember SP 358 // Outgoing argument set up 359 subl MACRO_LITERAL(12), %esp // alignment padding 360 CFI_ADJUST_CFA_OFFSET(12) 361 PUSH ebx // pass SP 362 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 363 CFI_ADJUST_CFA_OFFSET(4) 364 PUSH edx // pass arg3 365 PUSH ecx // pass arg2 366 PUSH eax // pass arg1 367 SETUP_GOT_NOSAVE // clobbers EBX 368 call PLT_VAR(cxx_name, 1) // cxx_name(arg1, arg2, arg3, Thread*, SP) 369 addl MACRO_LITERAL(32), %esp // pop arguments 370 CFI_ADJUST_CFA_OFFSET(-32) 371 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 372 CALL_MACRO(return_macro, 2) // return or deliver exception 373 END_FUNCTION VAR(c_name, 0) 374END_MACRO 375 376MACRO0(RETURN_IF_RESULT_IS_NON_ZERO) 377 testl %eax, %eax // eax == 0 ? 378 jz 1f // if eax == 0 goto 1 379 ret // return 3801: // deliver exception on current thread 381 DELIVER_PENDING_EXCEPTION 382END_MACRO 383 384MACRO0(RETURN_IF_EAX_ZERO) 385 testl %eax, %eax // eax == 0 ? 386 jnz 1f // if eax != 0 goto 1 387 ret // return 3881: // deliver exception on current thread 389 DELIVER_PENDING_EXCEPTION 390END_MACRO 391 392MACRO0(RETURN_OR_DELIVER_PENDING_EXCEPTION) 393 mov %fs:THREAD_EXCEPTION_OFFSET, %ebx // get exception field 394 testl %ebx, %ebx // ebx == 0 ? 395 jnz 1f // if ebx != 0 goto 1 396 ret // return 3971: // deliver exception on current thread 398 DELIVER_PENDING_EXCEPTION 399END_MACRO 400 401// Generate the allocation entrypoints for each allocator. 402// TODO: use arch/quick_alloc_entrypoints.S. Currently we don't as we need to use concatenation 403// macros to work around differences between OS/X's as and binutils as (OS/X lacks named arguments 404// to macros and the VAR macro won't concatenate arguments properly), this also breaks having 405// multi-line macros that use each other (hence using 1 macro per newline below). 406#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(c_suffix, cxx_suffix) \ 407 TWO_ARG_DOWNCALL art_quick_alloc_object ## c_suffix, artAllocObjectFromCode ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO 408#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(c_suffix, cxx_suffix) \ 409 TWO_ARG_DOWNCALL art_quick_alloc_object_with_access_check ## c_suffix, artAllocObjectFromCodeWithAccessCheck ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO 410#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(c_suffix, cxx_suffix) \ 411 THREE_ARG_DOWNCALL art_quick_alloc_array ## c_suffix, artAllocArrayFromCode ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO 412#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(c_suffix, cxx_suffix) \ 413 THREE_ARG_DOWNCALL art_quick_alloc_array_with_access_check ## c_suffix, artAllocArrayFromCodeWithAccessCheck ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO 414#define GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(c_suffix, cxx_suffix) \ 415 THREE_ARG_DOWNCALL art_quick_check_and_alloc_array ## c_suffix, artCheckAndAllocArrayFromCode ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO 416#define GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(c_suffix, cxx_suffix) \ 417 THREE_ARG_DOWNCALL art_quick_check_and_alloc_array_with_access_check ## c_suffix, artCheckAndAllocArrayFromCodeWithAccessCheck ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO 418 419GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_dlmalloc, DlMalloc) 420GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_dlmalloc, DlMalloc) 421GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_dlmalloc, DlMalloc) 422GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc, DlMalloc) 423GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_dlmalloc, DlMalloc) 424GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc, DlMalloc) 425 426GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_dlmalloc_instrumented, DlMallocInstrumented) 427GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_dlmalloc_instrumented, DlMallocInstrumented) 428GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_dlmalloc_instrumented, DlMallocInstrumented) 429GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc_instrumented, DlMallocInstrumented) 430GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_dlmalloc_instrumented, DlMallocInstrumented) 431GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc_instrumented, DlMallocInstrumented) 432 433GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_rosalloc, RosAlloc) 434GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_rosalloc, RosAlloc) 435GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_rosalloc, RosAlloc) 436GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc, RosAlloc) 437GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_rosalloc, RosAlloc) 438GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc, RosAlloc) 439 440GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_rosalloc_instrumented, RosAllocInstrumented) 441GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_rosalloc_instrumented, RosAllocInstrumented) 442GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_rosalloc_instrumented, RosAllocInstrumented) 443GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc_instrumented, RosAllocInstrumented) 444GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_rosalloc_instrumented, RosAllocInstrumented) 445GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc_instrumented, RosAllocInstrumented) 446 447GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_bump_pointer, BumpPointer) 448GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_bump_pointer, BumpPointer) 449GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_bump_pointer, BumpPointer) 450GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer, BumpPointer) 451GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_bump_pointer, BumpPointer) 452GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer, BumpPointer) 453 454GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_bump_pointer_instrumented, BumpPointerInstrumented) 455GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_bump_pointer_instrumented, BumpPointerInstrumented) 456GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_bump_pointer_instrumented, BumpPointerInstrumented) 457GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer_instrumented, BumpPointerInstrumented) 458GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_bump_pointer_instrumented, BumpPointerInstrumented) 459GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer_instrumented, BumpPointerInstrumented) 460 461GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_tlab, TLAB) 462GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_tlab, TLAB) 463GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_tlab, TLAB) 464GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab, TLAB) 465GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_tlab, TLAB) 466GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab, TLAB) 467 468GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_tlab_instrumented, TLABInstrumented) 469GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_tlab_instrumented, TLABInstrumented) 470GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_tlab_instrumented, TLABInstrumented) 471GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab_instrumented, TLABInstrumented) 472GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_tlab_instrumented, TLABInstrumented) 473GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab_instrumented, TLABInstrumented) 474 475TWO_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO 476TWO_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO 477TWO_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO 478TWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO 479 480TWO_ARG_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO 481 482DEFINE_FUNCTION art_quick_lock_object 483 testl %eax, %eax // null check object/eax 484 jz slow_lock 485retry_lock: 486 movl LOCK_WORD_OFFSET(%eax), %ecx // ecx := lock word 487 test LITERAL(0xC0000000), %ecx // test the 2 high bits. 488 jne slow_lock // slow path if either of the two high bits are set. 489 movl %fs:THREAD_ID_OFFSET, %edx // edx := thread id 490 test %ecx, %ecx 491 jnz already_thin // lock word contains a thin lock 492 // unlocked case - %edx holds thread id with count of 0 493 movl %eax, %ecx // remember object in case of retry 494 xor %eax, %eax // eax == 0 for comparison with lock word in cmpxchg 495 lock cmpxchg %edx, LOCK_WORD_OFFSET(%ecx) 496 jnz cmpxchg_fail // cmpxchg failed retry 497 ret 498cmpxchg_fail: 499 movl %ecx, %eax // restore eax 500 jmp retry_lock 501already_thin: 502 cmpw %ax, %dx // do we hold the lock already? 503 jne slow_lock 504 addl LITERAL(65536), %eax // increment recursion count 505 test LITERAL(0xC0000000), %eax // overflowed if either of top two bits are set 506 jne slow_lock // count overflowed so go slow 507 movl %eax, LOCK_WORD_OFFSET(%ecx) // update lockword, cmpxchg not necessary as we hold lock 508 ret 509slow_lock: 510 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 511 mov %esp, %edx // remember SP 512 SETUP_GOT_NOSAVE // clobbers EBX 513 // Outgoing argument set up 514 PUSH eax // push padding 515 PUSH edx // pass SP 516 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 517 CFI_ADJUST_CFA_OFFSET(4) 518 PUSH eax // pass object 519 call PLT_SYMBOL(artLockObjectFromCode) // artLockObjectFromCode(object, Thread*, SP) 520 addl LITERAL(16), %esp // pop arguments 521 CFI_ADJUST_CFA_OFFSET(-16) 522 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 523 RETURN_IF_EAX_ZERO 524END_FUNCTION art_quick_lock_object 525 526DEFINE_FUNCTION art_quick_unlock_object 527 testl %eax, %eax // null check object/eax 528 jz slow_unlock 529 movl LOCK_WORD_OFFSET(%eax), %ecx // ecx := lock word 530 movl %fs:THREAD_ID_OFFSET, %edx // edx := thread id 531 test %ecx, %ecx 532 jb slow_unlock // lock word contains a monitor 533 cmpw %cx, %dx // does the thread id match? 534 jne slow_unlock 535 cmpl LITERAL(65536), %ecx 536 jae recursive_thin_unlock 537 movl LITERAL(0), LOCK_WORD_OFFSET(%eax) 538 ret 539recursive_thin_unlock: 540 subl LITERAL(65536), %ecx 541 mov %ecx, LOCK_WORD_OFFSET(%eax) 542 ret 543slow_unlock: 544 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 545 mov %esp, %edx // remember SP 546 SETUP_GOT_NOSAVE // clobbers EBX 547 // Outgoing argument set up 548 PUSH eax // push padding 549 PUSH edx // pass SP 550 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 551 CFI_ADJUST_CFA_OFFSET(4) 552 PUSH eax // pass object 553 call PLT_SYMBOL(artUnlockObjectFromCode) // artUnlockObjectFromCode(object, Thread*, SP) 554 addl LITERAL(16), %esp // pop arguments 555 CFI_ADJUST_CFA_OFFSET(-16) 556 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 557 RETURN_IF_EAX_ZERO 558END_FUNCTION art_quick_unlock_object 559 560DEFINE_FUNCTION art_quick_is_assignable 561 SETUP_GOT_NOSAVE // clobbers EBX 562 PUSH eax // alignment padding 563 PUSH ecx // pass arg2 - obj->klass 564 PUSH eax // pass arg1 - checked class 565 call PLT_SYMBOL(artIsAssignableFromCode) // (Class* klass, Class* ref_klass) 566 addl LITERAL(12), %esp // pop arguments 567 CFI_ADJUST_CFA_OFFSET(-12) 568 ret 569END_FUNCTION art_quick_is_assignable 570 571DEFINE_FUNCTION art_quick_check_cast 572 SETUP_GOT_NOSAVE // clobbers EBX 573 PUSH eax // alignment padding 574 PUSH ecx // pass arg2 - obj->klass 575 PUSH eax // pass arg1 - checked class 576 call PLT_SYMBOL(artIsAssignableFromCode) // (Class* klass, Class* ref_klass) 577 testl %eax, %eax 578 jz 1f // jump forward if not assignable 579 addl LITERAL(12), %esp // pop arguments 580 CFI_ADJUST_CFA_OFFSET(-12) 581 ret 5821: 583 POP eax // pop arguments 584 POP ecx 585 addl LITERAL(4), %esp 586 CFI_ADJUST_CFA_OFFSET(-12) 587 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context 588 mov %esp, %edx 589 // Outgoing argument set up 590 PUSH edx // pass SP 591 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 592 CFI_ADJUST_CFA_OFFSET(4) 593 PUSH ecx // pass arg2 594 PUSH eax // pass arg1 595 call PLT_SYMBOL(artThrowClassCastException) // (Class* a, Class* b, Thread*, SP) 596 int3 // unreached 597END_FUNCTION art_quick_check_cast 598 599 /* 600 * Entry from managed code for array put operations of objects where the value being stored 601 * needs to be checked for compatibility. 602 * eax = array, ecx = index, edx = value 603 */ 604DEFINE_FUNCTION art_quick_aput_obj_with_null_and_bound_check 605 testl %eax, %eax 606 jnz art_quick_aput_obj_with_bound_check 607 jmp art_quick_throw_null_pointer_exception 608END_FUNCTION art_quick_aput_obj_with_null_and_bound_check 609 610DEFINE_FUNCTION art_quick_aput_obj_with_bound_check 611 movl ARRAY_LENGTH_OFFSET(%eax), %ebx 612 cmpl %ebx, %ecx 613 jb art_quick_aput_obj 614 mov %ecx, %eax 615 mov %ebx, %ecx 616 jmp art_quick_throw_array_bounds 617END_FUNCTION art_quick_aput_obj_with_bound_check 618 619DEFINE_FUNCTION art_quick_aput_obj 620 test %edx, %edx // store of null 621 jz do_aput_null 622 movl CLASS_OFFSET(%eax), %ebx 623 movl CLASS_COMPONENT_TYPE_OFFSET(%ebx), %ebx 624 cmpl CLASS_OFFSET(%edx), %ebx // value's type == array's component type - trivial assignability 625 jne check_assignability 626do_aput: 627 movl %edx, OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4) 628 movl %fs:THREAD_CARD_TABLE_OFFSET, %edx 629 shrl LITERAL(7), %eax 630 movb %dl, (%edx, %eax) 631 ret 632do_aput_null: 633 movl %edx, OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4) 634 ret 635check_assignability: 636 PUSH eax // save arguments 637 PUSH ecx 638 PUSH edx 639 subl LITERAL(8), %esp // alignment padding 640 CFI_ADJUST_CFA_OFFSET(8) 641 pushl CLASS_OFFSET(%edx) // pass arg2 - type of the value to be stored 642 CFI_ADJUST_CFA_OFFSET(4) 643 PUSH ebx // pass arg1 - component type of the array 644 SETUP_GOT_NOSAVE // clobbers EBX 645 call PLT_SYMBOL(artIsAssignableFromCode) // (Class* a, Class* b) 646 addl LITERAL(16), %esp // pop arguments 647 CFI_ADJUST_CFA_OFFSET(-16) 648 testl %eax, %eax 649 jz throw_array_store_exception 650 POP edx 651 POP ecx 652 POP eax 653 movl %edx, OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4) // do the aput 654 movl %fs:THREAD_CARD_TABLE_OFFSET, %edx 655 shrl LITERAL(7), %eax 656 movb %dl, (%edx, %eax) 657 ret 658throw_array_store_exception: 659 POP edx 660 POP ecx 661 POP eax 662 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context 663 mov %esp, %ecx 664 // Outgoing argument set up 665 PUSH ecx // pass SP 666 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 667 CFI_ADJUST_CFA_OFFSET(4) 668 PUSH edx // pass arg2 - value 669 PUSH eax // pass arg1 - array 670 call PLT_SYMBOL(artThrowArrayStoreException) // (array, value, Thread*, SP) 671 int3 // unreached 672END_FUNCTION art_quick_aput_obj 673 674DEFINE_FUNCTION art_quick_memcpy 675 SETUP_GOT_NOSAVE // clobbers EBX 676 PUSH edx // pass arg3 677 PUSH ecx // pass arg2 678 PUSH eax // pass arg1 679 call PLT_SYMBOL(memcpy) // (void*, const void*, size_t) 680 addl LITERAL(12), %esp // pop arguments 681 CFI_ADJUST_CFA_OFFSET(-12) 682 ret 683END_FUNCTION art_quick_memcpy 684 685NO_ARG_DOWNCALL art_quick_test_suspend, artTestSuspendFromCode, ret 686 687DEFINE_FUNCTION art_quick_fmod 688 subl LITERAL(12), %esp // alignment padding 689 CFI_ADJUST_CFA_OFFSET(12) 690 PUSH ebx // pass arg4 b.hi 691 PUSH edx // pass arg3 b.lo 692 PUSH ecx // pass arg2 a.hi 693 PUSH eax // pass arg1 a.lo 694 SETUP_GOT_NOSAVE // clobbers EBX 695 call PLT_SYMBOL(fmod) // (jdouble a, jdouble b) 696 fstpl (%esp) // pop return value off fp stack 697 movsd (%esp), %xmm0 // place into %xmm0 698 addl LITERAL(28), %esp // pop arguments 699 CFI_ADJUST_CFA_OFFSET(-28) 700 ret 701END_FUNCTION art_quick_fmod 702 703DEFINE_FUNCTION art_quick_fmodf 704 PUSH eax // alignment padding 705 PUSH ecx // pass arg2 b 706 PUSH eax // pass arg1 a 707 SETUP_GOT_NOSAVE // clobbers EBX 708 call PLT_SYMBOL(fmodf) // (jfloat a, jfloat b) 709 fstps (%esp) // pop return value off fp stack 710 movss (%esp), %xmm0 // place into %xmm0 711 addl LITERAL(12), %esp // pop arguments 712 CFI_ADJUST_CFA_OFFSET(-12) 713 ret 714END_FUNCTION art_quick_fmodf 715 716DEFINE_FUNCTION art_quick_l2d 717 PUSH ecx // push arg2 a.hi 718 PUSH eax // push arg1 a.lo 719 fildll (%esp) // load as integer and push into st0 720 fstpl (%esp) // pop value off fp stack as double 721 movsd (%esp), %xmm0 // place into %xmm0 722 addl LITERAL(8), %esp // pop arguments 723 CFI_ADJUST_CFA_OFFSET(-8) 724 ret 725END_FUNCTION art_quick_l2d 726 727DEFINE_FUNCTION art_quick_l2f 728 PUSH ecx // push arg2 a.hi 729 PUSH eax // push arg1 a.lo 730 fildll (%esp) // load as integer and push into st0 731 fstps (%esp) // pop value off fp stack as a single 732 movss (%esp), %xmm0 // place into %xmm0 733 addl LITERAL(8), %esp // pop argument 734 CFI_ADJUST_CFA_OFFSET(-8) 735 ret 736END_FUNCTION art_quick_l2f 737 738DEFINE_FUNCTION art_quick_d2l 739 PUSH eax // alignment padding 740 PUSH ecx // pass arg2 a.hi 741 PUSH eax // pass arg1 a.lo 742 SETUP_GOT_NOSAVE // clobbers EBX 743 call PLT_SYMBOL(art_d2l) // (jdouble a) 744 addl LITERAL(12), %esp // pop arguments 745 CFI_ADJUST_CFA_OFFSET(-12) 746 ret 747END_FUNCTION art_quick_d2l 748 749DEFINE_FUNCTION art_quick_f2l 750 subl LITERAL(8), %esp // alignment padding 751 CFI_ADJUST_CFA_OFFSET(8) 752 SETUP_GOT_NOSAVE // clobbers EBX 753 PUSH eax // pass arg1 a 754 call PLT_SYMBOL(art_f2l) // (jfloat a) 755 addl LITERAL(12), %esp // pop arguments 756 CFI_ADJUST_CFA_OFFSET(-12) 757 ret 758END_FUNCTION art_quick_f2l 759 760DEFINE_FUNCTION art_quick_idivmod 761 cmpl LITERAL(0x80000000), %eax 762 je check_arg2 // special case 763args_ok: 764 cdq // edx:eax = sign extend eax 765 idiv %ecx // (edx,eax) = (edx:eax % ecx, edx:eax / ecx) 766 ret 767check_arg2: 768 cmpl LITERAL(-1), %ecx 769 jne args_ok 770 xorl %edx, %edx 771 ret // eax already holds min int 772END_FUNCTION art_quick_idivmod 773 774DEFINE_FUNCTION art_quick_ldiv 775 subl LITERAL(12), %esp // alignment padding 776 CFI_ADJUST_CFA_OFFSET(12) 777 PUSH ebx // pass arg4 b.hi 778 PUSH edx // pass arg3 b.lo 779 PUSH ecx // pass arg2 a.hi 780 PUSH eax // pass arg1 a.lo 781 SETUP_GOT_NOSAVE // clobbers EBX 782 call PLT_SYMBOL(artLdiv) // (jlong a, jlong b) 783 addl LITERAL(28), %esp // pop arguments 784 CFI_ADJUST_CFA_OFFSET(-28) 785 ret 786END_FUNCTION art_quick_ldiv 787 788DEFINE_FUNCTION art_quick_lmod 789 subl LITERAL(12), %esp // alignment padding 790 CFI_ADJUST_CFA_OFFSET(12) 791 PUSH ebx // pass arg4 b.hi 792 PUSH edx // pass arg3 b.lo 793 PUSH ecx // pass arg2 a.hi 794 PUSH eax // pass arg1 a.lo 795 SETUP_GOT_NOSAVE // clobbers EBX 796 call PLT_SYMBOL(artLmod) // (jlong a, jlong b) 797 addl LITERAL(28), %esp // pop arguments 798 CFI_ADJUST_CFA_OFFSET(-28) 799 ret 800END_FUNCTION art_quick_lmod 801 802DEFINE_FUNCTION art_quick_lmul 803 imul %eax, %ebx // ebx = a.lo(eax) * b.hi(ebx) 804 imul %edx, %ecx // ecx = b.lo(edx) * a.hi(ecx) 805 mul %edx // edx:eax = a.lo(eax) * b.lo(edx) 806 add %ebx, %ecx 807 add %ecx, %edx // edx += (a.lo * b.hi) + (b.lo * a.hi) 808 ret 809END_FUNCTION art_quick_lmul 810 811DEFINE_FUNCTION art_quick_lshl 812 // ecx:eax << edx 813 xchg %edx, %ecx 814 shld %cl,%eax,%edx 815 shl %cl,%eax 816 test LITERAL(32), %cl 817 jz 1f 818 mov %eax, %edx 819 xor %eax, %eax 8201: 821 ret 822END_FUNCTION art_quick_lshl 823 824DEFINE_FUNCTION art_quick_lshr 825 // ecx:eax >> edx 826 xchg %edx, %ecx 827 shrd %cl,%edx,%eax 828 sar %cl,%edx 829 test LITERAL(32),%cl 830 jz 1f 831 mov %edx, %eax 832 sar LITERAL(31), %edx 8331: 834 ret 835END_FUNCTION art_quick_lshr 836 837DEFINE_FUNCTION art_quick_lushr 838 // ecx:eax >>> edx 839 xchg %edx, %ecx 840 shrd %cl,%edx,%eax 841 shr %cl,%edx 842 test LITERAL(32),%cl 843 jz 1f 844 mov %edx, %eax 845 xor %edx, %edx 8461: 847 ret 848END_FUNCTION art_quick_lushr 849 850DEFINE_FUNCTION art_quick_set32_instance 851 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 852 mov %esp, %ebx // remember SP 853 subl LITERAL(8), %esp // alignment padding 854 CFI_ADJUST_CFA_OFFSET(8) 855 PUSH ebx // pass SP 856 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 857 CFI_ADJUST_CFA_OFFSET(4) 858 mov 32(%ebx), %ebx // get referrer 859 PUSH ebx // pass referrer 860 PUSH edx // pass new_val 861 PUSH ecx // pass object 862 PUSH eax // pass field_idx 863 SETUP_GOT_NOSAVE // clobbers EBX 864 call PLT_SYMBOL(artSet32InstanceFromCode) // (field_idx, Object*, new_val, referrer, Thread*, SP) 865 addl LITERAL(32), %esp // pop arguments 866 CFI_ADJUST_CFA_OFFSET(-32) 867 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 868 RETURN_IF_EAX_ZERO // return or deliver exception 869END_FUNCTION art_quick_set32_instance 870 871DEFINE_FUNCTION art_quick_set64_instance 872 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 873 subl LITERAL(8), %esp // alignment padding 874 CFI_ADJUST_CFA_OFFSET(8) 875 PUSH esp // pass SP-8 876 addl LITERAL(8), (%esp) // fix SP on stack by adding 8 877 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 878 CFI_ADJUST_CFA_OFFSET(4) 879 PUSH ebx // pass high half of new_val 880 PUSH edx // pass low half of new_val 881 PUSH ecx // pass object 882 PUSH eax // pass field_idx 883 SETUP_GOT_NOSAVE // clobbers EBX 884 call PLT_SYMBOL(artSet64InstanceFromCode) // (field_idx, Object*, new_val, Thread*, SP) 885 addl LITERAL(32), %esp // pop arguments 886 CFI_ADJUST_CFA_OFFSET(-32) 887 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 888 RETURN_IF_EAX_ZERO // return or deliver exception 889END_FUNCTION art_quick_set64_instance 890 891DEFINE_FUNCTION art_quick_set_obj_instance 892 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 893 mov %esp, %ebx // remember SP 894 subl LITERAL(8), %esp // alignment padding 895 CFI_ADJUST_CFA_OFFSET(8) 896 PUSH ebx // pass SP 897 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 898 CFI_ADJUST_CFA_OFFSET(4) 899 mov 32(%ebx), %ebx // get referrer 900 PUSH ebx // pass referrer 901 PUSH edx // pass new_val 902 PUSH ecx // pass object 903 PUSH eax // pass field_idx 904 SETUP_GOT_NOSAVE // clobbers EBX 905 call PLT_SYMBOL(artSetObjInstanceFromCode) // (field_idx, Object*, new_val, referrer, Thread*, SP) 906 addl LITERAL(32), %esp // pop arguments 907 CFI_ADJUST_CFA_OFFSET(-32) 908 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 909 RETURN_IF_EAX_ZERO // return or deliver exception 910END_FUNCTION art_quick_set_obj_instance 911 912DEFINE_FUNCTION art_quick_get32_instance 913 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 914 mov %esp, %ebx // remember SP 915 mov 32(%esp), %edx // get referrer 916 subl LITERAL(12), %esp // alignment padding 917 CFI_ADJUST_CFA_OFFSET(12) 918 PUSH ebx // pass SP 919 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 920 CFI_ADJUST_CFA_OFFSET(4) 921 PUSH edx // pass referrer 922 PUSH ecx // pass object 923 PUSH eax // pass field_idx 924 SETUP_GOT_NOSAVE // clobbers EBX 925 call PLT_SYMBOL(artGet32InstanceFromCode) // (field_idx, Object*, referrer, Thread*, SP) 926 addl LITERAL(32), %esp // pop arguments 927 CFI_ADJUST_CFA_OFFSET(-32) 928 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 929 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 930END_FUNCTION art_quick_get32_instance 931 932DEFINE_FUNCTION art_quick_get64_instance 933 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 934 mov %esp, %ebx // remember SP 935 mov 32(%esp), %edx // get referrer 936 subl LITERAL(12), %esp // alignment padding 937 CFI_ADJUST_CFA_OFFSET(12) 938 PUSH ebx // pass SP 939 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 940 CFI_ADJUST_CFA_OFFSET(4) 941 PUSH edx // pass referrer 942 PUSH ecx // pass object 943 PUSH eax // pass field_idx 944 SETUP_GOT_NOSAVE // clobbers EBX 945 call PLT_SYMBOL(artGet64InstanceFromCode) // (field_idx, Object*, referrer, Thread*, SP) 946 addl LITERAL(32), %esp // pop arguments 947 CFI_ADJUST_CFA_OFFSET(-32) 948 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 949 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 950END_FUNCTION art_quick_get64_instance 951 952DEFINE_FUNCTION art_quick_get_obj_instance 953 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 954 mov %esp, %ebx // remember SP 955 mov 32(%esp), %edx // get referrer 956 subl LITERAL(12), %esp // alignment padding 957 CFI_ADJUST_CFA_OFFSET(12) 958 PUSH ebx // pass SP 959 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 960 CFI_ADJUST_CFA_OFFSET(4) 961 PUSH edx // pass referrer 962 PUSH ecx // pass object 963 PUSH eax // pass field_idx 964 SETUP_GOT_NOSAVE // clobbers EBX 965 call PLT_SYMBOL(artGetObjInstanceFromCode) // (field_idx, Object*, referrer, Thread*, SP) 966 addl LITERAL(32), %esp // pop arguments 967 CFI_ADJUST_CFA_OFFSET(-32) 968 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 969 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 970END_FUNCTION art_quick_get_obj_instance 971 972DEFINE_FUNCTION art_quick_set32_static 973 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 974 mov %esp, %ebx // remember SP 975 mov 32(%esp), %edx // get referrer 976 subl LITERAL(12), %esp // alignment padding 977 CFI_ADJUST_CFA_OFFSET(12) 978 PUSH ebx // pass SP 979 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 980 CFI_ADJUST_CFA_OFFSET(4) 981 PUSH edx // pass referrer 982 PUSH ecx // pass new_val 983 PUSH eax // pass field_idx 984 SETUP_GOT_NOSAVE // clobbers EBX 985 call PLT_SYMBOL(artSet32StaticFromCode) // (field_idx, new_val, referrer, Thread*, SP) 986 addl LITERAL(32), %esp // pop arguments 987 CFI_ADJUST_CFA_OFFSET(-32) 988 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 989 RETURN_IF_EAX_ZERO // return or deliver exception 990END_FUNCTION art_quick_set32_static 991 992DEFINE_FUNCTION art_quick_set64_static 993 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 994 mov %esp, %ebx // remember SP 995 subl LITERAL(8), %esp // alignment padding 996 CFI_ADJUST_CFA_OFFSET(8) 997 PUSH ebx // pass SP 998 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 999 CFI_ADJUST_CFA_OFFSET(4) 1000 mov 32(%ebx), %ebx // get referrer 1001 PUSH edx // pass high half of new_val 1002 PUSH ecx // pass low half of new_val 1003 PUSH ebx // pass referrer 1004 PUSH eax // pass field_idx 1005 SETUP_GOT_NOSAVE // clobbers EBX 1006 call PLT_SYMBOL(artSet64StaticFromCode) // (field_idx, referrer, new_val, Thread*, SP) 1007 addl LITERAL(32), %esp // pop arguments 1008 CFI_ADJUST_CFA_OFFSET(-32) 1009 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 1010 RETURN_IF_EAX_ZERO // return or deliver exception 1011END_FUNCTION art_quick_set64_static 1012 1013DEFINE_FUNCTION art_quick_set_obj_static 1014 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 1015 mov %esp, %ebx // remember SP 1016 mov 32(%esp), %edx // get referrer 1017 subl LITERAL(12), %esp // alignment padding 1018 CFI_ADJUST_CFA_OFFSET(12) 1019 PUSH ebx // pass SP 1020 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1021 CFI_ADJUST_CFA_OFFSET(4) 1022 PUSH edx // pass referrer 1023 PUSH ecx // pass new_val 1024 PUSH eax // pass field_idx 1025 SETUP_GOT_NOSAVE // clobbers EBX 1026 call PLT_SYMBOL(artSetObjStaticFromCode) // (field_idx, new_val, referrer, Thread*, SP) 1027 addl LITERAL(32), %esp // pop arguments 1028 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 1029 RETURN_IF_EAX_ZERO // return or deliver exception 1030END_FUNCTION art_quick_set_obj_static 1031 1032DEFINE_FUNCTION art_quick_get32_static 1033 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 1034 mov %esp, %edx // remember SP 1035 mov 32(%esp), %ecx // get referrer 1036 PUSH edx // pass SP 1037 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1038 CFI_ADJUST_CFA_OFFSET(4) 1039 PUSH ecx // pass referrer 1040 PUSH eax // pass field_idx 1041 SETUP_GOT_NOSAVE // clobbers EBX 1042 call PLT_SYMBOL(artGet32StaticFromCode) // (field_idx, referrer, Thread*, SP) 1043 addl LITERAL(16), %esp // pop arguments 1044 CFI_ADJUST_CFA_OFFSET(-16) 1045 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 1046 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 1047END_FUNCTION art_quick_get32_static 1048 1049DEFINE_FUNCTION art_quick_get64_static 1050 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 1051 mov %esp, %edx // remember SP 1052 mov 32(%esp), %ecx // get referrer 1053 PUSH edx // pass SP 1054 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1055 CFI_ADJUST_CFA_OFFSET(4) 1056 PUSH ecx // pass referrer 1057 PUSH eax // pass field_idx 1058 SETUP_GOT_NOSAVE // clobbers EBX 1059 call PLT_SYMBOL(artGet64StaticFromCode) // (field_idx, referrer, Thread*, SP) 1060 addl LITERAL(16), %esp // pop arguments 1061 CFI_ADJUST_CFA_OFFSET(-16) 1062 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 1063 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 1064END_FUNCTION art_quick_get64_static 1065 1066DEFINE_FUNCTION art_quick_get_obj_static 1067 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 1068 mov %esp, %edx // remember SP 1069 mov 32(%esp), %ecx // get referrer 1070 PUSH edx // pass SP 1071 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1072 CFI_ADJUST_CFA_OFFSET(4) 1073 PUSH ecx // pass referrer 1074 PUSH eax // pass field_idx 1075 SETUP_GOT_NOSAVE // clobbers EBX 1076 call PLT_SYMBOL(artGetObjStaticFromCode) // (field_idx, referrer, Thread*, SP) 1077 addl LITERAL(16), %esp // pop arguments 1078 CFI_ADJUST_CFA_OFFSET(-16) 1079 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 1080 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 1081END_FUNCTION art_quick_get_obj_static 1082 1083DEFINE_FUNCTION art_quick_proxy_invoke_handler 1084 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME // save frame and Method* 1085 PUSH esp // pass SP 1086 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1087 CFI_ADJUST_CFA_OFFSET(4) 1088 PUSH ecx // pass receiver 1089 PUSH eax // pass proxy method 1090 SETUP_GOT_NOSAVE // clobbers EBX 1091 call PLT_SYMBOL(artQuickProxyInvokeHandler) // (proxy method, receiver, Thread*, SP) 1092 movd %eax, %xmm0 // place return value also into floating point return value 1093 movd %edx, %xmm1 1094 punpckldq %xmm1, %xmm0 1095 addl LITERAL(44), %esp // pop arguments 1096 CFI_ADJUST_CFA_OFFSET(-44) 1097 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 1098END_FUNCTION art_quick_proxy_invoke_handler 1099 1100 /* 1101 * Called to resolve an imt conflict. xmm0 is a hidden argument that holds the target method's 1102 * dex method index. 1103 */ 1104DEFINE_FUNCTION art_quick_imt_conflict_trampoline 1105 PUSH ecx 1106 movl 8(%esp), %eax // load caller Method* 1107 movl METHOD_DEX_CACHE_METHODS_OFFSET(%eax), %eax // load dex_cache_resolved_methods 1108 movd %xmm0, %ecx // get target method index stored in xmm0 1109 movl OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4), %eax // load the target method 1110 POP ecx 1111 jmp art_quick_invoke_interface_trampoline 1112END_FUNCTION art_quick_imt_conflict_trampoline 1113 1114DEFINE_FUNCTION art_quick_resolution_trampoline 1115 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME 1116 PUSH esp // pass SP 1117 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1118 CFI_ADJUST_CFA_OFFSET(4) 1119 PUSH ecx // pass receiver 1120 PUSH eax // pass method 1121 SETUP_GOT_NOSAVE // clobbers EBX 1122 call PLT_SYMBOL(artQuickResolutionTrampoline) // (Method* called, receiver, Thread*, SP) 1123 movl %eax, %edi // remember code pointer in EDI 1124 addl LITERAL(16), %esp // pop arguments 1125 test %eax, %eax // if code pointer is NULL goto deliver pending exception 1126 jz 1f 1127 POP eax // called method 1128 POP ecx // restore args 1129 POP edx 1130 POP ebx 1131 POP ebp // restore callee saves except EDI 1132 POP esi 1133 xchgl 0(%esp),%edi // restore EDI and place code pointer as only value on stack 1134 ret // tail call into method 11351: 1136 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME 1137 DELIVER_PENDING_EXCEPTION 1138END_FUNCTION art_quick_resolution_trampoline 1139 1140DEFINE_FUNCTION art_quick_to_interpreter_bridge 1141 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME // save frame 1142 mov %esp, %edx // remember SP 1143 PUSH eax // alignment padding 1144 PUSH edx // pass SP 1145 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1146 CFI_ADJUST_CFA_OFFSET(4) 1147 PUSH eax // pass method 1148 SETUP_GOT_NOSAVE // clobbers EBX 1149 call PLT_SYMBOL(artQuickToInterpreterBridge) // (method, Thread*, SP) 1150 movd %eax, %xmm0 // place return value also into floating point return value 1151 movd %edx, %xmm1 1152 punpckldq %xmm1, %xmm0 1153 addl LITERAL(16), %esp // pop arguments 1154 CFI_ADJUST_CFA_OFFSET(-16) 1155 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME 1156 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 1157END_FUNCTION art_quick_to_interpreter_bridge 1158 1159 /* 1160 * Routine that intercepts method calls and returns. 1161 */ 1162DEFINE_FUNCTION art_quick_instrumentation_entry 1163 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME 1164 movl %esp, %edx // Save SP. 1165 PUSH eax // Save eax which will be clobbered by the callee-save method. 1166 subl LITERAL(8), %esp // Align stack. 1167 CFI_ADJUST_CFA_OFFSET(8) 1168 pushl 40(%esp) // Pass LR. 1169 CFI_ADJUST_CFA_OFFSET(4) 1170 PUSH edx // Pass SP. 1171 pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current(). 1172 CFI_ADJUST_CFA_OFFSET(4) 1173 PUSH ecx // Pass receiver. 1174 PUSH eax // Pass Method*. 1175 SETUP_GOT_NOSAVE // clobbers EBX 1176 call SYMBOL(artInstrumentationMethodEntryFromCode) // (Method*, Object*, Thread*, SP, LR) 1177 addl LITERAL(28), %esp // Pop arguments upto saved Method*. 1178 movl 28(%esp), %edi // Restore edi. 1179 movl %eax, 28(%esp) // Place code* over edi, just under return pc. 1180 movl LITERAL(SYMBOL(art_quick_instrumentation_exit)), 32(%esp) 1181 // Place instrumentation exit as return pc. 1182 movl (%esp), %eax // Restore eax. 1183 movl 8(%esp), %ecx // Restore ecx. 1184 movl 12(%esp), %edx // Restore edx. 1185 movl 16(%esp), %ebx // Restore ebx. 1186 movl 20(%esp), %ebp // Restore ebp. 1187 movl 24(%esp), %esi // Restore esi. 1188 addl LITERAL(28), %esp // Wind stack back upto code*. 1189 ret // Call method (and pop). 1190END_FUNCTION art_quick_instrumentation_entry 1191 1192DEFINE_FUNCTION art_quick_instrumentation_exit 1193 pushl LITERAL(0) // Push a fake return PC as there will be none on the stack. 1194 SETUP_REF_ONLY_CALLEE_SAVE_FRAME 1195 mov %esp, %ecx // Remember SP 1196 subl LITERAL(8), %esp // Save float return value. 1197 CFI_ADJUST_CFA_OFFSET(8) 1198 movd %xmm0, (%esp) 1199 PUSH edx // Save gpr return value. 1200 PUSH eax 1201 subl LITERAL(8), %esp // Align stack 1202 movd %xmm0, (%esp) 1203 subl LITERAL(8), %esp // Pass float return value. 1204 CFI_ADJUST_CFA_OFFSET(8) 1205 movd %xmm0, (%esp) 1206 PUSH edx // Pass gpr return value. 1207 PUSH eax 1208 PUSH ecx // Pass SP. 1209 pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current. 1210 CFI_ADJUST_CFA_OFFSET(4) 1211 SETUP_GOT_NOSAVE // clobbers EBX 1212 call PLT_SYMBOL(artInstrumentationMethodExitFromCode) // (Thread*, SP, gpr_result, fpr_result) 1213 mov %eax, %ecx // Move returned link register. 1214 addl LITERAL(32), %esp // Pop arguments. 1215 CFI_ADJUST_CFA_OFFSET(-32) 1216 movl %edx, %ebx // Move returned link register for deopt 1217 // (ebx is pretending to be our LR). 1218 POP eax // Restore gpr return value. 1219 POP edx 1220 movd (%esp), %xmm0 // Restore fpr return value. 1221 addl LITERAL(8), %esp 1222 CFI_ADJUST_CFA_OFFSET(-8) 1223 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME 1224 addl LITERAL(4), %esp // Remove fake return pc. 1225 jmp *%ecx // Return. 1226END_FUNCTION art_quick_instrumentation_exit 1227 1228 /* 1229 * Instrumentation has requested that we deoptimize into the interpreter. The deoptimization 1230 * will long jump to the upcall with a special exception of -1. 1231 */ 1232DEFINE_FUNCTION art_quick_deoptimize 1233 pushl %ebx // Fake that we were called. 1234 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME 1235 mov %esp, %ecx // Remember SP. 1236 subl LITERAL(8), %esp // Align stack. 1237 CFI_ADJUST_CFA_OFFSET(8) 1238 PUSH ecx // Pass SP. 1239 pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current(). 1240 CFI_ADJUST_CFA_OFFSET(4) 1241 SETUP_GOT_NOSAVE // clobbers EBX 1242 call PLT_SYMBOL(artDeoptimize) // artDeoptimize(Thread*, SP) 1243 int3 // Unreachable. 1244END_FUNCTION art_quick_deoptimize 1245 1246 /* 1247 * String's indexOf. 1248 * 1249 * On entry: 1250 * eax: string object (known non-null) 1251 * ecx: char to match (known <= 0xFFFF) 1252 * edx: Starting offset in string data 1253 */ 1254DEFINE_FUNCTION art_quick_indexof 1255 PUSH edi // push callee save reg 1256 mov STRING_COUNT_OFFSET(%eax), %ebx 1257 mov STRING_VALUE_OFFSET(%eax), %edi 1258 mov STRING_OFFSET_OFFSET(%eax), %eax 1259 testl %edx, %edx // check if start < 0 1260 jl clamp_min 1261clamp_done: 1262 cmpl %ebx, %edx // check if start >= count 1263 jge not_found 1264 lea STRING_DATA_OFFSET(%edi, %eax, 2), %edi // build a pointer to the start of string data 1265 mov %edi, %eax // save a copy in eax to later compute result 1266 lea (%edi, %edx, 2), %edi // build pointer to start of data to compare 1267 subl %edx, %ebx // compute iteration count 1268 /* 1269 * At this point we have: 1270 * eax: original start of string data 1271 * ecx: char to compare 1272 * ebx: length to compare 1273 * edi: start of data to test 1274 */ 1275 mov %eax, %edx 1276 mov %ecx, %eax // put char to match in %eax 1277 mov %ebx, %ecx // put length to compare in %ecx 1278 repne scasw // find %ax, starting at [%edi], up to length %ecx 1279 jne not_found 1280 subl %edx, %edi 1281 sar LITERAL(1), %edi 1282 decl %edi // index = ((curr_ptr - orig_ptr) / 2) - 1 1283 mov %edi, %eax 1284 POP edi // pop callee save reg 1285 ret 1286 .balign 16 1287not_found: 1288 mov LITERAL(-1), %eax // return -1 (not found) 1289 POP edi // pop callee save reg 1290 ret 1291clamp_min: 1292 xor %edx, %edx // clamp start to 0 1293 jmp clamp_done 1294END_FUNCTION art_quick_indexof 1295 1296 /* 1297 * String's compareTo. 1298 * 1299 * On entry: 1300 * eax: this string object (known non-null) 1301 * ecx: comp string object (known non-null) 1302 */ 1303DEFINE_FUNCTION art_quick_string_compareto 1304 PUSH esi // push callee save reg 1305 PUSH edi // push callee save reg 1306 mov STRING_COUNT_OFFSET(%eax), %edx 1307 mov STRING_COUNT_OFFSET(%ecx), %ebx 1308 mov STRING_VALUE_OFFSET(%eax), %esi 1309 mov STRING_VALUE_OFFSET(%ecx), %edi 1310 mov STRING_OFFSET_OFFSET(%eax), %eax 1311 mov STRING_OFFSET_OFFSET(%ecx), %ecx 1312 /* Build pointers to the start of string data */ 1313 lea STRING_DATA_OFFSET(%esi, %eax, 2), %esi 1314 lea STRING_DATA_OFFSET(%edi, %ecx, 2), %edi 1315 /* Calculate min length and count diff */ 1316 mov %edx, %ecx 1317 mov %edx, %eax 1318 subl %ebx, %eax 1319 cmovg %ebx, %ecx 1320 /* 1321 * At this point we have: 1322 * eax: value to return if first part of strings are equal 1323 * ecx: minimum among the lengths of the two strings 1324 * esi: pointer to this string data 1325 * edi: pointer to comp string data 1326 */ 1327 repe cmpsw // find nonmatching chars in [%esi] and [%edi], up to length %ecx 1328 jne not_equal 1329 POP edi // pop callee save reg 1330 POP esi // pop callee save reg 1331 ret 1332 .balign 16 1333not_equal: 1334 movzwl -2(%esi), %eax // get last compared char from this string 1335 movzwl -2(%edi), %ecx // get last compared char from comp string 1336 subl %ecx, %eax // return the difference 1337 POP edi // pop callee save reg 1338 POP esi // pop callee save reg 1339 ret 1340END_FUNCTION art_quick_string_compareto 1341 1342 // TODO: implement these! 1343UNIMPLEMENTED art_quick_memcmp16 1344