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