quick_entrypoints_x86.S revision 166db04e259ca51838c311891598664deeed85ad
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.h" 18 19#if defined(__APPLE__) 20 // Mac OS' as(1) doesn't let you name macro parameters. 21 #define MACRO0(macro_name) .macro macro_name 22 #define MACRO1(macro_name, macro_arg1) .macro macro_name 23 #define MACRO2(macro_name, macro_arg1, macro_args2) .macro macro_name 24 #define MACRO3(macro_name, macro_arg1, macro_args2, macro_args3) .macro macro_name 25 #define END_MACRO .endmacro 26 27 // Mac OS' as(1) uses $0, $1, and so on for macro arguments, and function names 28 // are mangled with an extra underscore prefix. The use of $x for arguments 29 // mean that literals need to be represented with $$x in macros. 30 #define SYMBOL(name) _ ## name 31 #define VAR(name,index) SYMBOL($index) 32 #define REG_VAR(name,index) %$index 33 #define CALL_MACRO(name,index) $index 34 #define LITERAL(value) $value 35 #define MACRO_LITERAL(value) $$value 36#else 37 // Regular gas(1) lets you name macro parameters. 38 #define MACRO0(macro_name) .macro macro_name 39 #define MACRO1(macro_name, macro_arg1) .macro macro_name macro_arg1 40 #define MACRO2(macro_name, macro_arg1, macro_arg2) .macro macro_name macro_arg1, macro_arg2 41 #define MACRO3(macro_name, macro_arg1, macro_arg2, macro_arg3) .macro macro_name macro_arg1, macro_arg2, macro_arg3 42 #define END_MACRO .endm 43 44 // Regular gas(1) uses \argument_name for macro arguments. 45 // We need to turn on alternate macro syntax so we can use & instead or the preprocessor 46 // will screw us by inserting a space between the \ and the name. Even in this mode there's 47 // no special meaning to $, so literals are still just $x. The use of altmacro means % is a 48 // special character meaning care needs to be taken when passing registers as macro arguments. 49 .altmacro 50 #define SYMBOL(name) name 51 #define VAR(name,index) name& 52 #define REG_VAR(name,index) %name 53 #define CALL_MACRO(name,index) name& 54 #define LITERAL(value) $value 55 #define MACRO_LITERAL(value) $value 56#endif 57 58 /* Cache alignment for function entry */ 59MACRO0(ALIGN_FUNCTION_ENTRY) 60 .balign 16 61END_MACRO 62 63MACRO1(DEFINE_FUNCTION, c_name) 64 .type VAR(c_name, 0), @function 65 .globl VAR(c_name, 0) 66 ALIGN_FUNCTION_ENTRY 67VAR(c_name, 0): 68 .cfi_startproc 69END_MACRO 70 71MACRO1(END_FUNCTION, c_name) 72 .cfi_endproc 73 .size \c_name, .-\c_name 74END_MACRO 75 76MACRO1(PUSH, reg) 77 pushl REG_VAR(reg, 0) 78 .cfi_adjust_cfa_offset 4 79 .cfi_rel_offset REG_VAR(reg, 0), 0 80END_MACRO 81 82MACRO1(POP, reg) 83 popl REG_VAR(reg,0) 84 .cfi_adjust_cfa_offset -4 85 .cfi_restore REG_VAR(reg,0) 86END_MACRO 87 88 /* 89 * Macro that sets up the callee save frame to conform with 90 * Runtime::CreateCalleeSaveMethod(kSaveAll) 91 */ 92MACRO0(SETUP_SAVE_ALL_CALLEE_SAVE_FRAME) 93 PUSH edi // Save callee saves (ebx is saved/restored by the upcall) 94 PUSH esi 95 PUSH ebp 96 subl MACRO_LITERAL(16), %esp // Grow stack by 4 words, bottom word will hold Method* 97 .cfi_adjust_cfa_offset 16 98END_MACRO 99 100 /* 101 * Macro that sets up the callee save frame to conform with 102 * Runtime::CreateCalleeSaveMethod(kRefsOnly) 103 */ 104MACRO0(SETUP_REF_ONLY_CALLEE_SAVE_FRAME) 105 PUSH edi // Save callee saves (ebx is saved/restored by the upcall) 106 PUSH esi 107 PUSH ebp 108 subl MACRO_LITERAL(16), %esp // Grow stack by 4 words, bottom word will hold Method* 109 .cfi_adjust_cfa_offset 16 110END_MACRO 111 112MACRO0(RESTORE_REF_ONLY_CALLEE_SAVE_FRAME) 113 addl MACRO_LITERAL(28), %esp // Unwind stack up to return address 114 .cfi_adjust_cfa_offset -28 115END_MACRO 116 117 /* 118 * Macro that sets up the callee save frame to conform with 119 * Runtime::CreateCalleeSaveMethod(kRefsAndArgs) 120 */ 121MACRO0(SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME) 122 PUSH edi // Save callee saves 123 PUSH esi 124 PUSH ebp 125 PUSH ebx // Save args 126 PUSH edx 127 PUSH ecx 128 PUSH eax // Align stack, eax will be clobbered by Method* 129END_MACRO 130 131MACRO0(RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME) 132 addl MACRO_LITERAL(4), %esp // Remove padding 133 .cfi_adjust_cfa_offset -4 134 POP ecx // Restore args except eax 135 POP edx 136 POP ebx 137 POP ebp // Restore callee saves 138 POP esi 139 POP edi 140END_MACRO 141 142 /* 143 * Macro that set calls through to artDeliverPendingExceptionFromCode, where the pending 144 * exception is Thread::Current()->exception_. 145 */ 146MACRO0(DELIVER_PENDING_EXCEPTION) 147 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save callee saves for throw 148 mov %esp, %ecx 149 // Outgoing argument set up 150 subl MACRO_LITERAL(8), %esp // Alignment padding 151 .cfi_adjust_cfa_offset 8 152 PUSH ecx // pass SP 153 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 154 .cfi_adjust_cfa_offset 4 155 call SYMBOL(artDeliverPendingExceptionFromCode) // artDeliverPendingExceptionFromCode(Thread*, SP) 156 int3 // unreached 157END_MACRO 158 159MACRO2(NO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name) 160 DEFINE_FUNCTION VAR(c_name, 0) 161 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context 162 mov %esp, %ecx 163 // Outgoing argument set up 164 subl MACRO_LITERAL(8), %esp // alignment padding 165 .cfi_adjust_cfa_offset 8 166 PUSH ecx // pass SP 167 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 168 .cfi_adjust_cfa_offset 4 169 call VAR(cxx_name, 1) // cxx_name(Thread*, SP) 170 int3 // unreached 171 END_FUNCTION VAR(c_name, 0) 172END_MACRO 173 174MACRO2(ONE_ARG_RUNTIME_EXCEPTION, c_name, cxx_name) 175 DEFINE_FUNCTION VAR(c_name, 0) 176 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context 177 mov %esp, %ecx 178 // Outgoing argument set up 179 PUSH eax // alignment padding 180 PUSH ecx // pass SP 181 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 182 .cfi_adjust_cfa_offset 4 183 PUSH eax // pass arg1 184 call VAR(cxx_name, 1) // cxx_name(arg1, Thread*, SP) 185 int3 // unreached 186 END_FUNCTION VAR(c_name, 0) 187END_MACRO 188 189MACRO2(TWO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name) 190 DEFINE_FUNCTION VAR(c_name, 0) 191 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context 192 mov %esp, %edx 193 // Outgoing argument set up 194 PUSH edx // pass SP 195 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 196 .cfi_adjust_cfa_offset 4 197 PUSH ecx // pass arg2 198 PUSH eax // pass arg1 199 call VAR(cxx_name, 1) // cxx_name(arg1, arg2, Thread*, SP) 200 int3 // unreached 201 END_FUNCTION VAR(c_name, 0) 202END_MACRO 203 204 /* 205 * Called by managed code to create and deliver a NullPointerException. 206 */ 207NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception_from_code, artThrowNullPointerExceptionFromCode 208 209 /* 210 * Called by managed code to create and deliver an ArithmeticException. 211 */ 212NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero_from_code, artThrowDivZeroFromCode 213 214 /* 215 * Called by managed code to create and deliver a StackOverflowError. 216 */ 217NO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow_from_code, artThrowStackOverflowFromCode 218 219 /* 220 * Called by managed code, saves callee saves and then calls artThrowException 221 * that will place a mock Method* at the bottom of the stack. Arg1 holds the exception. 222 */ 223ONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception_from_code, artDeliverExceptionFromCode 224 225 /* 226 * Called by managed code to create and deliver a NoSuchMethodError. 227 */ 228ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method_from_code, artThrowNoSuchMethodFromCode 229 230 /* 231 * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds 232 * index, arg2 holds limit. 233 */ 234TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds_from_code, artThrowArrayBoundsFromCode 235 236 /* 237 * All generated callsites for interface invokes and invocation slow paths will load arguments 238 * as usual - except instead of loading arg0/r0 with the target Method*, arg0/r0 will contain 239 * the method_idx. This wrapper will save arg1-arg3, load the caller's Method*, align the 240 * stack and call the appropriate C helper. 241 * NOTE: "this" is first visible argument of the target, and so can be found in arg1/r1. 242 * 243 * The helper will attempt to locate the target and return a 64-bit result in r0/r1 consisting 244 * of the target Method* in r0 and method->code_ in r1. 245 * 246 * If unsuccessful, the helper will return NULL/NULL. There will bea pending exception in the 247 * thread and we branch to another stub to deliver it. 248 * 249 * On success this wrapper will restore arguments and *jump* to the target, leaving the lr 250 * pointing back to the original caller. 251 */ 252MACRO2(INVOKE_TRAMPOLINE, c_name, cxx_name) 253 DEFINE_FUNCTION VAR(c_name, 0) 254 // Set up the callee save frame to conform with Runtime::CreateCalleeSaveMethod(kRefsAndArgs) 255 // return address 256 PUSH edi 257 PUSH esi 258 PUSH ebp 259 PUSH ebx 260 PUSH edx 261 PUSH ecx 262 PUSH eax // <-- callee save Method* to go here 263 movl %esp, %edx // remember SP 264 // Outgoing argument set up 265 subl MACRO_LITERAL(12), %esp // alignment padding 266 .cfi_adjust_cfa_offset 12 267 PUSH edx // pass SP 268 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 269 .cfi_adjust_cfa_offset 4 270 pushl 32(%edx) // pass caller Method* 271 .cfi_adjust_cfa_offset 4 272 PUSH ecx // pass arg2 273 PUSH eax // pass arg1 274 call VAR(cxx_name, 1) // cxx_name(arg1, arg2, arg3, Thread*, SP) 275 movl %edx, %edi // save code pointer in EDI 276 addl MACRO_LITERAL(36), %esp // Pop arguments skip eax 277 .cfi_adjust_cfa_offset -36 278 POP ecx // Restore args 279 POP edx 280 POP ebx 281 POP ebp // Restore callee saves. 282 POP esi 283 // Swap EDI callee save with code pointer. 284 xchgl %edi, (%esp) 285 testl %eax, %eax // Branch forward if exception pending. 286 jz 1f 287 // Tail call to intended method. 288 ret 2891: 290 addl MACRO_LITERAL(4), %esp // Pop code pointer off stack 291 .cfi_adjust_cfa_offset -4 292 DELIVER_PENDING_EXCEPTION 293 END_FUNCTION VAR(c_name, 0) 294END_MACRO 295 296INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline, artInvokeInterfaceTrampoline 297INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck 298 299INVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck 300INVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck 301INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck 302INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck 303 304 /* 305 * Portable invocation stub. 306 * On entry: 307 * [sp] = return address 308 * [sp + 4] = method pointer 309 * [sp + 8] = argument array or NULL for no argument methods 310 * [sp + 12] = size of argument array in bytes 311 * [sp + 16] = (managed) thread pointer 312 * [sp + 20] = JValue* result 313 * [sp + 24] = result type char 314 */ 315DEFINE_FUNCTION art_portable_invoke_stub 316 PUSH ebp // save ebp 317 PUSH ebx // save ebx 318 mov %esp, %ebp // copy value of stack pointer into base pointer 319 .cfi_def_cfa_register ebp 320 mov 20(%ebp), %ebx // get arg array size 321 addl LITERAL(28), %ebx // reserve space for return addr, method*, ebx, and ebp in frame 322 andl LITERAL(0xFFFFFFF0), %ebx // align frame size to 16 bytes 323 subl LITERAL(12), %ebx // remove space for return address, ebx, and ebp 324 subl %ebx, %esp // reserve stack space for argument array 325 lea 4(%esp), %eax // use stack pointer + method ptr as dest for memcpy 326 pushl 20(%ebp) // push size of region to memcpy 327 pushl 16(%ebp) // push arg array as source of memcpy 328 pushl %eax // push stack pointer as destination of memcpy 329 call SYMBOL(memcpy) // (void*, const void*, size_t) 330 addl LITERAL(12), %esp // pop arguments to memcpy 331 mov 12(%ebp), %eax // move method pointer into eax 332 mov %eax, (%esp) // push method pointer onto stack 333 call *METHOD_CODE_OFFSET(%eax) // call the method 334 mov %ebp, %esp // restore stack pointer 335 POP ebx // pop ebx 336 POP ebp // pop ebp 337 mov 20(%esp), %ecx // get result pointer 338 cmpl LITERAL(68), 24(%esp) // test if result type char == 'D' 339 je return_double_portable 340 cmpl LITERAL(70), 24(%esp) // test if result type char == 'F' 341 je return_float_portable 342 mov %eax, (%ecx) // store the result 343 mov %edx, 4(%ecx) // store the other half of the result 344 ret 345return_double_portable: 346 fstpl (%ecx) // store the floating point result as double 347 ret 348return_float_portable: 349 fstps (%ecx) // store the floating point result as float 350 ret 351END_FUNCTION art_portable_invoke_stub 352 353 /* 354 * Quick invocation stub. 355 * On entry: 356 * [sp] = return address 357 * [sp + 4] = method pointer 358 * [sp + 8] = argument array or NULL for no argument methods 359 * [sp + 12] = size of argument array in bytes 360 * [sp + 16] = (managed) thread pointer 361 * [sp + 20] = JValue* result 362 * [sp + 24] = result type char 363 */ 364DEFINE_FUNCTION art_quick_invoke_stub 365 PUSH ebp // save ebp 366 PUSH ebx // save ebx 367 mov %esp, %ebp // copy value of stack pointer into base pointer 368 .cfi_def_cfa_register ebp 369 mov 20(%ebp), %ebx // get arg array size 370 addl LITERAL(28), %ebx // reserve space for return addr, method*, ebx, and ebp in frame 371 andl LITERAL(0xFFFFFFF0), %ebx // align frame size to 16 bytes 372 subl LITERAL(12), %ebx // remove space for return address, ebx, and ebp 373 subl %ebx, %esp // reserve stack space for argument array 374 lea 4(%esp), %eax // use stack pointer + method ptr as dest for memcpy 375 pushl 20(%ebp) // push size of region to memcpy 376 pushl 16(%ebp) // push arg array as source of memcpy 377 pushl %eax // push stack pointer as destination of memcpy 378 call SYMBOL(memcpy) // (void*, const void*, size_t) 379 addl LITERAL(12), %esp // pop arguments to memcpy 380 movl LITERAL(0), (%esp) // store NULL for method* 381 mov 12(%ebp), %eax // move method pointer into eax 382 mov 4(%esp), %ecx // copy arg1 into ecx 383 mov 8(%esp), %edx // copy arg2 into edx 384 mov 12(%esp), %ebx // copy arg3 into ebx 385 call *METHOD_CODE_OFFSET(%eax) // call the method 386 mov %ebp, %esp // restore stack pointer 387 POP ebx // pop ebx 388 POP ebp // pop ebp 389 mov 20(%esp), %ecx // get result pointer 390 cmpl LITERAL(68), 24(%esp) // test if result type char == 'D' 391 je return_double_quick 392 cmpl LITERAL(70), 24(%esp) // test if result type char == 'F' 393 je return_float_quick 394 mov %eax, (%ecx) // store the result 395 mov %edx, 4(%ecx) // store the other half of the result 396 ret 397return_double_quick: 398return_float_quick: 399 movsd %xmm0, (%ecx) // store the floating point result 400 ret 401END_FUNCTION art_quick_invoke_stub 402 403MACRO3(NO_ARG_DOWNCALL, c_name, cxx_name, return_macro) 404 DEFINE_FUNCTION VAR(c_name, 0) 405 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 406 mov %esp, %edx // remember SP 407 // Outgoing argument set up 408 subl MACRO_LITERAL(8), %esp // push padding 409 .cfi_adjust_cfa_offset 8 410 PUSH edx // pass SP 411 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 412 .cfi_adjust_cfa_offset 4 413 call VAR(cxx_name, 1) // cxx_name(Thread*, SP) 414 addl MACRO_LITERAL(16), %esp // pop arguments 415 .cfi_adjust_cfa_offset -16 416 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 417 CALL_MACRO(return_macro, 2) // return or deliver exception 418 END_FUNCTION VAR(c_name, 0) 419END_MACRO 420 421MACRO3(ONE_ARG_DOWNCALL, c_name, cxx_name, return_macro) 422 DEFINE_FUNCTION VAR(c_name, 0) 423 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 424 mov %esp, %edx // remember SP 425 // Outgoing argument set up 426 PUSH eax // push padding 427 PUSH edx // pass SP 428 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 429 .cfi_adjust_cfa_offset 4 430 PUSH eax // pass arg1 431 call VAR(cxx_name, 1) // cxx_name(arg1, Thread*, SP) 432 addl MACRO_LITERAL(16), %esp // pop arguments 433 .cfi_adjust_cfa_offset -16 434 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 435 CALL_MACRO(return_macro, 2) // return or deliver exception 436 END_FUNCTION VAR(c_name, 0) 437END_MACRO 438 439MACRO3(TWO_ARG_DOWNCALL, c_name, cxx_name, return_macro) 440 DEFINE_FUNCTION VAR(c_name, 0) 441 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 442 mov %esp, %edx // remember SP 443 // Outgoing argument set up 444 PUSH edx // pass SP 445 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 446 .cfi_adjust_cfa_offset 4 447 PUSH ecx // pass arg2 448 PUSH eax // pass arg1 449 call VAR(cxx_name, 1) // cxx_name(arg1, arg2, Thread*, SP) 450 addl MACRO_LITERAL(16), %esp // pop arguments 451 .cfi_adjust_cfa_offset -16 452 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 453 CALL_MACRO(return_macro, 2) // return or deliver exception 454 END_FUNCTION VAR(c_name, 0) 455END_MACRO 456 457MACRO3(THREE_ARG_DOWNCALL, c_name, cxx_name, return_macro) 458 DEFINE_FUNCTION VAR(c_name, 0) 459 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 460 mov %esp, %ebx // remember SP 461 // Outgoing argument set up 462 subl MACRO_LITERAL(12), %esp // alignment padding 463 .cfi_adjust_cfa_offset 12 464 PUSH ebx // pass SP 465 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 466 .cfi_adjust_cfa_offset 4 467 PUSH edx // pass arg3 468 PUSH ecx // pass arg2 469 PUSH eax // pass arg1 470 call VAR(cxx_name, 1) // cxx_name(arg1, arg2, arg3, Thread*, SP) 471 addl MACRO_LITERAL(32), %esp // pop arguments 472 .cfi_adjust_cfa_offset -32 473 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 474 CALL_MACRO(return_macro, 2) // return or deliver exception 475 END_FUNCTION VAR(c_name, 0) 476END_MACRO 477 478MACRO0(RETURN_IF_EAX_NOT_ZERO) 479 testl %eax, %eax // eax == 0 ? 480 jz 1f // if eax == 0 goto 1 481 ret // return 4821: // deliver exception on current thread 483 DELIVER_PENDING_EXCEPTION 484END_MACRO 485 486MACRO0(RETURN_IF_EAX_ZERO) 487 testl %eax, %eax // eax == 0 ? 488 jnz 1f // if eax != 0 goto 1 489 ret // return 4901: // deliver exception on current thread 491 DELIVER_PENDING_EXCEPTION 492END_MACRO 493 494MACRO0(RETURN_OR_DELIVER_PENDING_EXCEPTION) 495 mov %fs:THREAD_EXCEPTION_OFFSET, %ebx // get exception field 496 testl %ebx, %ebx // ebx == 0 ? 497 jnz 1f // if ebx != 0 goto 1 498 ret // return 4991: // deliver exception on current thread 500 DELIVER_PENDING_EXCEPTION 501END_MACRO 502 503TWO_ARG_DOWNCALL art_quick_alloc_object_from_code, artAllocObjectFromCode, RETURN_IF_EAX_NOT_ZERO 504TWO_ARG_DOWNCALL art_quick_alloc_object_from_code_with_access_check, artAllocObjectFromCodeWithAccessCheck, RETURN_IF_EAX_NOT_ZERO 505THREE_ARG_DOWNCALL art_quick_alloc_array_from_code, artAllocArrayFromCode, RETURN_IF_EAX_NOT_ZERO 506THREE_ARG_DOWNCALL art_quick_alloc_array_from_code_with_access_check, artAllocArrayFromCodeWithAccessCheck, RETURN_IF_EAX_NOT_ZERO 507THREE_ARG_DOWNCALL art_quick_check_and_alloc_array_from_code, artCheckAndAllocArrayFromCode, RETURN_IF_EAX_NOT_ZERO 508THREE_ARG_DOWNCALL art_quick_check_and_alloc_array_from_code_with_access_check, artCheckAndAllocArrayFromCodeWithAccessCheck, RETURN_IF_EAX_NOT_ZERO 509 510TWO_ARG_DOWNCALL art_quick_resolve_string_from_code, artResolveStringFromCode, RETURN_IF_EAX_NOT_ZERO 511TWO_ARG_DOWNCALL art_quick_initialize_static_storage_from_code, artInitializeStaticStorageFromCode, RETURN_IF_EAX_NOT_ZERO 512TWO_ARG_DOWNCALL art_quick_initialize_type_from_code, artInitializeTypeFromCode, RETURN_IF_EAX_NOT_ZERO 513TWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access_from_code, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_EAX_NOT_ZERO 514 515ONE_ARG_DOWNCALL art_quick_lock_object_from_code, artLockObjectFromCode, ret 516ONE_ARG_DOWNCALL art_quick_unlock_object_from_code, artUnlockObjectFromCode, RETURN_IF_EAX_ZERO 517 518TWO_ARG_DOWNCALL art_quick_handle_fill_data_from_code, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO 519 520DEFINE_FUNCTION art_quick_is_assignable_from_code 521 PUSH eax // alignment padding 522 PUSH ecx // pass arg2 523 PUSH eax // pass arg1 524 call SYMBOL(artIsAssignableFromCode) // (Class* a, Class* b, Thread*, SP) 525 addl LITERAL(12), %esp // pop arguments 526 .cfi_adjust_cfa_offset -12 527 ret 528END_FUNCTION art_quick_is_assignable_from_code 529 530DEFINE_FUNCTION art_quick_memcpy 531 PUSH edx // pass arg3 532 PUSH ecx // pass arg2 533 PUSH eax // pass arg1 534 call SYMBOL(memcpy) // (void*, const void*, size_t) 535 addl LITERAL(12), %esp // pop arguments 536 .cfi_adjust_cfa_offset -12 537 ret 538END_FUNCTION art_quick_memcpy 539 540TWO_ARG_DOWNCALL art_quick_check_cast_from_code, artCheckCastFromCode, RETURN_IF_EAX_ZERO 541TWO_ARG_DOWNCALL art_quick_can_put_array_element_from_code, artCanPutArrayElementFromCode, RETURN_IF_EAX_ZERO 542 543NO_ARG_DOWNCALL art_quick_test_suspend, artTestSuspendFromCode, ret 544 545DEFINE_FUNCTION art_quick_fmod_from_code 546 subl LITERAL(12), %esp // alignment padding 547 .cfi_adjust_cfa_offset 12 548 PUSH ebx // pass arg4 b.hi 549 PUSH edx // pass arg3 b.lo 550 PUSH ecx // pass arg2 a.hi 551 PUSH eax // pass arg1 a.lo 552 call SYMBOL(fmod) // (jdouble a, jdouble b) 553 fstpl (%esp) // pop return value off fp stack 554 movsd (%esp), %xmm0 // place into %xmm0 555 addl LITERAL(28), %esp // pop arguments 556 .cfi_adjust_cfa_offset -28 557 ret 558END_FUNCTION art_quick_fmod_from_code 559 560DEFINE_FUNCTION art_quick_fmodf_from_code 561 PUSH eax // alignment padding 562 PUSH ecx // pass arg2 b 563 PUSH eax // pass arg1 a 564 call SYMBOL(fmodf) // (jfloat a, jfloat b) 565 fstps (%esp) // pop return value off fp stack 566 movss (%esp), %xmm0 // place into %xmm0 567 addl LITERAL(12), %esp // pop arguments 568 .cfi_adjust_cfa_offset -12 569 ret 570END_FUNCTION art_quick_fmodf_from_code 571 572DEFINE_FUNCTION art_quick_l2d_from_code 573 PUSH ecx // push arg2 a.hi 574 PUSH eax // push arg1 a.lo 575 fildll (%esp) // load as integer and push into st0 576 fstpl (%esp) // pop value off fp stack as double 577 movsd (%esp), %xmm0 // place into %xmm0 578 addl LITERAL(8), %esp // pop arguments 579 .cfi_adjust_cfa_offset -8 580 ret 581END_FUNCTION art_quick_l2d_from_code 582 583DEFINE_FUNCTION art_quick_l2f_from_code 584 PUSH ecx // push arg2 a.hi 585 PUSH eax // push arg1 a.lo 586 fildll (%esp) // load as integer and push into st0 587 fstps (%esp) // pop value off fp stack as a single 588 movss (%esp), %xmm0 // place into %xmm0 589 addl LITERAL(8), %esp // pop argument 590 .cfi_adjust_cfa_offset -8 591 ret 592END_FUNCTION art_quick_l2f_from_code 593 594DEFINE_FUNCTION art_quick_d2l_from_code 595 PUSH eax // alignment padding 596 PUSH ecx // pass arg2 a.hi 597 PUSH eax // pass arg1 a.lo 598 call SYMBOL(art_d2l) // (jdouble a) 599 addl LITERAL(12), %esp // pop arguments 600 .cfi_adjust_cfa_offset -12 601 ret 602END_FUNCTION art_quick_d2l_from_code 603 604DEFINE_FUNCTION art_quick_f2l_from_code 605 subl LITERAL(8), %esp // alignment padding 606 .cfi_adjust_cfa_offset 8 607 PUSH eax // pass arg1 a 608 call SYMBOL(art_f2l) // (jfloat a) 609 addl LITERAL(12), %esp // pop arguments 610 .cfi_adjust_cfa_offset -12 611 ret 612END_FUNCTION art_quick_f2l_from_code 613 614DEFINE_FUNCTION art_quick_idivmod_from_code 615 cmpl LITERAL(0x80000000), %eax 616 je check_arg2 // special case 617args_ok: 618 cdq // edx:eax = sign extend eax 619 idiv %ecx // (edx,eax) = (edx:eax % ecx, edx:eax / ecx) 620 ret 621check_arg2: 622 cmpl LITERAL(-1), %ecx 623 jne args_ok 624 xorl %edx, %edx 625 ret // eax already holds min int 626END_FUNCTION art_quick_idivmod_from_code 627 628DEFINE_FUNCTION art_quick_ldiv_from_code 629 subl LITERAL(12), %esp // alignment padding 630 .cfi_adjust_cfa_offset 12 631 PUSH ebx // pass arg4 b.hi 632 PUSH edx // pass arg3 b.lo 633 PUSH ecx // pass arg2 a.hi 634 PUSH eax // pass arg1 a.lo 635 call SYMBOL(artLdivFromCode) // (jlong a, jlong b) 636 addl LITERAL(28), %esp // pop arguments 637 .cfi_adjust_cfa_offset -28 638 ret 639END_FUNCTION art_quick_ldiv_from_code 640 641DEFINE_FUNCTION art_quick_ldivmod_from_code 642 subl LITERAL(12), %esp // alignment padding 643 .cfi_adjust_cfa_offset 12 644 PUSH ebx // pass arg4 b.hi 645 PUSH edx // pass arg3 b.lo 646 PUSH ecx // pass arg2 a.hi 647 PUSH eax // pass arg1 a.lo 648 call SYMBOL(artLdivmodFromCode) // (jlong a, jlong b) 649 addl LITERAL(28), %esp // pop arguments 650 .cfi_adjust_cfa_offset -28 651 ret 652END_FUNCTION art_quick_ldivmod_from_code 653 654DEFINE_FUNCTION art_quick_lmul_from_code 655 imul %eax, %ebx // ebx = a.lo(eax) * b.hi(ebx) 656 imul %edx, %ecx // ecx = b.lo(edx) * a.hi(ecx) 657 mul %edx // edx:eax = a.lo(eax) * b.lo(edx) 658 add %ebx, %ecx 659 add %ecx, %edx // edx += (a.lo * b.hi) + (b.lo * a.hi) 660 ret 661END_FUNCTION art_quick_lmul_from_code 662 663DEFINE_FUNCTION art_quick_lshl_from_code 664 // ecx:eax << edx 665 xchg %edx, %ecx 666 shld %cl,%eax,%edx 667 shl %cl,%eax 668 test LITERAL(32), %cl 669 jz 1f 670 mov %eax, %edx 671 xor %eax, %eax 6721: 673 ret 674END_FUNCTION art_quick_lshl_from_code 675 676DEFINE_FUNCTION art_quick_lshr_from_code 677 // ecx:eax >> edx 678 xchg %edx, %ecx 679 shrd %cl,%edx,%eax 680 sar %cl,%edx 681 test LITERAL(32),%cl 682 jz 1f 683 mov %edx, %eax 684 sar LITERAL(31), %edx 6851: 686 ret 687END_FUNCTION art_quick_lshr_from_code 688 689DEFINE_FUNCTION art_quick_lushr_from_code 690 // ecx:eax >>> edx 691 xchg %edx, %ecx 692 shrd %cl,%edx,%eax 693 shr %cl,%edx 694 test LITERAL(32),%cl 695 jz 1f 696 mov %edx, %eax 697 xor %edx, %edx 6981: 699 ret 700END_FUNCTION art_quick_lushr_from_code 701 702DEFINE_FUNCTION art_quick_set32_instance_from_code 703 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 704 mov %esp, %ebx // remember SP 705 subl LITERAL(8), %esp // alignment padding 706 .cfi_adjust_cfa_offset 8 707 PUSH ebx // pass SP 708 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 709 .cfi_adjust_cfa_offset 4 710 mov 32(%ebx), %ebx // get referrer 711 PUSH ebx // pass referrer 712 PUSH edx // pass new_val 713 PUSH ecx // pass object 714 PUSH eax // pass field_idx 715 call SYMBOL(artSet32InstanceFromCode) // (field_idx, Object*, new_val, referrer, Thread*, SP) 716 addl LITERAL(32), %esp // pop arguments 717 .cfi_adjust_cfa_offset -32 718 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 719 RETURN_IF_EAX_ZERO // return or deliver exception 720END_FUNCTION art_quick_set32_instance_from_code 721 722DEFINE_FUNCTION art_quick_set64_instance_from_code 723 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 724 subl LITERAL(8), %esp // alignment padding 725 .cfi_adjust_cfa_offset 8 726 PUSH esp // pass SP-8 727 addl LITERAL(8), (%esp) // fix SP on stack by adding 8 728 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 729 .cfi_adjust_cfa_offset 4 730 PUSH ebx // pass high half of new_val 731 PUSH edx // pass low half of new_val 732 PUSH ecx // pass object 733 PUSH eax // pass field_idx 734 call SYMBOL(artSet64InstanceFromCode) // (field_idx, Object*, new_val, Thread*, SP) 735 addl LITERAL(32), %esp // pop arguments 736 .cfi_adjust_cfa_offset -32 737 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 738 RETURN_IF_EAX_ZERO // return or deliver exception 739END_FUNCTION art_quick_set64_instance_from_code 740 741DEFINE_FUNCTION art_quick_set_obj_instance_from_code 742 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 743 mov %esp, %ebx // remember SP 744 subl LITERAL(8), %esp // alignment padding 745 .cfi_adjust_cfa_offset 8 746 PUSH ebx // pass SP 747 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 748 .cfi_adjust_cfa_offset 4 749 mov 32(%ebx), %ebx // get referrer 750 PUSH ebx // pass referrer 751 PUSH edx // pass new_val 752 PUSH ecx // pass object 753 PUSH eax // pass field_idx 754 call SYMBOL(artSetObjInstanceFromCode) // (field_idx, Object*, new_val, referrer, Thread*, SP) 755 addl LITERAL(32), %esp // pop arguments 756 .cfi_adjust_cfa_offset -32 757 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 758 RETURN_IF_EAX_ZERO // return or deliver exception 759END_FUNCTION art_quick_set_obj_instance_from_code 760 761DEFINE_FUNCTION art_quick_get32_instance_from_code 762 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 763 mov %esp, %ebx // remember SP 764 mov 32(%esp), %edx // get referrer 765 subl LITERAL(12), %esp // alignment padding 766 .cfi_adjust_cfa_offset 12 767 PUSH ebx // pass SP 768 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 769 .cfi_adjust_cfa_offset 4 770 PUSH edx // pass referrer 771 PUSH ecx // pass object 772 PUSH eax // pass field_idx 773 call SYMBOL(artGet32InstanceFromCode) // (field_idx, Object*, referrer, Thread*, SP) 774 addl LITERAL(32), %esp // pop arguments 775 .cfi_adjust_cfa_offset -32 776 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 777 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 778END_FUNCTION art_quick_get32_instance_from_code 779 780DEFINE_FUNCTION art_quick_get64_instance_from_code 781 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 782 mov %esp, %ebx // remember SP 783 mov 32(%esp), %edx // get referrer 784 subl LITERAL(12), %esp // alignment padding 785 .cfi_adjust_cfa_offset 12 786 PUSH ebx // pass SP 787 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 788 .cfi_adjust_cfa_offset 4 789 PUSH edx // pass referrer 790 PUSH ecx // pass object 791 PUSH eax // pass field_idx 792 call SYMBOL(artGet64InstanceFromCode) // (field_idx, Object*, referrer, Thread*, SP) 793 addl LITERAL(32), %esp // pop arguments 794 .cfi_adjust_cfa_offset -32 795 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 796 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 797END_FUNCTION art_quick_get64_instance_from_code 798 799DEFINE_FUNCTION art_quick_get_obj_instance_from_code 800 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 801 mov %esp, %ebx // remember SP 802 mov 32(%esp), %edx // get referrer 803 subl LITERAL(12), %esp // alignment padding 804 .cfi_adjust_cfa_offset 12 805 PUSH ebx // pass SP 806 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 807 .cfi_adjust_cfa_offset 4 808 PUSH edx // pass referrer 809 PUSH ecx // pass object 810 PUSH eax // pass field_idx 811 call SYMBOL(artGetObjInstanceFromCode) // (field_idx, Object*, referrer, Thread*, SP) 812 addl LITERAL(32), %esp // pop arguments 813 .cfi_adjust_cfa_offset -32 814 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 815 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 816END_FUNCTION art_quick_get_obj_instance_from_code 817 818DEFINE_FUNCTION art_quick_set32_static_from_code 819 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 820 mov %esp, %ebx // remember SP 821 mov 32(%esp), %edx // get referrer 822 subl LITERAL(12), %esp // alignment padding 823 .cfi_adjust_cfa_offset 12 824 PUSH ebx // pass SP 825 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 826 .cfi_adjust_cfa_offset 4 827 PUSH edx // pass referrer 828 PUSH ecx // pass new_val 829 PUSH eax // pass field_idx 830 call SYMBOL(artSet32StaticFromCode) // (field_idx, new_val, referrer, Thread*, SP) 831 addl LITERAL(32), %esp // pop arguments 832 .cfi_adjust_cfa_offset -32 833 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 834 RETURN_IF_EAX_ZERO // return or deliver exception 835END_FUNCTION art_quick_set32_static_from_code 836 837DEFINE_FUNCTION art_quick_set64_static_from_code 838 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 839 mov %esp, %ebx // remember SP 840 subl LITERAL(8), %esp // alignment padding 841 .cfi_adjust_cfa_offset 8 842 PUSH ebx // pass SP 843 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 844 .cfi_adjust_cfa_offset 4 845 mov 32(%ebx), %ebx // get referrer 846 PUSH edx // pass high half of new_val 847 PUSH ecx // pass low half of new_val 848 PUSH ebx // pass referrer 849 PUSH eax // pass field_idx 850 call SYMBOL(artSet64StaticFromCode) // (field_idx, referrer, new_val, Thread*, SP) 851 addl LITERAL(32), %esp // pop arguments 852 .cfi_adjust_cfa_offset -32 853 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 854 RETURN_IF_EAX_ZERO // return or deliver exception 855END_FUNCTION art_quick_set64_static_from_code 856 857DEFINE_FUNCTION art_quick_set_obj_static_from_code 858 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 859 mov %esp, %ebx // remember SP 860 mov 32(%esp), %edx // get referrer 861 subl LITERAL(12), %esp // alignment padding 862 .cfi_adjust_cfa_offset 12 863 PUSH ebx // pass SP 864 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 865 .cfi_adjust_cfa_offset 4 866 PUSH edx // pass referrer 867 PUSH ecx // pass new_val 868 PUSH eax // pass field_idx 869 call SYMBOL(artSetObjStaticFromCode) // (field_idx, new_val, referrer, Thread*, SP) 870 addl LITERAL(32), %esp // pop arguments 871 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 872 RETURN_IF_EAX_ZERO // return or deliver exception 873END_FUNCTION art_quick_set_obj_static_from_code 874 875DEFINE_FUNCTION art_quick_get32_static_from_code 876 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 877 mov %esp, %edx // remember SP 878 mov 32(%esp), %ecx // get referrer 879 PUSH edx // pass SP 880 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 881 .cfi_adjust_cfa_offset 4 882 PUSH ecx // pass referrer 883 PUSH eax // pass field_idx 884 call SYMBOL(artGet32StaticFromCode) // (field_idx, referrer, Thread*, SP) 885 addl LITERAL(16), %esp // pop arguments 886 .cfi_adjust_cfa_offset -16 887 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 888 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 889END_FUNCTION art_quick_get32_static_from_code 890 891DEFINE_FUNCTION art_quick_get64_static_from_code 892 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 893 mov %esp, %edx // remember SP 894 mov 32(%esp), %ecx // get referrer 895 PUSH edx // pass SP 896 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 897 .cfi_adjust_cfa_offset 4 898 PUSH ecx // pass referrer 899 PUSH eax // pass field_idx 900 call SYMBOL(artGet64StaticFromCode) // (field_idx, referrer, Thread*, SP) 901 addl LITERAL(16), %esp // pop arguments 902 .cfi_adjust_cfa_offset -16 903 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 904 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 905END_FUNCTION art_quick_get64_static_from_code 906 907DEFINE_FUNCTION art_quick_get_obj_static_from_code 908 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 909 mov %esp, %edx // remember SP 910 mov 32(%esp), %ecx // get referrer 911 PUSH edx // pass SP 912 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 913 .cfi_adjust_cfa_offset 4 914 PUSH ecx // pass referrer 915 PUSH eax // pass field_idx 916 call SYMBOL(artGetObjStaticFromCode) // (field_idx, referrer, Thread*, SP) 917 addl LITERAL(16), %esp // pop arguments 918 .cfi_adjust_cfa_offset -16 919 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 920 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 921END_FUNCTION art_quick_get_obj_static_from_code 922 923DEFINE_FUNCTION art_portable_proxy_invoke_handler 924 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME // save frame and Method* 925 PUSH esp // pass SP 926 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 927 .cfi_adjust_cfa_offset 4 928 PUSH ecx // pass receiver 929 PUSH eax // pass proxy method 930 call SYMBOL(artPortableProxyInvokeHandler) // (proxy method, receiver, Thread*, SP) 931 movd %eax, %xmm0 // place return value also into floating point return value 932 movd %edx, %xmm1 933 punpckldq %xmm1, %xmm0 934 addl LITERAL(44), %esp // pop arguments 935 .cfi_adjust_cfa_offset -44 936 ret 937END_FUNCTION art_portable_proxy_invoke_handler 938 939DEFINE_FUNCTION art_quick_proxy_invoke_handler 940 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME // save frame and Method* 941 PUSH esp // pass SP 942 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 943 .cfi_adjust_cfa_offset 4 944 PUSH ecx // pass receiver 945 PUSH eax // pass proxy method 946 call SYMBOL(artQuickProxyInvokeHandler) // (proxy method, receiver, Thread*, SP) 947 movd %eax, %xmm0 // place return value also into floating point return value 948 movd %edx, %xmm1 949 punpckldq %xmm1, %xmm0 950 addl LITERAL(44), %esp // pop arguments 951 .cfi_adjust_cfa_offset -44 952 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 953END_FUNCTION art_quick_proxy_invoke_handler 954 955DEFINE_FUNCTION art_quick_interpreter_entry 956 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME // save frame 957 mov %esp, %edx // remember SP 958 PUSH eax // alignment padding 959 PUSH edx // pass SP 960 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 961 .cfi_adjust_cfa_offset 4 962 PUSH eax // pass method 963 call SYMBOL(artInterpreterEntry) // (method, Thread*, SP) 964 movd %eax, %xmm0 // place return value also into floating point return value 965 movd %edx, %xmm1 966 punpckldq %xmm1, %xmm0 967 addl LITERAL(44), %esp // pop arguments 968 .cfi_adjust_cfa_offset -44 969 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 970END_FUNCTION art_quick_interpreter_entry 971 972 /* 973 * Routine that intercepts method calls and returns. 974 */ 975DEFINE_FUNCTION art_quick_instrumentation_entry_from_code 976 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME 977 movl %esp, %edx // Save SP. 978 PUSH eax // Save eax which will be clobbered by the callee-save method. 979 subl LITERAL(8), %esp // Align stack. 980 .cfi_adjust_cfa_offset 8 981 pushl 40(%esp) // Pass LR. 982 .cfi_adjust_cfa_offset 4 983 PUSH edx // Pass SP. 984 pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current(). 985 .cfi_adjust_cfa_offset 4 986 PUSH ecx // Pass receiver. 987 PUSH eax // Pass Method*. 988 call SYMBOL(artInstrumentationMethodEntryFromCode) // (Method*, Object*, Thread*, SP, LR) 989 addl LITERAL(28), %esp // Pop arguments upto saved Method*. 990 movl 28(%esp), %edi // Restore edi. 991 movl %eax, 28(%esp) // Place code* over edi, just under return pc. 992 movl LITERAL(SYMBOL(art_quick_instrumentation_exit_from_code)), 32(%esp) 993 // Place instrumentation exit as return pc. 994 movl (%esp), %eax // Restore eax. 995 movl 8(%esp), %ecx // Restore ecx. 996 movl 12(%esp), %edx // Restore edx. 997 movl 16(%esp), %ebx // Restore ebx. 998 movl 20(%esp), %ebp // Restore ebp. 999 movl 24(%esp), %esi // Restore esi. 1000 addl LITERAL(28), %esp // Wind stack back upto code*. 1001 ret // Call method (and pop). 1002END_FUNCTION art_quick_instrumentation_entry_from_code 1003 1004DEFINE_FUNCTION art_quick_instrumentation_exit_from_code 1005 pushl LITERAL(0) // Push a fake return PC as there will be none on the stack. 1006 SETUP_REF_ONLY_CALLEE_SAVE_FRAME 1007 mov %esp, %ecx // Remember SP 1008 subl LITERAL(8), %esp // Save float return value. 1009 .cfi_adjust_cfa_offset 8 1010 movd %xmm0, (%esp) 1011 PUSH edx // Save gpr return value. 1012 PUSH eax 1013 subl LITERAL(8), %esp // Align stack 1014 movd %xmm0, (%esp) 1015 subl LITERAL(8), %esp // Pass float return value. 1016 .cfi_adjust_cfa_offset 8 1017 movd %xmm0, (%esp) 1018 PUSH edx // Pass gpr return value. 1019 PUSH eax 1020 PUSH ecx // Pass SP. 1021 pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current. 1022 .cfi_adjust_cfa_offset 4 1023 call SYMBOL(artInstrumentationMethodExitFromCode) // (Thread*, SP, gpr_result, fpr_result) 1024 mov %eax, %ecx // Move returned link register. 1025 addl LITERAL(32), %esp // Pop arguments. 1026 .cfi_adjust_cfa_offset -32 1027 movl %edx, %ebx // Move returned link register for deopt 1028 // (ebx is pretending to be our LR). 1029 POP eax // Restore gpr return value. 1030 POP edx 1031 movd (%esp), %xmm0 // Restore fpr return value. 1032 addl LITERAL(8), %esp 1033 .cfi_adjust_cfa_offset -8 1034 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME 1035 addl LITERAL(4), %esp // Remove fake return pc. 1036 jmp *%ecx // Return. 1037END_FUNCTION art_quick_instrumentation_exit_from_code 1038 1039 /* 1040 * Instrumentation has requested that we deoptimize into the interpreter. The deoptimization 1041 * will long jump to the upcall with a special exception of -1. 1042 */ 1043DEFINE_FUNCTION art_quick_deoptimize 1044 pushl %ebx // Fake that we were called. 1045 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME 1046 mov %esp, %ecx // Remember SP. 1047 subl LITERAL(8), %esp // Align stack. 1048 .cfi_adjust_cfa_offset 8 1049 PUSH ecx // Pass SP. 1050 pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current(). 1051 .cfi_adjust_cfa_offset 4 1052 call SYMBOL(artDeoptimize) // artDeoptimize(Thread*, SP) 1053 int3 // Unreachable. 1054END_FUNCTION art_quick_deoptimize 1055 1056 /* 1057 * Portable abstract method error stub. method* is at %esp + 4 on entry. 1058 */ 1059DEFINE_FUNCTION art_portable_abstract_method_error_stub 1060 PUSH ebp 1061 movl %esp, %ebp // Remember SP. 1062 .cfi_def_cfa_register ebp 1063 subl LITERAL(12), %esp // Align stack. 1064 PUSH esp // Pass sp (not used). 1065 pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current(). 1066 pushl 8(%ebp) // Pass Method*. 1067 call SYMBOL(artThrowAbstractMethodErrorFromCode) // (Method*, Thread*, SP) 1068 leave // Restore the stack and %ebp. 1069 .cfi_def_cfa esp, 4 1070 .cfi_restore ebp 1071 ret // Return to caller to handle pending exception. 1072END_FUNCTION art_portable_abstract_method_error_stub 1073 1074 /* 1075 * Quick abstract method error stub. %eax contains method* on entry. 1076 */ 1077DEFINE_FUNCTION art_quick_abstract_method_error_stub 1078 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME 1079 movl %esp, %ecx // Remember SP. 1080 PUSH eax // Align frame. 1081 PUSH ecx // Pass SP for Method*. 1082 pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current(). 1083 .cfi_adjust_cfa_offset 4 1084 PUSH eax // Pass Method*. 1085 call SYMBOL(artThrowAbstractMethodErrorFromCode) // (Method*, Thread*, SP) 1086 int3 // Unreachable. 1087END_FUNCTION art_quick_abstract_method_error_stub 1088 1089 /* 1090 * Portable resolution trampoline. 1091 */ 1092DEFINE_FUNCTION art_jni_dlsym_lookup_stub 1093 subl LITERAL(8), %esp // align stack 1094 .cfi_adjust_cfa_offset 8 1095 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1096 .cfi_adjust_cfa_offset 4 1097 call SYMBOL(artFindNativeMethod) // (Thread*) 1098 addl LITERAL(12), %esp // restore the stack 1099 .cfi_adjust_cfa_offset -12 1100 cmpl LITERAL(0), %eax // check if returned method code is null 1101 je no_native_code_found // if null, jump to return to handle 1102 jmp *%eax // otherwise, tail call to intended method 1103no_native_code_found: 1104 ret 1105END_FUNCTION art_jni_dlsym_lookup_stub 1106 1107 /* 1108 * String's indexOf. 1109 * 1110 * On entry: 1111 * eax: string object (known non-null) 1112 * ecx: char to match (known <= 0xFFFF) 1113 * edx: Starting offset in string data 1114 */ 1115DEFINE_FUNCTION art_quick_indexof 1116 PUSH edi // push callee save reg 1117 mov STRING_COUNT_OFFSET(%eax), %ebx 1118 mov STRING_VALUE_OFFSET(%eax), %edi 1119 mov STRING_OFFSET_OFFSET(%eax), %eax 1120 testl %edx, %edx // check if start < 0 1121 jl clamp_min 1122clamp_done: 1123 cmpl %ebx, %edx // check if start >= count 1124 jge not_found 1125 lea STRING_DATA_OFFSET(%edi, %eax, 2), %edi // build a pointer to the start of string data 1126 mov %edi, %eax // save a copy in eax to later compute result 1127 lea (%edi, %edx, 2), %edi // build pointer to start of data to compare 1128 subl %edx, %ebx // compute iteration count 1129 /* 1130 * At this point we have: 1131 * eax: original start of string data 1132 * ecx: char to compare 1133 * ebx: length to compare 1134 * edi: start of data to test 1135 */ 1136 mov %eax, %edx 1137 mov %ecx, %eax // put char to match in %eax 1138 mov %ebx, %ecx // put length to compare in %ecx 1139 repne scasw // find %ax, starting at [%edi], up to length %ecx 1140 jne not_found 1141 subl %edx, %edi 1142 sar LITERAL(1), %edi 1143 decl %edi // index = ((curr_ptr - orig_ptr) / 2) - 1 1144 mov %edi, %eax 1145 POP edi // pop callee save reg 1146 ret 1147 .balign 16 1148not_found: 1149 mov LITERAL(-1), %eax // return -1 (not found) 1150 POP edi // pop callee save reg 1151 ret 1152clamp_min: 1153 xor %edx, %edx // clamp start to 0 1154 jmp clamp_done 1155END_FUNCTION art_quick_indexof 1156 1157 /* 1158 * String's compareTo. 1159 * 1160 * On entry: 1161 * eax: this string object (known non-null) 1162 * ecx: comp string object (known non-null) 1163 */ 1164DEFINE_FUNCTION art_quick_string_compareto 1165 PUSH esi // push callee save reg 1166 PUSH edi // push callee save reg 1167 mov STRING_COUNT_OFFSET(%eax), %edx 1168 mov STRING_COUNT_OFFSET(%ecx), %ebx 1169 mov STRING_VALUE_OFFSET(%eax), %esi 1170 mov STRING_VALUE_OFFSET(%ecx), %edi 1171 mov STRING_OFFSET_OFFSET(%eax), %eax 1172 mov STRING_OFFSET_OFFSET(%ecx), %ecx 1173 /* Build pointers to the start of string data */ 1174 lea STRING_DATA_OFFSET(%esi, %eax, 2), %esi 1175 lea STRING_DATA_OFFSET(%edi, %ecx, 2), %edi 1176 /* Calculate min length and count diff */ 1177 mov %edx, %ecx 1178 mov %edx, %eax 1179 subl %ebx, %eax 1180 cmovg %ebx, %ecx 1181 /* 1182 * At this point we have: 1183 * eax: value to return if first part of strings are equal 1184 * ecx: minimum among the lengths of the two strings 1185 * esi: pointer to this string data 1186 * edi: pointer to comp string data 1187 */ 1188 repe cmpsw // find nonmatching chars in [%esi] and [%edi], up to length %ecx 1189 jne not_equal 1190 POP edi // pop callee save reg 1191 POP esi // pop callee save reg 1192 ret 1193 .balign 16 1194not_equal: 1195 movzwl -2(%esi), %eax // get last compared char from this string 1196 movzwl -2(%edi), %ecx // get last compared char from comp string 1197 subl %ecx, %eax // return the difference 1198 POP edi // pop callee save reg 1199 POP esi // pop callee save reg 1200 ret 1201END_FUNCTION art_quick_string_compareto 1202 1203MACRO1(UNIMPLEMENTED,name) 1204 .globl VAR(name, 0) 1205 ALIGN_FUNCTION_ENTRY 1206VAR(name, 0): 1207 int3 1208END_MACRO 1209 1210 // TODO: implement these! 1211UNIMPLEMENTED art_quick_memcmp16 1212