10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 #include "asm/macroAssembler.hpp"
27 #include "asm/macroAssembler.inline.hpp"
28 #include "asm/register.hpp"
29 #include "atomic_aarch64.hpp"
30 #include "compiler/oopMap.hpp"
31 #include "gc/shared/barrierSet.hpp"
32 #include "gc/shared/barrierSetAssembler.hpp"
33 #include "gc/shared/gc_globals.hpp"
34 #include "gc/shared/tlab_globals.hpp"
35 #include "interpreter/interpreter.hpp"
36 #include "memory/universe.hpp"
37 #include "nativeInst_aarch64.hpp"
38 #include "oops/instanceOop.hpp"
39 #include "oops/method.hpp"
40 #include "oops/objArrayKlass.hpp"
41 #include "oops/oop.inline.hpp"
42 #include "prims/methodHandles.hpp"
43 #include "prims/upcallLinker.hpp"
44 #include "runtime/arguments.hpp"
45 #include "runtime/atomic.hpp"
46 #include "runtime/continuation.hpp"
47 #include "runtime/continuationEntry.inline.hpp"
48 #include "runtime/frame.inline.hpp"
49 #include "runtime/handles.inline.hpp"
7386 __ add(s1, s1, temp0);
7387 __ add(s2, s2, temp1);
7388 }
7389
7390 /**
7391 * Arguments:
7392 *
7393 * Input:
7394 * c_rarg0 - x address
7395 * c_rarg1 - x length
7396 * c_rarg2 - y address
7397 * c_rarg3 - y length
7398 * c_rarg4 - z address
7399 */
7400 address generate_multiplyToLen() {
7401 __ align(CodeEntryAlignment);
7402 StubGenStubId stub_id = StubGenStubId::multiplyToLen_id;
7403 StubCodeMark mark(this, stub_id);
7404
7405 address start = __ pc();
7406 const Register x = r0;
7407 const Register xlen = r1;
7408 const Register y = r2;
7409 const Register ylen = r3;
7410 const Register z = r4;
7411
7412 const Register tmp0 = r5;
7413 const Register tmp1 = r10;
7414 const Register tmp2 = r11;
7415 const Register tmp3 = r12;
7416 const Register tmp4 = r13;
7417 const Register tmp5 = r14;
7418 const Register tmp6 = r15;
7419 const Register tmp7 = r16;
7420
7421 BLOCK_COMMENT("Entry:");
7422 __ enter(); // required for proper stackwalking of RuntimeStub frame
7423 __ multiply_to_len(x, xlen, y, ylen, z, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7);
7424 __ leave(); // required for proper stackwalking of RuntimeStub frame
7425 __ ret(lr);
7426
7427 return start;
7428 }
7429
7430 address generate_squareToLen() {
7431 // squareToLen algorithm for sizes 1..127 described in java code works
7432 // faster than multiply_to_len on some CPUs and slower on others, but
7433 // multiply_to_len shows a bit better overall results
7434 __ align(CodeEntryAlignment);
7435 StubGenStubId stub_id = StubGenStubId::squareToLen_id;
7436 StubCodeMark mark(this, stub_id);
7437 address start = __ pc();
7438
7439 const Register x = r0;
7440 const Register xlen = r1;
7441 const Register z = r2;
7442 const Register y = r4; // == x
7443 const Register ylen = r5; // == xlen
7444
7445 const Register tmp0 = r3;
7446 const Register tmp1 = r10;
7447 const Register tmp2 = r11;
7448 const Register tmp3 = r12;
7449 const Register tmp4 = r13;
7450 const Register tmp5 = r14;
7451 const Register tmp6 = r15;
7452 const Register tmp7 = r16;
7453
7454 RegSet spilled_regs = RegSet::of(y, ylen);
7455 BLOCK_COMMENT("Entry:");
7456 __ enter();
7457 __ push(spilled_regs, sp);
7458 __ mov(y, x);
7459 __ mov(ylen, xlen);
7460 __ multiply_to_len(x, xlen, y, ylen, z, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7);
7461 __ pop(spilled_regs, sp);
7462 __ leave();
7463 __ ret(lr);
7464 return start;
7465 }
7466
7467 address generate_mulAdd() {
7468 __ align(CodeEntryAlignment);
7469 StubGenStubId stub_id = StubGenStubId::mulAdd_id;
7470 StubCodeMark mark(this, stub_id);
7471
7472 address start = __ pc();
7473
7474 const Register out = r0;
7475 const Register in = r1;
7476 const Register offset = r2;
7477 const Register len = r3;
7478 const Register k = r4;
7479
7480 BLOCK_COMMENT("Entry:");
7481 __ enter();
7482 __ mul_add(out, in, offset, len, k);
7483 __ leave();
7484 __ ret(lr);
7485
7486 return start;
7487 }
7488
7489 // Arguments:
7490 //
7491 // Input:
7492 // c_rarg0 - newArr address
7493 // c_rarg1 - oldArr address
7494 // c_rarg2 - newIdx
7495 // c_rarg3 - shiftCount
7496 // c_rarg4 - numIter
7497 //
7498 address generate_bigIntegerRightShift() {
7499 __ align(CodeEntryAlignment);
7500 StubGenStubId stub_id = StubGenStubId::bigIntegerRightShiftWorker_id;
7501 StubCodeMark mark(this, stub_id);
7502 address start = __ pc();
7503
7504 Label ShiftSIMDLoop, ShiftTwoLoop, ShiftThree, ShiftTwo, ShiftOne, Exit;
7505
11276 // MACC(Ra, Ra, t0, t1, t2);
11277 // }
11278 // iters = (2*len-i)/2;
11279 // assert(iters == len-j, "must be");
11280 // for (; iters--; j++) {
11281 // assert(Rm == Pm_base[j] && Rn == Pn_base[i-j], "must be");
11282 // MACC(Rm, Rn, t0, t1, t2);
11283 // Rm = *++Pm;
11284 // Rn = *--Pn;
11285 // }
11286 // Pm_base[i-len] = t0;
11287 // t0 = t1; t1 = t2; t2 = 0;
11288 // }
11289
11290 // while (t0)
11291 // t0 = sub(Pm_base, Pn_base, t0, len);
11292 // }
11293 };
11294
11295 // Initialization
11296 void generate_initial_stubs() {
11297 // Generate initial stubs and initializes the entry points
11298
11299 // entry points that exist in all platforms Note: This is code
11300 // that could be shared among different platforms - however the
11301 // benefit seems to be smaller than the disadvantage of having a
11302 // much more complicated generator structure. See also comment in
11303 // stubRoutines.hpp.
11304
11305 StubRoutines::_forward_exception_entry = generate_forward_exception();
11306
11307 StubRoutines::_call_stub_entry =
11308 generate_call_stub(StubRoutines::_call_stub_return_address);
11309
11310 // is referenced by megamorphic call
11311 StubRoutines::_catch_exception_entry = generate_catch_exception();
11312
11313 // Initialize table for copy memory (arraycopy) check.
11314 if (UnsafeMemoryAccess::_table == nullptr) {
11315 UnsafeMemoryAccess::create_table(8 + 4); // 8 for copyMemory; 4 for setMemory
11515 StubRoutines::_sha3_implCompress = generate_sha3_implCompress(StubGenStubId::sha3_implCompress_id);
11516 StubRoutines::_double_keccak = generate_double_keccak();
11517 StubRoutines::_sha3_implCompressMB = generate_sha3_implCompress(StubGenStubId::sha3_implCompressMB_id);
11518 }
11519
11520 if (UsePoly1305Intrinsics) {
11521 StubRoutines::_poly1305_processBlocks = generate_poly1305_processBlocks();
11522 }
11523
11524 // generate Adler32 intrinsics code
11525 if (UseAdler32Intrinsics) {
11526 StubRoutines::_updateBytesAdler32 = generate_updateBytesAdler32();
11527 }
11528
11529 #endif // COMPILER2_OR_JVMCI
11530 }
11531
11532 public:
11533 StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) {
11534 switch(blob_id) {
11535 case initial_id:
11536 generate_initial_stubs();
11537 break;
11538 case continuation_id:
11539 generate_continuation_stubs();
11540 break;
11541 case compiler_id:
11542 generate_compiler_stubs();
11543 break;
11544 case final_id:
11545 generate_final_stubs();
11546 break;
11547 default:
11548 fatal("unexpected blob id: %d", blob_id);
11549 break;
11550 };
11551 }
11552 }; // end class declaration
11553
11554 void StubGenerator_generate(CodeBuffer* code, StubGenBlobId blob_id) {
|
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 #include "asm/macroAssembler.hpp"
27 #include "asm/macroAssembler.inline.hpp"
28 #include "asm/register.hpp"
29 #include "atomic_aarch64.hpp"
30 #include "code/aotCodeCache.hpp"
31 #include "compiler/oopMap.hpp"
32 #include "gc/shared/barrierSet.hpp"
33 #include "gc/shared/barrierSetAssembler.hpp"
34 #include "gc/shared/gc_globals.hpp"
35 #include "gc/shared/tlab_globals.hpp"
36 #include "interpreter/interpreter.hpp"
37 #include "memory/universe.hpp"
38 #include "nativeInst_aarch64.hpp"
39 #include "oops/instanceOop.hpp"
40 #include "oops/method.hpp"
41 #include "oops/objArrayKlass.hpp"
42 #include "oops/oop.inline.hpp"
43 #include "prims/methodHandles.hpp"
44 #include "prims/upcallLinker.hpp"
45 #include "runtime/arguments.hpp"
46 #include "runtime/atomic.hpp"
47 #include "runtime/continuation.hpp"
48 #include "runtime/continuationEntry.inline.hpp"
49 #include "runtime/frame.inline.hpp"
50 #include "runtime/handles.inline.hpp"
7387 __ add(s1, s1, temp0);
7388 __ add(s2, s2, temp1);
7389 }
7390
7391 /**
7392 * Arguments:
7393 *
7394 * Input:
7395 * c_rarg0 - x address
7396 * c_rarg1 - x length
7397 * c_rarg2 - y address
7398 * c_rarg3 - y length
7399 * c_rarg4 - z address
7400 */
7401 address generate_multiplyToLen() {
7402 __ align(CodeEntryAlignment);
7403 StubGenStubId stub_id = StubGenStubId::multiplyToLen_id;
7404 StubCodeMark mark(this, stub_id);
7405
7406 address start = __ pc();
7407
7408 if (AOTCodeCache::load_stub(this, vmIntrinsics::_multiplyToLen, "multiplyToLen", start)) {
7409 return start;
7410 }
7411 const Register x = r0;
7412 const Register xlen = r1;
7413 const Register y = r2;
7414 const Register ylen = r3;
7415 const Register z = r4;
7416
7417 const Register tmp0 = r5;
7418 const Register tmp1 = r10;
7419 const Register tmp2 = r11;
7420 const Register tmp3 = r12;
7421 const Register tmp4 = r13;
7422 const Register tmp5 = r14;
7423 const Register tmp6 = r15;
7424 const Register tmp7 = r16;
7425
7426 BLOCK_COMMENT("Entry:");
7427 __ enter(); // required for proper stackwalking of RuntimeStub frame
7428 __ multiply_to_len(x, xlen, y, ylen, z, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7);
7429 __ leave(); // required for proper stackwalking of RuntimeStub frame
7430 __ ret(lr);
7431
7432 AOTCodeCache::store_stub(this, vmIntrinsics::_multiplyToLen, "multiplyToLen", start);
7433 return start;
7434 }
7435
7436 address generate_squareToLen() {
7437 // squareToLen algorithm for sizes 1..127 described in java code works
7438 // faster than multiply_to_len on some CPUs and slower on others, but
7439 // multiply_to_len shows a bit better overall results
7440 __ align(CodeEntryAlignment);
7441 StubGenStubId stub_id = StubGenStubId::squareToLen_id;
7442 StubCodeMark mark(this, stub_id);
7443 address start = __ pc();
7444
7445 if (AOTCodeCache::load_stub(this, vmIntrinsics::_squareToLen, "squareToLen", start)) {
7446 return start;
7447 }
7448 const Register x = r0;
7449 const Register xlen = r1;
7450 const Register z = r2;
7451 const Register y = r4; // == x
7452 const Register ylen = r5; // == xlen
7453
7454 const Register tmp0 = r3;
7455 const Register tmp1 = r10;
7456 const Register tmp2 = r11;
7457 const Register tmp3 = r12;
7458 const Register tmp4 = r13;
7459 const Register tmp5 = r14;
7460 const Register tmp6 = r15;
7461 const Register tmp7 = r16;
7462
7463 RegSet spilled_regs = RegSet::of(y, ylen);
7464 BLOCK_COMMENT("Entry:");
7465 __ enter();
7466 __ push(spilled_regs, sp);
7467 __ mov(y, x);
7468 __ mov(ylen, xlen);
7469 __ multiply_to_len(x, xlen, y, ylen, z, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7);
7470 __ pop(spilled_regs, sp);
7471 __ leave();
7472 __ ret(lr);
7473
7474 AOTCodeCache::store_stub(this, vmIntrinsics::_squareToLen, "squareToLen", start);
7475 return start;
7476 }
7477
7478 address generate_mulAdd() {
7479 __ align(CodeEntryAlignment);
7480 StubGenStubId stub_id = StubGenStubId::mulAdd_id;
7481 StubCodeMark mark(this, stub_id);
7482
7483 address start = __ pc();
7484
7485 if (AOTCodeCache::load_stub(this, vmIntrinsics::_mulAdd, "mulAdd", start)) {
7486 return start;
7487 }
7488 const Register out = r0;
7489 const Register in = r1;
7490 const Register offset = r2;
7491 const Register len = r3;
7492 const Register k = r4;
7493
7494 BLOCK_COMMENT("Entry:");
7495 __ enter();
7496 __ mul_add(out, in, offset, len, k);
7497 __ leave();
7498 __ ret(lr);
7499
7500 AOTCodeCache::store_stub(this, vmIntrinsics::_mulAdd, "mulAdd", start);
7501 return start;
7502 }
7503
7504 // Arguments:
7505 //
7506 // Input:
7507 // c_rarg0 - newArr address
7508 // c_rarg1 - oldArr address
7509 // c_rarg2 - newIdx
7510 // c_rarg3 - shiftCount
7511 // c_rarg4 - numIter
7512 //
7513 address generate_bigIntegerRightShift() {
7514 __ align(CodeEntryAlignment);
7515 StubGenStubId stub_id = StubGenStubId::bigIntegerRightShiftWorker_id;
7516 StubCodeMark mark(this, stub_id);
7517 address start = __ pc();
7518
7519 Label ShiftSIMDLoop, ShiftTwoLoop, ShiftThree, ShiftTwo, ShiftOne, Exit;
7520
11291 // MACC(Ra, Ra, t0, t1, t2);
11292 // }
11293 // iters = (2*len-i)/2;
11294 // assert(iters == len-j, "must be");
11295 // for (; iters--; j++) {
11296 // assert(Rm == Pm_base[j] && Rn == Pn_base[i-j], "must be");
11297 // MACC(Rm, Rn, t0, t1, t2);
11298 // Rm = *++Pm;
11299 // Rn = *--Pn;
11300 // }
11301 // Pm_base[i-len] = t0;
11302 // t0 = t1; t1 = t2; t2 = 0;
11303 // }
11304
11305 // while (t0)
11306 // t0 = sub(Pm_base, Pn_base, t0, len);
11307 // }
11308 };
11309
11310 // Initialization
11311 void generate_preuniverse_stubs() {
11312 // preuniverse stubs are not needed for aarch64
11313 }
11314
11315 void generate_initial_stubs() {
11316 // Generate initial stubs and initializes the entry points
11317
11318 // entry points that exist in all platforms Note: This is code
11319 // that could be shared among different platforms - however the
11320 // benefit seems to be smaller than the disadvantage of having a
11321 // much more complicated generator structure. See also comment in
11322 // stubRoutines.hpp.
11323
11324 StubRoutines::_forward_exception_entry = generate_forward_exception();
11325
11326 StubRoutines::_call_stub_entry =
11327 generate_call_stub(StubRoutines::_call_stub_return_address);
11328
11329 // is referenced by megamorphic call
11330 StubRoutines::_catch_exception_entry = generate_catch_exception();
11331
11332 // Initialize table for copy memory (arraycopy) check.
11333 if (UnsafeMemoryAccess::_table == nullptr) {
11334 UnsafeMemoryAccess::create_table(8 + 4); // 8 for copyMemory; 4 for setMemory
11534 StubRoutines::_sha3_implCompress = generate_sha3_implCompress(StubGenStubId::sha3_implCompress_id);
11535 StubRoutines::_double_keccak = generate_double_keccak();
11536 StubRoutines::_sha3_implCompressMB = generate_sha3_implCompress(StubGenStubId::sha3_implCompressMB_id);
11537 }
11538
11539 if (UsePoly1305Intrinsics) {
11540 StubRoutines::_poly1305_processBlocks = generate_poly1305_processBlocks();
11541 }
11542
11543 // generate Adler32 intrinsics code
11544 if (UseAdler32Intrinsics) {
11545 StubRoutines::_updateBytesAdler32 = generate_updateBytesAdler32();
11546 }
11547
11548 #endif // COMPILER2_OR_JVMCI
11549 }
11550
11551 public:
11552 StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) {
11553 switch(blob_id) {
11554 case preuniverse_id:
11555 generate_preuniverse_stubs();
11556 break;
11557 case initial_id:
11558 generate_initial_stubs();
11559 break;
11560 case continuation_id:
11561 generate_continuation_stubs();
11562 break;
11563 case compiler_id:
11564 generate_compiler_stubs();
11565 break;
11566 case final_id:
11567 generate_final_stubs();
11568 break;
11569 default:
11570 fatal("unexpected blob id: %d", blob_id);
11571 break;
11572 };
11573 }
11574 }; // end class declaration
11575
11576 void StubGenerator_generate(CodeBuffer* code, StubGenBlobId blob_id) {
|