quick_entrypoints_arm64.S revision 525cde2dd7cc7ad4212765ad3975cf260a934d3e
1/* 2 * Copyright (C) 2014 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_arm64.S" 18 19#include "arch/quick_alloc_entrypoints.S" 20 21 22 /* 23 * Macro that sets up the callee save frame to conform with 24 * Runtime::CreateCalleeSaveMethod(kSaveAll) 25 */ 26.macro SETUP_SAVE_ALL_CALLEE_SAVE_FRAME 27 adrp x9, :got:_ZN3art7Runtime9instance_E 28 ldr x9, [x9, #:got_lo12:_ZN3art7Runtime9instance_E] 29 30 // Our registers aren't intermixed - just spill in order. 31 ldr x9,[x9] // x9 = & (art::Runtime * art::Runtime.instance_) . 32 33 // x9 = (ArtMethod*) Runtime.instance_.callee_save_methods[kRefAndArgs] . 34 ldr x9, [x9, RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET ] 35 36 sub sp, sp, #368 37 .cfi_adjust_cfa_offset 368 38 39 // FP args 40 stp d1, d2, [sp, #8] 41 stp d2, d3, [sp, #24] 42 stp d4, d5, [sp, #40] 43 stp d6, d7, [sp, #56] 44 45 // FP callee-saves 46 stp d8, d9, [sp, #72] 47 stp d10, d11, [sp, #88] 48 stp d12, d13, [sp, #104] 49 stp d14, d15, [sp, #120] 50 51 stp d16, d17, [sp, #136] 52 stp d18, d19, [sp, #152] 53 stp d20, d21, [sp, #168] 54 stp d22, d23, [sp, #184] 55 stp d24, d25, [sp, #200] 56 stp d26, d27, [sp, #216] 57 stp d28, d29, [sp, #232] 58 stp d30, d31, [sp, #248] 59 60 61 // Callee saved. 62 stp xSELF, x19, [sp, #264] 63 .cfi_rel_offset x18, 264 64 .cfi_rel_offset x19, 272 65 66 stp x20, x21, [sp, #280] 67 .cfi_rel_offset x20, 280 68 .cfi_rel_offset x21, 288 69 70 stp x22, x23, [sp, #296] 71 .cfi_rel_offset x22, 296 72 .cfi_rel_offset x23, 304 73 74 stp x24, x25, [sp, #312] 75 .cfi_rel_offset x24, 312 76 .cfi_rel_offset x25, 320 77 78 stp x26, x27, [sp, #328] 79 .cfi_rel_offset x26, 328 80 .cfi_rel_offset x27, 336 81 82 stp x28, xFP, [sp, #344] // Save FP. 83 .cfi_rel_offset x28, 344 84 .cfi_rel_offset x29, 352 85 86 str xLR, [sp, #360] 87 .cfi_rel_offset x30, 360 88 89 // Loads appropriate callee-save-method 90 str x9, [sp] // Store ArtMethod* Runtime::callee_save_methods_[kRefsAndArgs] 91 92.endm 93 94 /* 95 * Macro that sets up the callee save frame to conform with 96 * Runtime::CreateCalleeSaveMethod(kRefsOnly). 97 */ 98.macro SETUP_REF_ONLY_CALLEE_SAVE_FRAME 99 brk 0 100.endm 101 102.macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME 103 brk 0 104.endm 105 106.macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN 107 brk 0 108.endm 109 110 111.macro SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL 112 sub sp, sp, #304 113 .cfi_adjust_cfa_offset 304 114 115 stp d0, d1, [sp, #16] 116 stp d2, d3, [sp, #32] 117 stp d4, d5, [sp, #48] 118 stp d6, d7, [sp, #64] 119 stp d8, d9, [sp, #80] 120 stp d10, d11, [sp, #96] 121 stp d12, d13, [sp, #112] 122 stp d14, d15, [sp, #128] 123 124 stp x1, x2, [sp, #144] 125 .cfi_rel_offset x1, 144 126 .cfi_rel_offset x2, 152 127 128 stp x3, x4, [sp, #160] 129 .cfi_rel_offset x3, 160 130 .cfi_rel_offset x4, 168 131 132 stp x5, x6, [sp, #176] 133 .cfi_rel_offset x5, 176 134 .cfi_rel_offset x6, 184 135 136 stp x7, xSELF, [sp, #192] 137 .cfi_rel_offset x7, 192 138 .cfi_rel_offset x18, 200 139 140 stp x19, x20, [sp, #208] 141 .cfi_rel_offset x19, 208 142 .cfi_rel_offset x20, 216 143 144 stp x21, x22, [sp, #224] 145 .cfi_rel_offset x21, 224 146 .cfi_rel_offset x22, 232 147 148 stp x23, x24, [sp, #240] 149 .cfi_rel_offset x23, 240 150 .cfi_rel_offset x24, 248 151 152 stp x25, x26, [sp, #256] 153 .cfi_rel_offset x25, 256 154 .cfi_rel_offset x26, 264 155 156 stp x27, x28, [sp, #272] 157 .cfi_rel_offset x27, 272 158 .cfi_rel_offset x28, 280 159 160 stp xFP, xLR, [sp, #288] 161 .cfi_rel_offset x29, 288 162 .cfi_rel_offset x30, 296 163.endm 164 165 /* 166 * Macro that sets up the callee save frame to conform with 167 * Runtime::CreateCalleeSaveMethod(kRefsAndArgs). 168 * 169 * TODO This is probably too conservative - saving FP & LR. 170 */ 171.macro SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME 172 adrp x9, :got:_ZN3art7Runtime9instance_E 173 ldr x9, [x9, #:got_lo12:_ZN3art7Runtime9instance_E] 174 175 // Our registers aren't intermixed - just spill in order. 176 ldr x9,[x9] // x9 = & (art::Runtime * art::Runtime.instance_) . 177 178 // x9 = (ArtMethod*) Runtime.instance_.callee_save_methods[kRefAndArgs] . 179 ldr x9, [x9, RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET ] 180 181 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL 182 183 str x9, [sp] // Store ArtMethod* Runtime::callee_save_methods_[kRefsAndArgs] 184.endm 185 186.macro RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME 187 188 ldp d0, d1, [sp, #16] 189 ldp d2, d3, [sp, #32] 190 ldp d4, d5, [sp, #48] 191 ldp d6, d7, [sp, #64] 192 ldp d8, d9, [sp, #80] 193 ldp d10, d11, [sp, #96] 194 ldp d12, d13, [sp, #112] 195 ldp d14, d15, [sp, #128] 196 197 // args. 198 ldp x1, x2, [sp, #144] 199 .cfi_restore x1 200 .cfi_restore x2 201 202 ldp x3, x4, [sp, #160] 203 .cfi_restore x3 204 .cfi_restore x4 205 206 ldp x5, x6, [sp, #176] 207 .cfi_restore x5 208 .cfi_restore x6 209 210 ldp x7, xSELF, [sp, #192] 211 .cfi_restore x7 212 .cfi_restore x18 213 214 ldp x19, x20, [sp, #208] 215 .cfi_restore x19 216 .cfi_restore x20 217 218 ldp x21, x22, [sp, #224] 219 .cfi_restore x21 220 .cfi_restore x22 221 222 ldp x23, x24, [sp, #240] 223 .cfi_restore x23 224 .cfi_restore x24 225 226 ldp x25, x26, [sp, #256] 227 .cfi_restore x25 228 .cfi_restore x26 229 230 ldp x27, x28, [sp, #272] 231 .cfi_restore x27 232 .cfi_restore x28 233 234 ldp xFP, xLR, [sp, #288] 235 .cfi_restore x29 236 .cfi_restore x30 237 238 add sp, sp, #304 239 .cfi_adjust_cfa_offset -304 240.endm 241 242.macro RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME_NO_D0 243 244 ldr d1, [sp, #24] 245 ldp d2, d3, [sp, #32] 246 ldp d4, d5, [sp, #48] 247 ldp d6, d7, [sp, #64] 248 ldp d8, d9, [sp, #80] 249 ldp d10, d11, [sp, #96] 250 ldp d12, d13, [sp, #112] 251 ldp d14, d15, [sp, #128] 252 253 // args. 254 ldp x1, x2, [sp, #144] 255 .cfi_restore x1 256 .cfi_restore x2 257 258 ldp x3, x4, [sp, #160] 259 .cfi_restore x3 260 .cfi_restore x4 261 262 ldp x5, x6, [sp, #176] 263 .cfi_restore x5 264 .cfi_restore x6 265 266 ldp x7, xSELF, [sp, #192] 267 .cfi_restore x7 268 .cfi_restore x18 269 270 ldp x19, x20, [sp, #208] 271 .cfi_restore x19 272 .cfi_restore x20 273 274 ldp x21, x22, [sp, #224] 275 .cfi_restore x21 276 .cfi_restore x22 277 278 ldp x23, x24, [sp, #240] 279 .cfi_restore x23 280 .cfi_restore x24 281 282 ldp x25, x26, [sp, #256] 283 .cfi_restore x25 284 .cfi_restore x26 285 286 ldp x27, x28, [sp, #272] 287 .cfi_restore x27 288 .cfi_restore x28 289 290 ldp xFP, xLR, [sp, #288] 291 .cfi_restore x29 292 .cfi_restore x30 293 294 add sp, sp, #304 295 .cfi_adjust_cfa_offset -304 296.endm 297 298.macro RETURN_IF_RESULT_IS_ZERO 299 brk 0 300.endm 301 302.macro RETURN_IF_RESULT_IS_NON_ZERO 303 brk 0 304.endm 305 306 /* 307 * Macro that set calls through to artDeliverPendingExceptionFromCode, where the pending 308 * exception is Thread::Current()->exception_ 309 */ 310.macro DELIVER_PENDING_EXCEPTION 311 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME 312 mov x0, xSELF 313 mov x1, sp 314 315 // Point of no return. 316 b artDeliverPendingExceptionFromCode // artDeliverPendingExceptionFromCode(Thread*, SP) 317 brk 0 // Unreached 318.endm 319 320.macro RETURN_OR_DELIVER_PENDING_EXCEPTION 321 ldr x9, [xSELF, # THREAD_EXCEPTION_OFFSET] // Get exception field. 322 cbnz x9, 1f 323 ret 3241: 325 DELIVER_PENDING_EXCEPTION 326.endm 327 328.macro NO_ARG_RUNTIME_EXCEPTION c_name, cxx_name 329 .extern \cxx_name 330ENTRY \c_name 331 brk 0 332END \c_name 333.endm 334 335// FIXME: Temporary fix for TR(XSELF). 336.macro ONE_ARG_RUNTIME_EXCEPTION c_name, cxx_name 337 .extern \cxx_name 338ENTRY \c_name 339 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context. 340 mov x1, x19 // pass Thread::Current. 341 mov x2, sp // pass SP. 342 b \cxx_name // \cxx_name(Thread*, SP). 343 brk 0 344END \c_name 345.endm 346 347.macro TWO_ARG_RUNTIME_EXCEPTION c_name, cxx_name 348 .extern \cxx_name 349ENTRY \c_name 350 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context 351 brk 0 352END \c_name 353.endm 354 355 /* 356 * Called by managed code, saves callee saves and then calls artThrowException 357 * that will place a mock Method* at the bottom of the stack. Arg1 holds the exception. 358 */ 359ONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception, artDeliverExceptionFromCode 360 361 /* 362 * Called by managed code to create and deliver a NullPointerException. 363 */ 364NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode 365 366 /* 367 * Called by managed code to create and deliver an ArithmeticException. 368 */ 369NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode 370 371 /* 372 * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds 373 * index, arg2 holds limit. 374 */ 375TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode 376 377 /* 378 * Called by managed code to create and deliver a StackOverflowError. 379 */ 380NO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow, artThrowStackOverflowFromCode 381 382 /* 383 * Called by managed code to create and deliver a NoSuchMethodError. 384 */ 385ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method, artThrowNoSuchMethodFromCode 386 387 /* 388 * TODO arm64 specifics need to be fleshed out. 389 * All generated callsites for interface invokes and invocation slow paths will load arguments 390 * as usual - except instead of loading x0 with the target Method*, x0 will contain 391 * the method_idx. This wrapper will save x1-x3, load the caller's Method*, align the 392 * stack and call the appropriate C helper. 393 * NOTE: "this" is first visible argument of the target, and so can be found in x1. 394 * 395 * The helper will attempt to locate the target and return a result in x0 consisting 396 * of the target Method* in x0 and method->code_ in x1. 397 * 398 * If unsuccessful, the helper will return NULL/NULL. There will be a pending exception in the 399 * thread and we branch to another stub to deliver it. 400 * 401 * On success this wrapper will restore arguments and *jump* to the target, leaving the lr 402 * pointing back to the original caller. 403 */ 404.macro INVOKE_TRAMPOLINE c_name, cxx_name 405 .extern \cxx_name 406ENTRY \c_name 407 brk 0 408END \c_name 409.endm 410 411INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline, artInvokeInterfaceTrampoline 412INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck 413 414INVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck 415INVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck 416INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck 417INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck 418 419 420.macro INVOKE_STUB_CREATE_FRAME 421 422SAVE_SIZE=5*8 // x4, x5, SP, LR & FP saved. 423SAVE_SIZE_AND_METHOD=SAVE_SIZE+8 424 425 mov x9, sp // Save stack pointer. 426 .cfi_register sp,x9 427 428 add x10, x2, # SAVE_SIZE_AND_METHOD // calculate size of frame. 429 sub x10, sp, x10 // Calculate SP position - saves + ArtMethod* + args 430 and x10, x10, # ~0xf // Enforce 16 byte stack alignment. 431 mov sp, x10 // Set new SP. 432 433 sub x10, x9, #SAVE_SIZE // Calculate new FP (later). Done here as we must move SP 434 .cfi_def_cfa_register x10 // before this. 435 .cfi_adjust_cfa_offset SAVE_SIZE 436 437 str x9, [x10, #32] // Save old stack pointer. 438 .cfi_rel_offset sp, 32 439 440 stp x4, x5, [x10, #16] // Save result and shorty addresses. 441 .cfi_rel_offset x4, 16 442 .cfi_rel_offset x5, 24 443 444 stp xFP, xLR, [x10] // Store LR & FP. 445 .cfi_rel_offset x29, 0 446 .cfi_rel_offset x30, 8 447 448 mov xFP, x10 // Use xFP now, as it's callee-saved. 449 .cfi_def_cfa_register x29 450 mov xSELF, x3 // Move thread pointer into SELF register. 451 452 // Copy arguments into stack frame. 453 // Use simple copy routine for now. 454 // 4 bytes per slot. 455 // X1 - source address 456 // W2 - args length 457 // X9 - destination address. 458 // W10 - temporary 459 add x9, sp, #8 // Destination address is bottom of stack + NULL. 460 461 // Use \@ to differentiate between macro invocations. 462.LcopyParams\@: 463 cmp w2, #0 464 beq .LendCopyParams\@ 465 sub w2, w2, #4 // Need 65536 bytes of range. 466 ldr w10, [x1, x2] 467 str w10, [x9, x2] 468 469 b .LcopyParams\@ 470 471.LendCopyParams\@: 472 473 // Store NULL into Method* at bottom of frame. 474 str xzr, [sp] 475 476.endm 477 478.macro INVOKE_STUB_CALL_AND_RETURN 479 480 // load method-> METHOD_QUICK_CODE_OFFSET 481 ldr x9, [x0 , #METHOD_QUICK_CODE_OFFSET] 482 // Branch to method. 483 blr x9 484 485 // Restore return value address and shorty address. 486 ldp x4,x5, [xFP, #16] 487 .cfi_restore x4 488 .cfi_restore x5 489 490 // Store result (w0/x0/s0/d0) appropriately, depending on resultType. 491 ldrb w10, [x5] 492 493 // Don't set anything for a void type. 494 cmp w10, #'V' 495 beq .Lexit_art_quick_invoke_stub\@ 496 497 cmp w10, #'D' 498 bne .Lreturn_is_float\@ 499 str d0, [x4] 500 b .Lexit_art_quick_invoke_stub\@ 501 502.Lreturn_is_float\@: 503 cmp w10, #'F' 504 bne .Lreturn_is_int\@ 505 str s0, [x4] 506 b .Lexit_art_quick_invoke_stub\@ 507 508 // Just store x0. Doesn't matter if it is 64 or 32 bits. 509.Lreturn_is_int\@: 510 str x0, [x4] 511 512.Lexit_art_quick_invoke_stub\@: 513 ldr x2, [x29, #32] // Restore stack pointer. 514 mov sp, x2 515 .cfi_restore sp 516 517 ldp x29, x30, [x29] // Restore old frame pointer and link register. 518 .cfi_restore x29 519 .cfi_restore x30 520 521 ret 522 523.endm 524 525 526/* 527 * extern"C" void art_quick_invoke_stub(ArtMethod *method, x0 528 * uint32_t *args, x1 529 * uint32_t argsize, w2 530 * Thread *self, x3 531 * JValue *result, x4 532 * char *shorty); x5 533 * +----------------------+ 534 * | | 535 * | C/C++ frame | 536 * | LR'' | 537 * | FP'' | <- SP' 538 * +----------------------+ 539 * +----------------------+ 540 * | SP' | 541 * | X5 | 542 * | X4 | Saved registers 543 * | LR' | 544 * | FP' | <- FP 545 * +----------------------+ 546 * | uint32_t out[n-1] | 547 * | : : | Outs 548 * | uint32_t out[0] | 549 * | ArtMethod* NULL | <- SP 550 * +----------------------+ 551 * 552 * Outgoing registers: 553 * x0 - Method* 554 * x1-x7 - integer parameters. 555 * d0-d7 - Floating point parameters. 556 * xSELF = self 557 * SP = & of ArtMethod* 558 * x1 = "this" pointer. 559 * 560 */ 561ENTRY art_quick_invoke_stub 562 // Spill registers as per AACPS64 calling convention. 563 INVOKE_STUB_CREATE_FRAME 564 565 // Fill registers x/w1 to x/w7 and s/d0 to s/d7 with parameters. 566 // Parse the passed shorty to determine which register to load. 567 // Load addresses for routines that load WXSD registers. 568 adr x11, .LstoreW2 569 adr x12, .LstoreX2 570 adr x13, .LstoreS0 571 adr x14, .LstoreD0 572 573 // Initialize routine offsets to 0 for integers and floats. 574 // x8 for integers, x15 for floating point. 575 mov x8, #0 576 mov x15, #0 577 578 add x10, x5, #1 // Load shorty address, plus one to skip return value. 579 ldr w1, [x9],#4 // Load "this" parameter, and increment arg pointer. 580 581 // Loop to fill registers. 582.LfillRegisters: 583 ldrb w17, [x10], #1 // Load next character in signature, and increment. 584 cbz w17, .LcallFunction // Exit at end of signature. Shorty 0 terminated. 585 586 cmp w17, #'F' // is this a float? 587 bne .LisDouble 588 589 cmp x15, # 8*12 // Skip this load if all registers full. 590 beq .Ladvance4 591 592 add x17, x13, x15 // Calculate subroutine to jump to. 593 br x17 594 595.LisDouble: 596 cmp w17, #'D' // is this a double? 597 bne .LisLong 598 599 cmp x15, # 8*12 // Skip this load if all registers full. 600 beq .Ladvance8 601 602 add x17, x14, x15 // Calculate subroutine to jump to. 603 br x17 604 605.LisLong: 606 cmp w17, #'J' // is this a long? 607 bne .LisOther 608 609 cmp x8, # 6*12 // Skip this load if all registers full. 610 beq .Ladvance8 611 612 add x17, x12, x8 // Calculate subroutine to jump to. 613 br x17 614 615.LisOther: // Everything else takes one vReg. 616 cmp x8, # 6*12 // Skip this load if all registers full. 617 beq .Ladvance4 618 619 add x17, x11, x8 // Calculate subroutine to jump to. 620 br x17 621 622.Ladvance4: 623 add x9, x9, #4 624 b .LfillRegisters 625 626.Ladvance8: 627 add x9, x9, #8 628 b .LfillRegisters 629 630// Macro for loading a parameter into a register. 631// counter - the register with offset into these tables 632// size - the size of the register - 4 or 8 bytes. 633// register - the name of the register to be loaded. 634.macro LOADREG counter size register return 635 ldr \register , [x9], #\size 636 add \counter, \counter, 12 637 b \return 638.endm 639 640// Store ints. 641.LstoreW2: 642 LOADREG x8 4 w2 .LfillRegisters 643 LOADREG x8 4 w3 .LfillRegisters 644 LOADREG x8 4 w4 .LfillRegisters 645 LOADREG x8 4 w5 .LfillRegisters 646 LOADREG x8 4 w6 .LfillRegisters 647 LOADREG x8 4 w7 .LfillRegisters 648 649// Store longs. 650.LstoreX2: 651 LOADREG x8 8 x2 .LfillRegisters 652 LOADREG x8 8 x3 .LfillRegisters 653 LOADREG x8 8 x4 .LfillRegisters 654 LOADREG x8 8 x5 .LfillRegisters 655 LOADREG x8 8 x6 .LfillRegisters 656 LOADREG x8 8 x7 .LfillRegisters 657 658// Store singles. 659.LstoreS0: 660 LOADREG x15 4 s0 .LfillRegisters 661 LOADREG x15 4 s1 .LfillRegisters 662 LOADREG x15 4 s2 .LfillRegisters 663 LOADREG x15 4 s3 .LfillRegisters 664 LOADREG x15 4 s4 .LfillRegisters 665 LOADREG x15 4 s5 .LfillRegisters 666 LOADREG x15 4 s6 .LfillRegisters 667 LOADREG x15 4 s7 .LfillRegisters 668 669// Store doubles. 670.LstoreD0: 671 LOADREG x15 8 d0 .LfillRegisters 672 LOADREG x15 8 d1 .LfillRegisters 673 LOADREG x15 8 d2 .LfillRegisters 674 LOADREG x15 8 d3 .LfillRegisters 675 LOADREG x15 8 d4 .LfillRegisters 676 LOADREG x15 8 d5 .LfillRegisters 677 LOADREG x15 8 d6 .LfillRegisters 678 LOADREG x15 8 d7 .LfillRegisters 679 680 681.LcallFunction: 682 683 INVOKE_STUB_CALL_AND_RETURN 684 685END art_quick_invoke_stub 686 687/* extern"C" 688 * void art_quick_invoke_static_stub(ArtMethod *method, x0 689 * uint32_t *args, x1 690 * uint32_t argsize, w2 691 * Thread *self, x3 692 * JValue *result, x4 693 * char *shorty); x5 694 */ 695ENTRY art_quick_invoke_static_stub 696 // Spill registers as per AACPS64 calling convention. 697 INVOKE_STUB_CREATE_FRAME 698 699 // Fill registers x/w1 to x/w7 and s/d0 to s/d7 with parameters. 700 // Parse the passed shorty to determine which register to load. 701 // Load addresses for routines that load WXSD registers. 702 adr x11, .LstoreW1_2 703 adr x12, .LstoreX1_2 704 adr x13, .LstoreS0_2 705 adr x14, .LstoreD0_2 706 707 // Initialize routine offsets to 0 for integers and floats. 708 // x8 for integers, x15 for floating point. 709 mov x8, #0 710 mov x15, #0 711 712 add x10, x5, #1 // Load shorty address, plus one to skip return value. 713 714 // Loop to fill registers. 715.LfillRegisters2: 716 ldrb w17, [x10], #1 // Load next character in signature, and increment. 717 cbz w17, .LcallFunction2 // Exit at end of signature. Shorty 0 terminated. 718 719 cmp w17, #'F' // is this a float? 720 bne .LisDouble2 721 722 cmp x15, # 8*12 // Skip this load if all registers full. 723 beq .Ladvance4_2 724 725 add x17, x13, x15 // Calculate subroutine to jump to. 726 br x17 727 728.LisDouble2: 729 cmp w17, #'D' // is this a double? 730 bne .LisLong2 731 732 cmp x15, # 8*12 // Skip this load if all registers full. 733 beq .Ladvance8_2 734 735 add x17, x14, x15 // Calculate subroutine to jump to. 736 br x17 737 738.LisLong2: 739 cmp w17, #'J' // is this a long? 740 bne .LisOther2 741 742 cmp x8, # 7*12 // Skip this load if all registers full. 743 beq .Ladvance8_2 744 745 add x17, x12, x8 // Calculate subroutine to jump to. 746 br x17 747 748.LisOther2: // Everything else takes one vReg. 749 cmp x8, # 7*12 // Skip this load if all registers full. 750 beq .Ladvance4_2 751 752 add x17, x11, x8 // Calculate subroutine to jump to. 753 br x17 754 755.Ladvance4_2: 756 add x9, x9, #4 757 b .LfillRegisters2 758 759.Ladvance8_2: 760 add x9, x9, #8 761 b .LfillRegisters2 762 763// Store ints. 764.LstoreW1_2: 765 LOADREG x8 4 w1 .LfillRegisters2 766 LOADREG x8 4 w2 .LfillRegisters2 767 LOADREG x8 4 w3 .LfillRegisters2 768 LOADREG x8 4 w4 .LfillRegisters2 769 LOADREG x8 4 w5 .LfillRegisters2 770 LOADREG x8 4 w6 .LfillRegisters2 771 LOADREG x8 4 w7 .LfillRegisters2 772 773// Store longs. 774.LstoreX1_2: 775 LOADREG x8 8 x1 .LfillRegisters2 776 LOADREG x8 8 x2 .LfillRegisters2 777 LOADREG x8 8 x3 .LfillRegisters2 778 LOADREG x8 8 x4 .LfillRegisters2 779 LOADREG x8 8 x5 .LfillRegisters2 780 LOADREG x8 8 x6 .LfillRegisters2 781 LOADREG x8 8 x7 .LfillRegisters2 782 783// Store singles. 784.LstoreS0_2: 785 LOADREG x15 4 s0 .LfillRegisters2 786 LOADREG x15 4 s1 .LfillRegisters2 787 LOADREG x15 4 s2 .LfillRegisters2 788 LOADREG x15 4 s3 .LfillRegisters2 789 LOADREG x15 4 s4 .LfillRegisters2 790 LOADREG x15 4 s5 .LfillRegisters2 791 LOADREG x15 4 s6 .LfillRegisters2 792 LOADREG x15 4 s7 .LfillRegisters2 793 794// Store doubles. 795.LstoreD0_2: 796 LOADREG x15 8 d0 .LfillRegisters2 797 LOADREG x15 8 d1 .LfillRegisters2 798 LOADREG x15 8 d2 .LfillRegisters2 799 LOADREG x15 8 d3 .LfillRegisters2 800 LOADREG x15 8 d4 .LfillRegisters2 801 LOADREG x15 8 d5 .LfillRegisters2 802 LOADREG x15 8 d6 .LfillRegisters2 803 LOADREG x15 8 d7 .LfillRegisters2 804 805 806.LcallFunction2: 807 808 INVOKE_STUB_CALL_AND_RETURN 809 810END art_quick_invoke_static_stub 811 812 813 814 /* 815 * On entry x0 is uintptr_t* gprs_ and x1 is uint64_t* fprs_ 816 */ 817 818ENTRY art_quick_do_long_jump 819 // Load FPRs 820 ldp d0, d1, [x1], #16 821 ldp d2, d3, [x1], #16 822 ldp d4, d5, [x1], #16 823 ldp d6, d7, [x1], #16 824 ldp d8, d9, [x1], #16 825 ldp d10, d11, [x1], #16 826 ldp d12, d13, [x1], #16 827 ldp d14, d15, [x1], #16 828 ldp d16, d17, [x1], #16 829 ldp d18, d19, [x1], #16 830 ldp d20, d21, [x1], #16 831 ldp d22, d23, [x1], #16 832 ldp d24, d25, [x1], #16 833 ldp d26, d27, [x1], #16 834 ldp d28, d29, [x1], #16 835 ldp d30, d31, [x1] 836 837 // Load GPRs 838 // TODO: lots of those are smashed, could optimize. 839 add x0, x0, #30*8 840 ldp x30, x1, [x0], #-16 841 ldp x28, x29, [x0], #-16 842 ldp x26, x27, [x0], #-16 843 ldp x24, x25, [x0], #-16 844 ldp x22, x23, [x0], #-16 845 ldp x20, x21, [x0], #-16 846 ldp x18, x19, [x0], #-16 847 ldp x16, x17, [x0], #-16 848 ldp x14, x15, [x0], #-16 849 ldp x12, x13, [x0], #-16 850 ldp x10, x11, [x0], #-16 851 ldp x8, x9, [x0], #-16 852 ldp x6, x7, [x0], #-16 853 ldp x4, x5, [x0], #-16 854 ldp x2, x3, [x0], #-16 855 mov sp, x1 856 857 // TODO: Is it really OK to use LR for the target PC? 858 mov x0, #0 859 mov x1, #0 860 br xLR 861END art_quick_do_long_jump 862 863UNIMPLEMENTED art_quick_handle_fill_data 864 865UNIMPLEMENTED art_quick_lock_object 866UNIMPLEMENTED art_quick_unlock_object 867 868 /* 869 * Entry from managed code that calls artIsAssignableFromCode and on failure calls 870 * artThrowClassCastException. 871 */ 872 .extern artThrowClassCastException 873ENTRY art_quick_check_cast 874 // Store arguments and link register 875 sub sp, sp, #32 // Stack needs to be 16b aligned on calls 876 .cfi_adjust_cfa_offset 32 877 stp x0, x1, [sp] 878 .cfi_rel_offset x0, 0 879 .cfi_rel_offset x1, 8 880 stp xSELF, xLR, [sp, #16] 881 .cfi_rel_offset x18, 16 882 .cfi_rel_offset x30, 24 883 884 // Call runtime code 885 bl artIsAssignableFromCode 886 887 // Check for exception 888 cbz x0, .Lthrow_class_cast_exception 889 890 // Restore and return 891 ldp x0, x1, [sp] 892 .cfi_restore x0 893 .cfi_restore x1 894 ldp xSELF, xLR, [sp, #16] 895 .cfi_restore x18 896 .cfi_restore x30 897 add sp, sp, #32 898 .cfi_adjust_cfa_offset -32 899 ret 900 901.Lthrow_class_cast_exception: 902 // Restore 903 ldp x0, x1, [sp] 904 .cfi_restore x0 905 .cfi_restore x1 906 ldp xSELF, xLR, [sp, #16] 907 .cfi_restore x18 908 .cfi_restore x30 909 add sp, sp, #32 910 .cfi_adjust_cfa_offset -32 911 912 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context 913 mov x2, xSELF // pass Thread::Current 914 mov x3, sp // pass SP 915 b artThrowClassCastException // (Class*, Class*, Thread*, SP) 916 brk 0 // We should not return here... 917END art_quick_check_cast 918 919UNIMPLEMENTED art_quick_aput_obj_with_null_and_bound_check 920UNIMPLEMENTED art_quick_aput_obj_with_bound_check 921UNIMPLEMENTED art_quick_aput_obj 922UNIMPLEMENTED art_quick_initialize_static_storage 923UNIMPLEMENTED art_quick_initialize_type 924UNIMPLEMENTED art_quick_initialize_type_and_verify_access 925UNIMPLEMENTED art_quick_get32_static 926UNIMPLEMENTED art_quick_get64_static 927UNIMPLEMENTED art_quick_get_obj_static 928UNIMPLEMENTED art_quick_get32_instance 929UNIMPLEMENTED art_quick_get64_instance 930UNIMPLEMENTED art_quick_get_obj_instance 931UNIMPLEMENTED art_quick_set32_static 932UNIMPLEMENTED art_quick_set64_static 933UNIMPLEMENTED art_quick_set_obj_static 934UNIMPLEMENTED art_quick_set32_instance 935UNIMPLEMENTED art_quick_set64_instance 936UNIMPLEMENTED art_quick_set_obj_instance 937UNIMPLEMENTED art_quick_resolve_string 938 939// Macro to facilitate adding new allocation entrypoints. 940.macro TWO_ARG_DOWNCALL name, entrypoint, return 941 .extern \entrypoint 942ENTRY \name 943 brk 0 944END \name 945.endm 946 947// Macro to facilitate adding new array allocation entrypoints. 948.macro THREE_ARG_DOWNCALL name, entrypoint, return 949 .extern \entrypoint 950ENTRY \name 951 brk 0 952END \name 953.endm 954 955// Generate the allocation entrypoints for each allocator. 956GENERATE_ALL_ALLOC_ENTRYPOINTS 957 958UNIMPLEMENTED art_quick_test_suspend 959 960 /* 961 * Called by managed code that is attempting to call a method on a proxy class. On entry 962 * x0 holds the proxy method and x1 holds the receiver; The frame size of the invoked proxy 963 * method agrees with a ref and args callee save frame. 964 */ 965 .extern artQuickProxyInvokeHandler 966ENTRY art_quick_proxy_invoke_handler 967 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME 968 str x0, [sp, #0] // place proxy method at bottom of frame 969 mov x2, xSELF // pass Thread::Current 970 mov x3, sp // pass SP 971 bl artQuickProxyInvokeHandler // (Method* proxy method, receiver, Thread*, SP) 972 ldr xSELF, [sp, #200] // Restore self pointer. 973 ldr x2, [xSELF, THREAD_EXCEPTION_OFFSET] 974 cbnz x2, .Lexception_in_proxy // success if no exception is pending 975 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME_NO_D0 // keep d0 976 ret // return on success 977.Lexception_in_proxy: 978 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME 979 DELIVER_PENDING_EXCEPTION 980END art_quick_proxy_invoke_handler 981 982UNIMPLEMENTED art_quick_imt_conflict_trampoline 983 984 985ENTRY art_quick_resolution_trampoline 986 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME 987 mov x19, x0 // save the called method 988 mov x2, xSELF 989 mov x3, sp 990 bl artQuickResolutionTrampoline // (called, receiver, Thread*, SP) 991 mov x9, x0 // Remember returned code pointer in x9. 992 mov x0, x19 // Restore the method, before x19 is restored to on-call value 993 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME 994 cbz x9, 1f 995 br x9 9961: 997 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME 998 DELIVER_PENDING_EXCEPTION 999END art_quick_resolution_trampoline 1000 1001/* 1002 * Generic JNI frame layout: 1003 * 1004 * #-------------------# 1005 * | | 1006 * | caller method... | 1007 * #-------------------# <--- SP on entry 1008 * | Return X30/LR | 1009 * | X29/FP | callee save 1010 * | X28 | callee save 1011 * | X27 | callee save 1012 * | X26 | callee save 1013 * | X25 | callee save 1014 * | X24 | callee save 1015 * | X23 | callee save 1016 * | X22 | callee save 1017 * | X21 | callee save 1018 * | X20 | callee save 1019 * | X19 | callee save 1020 * | X7 | arg7 1021 * | X6 | arg6 1022 * | X5 | arg5 1023 * | X4 | arg4 1024 * | X3 | arg3 1025 * | X2 | arg2 1026 * | X1 | arg1 1027 * | D15 | float arg 8 1028 * | D14 | float arg 8 1029 * | D13 | float arg 8 1030 * | D12 | callee save 1031 * | D11 | callee save 1032 * | D10 | callee save 1033 * | D9 | callee save 1034 * | D8 | callee save 1035 * | D7 | float arg 8 1036 * | D6 | float arg 7 1037 * | D5 | float arg 6 1038 * | D4 | float arg 5 1039 * | D3 | float arg 4 1040 * | D2 | float arg 3 1041 * | D1 | float arg 2 1042 * | D0 | float arg 1 1043 * | RDI/Method* | <- X0 1044 * #-------------------# 1045 * | local ref cookie | // 4B 1046 * | SIRT size | // 4B 1047 * #-------------------# 1048 * | JNI Call Stack | 1049 * #-------------------# <--- SP on native call 1050 * | | 1051 * | Stack for Regs | The trampoline assembly will pop these values 1052 * | | into registers for native call 1053 * #-------------------# 1054 * | Native code ptr | 1055 * #-------------------# 1056 * | Free scratch | 1057 * #-------------------# 1058 * | Ptr to (1) | <--- SP 1059 * #-------------------# 1060 */ 1061 /* 1062 * Called to do a generic JNI down-call 1063 */ 1064ENTRY art_quick_generic_jni_trampoline 1065 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL 1066 str x0, [sp, #0] // Store native ArtMethod* to bottom of stack. 1067 1068 // Save SP , so we can have static CFI info. 1069 mov x28, sp 1070 .cfi_def_cfa_register x28 1071 1072 // This looks the same, but is different: this will be updated to point to the bottom 1073 // of the frame when the SIRT is inserted. 1074 mov xFP, sp 1075 1076 mov x8, #5120 1077 sub sp, sp, x8 1078 1079 // prepare for artQuickGenericJniTrampoline call 1080 // (Thread*, SP) 1081 // x0 x1 <= C calling convention 1082 // xSELF xFP <= where they are 1083 1084 mov x0, xSELF // Thread* 1085 mov x1, xFP 1086 bl artQuickGenericJniTrampoline // (Thread*, sp) 1087 1088 // Get the updated pointer. This is the bottom of the frame _with_ SIRT. 1089 ldr xFP, [sp] 1090 add x9, sp, #8 1091 1092 cmp x0, #0 1093 b.mi .Lentry_error // Check for error, negative value. 1094 1095 // release part of the alloca. 1096 add x9, x9, x0 1097 1098 // Get the code pointer 1099 ldr xIP0, [x9, #0] 1100 1101 // Load parameters from frame into registers. 1102 // TODO Check with artQuickGenericJniTrampoline. 1103 // Also, check again APPCS64 - the stack arguments are interleaved. 1104 ldp x0, x1, [x9, #8] 1105 ldp x2, x3, [x9, #24] 1106 ldp x4, x5, [x9, #40] 1107 ldp x6, x7, [x9, #56] 1108 1109 ldp d0, d1, [x9, #72] 1110 ldp d2, d3, [x9, #88] 1111 ldp d4, d5, [x9, #104] 1112 ldp d6, d7, [x9, #120] 1113 1114 add sp, x9, #136 1115 1116 blr xIP0 // native call. 1117 1118 // Restore self pointer. 1119 ldr xSELF, [x28, #200] 1120 1121 // result sign extension is handled in C code 1122 // prepare for artQuickGenericJniEndTrampoline call 1123 // (Thread*, SP, result, result_f) 1124 // x0 x1 x2 x3 <= C calling convention 1125 mov x5, x0 // Save return value 1126 mov x0, xSELF // Thread register 1127 mov x1, xFP // Stack pointer 1128 mov x2, x5 // Result (from saved) 1129 fmov x3, d0 // d0 will contain floating point result, but needs to go into x3 1130 1131 bl artQuickGenericJniEndTrampoline 1132 1133 // Tear down the alloca. 1134 mov sp, x28 1135 .cfi_def_cfa_register sp 1136 1137 // Restore self pointer. 1138 ldr xSELF, [x28, #200] 1139 1140 // Pending exceptions possible. 1141 ldr x1, [xSELF, THREAD_EXCEPTION_OFFSET] 1142 cbnz x1, .Lexception_in_native 1143 1144 // Tear down the callee-save frame. 1145 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME 1146 1147 // store into fpr, for when it's a fpr return... 1148 fmov d0, x0 1149 ret 1150 1151.Lentry_error: 1152 mov sp, x28 1153 .cfi_def_cfa_register sp 1154 ldr xSELF, [x28, #200] 1155.Lexception_in_native: 1156 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME 1157 DELIVER_PENDING_EXCEPTION 1158 1159END art_quick_generic_jni_trampoline 1160 1161/* 1162 * Called to bridge from the quick to interpreter ABI. On entry the arguments match those 1163 * of a quick call: 1164 * x0 = method being called/to bridge to. 1165 * x1..x7, d0..d7 = arguments to that method. 1166 */ 1167ENTRY art_quick_to_interpreter_bridge 1168 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME // Set up frame and save arguments. 1169 1170 // x0 will contain mirror::ArtMethod* method. 1171 mov x1, xSELF // How to get Thread::Current() ??? 1172 mov x2, sp 1173 1174 // uint64_t artQuickToInterpreterBridge(mirror::ArtMethod* method, Thread* self, 1175 // mirror::ArtMethod** sp) 1176 bl artQuickToInterpreterBridge 1177 1178 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME // TODO: no need to restore arguments in this case. 1179 1180 fmov d0, x0 1181 1182 RETURN_OR_DELIVER_PENDING_EXCEPTION 1183END art_quick_to_interpreter_bridge 1184 1185UNIMPLEMENTED art_quick_instrumentation_entry 1186UNIMPLEMENTED art_quick_instrumentation_exit 1187UNIMPLEMENTED art_quick_deoptimize 1188UNIMPLEMENTED art_quick_mul_long 1189UNIMPLEMENTED art_quick_shl_long 1190UNIMPLEMENTED art_quick_shr_long 1191UNIMPLEMENTED art_quick_ushr_long 1192UNIMPLEMENTED art_quick_indexof 1193UNIMPLEMENTED art_quick_string_compareto 1194