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