quick_entrypoints_mips64.S revision cc7c39d747f5802282adcc51ffe44405f116f84b
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_mips64.S" 18 19#include "arch/quick_alloc_entrypoints.S" 20 21 .set noreorder 22 .balign 16 23 24 /* Deliver the given exception */ 25 .extern artDeliverExceptionFromCode 26 /* Deliver an exception pending on a thread */ 27 .extern artDeliverPendingExceptionFromCode 28 29 /* 30 * Macro that sets up the callee save frame to conform with 31 * Runtime::CreateCalleeSaveMethod(kSaveAll) 32 * callee-save: padding + $f24-$f31 + $s0-$s7 + $gp + $ra + $s8 = 19 total + 1x8 bytes padding 33 */ 34.macro SETUP_SAVE_ALL_CALLEE_SAVE_FRAME 35 daddiu $sp, $sp, -160 36 .cfi_adjust_cfa_offset 160 37 38 // Ugly compile-time check, but we only have the preprocessor. 39#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVE != 160) 40#error "SAVE_ALL_CALLEE_SAVE_FRAME(MIPS64) size not as expected." 41#endif 42 43 sd $ra, 152($sp) 44 .cfi_rel_offset 31, 152 45 sd $s8, 144($sp) 46 .cfi_rel_offset 30, 144 47 sd $gp, 136($sp) 48 .cfi_rel_offset 28, 136 49 sd $s7, 128($sp) 50 .cfi_rel_offset 23, 128 51 sd $s6, 120($sp) 52 .cfi_rel_offset 22, 120 53 sd $s5, 112($sp) 54 .cfi_rel_offset 21, 112 55 sd $s4, 104($sp) 56 .cfi_rel_offset 20, 104 57 sd $s3, 96($sp) 58 .cfi_rel_offset 19, 96 59 sd $s2, 88($sp) 60 .cfi_rel_offset 18, 88 61 sd $s1, 80($sp) 62 .cfi_rel_offset 17, 80 63 sd $s0, 72($sp) 64 .cfi_rel_offset 16, 72 65 66 // FP callee-saves 67 s.d $f31, 64($sp) 68 s.d $f30, 56($sp) 69 s.d $f29, 48($sp) 70 s.d $f28, 40($sp) 71 s.d $f27, 32($sp) 72 s.d $f26, 24($sp) 73 s.d $f25, 16($sp) 74 s.d $f24, 8($sp) 75 76 # load appropriate callee-save-method 77 ld $v0, %got(_ZN3art7Runtime9instance_E)($gp) 78 ld $v0, 0($v0) 79 THIS_LOAD_REQUIRES_READ_BARRIER 80 ld $v0, RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET($v0) 81 sw $v0, 0($sp) # Place Method* at bottom of stack. 82 sd $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF) # Place sp in Thread::Current()->top_quick_frame. 83.endm 84 85 /* 86 * Macro that sets up the callee save frame to conform with 87 * Runtime::CreateCalleeSaveMethod(kRefsOnly). Restoration assumes 88 * non-moving GC. 89 * Does not include rSUSPEND or rSELF 90 * callee-save: padding + $s2-$s7 + $gp + $ra + $s8 = 9 total + 1x8 bytes padding 91 */ 92.macro SETUP_REFS_ONLY_CALLEE_SAVE_FRAME 93 daddiu $sp, $sp, -80 94 .cfi_adjust_cfa_offset 80 95 96 // Ugly compile-time check, but we only have the preprocessor. 97#if (FRAME_SIZE_REFS_ONLY_CALLEE_SAVE != 80) 98#error "REFS_ONLY_CALLEE_SAVE_FRAME(MIPS64) size not as expected." 99#endif 100 101 sd $ra, 72($sp) 102 .cfi_rel_offset 31, 72 103 sd $s8, 64($sp) 104 .cfi_rel_offset 30, 64 105 sd $gp, 56($sp) 106 .cfi_rel_offset 28, 56 107 sd $s7, 48($sp) 108 .cfi_rel_offset 23, 48 109 sd $s6, 40($sp) 110 .cfi_rel_offset 22, 40 111 sd $s5, 32($sp) 112 .cfi_rel_offset 21, 32 113 sd $s4, 24($sp) 114 .cfi_rel_offset 20, 24 115 sd $s3, 16($sp) 116 .cfi_rel_offset 19, 16 117 sd $s2, 8($sp) 118 .cfi_rel_offset 18, 8 119 # load appropriate callee-save-method 120 ld $v0, %got(_ZN3art7Runtime9instance_E)($gp) 121 ld $v0, 0($v0) 122 THIS_LOAD_REQUIRES_READ_BARRIER 123 ld $v0, RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET($v0) 124 sw $v0, 0($sp) # Place Method* at bottom of stack. 125 sd $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF) # Place sp in Thread::Current()->top_quick_frame. 126.endm 127 128.macro RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME 129 ld $ra, 72($sp) 130 .cfi_restore 31 131 ld $s8, 64($sp) 132 .cfi_restore 30 133 ld $gp, 56($sp) 134 .cfi_restore 28 135 ld $s7, 48($sp) 136 .cfi_restore 23 137 ld $s6, 40($sp) 138 .cfi_restore 22 139 ld $s5, 32($sp) 140 .cfi_restore 21 141 ld $s4, 24($sp) 142 .cfi_restore 20 143 ld $s3, 16($sp) 144 .cfi_restore 19 145 ld $s2, 8($sp) 146 .cfi_restore 18 147 daddiu $sp, $sp, 80 148 .cfi_adjust_cfa_offset -80 149.endm 150 151.macro RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME_AND_RETURN 152 ld $ra, 72($sp) 153 .cfi_restore 31 154 ld $s8, 64($sp) 155 .cfi_restore 30 156 ld $gp, 56($sp) 157 .cfi_restore 28 158 ld $s7, 48($sp) 159 .cfi_restore 23 160 ld $s6, 40($sp) 161 .cfi_restore 22 162 ld $s5, 32($sp) 163 .cfi_restore 21 164 ld $s4, 24($sp) 165 .cfi_restore 20 166 ld $s3, 16($sp) 167 .cfi_restore 19 168 ld $s2, 8($sp) 169 .cfi_restore 18 170 jalr $zero, $ra 171 daddiu $sp, $sp, 80 172 .cfi_adjust_cfa_offset -80 173.endm 174 175// This assumes the top part of these stack frame types are identical. 176#define REFS_AND_ARGS_MINUS_REFS_SIZE (FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE - FRAME_SIZE_REFS_ONLY_CALLEE_SAVE) 177 178 /* 179 * Macro that sets up the callee save frame to conform with 180 * Runtime::CreateCalleeSaveMethod(kRefsAndArgs). Restoration assumes 181 * non-moving GC. 182 * callee-save: padding + $f12-$f19 + $a1-$a7 + $s2-$s7 + $gp + $ra + $s8 = 24 total + 1 words padding + Method* 183 */ 184.macro SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL 185 daddiu $sp, $sp, -208 186 .cfi_adjust_cfa_offset 208 187 188 // Ugly compile-time check, but we only have the preprocessor. 189#if (FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE != 208) 190#error "REFS_AND_ARGS_CALLEE_SAVE_FRAME(MIPS64) size not as expected." 191#endif 192 193 sd $ra, 200($sp) # = kQuickCalleeSaveFrame_RefAndArgs_LrOffset 194 .cfi_rel_offset 31, 200 195 sd $s8, 192($sp) 196 .cfi_rel_offset 30, 192 197 sd $gp, 184($sp) 198 .cfi_rel_offset 28, 184 199 sd $s7, 176($sp) 200 .cfi_rel_offset 23, 176 201 sd $s6, 168($sp) 202 .cfi_rel_offset 22, 168 203 sd $s5, 160($sp) 204 .cfi_rel_offset 21, 160 205 sd $s4, 152($sp) 206 .cfi_rel_offset 20, 152 207 sd $s3, 144($sp) 208 .cfi_rel_offset 19, 144 209 sd $s2, 136($sp) 210 .cfi_rel_offset 18, 136 211 212 sd $a7, 128($sp) 213 .cfi_rel_offset 11, 128 214 sd $a6, 120($sp) 215 .cfi_rel_offset 10, 120 216 sd $a5, 112($sp) 217 .cfi_rel_offset 9, 112 218 sd $a4, 104($sp) 219 .cfi_rel_offset 8, 104 220 sd $a3, 96($sp) 221 .cfi_rel_offset 7, 96 222 sd $a2, 88($sp) 223 .cfi_rel_offset 6, 88 224 sd $a1, 80($sp) # = kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset 225 .cfi_rel_offset 5, 80 226 227 s.d $f19, 72($sp) 228 s.d $f18, 64($sp) 229 s.d $f17, 56($sp) 230 s.d $f16, 48($sp) 231 s.d $f15, 40($sp) 232 s.d $f14, 32($sp) 233 s.d $f13, 24($sp) # = kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset 234 s.d $f12, 16($sp) # This isn't necessary to store. 235 236 # 1x8 bytes paddig + Method* 237 ld $v0, %got(_ZN3art7Runtime9instance_E)($gp) 238 ld $v0, 0($v0) 239 THIS_LOAD_REQUIRES_READ_BARRIER 240 ld $v0, RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET($v0) 241 sw $v0, 0($sp) # Place Method* at bottom of stack. 242 sd $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF) # Place sp in Thread::Current()->top_quick_frame. 243.endm 244 245.macro SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME 246 SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL 247 # load appropriate callee-save-method 248 ld $v0, %got(_ZN3art7Runtime9instance_E)($gp) 249 ld $v0, 0($v0) 250 THIS_LOAD_REQUIRES_READ_BARRIER 251 ld $v0, RUNTIME_REFS_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET($v0) 252 sw $v0, 0($sp) # Place Method* at bottom of stack. 253 sd $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF) # Place sp in Thread::Current()->top_quick_frame. 254.endm 255 256.macro RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME 257 ld $ra, 200($sp) 258 .cfi_restore 31 259 ld $s8, 192($sp) 260 .cfi_restore 30 261 ld $gp, 184($sp) 262 .cfi_restore 28 263 ld $s7, 176($sp) 264 .cfi_restore 23 265 ld $s6, 168($sp) 266 .cfi_restore 22 267 ld $s5, 160($sp) 268 .cfi_restore 21 269 ld $s4, 152($sp) 270 .cfi_restore 20 271 ld $s3, 144($sp) 272 .cfi_restore 19 273 ld $s2, 136($sp) 274 .cfi_restore 18 275 276 ld $a7, 128($sp) 277 .cfi_restore 11 278 ld $a6, 120($sp) 279 .cfi_restore 10 280 ld $a5, 112($sp) 281 .cfi_restore 9 282 ld $a4, 104($sp) 283 .cfi_restore 8 284 ld $a3, 96($sp) 285 .cfi_restore 7 286 ld $a2, 88($sp) 287 .cfi_restore 6 288 ld $a1, 80($sp) 289 .cfi_restore 5 290 291 l.d $f19, 72($sp) 292 l.d $f18, 64($sp) 293 l.d $f17, 56($sp) 294 l.d $f16, 48($sp) 295 l.d $f15, 40($sp) 296 l.d $f14, 32($sp) 297 l.d $f13, 24($sp) 298 l.d $f12, 16($sp) 299 300 daddiu $sp, $sp, 208 301 .cfi_adjust_cfa_offset -208 302.endm 303 304 /* 305 * Macro that set calls through to artDeliverPendingExceptionFromCode, 306 * where the pending 307 * exception is Thread::Current()->exception_ 308 */ 309.macro DELIVER_PENDING_EXCEPTION 310 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME # save callee saves for throw 311 dla $t9, artDeliverPendingExceptionFromCode 312 jalr $zero, $t9 # artDeliverPendingExceptionFromCode(Thread*) 313 move $a0, rSELF # pass Thread::Current 314.endm 315 316.macro RETURN_IF_NO_EXCEPTION 317 ld $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_ 318 RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME 319 bne $t0, $zero, 1f # success if no exception is pending 320 nop 321 jalr $zero, $ra 322 nop 3231: 324 DELIVER_PENDING_EXCEPTION 325.endm 326 327.macro RETURN_IF_ZERO 328 RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME 329 bne $v0, $zero, 1f # success? 330 nop 331 jalr $zero, $ra # return on success 332 nop 3331: 334 DELIVER_PENDING_EXCEPTION 335.endm 336 337.macro RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER 338 RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME 339 beq $v0, $zero, 1f # success? 340 nop 341 jalr $zero, $ra # return on success 342 nop 3431: 344 DELIVER_PENDING_EXCEPTION 345.endm 346 347 /* 348 * On entry $a0 is uint32_t* gprs_ and $a1 is uint32_t* fprs_ 349 * FIXME: just guessing about the shape of the jmpbuf. Where will pc be? 350 */ 351ENTRY art_quick_do_long_jump 352 l.d $f0, 0($a1) 353 l.d $f1, 8($a1) 354 l.d $f2, 16($a1) 355 l.d $f3, 24($a1) 356 l.d $f4, 32($a1) 357 l.d $f5, 40($a1) 358 l.d $f6, 48($a1) 359 l.d $f7, 56($a1) 360 l.d $f8, 64($a1) 361 l.d $f9, 72($a1) 362 l.d $f10, 80($a1) 363 l.d $f11, 88($a1) 364 l.d $f12, 96($a1) 365 l.d $f13, 104($a1) 366 l.d $f14, 112($a1) 367 l.d $f15, 120($a1) 368 l.d $f16, 128($a1) 369 l.d $f17, 136($a1) 370 l.d $f18, 144($a1) 371 l.d $f19, 152($a1) 372 l.d $f20, 160($a1) 373 l.d $f21, 168($a1) 374 l.d $f22, 176($a1) 375 l.d $f23, 184($a1) 376 l.d $f24, 192($a1) 377 l.d $f25, 200($a1) 378 l.d $f26, 208($a1) 379 l.d $f27, 216($a1) 380 l.d $f28, 224($a1) 381 l.d $f29, 232($a1) 382 l.d $f30, 240($a1) 383 l.d $f31, 248($a1) 384 .set push 385 .set nomacro 386 .set noat 387# no need to load zero 388 ld $at, 8($a0) 389 .set pop 390 ld $v0, 16($a0) 391 ld $v1, 24($a0) 392# a0 has to be loaded last 393 ld $a1, 40($a0) 394 ld $a2, 48($a0) 395 ld $a3, 56($a0) 396 ld $a4, 64($a0) 397 ld $a5, 72($a0) 398 ld $a6, 80($a0) 399 ld $a7, 88($a0) 400 ld $t0, 96($a0) 401 ld $t1, 104($a0) 402 ld $t2, 112($a0) 403 ld $t3, 120($a0) 404 ld $s0, 128($a0) 405 ld $s1, 136($a0) 406 ld $s2, 144($a0) 407 ld $s3, 152($a0) 408 ld $s4, 160($a0) 409 ld $s5, 168($a0) 410 ld $s6, 176($a0) 411 ld $s7, 184($a0) 412 ld $t8, 192($a0) 413 ld $t9, 200($a0) 414# no need to load k0, k1 415 ld $gp, 224($a0) 416 ld $sp, 232($a0) 417 ld $s8, 240($a0) 418 ld $ra, 248($a0) 419 ld $a0, 32($a0) 420 move $v0, $zero # clear result registers v0 and v1 421 jalr $zero, $ra # do long jump 422 move $v1, $zero 423END art_quick_do_long_jump 424 425UNIMPLEMENTED art_quick_deliver_exception 426UNIMPLEMENTED art_quick_throw_null_pointer_exception 427UNIMPLEMENTED art_quick_throw_div_zero 428UNIMPLEMENTED art_quick_throw_array_bounds 429UNIMPLEMENTED art_quick_throw_stack_overflow 430UNIMPLEMENTED art_quick_throw_no_such_method 431 432UNIMPLEMENTED art_quick_invoke_interface_trampoline 433UNIMPLEMENTED art_quick_invoke_interface_trampoline_with_access_check 434 435UNIMPLEMENTED art_quick_invoke_static_trampoline_with_access_check 436UNIMPLEMENTED art_quick_invoke_direct_trampoline_with_access_check 437UNIMPLEMENTED art_quick_invoke_super_trampoline_with_access_check 438UNIMPLEMENTED art_quick_invoke_virtual_trampoline_with_access_check 439 440 # On entry: 441 # t0 = shorty 442 # t1 = ptr to arg_array 443 # t2 = number of argument bytes remain 444 # v0 = ptr to stack frame where to copy arg_array 445 # This macro modifies t3, t9 and v0 446.macro LOOP_OVER_SHORTY_LOADING_REG gpu, fpu, label 447 lbu $t3, 0($t0) # get argument type from shorty 448 beqz $t3, \label 449 daddiu $t0, 1 450 li $t9, 68 # put char 'D' into t9 451 beq $t9, $t3, 1f # branch if result type char == 'D' 452 li $t9, 70 # put char 'F' into t9 453 beq $t9, $t3, 2f # branch if result type char == 'F' 454 li $t9, 74 # put char 'J' into t9 455 beq $t9, $t3, 3f # branch if result type char == 'J' 456 nop 457 lwu $\gpu, 0($t1) 458 sw $\gpu, 0($v0) 459 daddiu $v0, 4 460 daddiu $t1, 4 461 b 4f 462 daddiu $t2, -4 # delay slot 463 4641: # found double 465 lwu $t3, 0($t1) 466 mtc1 $t3, $\fpu 467 sw $t3, 0($v0) 468 lwu $t3, 4($t1) 469 mthc1 $t3, $\fpu 470 sw $t3, 4($v0) 471 daddiu $v0, 8 472 daddiu $t1, 8 473 b 4f 474 daddiu $t2, -8 # delay slot 475 4762: # found float 477 lwu $t3, 0($t1) 478 mtc1 $t3, $\fpu 479 sw $t3, 0($v0) 480 daddiu $v0, 4 481 daddiu $t1, 4 482 b 4f 483 daddiu $t2, -4 # delay slot 484 4853: # found long (8 bytes) 486 lwu $t3, 0($t1) 487 sw $t3, 0($v0) 488 lwu $t9, 4($t1) 489 sw $t9, 4($v0) 490 dsll $t9, $t9, 32 491 or $\gpu, $t9, $t3 492 daddiu $v0, 8 493 daddiu $t1, 8 494 daddiu $t2, -8 4954: 496.endm 497 498 /* 499 * Invocation stub for quick code. 500 * On entry: 501 * a0 = method pointer 502 * a1 = argument array that must at least contain the this ptr. 503 * a2 = size of argument array in bytes 504 * a3 = (managed) thread pointer 505 * a4 = JValue* result 506 * a5 = shorty 507 */ 508ENTRY art_quick_invoke_stub 509 # push a4, a5, s0(rSUSPEND), s1(rSELF), s8, ra onto the stack 510 daddiu $sp, $sp, -48 511 .cfi_adjust_cfa_offset 48 512 sd $ra, 40($sp) 513 .cfi_rel_offset 31, 40 514 sd $s8, 32($sp) 515 .cfi_rel_offset 30, 32 516 sd $s1, 24($sp) 517 .cfi_rel_offset 17, 24 518 sd $s0, 16($sp) 519 .cfi_rel_offset 16, 16 520 sd $a5, 8($sp) 521 .cfi_rel_offset 9, 8 522 sd $a4, 0($sp) 523 .cfi_rel_offset 8, 0 524 525 daddiu $s0, $zero, SUSPEND_CHECK_INTERVAL # reset rSUSPEND to SUSPEND_CHECK_INTERVAL 526 move $s1, $a3 # move managed thread pointer into s1 (rSELF) 527 move $s8, $sp # save sp in s8 (fp) 528 529 daddiu $t3, $a2, 20 # add 4 for method* and 16 for stack alignment 530 dsrl $t3, $t3, 4 # shift the frame size right 4 531 dsll $t3, $t3, 4 # shift the frame size left 4 to align to 16 bytes 532 dsubu $sp, $sp, $t3 # reserve stack space for argument array 533 534 daddiu $t0, $a5, 1 # t0 = shorty[1] (skip 1 for return type) 535 daddiu $t1, $a1, 4 # t1 = ptr to arg_array[4] (skip this ptr) 536 daddiu $t2, $a2, -4 # t2 = number of argument bytes remain (skip this ptr) 537 daddiu $v0, $sp, 8 # v0 points to where to copy arg_array 538 LOOP_OVER_SHORTY_LOADING_REG a2, f14, call_fn 539 LOOP_OVER_SHORTY_LOADING_REG a3, f15, call_fn 540 LOOP_OVER_SHORTY_LOADING_REG a4, f16, call_fn 541 LOOP_OVER_SHORTY_LOADING_REG a5, f17, call_fn 542 LOOP_OVER_SHORTY_LOADING_REG a6, f18, call_fn 543 LOOP_OVER_SHORTY_LOADING_REG a7, f19, call_fn 544 545 # copy arguments onto stack (t2 should be multiples of 4) 546 ble $t2, $zero, call_fn # t2 = number of argument bytes remain 5471: 548 lw $t3, 0($t1) # load from argument array 549 daddiu $t1, $t1, 4 550 sw $t3, 0($v0) # save to stack 551 daddiu $t2, -4 552 bgt $t2, $zero, 1b # t2 = number of argument bytes remain 553 daddiu $v0, $v0, 4 554 555call_fn: 556 # call method (a0 and a1 have been untouched) 557 lwu $a1, 0($a1) # make a1 = this ptr 558 sw $a1, 4($sp) # copy this ptr (skip 4 bytes for method*) 559 sw $zero, 0($sp) # store NULL for method* at bottom of frame 560 ld $t9, MIRROR_ART_METHOD_QUICK_CODE_OFFSET_64($a0) # get pointer to the code 561 jalr $t9 # call the method 562 nop 563 move $sp, $s8 # restore sp 564 565 # pop a4, a5, s1(rSELF), s8, ra off of the stack 566 ld $a4, 0($sp) 567 .cfi_restore 8 568 ld $a5, 8($sp) 569 .cfi_restore 9 570 ld $s0, 16($sp) 571 .cfi_restore 16 572 ld $s1, 24($sp) 573 .cfi_restore 17 574 ld $s8, 32($sp) 575 .cfi_restore 30 576 ld $ra, 40($sp) 577 .cfi_restore 31 578 daddiu $sp, $sp, 48 579 .cfi_adjust_cfa_offset -48 580 581 # a4 = JValue* result 582 # a5 = shorty string 583 lbu $t1, 0($a5) # get result type from shorty 584 li $t2, 68 # put char 'D' into t2 585 beq $t1, $t2, 1f # branch if result type char == 'D' 586 li $t3, 70 # put char 'F' into t3 587 beq $t1, $t3, 1f # branch if result type char == 'F' 588 sw $v0, 0($a4) # store the result 589 dsrl $v1, $v0, 32 590 jalr $zero, $ra 591 sw $v1, 4($a4) # store the other half of the result 5921: 593 mfc1 $v0, $f0 594 mfhc1 $v1, $f0 595 sw $v0, 0($a4) # store the result 596 jalr $zero, $ra 597 sw $v1, 4($a4) # store the other half of the result 598END art_quick_invoke_stub 599 600 /* 601 * Invocation static stub for quick code. 602 * On entry: 603 * a0 = method pointer 604 * a1 = argument array that must at least contain the this ptr. 605 * a2 = size of argument array in bytes 606 * a3 = (managed) thread pointer 607 * a4 = JValue* result 608 * a5 = shorty 609 */ 610ENTRY art_quick_invoke_static_stub 611 612 # push a4, a5, s0(rSUSPEND), s1(rSELF), s8, ra, onto the stack 613 daddiu $sp, $sp, -48 614 .cfi_adjust_cfa_offset 48 615 sd $ra, 40($sp) 616 .cfi_rel_offset 31, 40 617 sd $s8, 32($sp) 618 .cfi_rel_offset 30, 32 619 sd $s1, 24($sp) 620 .cfi_rel_offset 17, 24 621 sd $s0, 16($sp) 622 .cfi_rel_offset 16, 16 623 sd $a5, 8($sp) 624 .cfi_rel_offset 9, 8 625 sd $a4, 0($sp) 626 .cfi_rel_offset 8, 0 627 628 daddiu $s0, $zero, SUSPEND_CHECK_INTERVAL # reset rSUSPEND to SUSPEND_CHECK_INTERVAL 629 move $s1, $a3 # move managed thread pointer into s1 (rSELF) 630 move $s8, $sp # save sp in s8 (fp) 631 632 daddiu $t3, $a2, 20 # add 4 for method* and 16 for stack alignment 633 dsrl $t3, $t3, 4 # shift the frame size right 4 634 dsll $t3, $t3, 4 # shift the frame size left 4 to align to 16 bytes 635 dsubu $sp, $sp, $t3 # reserve stack space for argument array 636 637 daddiu $t0, $a5, 1 # t0 = shorty[1] (skip 1 for return type) 638 move $t1, $a1 # t1 = arg_array 639 move $t2, $a2 # t2 = number of argument bytes remain 640 daddiu $v0, $sp, 4 # v0 points to where to copy arg_array 641 LOOP_OVER_SHORTY_LOADING_REG a1, f13, call_sfn 642 LOOP_OVER_SHORTY_LOADING_REG a2, f14, call_sfn 643 LOOP_OVER_SHORTY_LOADING_REG a3, f15, call_sfn 644 LOOP_OVER_SHORTY_LOADING_REG a4, f16, call_sfn 645 LOOP_OVER_SHORTY_LOADING_REG a5, f17, call_sfn 646 LOOP_OVER_SHORTY_LOADING_REG a6, f18, call_sfn 647 LOOP_OVER_SHORTY_LOADING_REG a7, f19, call_sfn 648 649 # copy arguments onto stack (t2 should be multiples of 4) 650 ble $t2, $zero, call_sfn # t2 = number of argument bytes remain 6511: 652 lw $t3, 0($t1) # load from argument array 653 daddiu $t1, $t1, 4 654 sw $t3, 0($v0) # save to stack 655 daddiu $t2, -4 656 bgt $t2, $zero, 1b # t2 = number of argument bytes remain 657 daddiu $v0, $v0, 4 658 659call_sfn: 660 # call method (a0 has been untouched) 661 sw $zero, 0($sp) # store NULL for method* at bottom of frame 662 ld $t9, MIRROR_ART_METHOD_QUICK_CODE_OFFSET_64($a0) # get pointer to the code 663 jalr $t9 # call the method 664 nop 665 move $sp, $s8 # restore sp 666 667 # pop a4, a5, s0(rSUSPEND), s1(rSELF), s8, ra off of the stack 668 ld $a4, 0($sp) 669 .cfi_restore 8 670 ld $a5, 8($sp) 671 .cfi_restore 9 672 ld $s0, 16($sp) 673 .cfi_restore 16 674 ld $s1, 24($sp) 675 .cfi_restore 17 676 ld $s8, 32($sp) 677 .cfi_restore 30 678 ld $ra, 40($sp) 679 .cfi_restore 31 680 daddiu $sp, $sp, 48 681 .cfi_adjust_cfa_offset -48 682 683 # a4 = JValue* result 684 # a5 = shorty string 685 lbu $t1, 0($a5) # get result type from shorty 686 li $t2, 68 # put char 'D' into t2 687 beq $t1, $t2, 1f # branch if result type char == 'D' 688 li $t3, 70 # put char 'F' into t3 689 beq $t1, $t3, 1f # branch if result type char == 'F' 690 sw $v0, 0($a4) # store the result 691 dsrl $v1, $v0, 32 692 jalr $zero, $ra 693 sw $v1, 4($a4) # store the other half of the result 6941: 695 mfc1 $v0, $f0 696 mfhc1 $v1, $f0 697 sw $v0, 0($a4) # store the result 698 jalr $zero, $ra 699 sw $v1, 4($a4) # store the other half of the result 700END art_quick_invoke_static_stub 701 702 703 704UNIMPLEMENTED art_quick_handle_fill_data 705UNIMPLEMENTED art_quick_lock_object 706UNIMPLEMENTED art_quick_unlock_object 707UNIMPLEMENTED art_quick_check_cast 708UNIMPLEMENTED art_quick_aput_obj_with_null_and_bound_check 709UNIMPLEMENTED art_quick_aput_obj_with_bound_check 710UNIMPLEMENTED art_quick_aput_obj 711UNIMPLEMENTED art_quick_initialize_static_storage 712UNIMPLEMENTED art_quick_initialize_type 713UNIMPLEMENTED art_quick_initialize_type_and_verify_access 714UNIMPLEMENTED art_quick_get_boolean_static 715UNIMPLEMENTED art_quick_get_byte_static 716UNIMPLEMENTED art_quick_get_char_static 717UNIMPLEMENTED art_quick_get_short_static 718UNIMPLEMENTED art_quick_get32_static 719UNIMPLEMENTED art_quick_get64_static 720UNIMPLEMENTED art_quick_get_obj_static 721UNIMPLEMENTED art_quick_get_boolean_instance 722UNIMPLEMENTED art_quick_get_byte_instance 723UNIMPLEMENTED art_quick_get_char_instance 724UNIMPLEMENTED art_quick_get_short_instance 725UNIMPLEMENTED art_quick_get32_instance 726UNIMPLEMENTED art_quick_get64_instance 727UNIMPLEMENTED art_quick_get_obj_instance 728UNIMPLEMENTED art_quick_set8_static 729UNIMPLEMENTED art_quick_set16_static 730UNIMPLEMENTED art_quick_set32_static 731UNIMPLEMENTED art_quick_set64_static 732UNIMPLEMENTED art_quick_set_obj_static 733UNIMPLEMENTED art_quick_set8_instance 734UNIMPLEMENTED art_quick_set16_instance 735UNIMPLEMENTED art_quick_set32_instance 736UNIMPLEMENTED art_quick_set64_instance 737UNIMPLEMENTED art_quick_set_obj_instance 738UNIMPLEMENTED art_quick_resolve_string 739 740// Macro to facilitate adding new allocation entrypoints. 741.macro TWO_ARG_DOWNCALL name, entrypoint, return 742ENTRY \name 743 break 744 break 745END \name 746.endm 747 748.macro THREE_ARG_DOWNCALL name, entrypoint, return 749ENTRY \name 750 break 751 break 752END \name 753.endm 754 755// Generate the allocation entrypoints for each allocator. 756GENERATE_ALL_ALLOC_ENTRYPOINTS 757 758UNIMPLEMENTED art_quick_test_suspend 759UNIMPLEMENTED art_quick_proxy_invoke_handler 760UNIMPLEMENTED art_quick_imt_conflict_trampoline 761 762 .extern artQuickResolutionTrampoline 763ENTRY art_quick_resolution_trampoline 764 SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME 765 move $a2, rSELF # pass Thread::Current 766 jal artQuickResolutionTrampoline # (Method* called, receiver, Thread*, SP) 767 move $a3, $sp # pass $sp 768 beq $v0, $zero, 1f 769 lwu $a0, 0($sp) # load resolved method in $a0 770 # artQuickResolutionTrampoline puts resolved method in *SP 771 RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME 772 move $t9, $v0 # code pointer must be in $t9 to generate the global pointer 773 jalr $zero, $t9 # tail call to method 774 nop 7751: 776 RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME 777 DELIVER_PENDING_EXCEPTION 778END art_quick_resolution_trampoline 779 780 .extern artQuickGenericJniTrampoline 781 .extern artQuickGenericJniEndTrampoline 782ENTRY art_quick_generic_jni_trampoline 783 SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL 784 sd $a0, 0($sp) # store native ArtMethod* to bottom of stack 785 move $s8, $sp # save $sp 786 787 # prepare for call to artQuickGenericJniTrampoline(Thread*, SP) 788 move $a0, rSELF # pass Thread::Current 789 move $a1, $sp # pass $sp 790 jal artQuickGenericJniTrampoline # (Thread*, SP) 791 daddiu $sp, $sp, -5120 # reserve space on the stack 792 793 # The C call will have registered the complete save-frame on success. 794 # The result of the call is: 795 # v0: ptr to native code, 0 on error. 796 # v1: ptr to the bottom of the used area of the alloca, can restore stack till here. 797 beq $v0, $zero, 1f # check entry error 798 move $t9, $v0 # save the code ptr 799 move $sp, $v1 # release part of the alloca 800 801 # Load parameters from stack into registers 802 ld $a0, 0($sp) 803 ld $a1, 8($sp) 804 ld $a2, 16($sp) 805 ld $a3, 24($sp) 806 ld $a4, 32($sp) 807 ld $a5, 40($sp) 808 ld $a6, 48($sp) 809 ld $a7, 56($sp) 810 # Load FPRs the same as GPRs. Look at BuildNativeCallFrameStateMachine. 811 l.d $f12, 0($sp) 812 l.d $f13, 8($sp) 813 l.d $f14, 16($sp) 814 l.d $f15, 24($sp) 815 l.d $f16, 32($sp) 816 l.d $f17, 40($sp) 817 l.d $f18, 48($sp) 818 l.d $f19, 56($sp) 819 jalr $t9 # native call 820 daddiu $sp, $sp, 64 821 822 # result sign extension is handled in C code 823 # prepare for call to artQuickGenericJniEndTrampoline(Thread*, result, result_f) 824 move $a0, rSELF # pass Thread::Current 825 move $a1, $v0 826 jal artQuickGenericJniEndTrampoline 827 dmfc1 $a2, $f0 828 829 ld $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_ 830 bne $t0, $zero, 2f # check for pending exceptions 831 move $sp, $s8 # tear down the alloca 832 833 # tear dpown the callee-save frame 834 RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME 835 836 jalr $zero, $ra 837 dmtc1 $v0, $f0 # place return value to FP return value 838 8391: 840 move $sp, $s8 # tear down the alloca 8412: 842 RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME 843 DELIVER_PENDING_EXCEPTION 844END art_quick_generic_jni_trampoline 845 846 .extern artQuickToInterpreterBridge 847ENTRY art_quick_to_interpreter_bridge 848 SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME 849 move $a1, rSELF # pass Thread::Current 850 jal artQuickToInterpreterBridge # (Method* method, Thread*, SP) 851 move $a2, $sp # pass $sp 852 ld $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_ 853 daddiu $sp, $sp, REFS_AND_ARGS_MINUS_REFS_SIZE # skip a0-a7 and f12-f19 854 RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME 855 bne $t0, $zero, 1f 856 dmtc1 $v0, $f0 # place return value to FP return value 857 jalr $zero, $ra 858 dmtc1 $v1, $f1 # place return value to FP return value 8591: 860 DELIVER_PENDING_EXCEPTION 861END art_quick_to_interpreter_bridge 862 863 /* 864 * Routine that intercepts method calls and returns. 865 */ 866 .extern artInstrumentationMethodEntryFromCode 867 .extern artInstrumentationMethodExitFromCode 868ENTRY art_quick_instrumentation_entry 869 SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME 870 daddiu $sp, $sp, -16 # space for saving arg0 871 .cfi_adjust_cfa_offset 16 872 sd $a0, 0($sp) # save arg0 873 move $a3, $ra # pass $ra 874 jal artInstrumentationMethodEntryFromCode # (Method*, Object*, Thread*, RA) 875 move $a2, rSELF # pass Thread::Current 876 move $t9, $v0 # $t9 holds reference to code 877 ld $a0, 0($sp) # restore arg0 878 daddiu $sp, $sp, 16 # remove args 879 .cfi_adjust_cfa_offset -16 880 RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME 881 jalr $t9 # call method 882 nop 883END art_quick_instrumentation_entry 884 /* intentional fallthrough */ 885 .global art_quick_instrumentation_exit 886art_quick_instrumentation_exit: 887 .cfi_startproc 888 daddiu $t9, $ra, 4 # put current address into $t9 to rebuild $gp 889 .cpload $t9 890 move $ra, $zero # link register is to here, so clobber with 0 for later checks 891 SETUP_REFS_ONLY_CALLEE_SAVE_FRAME 892 move $t0, $sp # remember bottom of caller's frame 893 daddiu $sp, $sp, -16 # save return values and set up args 894 .cfi_adjust_cfa_offset 16 895 sd $v0, 0($sp) 896 .cfi_rel_offset 2, 0 897 s.d $f0, 8($sp) 898 mov.d $f15, $f0 # pass fpr result 899 move $a2, $v0 # pass gpr result 900 move $a1, $t0 # pass $sp 901 jal artInstrumentationMethodExitFromCode # (Thread*, SP, gpr_res, fpr_res) 902 move $a0, rSELF # pass Thread::Current 903 move $t0, $v0 # set aside returned link register 904 move $ra, $v1 # set link register for deoptimization 905 ld $v0, 0($sp) # restore return values 906 l.d $f0, 8($sp) 907 jalr $zero, $t0 # return 908 daddiu $sp, $sp, 16+FRAME_SIZE_REFS_ONLY_CALLEE_SAVE # 16 bytes of saved values + ref_only callee save frame 909 .cfi_adjust_cfa_offset -(16+FRAME_SIZE_REFS_ONLY_CALLEE_SAVE) 910END art_quick_instrumentation_exit 911 912UNIMPLEMENTED art_quick_deoptimize 913UNIMPLEMENTED art_quick_indexof 914UNIMPLEMENTED art_quick_string_compareto 915