8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "asm/macroAssembler.hpp"
26 #include "classfile/javaClasses.hpp"
27 #include "classfile/vmIntrinsics.hpp"
28 #include "compiler/oopMap.hpp"
29 #include "gc/shared/barrierSet.hpp"
30 #include "gc/shared/barrierSetAssembler.hpp"
31 #include "gc/shared/barrierSetNMethod.hpp"
32 #include "gc/shared/gc_globals.hpp"
33 #include "memory/universe.hpp"
34 #include "prims/jvmtiExport.hpp"
35 #include "prims/upcallLinker.hpp"
36 #include "runtime/arguments.hpp"
37 #include "runtime/continuationEntry.hpp"
38 #include "runtime/javaThread.hpp"
39 #include "runtime/sharedRuntime.hpp"
40 #include "runtime/stubRoutines.hpp"
41 #include "stubGenerator_x86_64.hpp"
42 #ifdef COMPILER2
43 #include "opto/runtime.hpp"
44 #include "opto/c2_globals.hpp"
45 #endif
46 #if INCLUDE_JVMCI
47 #include "jvmci/jvmci_globals.hpp"
3142
3143 /**
3144 * Arguments:
3145 *
3146 * Input:
3147 * c_rarg0 - x address
3148 * c_rarg1 - x length
3149 * c_rarg2 - y address
3150 * c_rarg3 - y length
3151 * not Win64
3152 * c_rarg4 - z address
3153 * Win64
3154 * rsp+40 - z address
3155 */
3156 address StubGenerator::generate_multiplyToLen() {
3157 __ align(CodeEntryAlignment);
3158 StubGenStubId stub_id = StubGenStubId::multiplyToLen_id;
3159 StubCodeMark mark(this, stub_id);
3160 address start = __ pc();
3161
3162 // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3163 // Unix: rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
3164 const Register x = rdi;
3165 const Register xlen = rax;
3166 const Register y = rsi;
3167 const Register ylen = rcx;
3168 const Register z = r8;
3169
3170 // Next registers will be saved on stack in multiply_to_len().
3171 const Register tmp0 = r11;
3172 const Register tmp1 = r12;
3173 const Register tmp2 = r13;
3174 const Register tmp3 = r14;
3175 const Register tmp4 = r15;
3176 const Register tmp5 = rbx;
3177
3178 BLOCK_COMMENT("Entry:");
3179 __ enter(); // required for proper stackwalking of RuntimeStub frame
3180
3181 setup_arg_regs(4); // x => rdi, xlen => rsi, y => rdx
3182 // ylen => rcx, z => r8
3183 // r9 and r10 may be used to save non-volatile registers
3184 #ifdef _WIN64
3185 // last argument (#4) is on stack on Win64
3186 __ movptr(z, Address(rsp, 6 * wordSize));
3187 #endif
3188
3189 __ movptr(xlen, rsi);
3190 __ movptr(y, rdx);
3191 __ multiply_to_len(x, xlen, y, ylen, z, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
3192
3193 restore_arg_regs();
3194
3195 __ leave(); // required for proper stackwalking of RuntimeStub frame
3196 __ ret(0);
3197
3198 return start;
3199 }
3200
3201 /**
3202 * Arguments:
3203 *
3204 * Input:
3205 * c_rarg0 - obja address
3206 * c_rarg1 - objb address
3207 * c_rarg3 - length length
3208 * c_rarg4 - scale log2_array_indxscale
3209 *
3210 * Output:
3211 * rax - int >= mismatched index, < 0 bitwise complement of tail
3212 */
3213 address StubGenerator::generate_vectorizedMismatch() {
3214 __ align(CodeEntryAlignment);
3215 StubGenStubId stub_id = StubGenStubId::vectorizedMismatch_id;
3216 StubCodeMark mark(this, stub_id);
3217 address start = __ pc();
3251 return start;
3252 }
3253
3254 /**
3255 * Arguments:
3256 *
3257 // Input:
3258 // c_rarg0 - x address
3259 // c_rarg1 - x length
3260 // c_rarg2 - z address
3261 // c_rarg3 - z length
3262 *
3263 */
3264 address StubGenerator::generate_squareToLen() {
3265
3266 __ align(CodeEntryAlignment);
3267 StubGenStubId stub_id = StubGenStubId::squareToLen_id;
3268 StubCodeMark mark(this, stub_id);
3269 address start = __ pc();
3270
3271 // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3272 // Unix: rdi, rsi, rdx, rcx (c_rarg0, c_rarg1, ...)
3273 const Register x = rdi;
3274 const Register len = rsi;
3275 const Register z = r8;
3276 const Register zlen = rcx;
3277
3278 const Register tmp1 = r12;
3279 const Register tmp2 = r13;
3280 const Register tmp3 = r14;
3281 const Register tmp4 = r15;
3282 const Register tmp5 = rbx;
3283
3284 BLOCK_COMMENT("Entry:");
3285 __ enter(); // required for proper stackwalking of RuntimeStub frame
3286
3287 setup_arg_regs(4); // x => rdi, len => rsi, z => rdx
3288 // zlen => rcx
3289 // r9 and r10 may be used to save non-volatile registers
3290 __ movptr(r8, rdx);
3291 __ square_to_len(x, len, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
3292
3293 restore_arg_regs();
3294
3295 __ leave(); // required for proper stackwalking of RuntimeStub frame
3296 __ ret(0);
3297
3298 return start;
3299 }
3300
3301 address StubGenerator::generate_method_entry_barrier() {
3302 __ align(CodeEntryAlignment);
3303 StubGenStubId stub_id = StubGenStubId::method_entry_barrier_id;
3304 StubCodeMark mark(this, stub_id);
3305 address start = __ pc();
3306
3307 Label deoptimize_label;
3308
3309 __ push(-1); // cookie, this is used for writing the new rsp when deoptimizing
3310
3311 BLOCK_COMMENT("Entry:");
3312 __ enter(); // save rbp
3313
3314 // save c_rarg0, because we want to use that value.
3315 // We could do without it but then we depend on the number of slots used by pusha
3316 __ push(c_rarg0);
3317
3377
3378 /**
3379 * Arguments:
3380 *
3381 * Input:
3382 * c_rarg0 - out address
3383 * c_rarg1 - in address
3384 * c_rarg2 - offset
3385 * c_rarg3 - len
3386 * not Win64
3387 * c_rarg4 - k
3388 * Win64
3389 * rsp+40 - k
3390 */
3391 address StubGenerator::generate_mulAdd() {
3392 __ align(CodeEntryAlignment);
3393 StubGenStubId stub_id = StubGenStubId::mulAdd_id;
3394 StubCodeMark mark(this, stub_id);
3395 address start = __ pc();
3396
3397 // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3398 // Unix: rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
3399 const Register out = rdi;
3400 const Register in = rsi;
3401 const Register offset = r11;
3402 const Register len = rcx;
3403 const Register k = r8;
3404
3405 // Next registers will be saved on stack in mul_add().
3406 const Register tmp1 = r12;
3407 const Register tmp2 = r13;
3408 const Register tmp3 = r14;
3409 const Register tmp4 = r15;
3410 const Register tmp5 = rbx;
3411
3412 BLOCK_COMMENT("Entry:");
3413 __ enter(); // required for proper stackwalking of RuntimeStub frame
3414
3415 setup_arg_regs(4); // out => rdi, in => rsi, offset => rdx
3416 // len => rcx, k => r8
3417 // r9 and r10 may be used to save non-volatile registers
3418 #ifdef _WIN64
3419 // last argument is on stack on Win64
3420 __ movl(k, Address(rsp, 6 * wordSize));
3421 #endif
3422 __ movptr(r11, rdx); // move offset in rdx to offset(r11)
3423 __ mul_add(out, in, offset, len, k, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
3424
3425 restore_arg_regs();
3426
3427 __ leave(); // required for proper stackwalking of RuntimeStub frame
3428 __ ret(0);
3429
3430 return start;
3431 }
3432
3433 address StubGenerator::generate_bigIntegerRightShift() {
3434 __ align(CodeEntryAlignment);
3435 StubGenStubId stub_id = StubGenStubId::bigIntegerRightShiftWorker_id;
3436 StubCodeMark mark(this, stub_id);
3437 address start = __ pc();
3438
3439 Label Shift512Loop, ShiftTwo, ShiftTwoLoop, ShiftOne, Exit;
3440 // For Unix, the arguments are as follows: rdi, rsi, rdx, rcx, r8.
3441 const Register newArr = rdi;
3442 const Register oldArr = rsi;
3443 const Register newIdx = rdx;
3444 const Register shiftCount = rcx; // It was intentional to have shiftCount in rcx since it is used implicitly for shift.
3445 const Register totalNumIter = r8;
3446
3447 // For windows, we use r9 and r10 as temps to save rdi and rsi. Thus we cannot allocate them for our temps.
3448 // For everything else, we prefer using r9 and r10 since we do not have to save them before use.
3449 const Register tmp1 = r11; // Caller save.
|
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "asm/macroAssembler.hpp"
26 #include "classfile/javaClasses.hpp"
27 #include "classfile/vmIntrinsics.hpp"
28 #include "code/SCCache.hpp"
29 #include "compiler/oopMap.hpp"
30 #include "gc/shared/barrierSet.hpp"
31 #include "gc/shared/barrierSetAssembler.hpp"
32 #include "gc/shared/barrierSetNMethod.hpp"
33 #include "gc/shared/gc_globals.hpp"
34 #include "memory/universe.hpp"
35 #include "prims/jvmtiExport.hpp"
36 #include "prims/upcallLinker.hpp"
37 #include "runtime/arguments.hpp"
38 #include "runtime/continuationEntry.hpp"
39 #include "runtime/javaThread.hpp"
40 #include "runtime/sharedRuntime.hpp"
41 #include "runtime/stubRoutines.hpp"
42 #include "stubGenerator_x86_64.hpp"
43 #ifdef COMPILER2
44 #include "opto/runtime.hpp"
45 #include "opto/c2_globals.hpp"
46 #endif
47 #if INCLUDE_JVMCI
48 #include "jvmci/jvmci_globals.hpp"
3143
3144 /**
3145 * Arguments:
3146 *
3147 * Input:
3148 * c_rarg0 - x address
3149 * c_rarg1 - x length
3150 * c_rarg2 - y address
3151 * c_rarg3 - y length
3152 * not Win64
3153 * c_rarg4 - z address
3154 * Win64
3155 * rsp+40 - z address
3156 */
3157 address StubGenerator::generate_multiplyToLen() {
3158 __ align(CodeEntryAlignment);
3159 StubGenStubId stub_id = StubGenStubId::multiplyToLen_id;
3160 StubCodeMark mark(this, stub_id);
3161 address start = __ pc();
3162
3163 if (SCCache::load_stub(this, vmIntrinsics::_multiplyToLen, "multiplyToLen", start)) {
3164 return start;
3165 }
3166
3167 // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3168 // Unix: rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
3169 const Register x = rdi;
3170 const Register xlen = rax;
3171 const Register y = rsi;
3172 const Register ylen = rcx;
3173 const Register z = r8;
3174
3175 // Next registers will be saved on stack in multiply_to_len().
3176 const Register tmp0 = r11;
3177 const Register tmp1 = r12;
3178 const Register tmp2 = r13;
3179 const Register tmp3 = r14;
3180 const Register tmp4 = r15;
3181 const Register tmp5 = rbx;
3182
3183 BLOCK_COMMENT("Entry:");
3184 __ enter(); // required for proper stackwalking of RuntimeStub frame
3185
3186 setup_arg_regs(4); // x => rdi, xlen => rsi, y => rdx
3187 // ylen => rcx, z => r8
3188 // r9 and r10 may be used to save non-volatile registers
3189 #ifdef _WIN64
3190 // last argument (#4) is on stack on Win64
3191 __ movptr(z, Address(rsp, 6 * wordSize));
3192 #endif
3193
3194 __ movptr(xlen, rsi);
3195 __ movptr(y, rdx);
3196 __ multiply_to_len(x, xlen, y, ylen, z, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
3197
3198 restore_arg_regs();
3199
3200 __ leave(); // required for proper stackwalking of RuntimeStub frame
3201 __ ret(0);
3202
3203 SCCache::store_stub(this, vmIntrinsics::_multiplyToLen, "multiplyToLen", start);
3204 return start;
3205 }
3206
3207 /**
3208 * Arguments:
3209 *
3210 * Input:
3211 * c_rarg0 - obja address
3212 * c_rarg1 - objb address
3213 * c_rarg3 - length length
3214 * c_rarg4 - scale log2_array_indxscale
3215 *
3216 * Output:
3217 * rax - int >= mismatched index, < 0 bitwise complement of tail
3218 */
3219 address StubGenerator::generate_vectorizedMismatch() {
3220 __ align(CodeEntryAlignment);
3221 StubGenStubId stub_id = StubGenStubId::vectorizedMismatch_id;
3222 StubCodeMark mark(this, stub_id);
3223 address start = __ pc();
3257 return start;
3258 }
3259
3260 /**
3261 * Arguments:
3262 *
3263 // Input:
3264 // c_rarg0 - x address
3265 // c_rarg1 - x length
3266 // c_rarg2 - z address
3267 // c_rarg3 - z length
3268 *
3269 */
3270 address StubGenerator::generate_squareToLen() {
3271
3272 __ align(CodeEntryAlignment);
3273 StubGenStubId stub_id = StubGenStubId::squareToLen_id;
3274 StubCodeMark mark(this, stub_id);
3275 address start = __ pc();
3276
3277 if (SCCache::load_stub(this, vmIntrinsics::_squareToLen, "squareToLen", start)) {
3278 return start;
3279 }
3280
3281 // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3282 // Unix: rdi, rsi, rdx, rcx (c_rarg0, c_rarg1, ...)
3283 const Register x = rdi;
3284 const Register len = rsi;
3285 const Register z = r8;
3286 const Register zlen = rcx;
3287
3288 const Register tmp1 = r12;
3289 const Register tmp2 = r13;
3290 const Register tmp3 = r14;
3291 const Register tmp4 = r15;
3292 const Register tmp5 = rbx;
3293
3294 BLOCK_COMMENT("Entry:");
3295 __ enter(); // required for proper stackwalking of RuntimeStub frame
3296
3297 setup_arg_regs(4); // x => rdi, len => rsi, z => rdx
3298 // zlen => rcx
3299 // r9 and r10 may be used to save non-volatile registers
3300 __ movptr(r8, rdx);
3301 __ square_to_len(x, len, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
3302
3303 restore_arg_regs();
3304
3305 __ leave(); // required for proper stackwalking of RuntimeStub frame
3306 __ ret(0);
3307
3308 SCCache::store_stub(this, vmIntrinsics::_squareToLen, "squareToLen", start);
3309 return start;
3310 }
3311
3312 address StubGenerator::generate_method_entry_barrier() {
3313 __ align(CodeEntryAlignment);
3314 StubGenStubId stub_id = StubGenStubId::method_entry_barrier_id;
3315 StubCodeMark mark(this, stub_id);
3316 address start = __ pc();
3317
3318 Label deoptimize_label;
3319
3320 __ push(-1); // cookie, this is used for writing the new rsp when deoptimizing
3321
3322 BLOCK_COMMENT("Entry:");
3323 __ enter(); // save rbp
3324
3325 // save c_rarg0, because we want to use that value.
3326 // We could do without it but then we depend on the number of slots used by pusha
3327 __ push(c_rarg0);
3328
3388
3389 /**
3390 * Arguments:
3391 *
3392 * Input:
3393 * c_rarg0 - out address
3394 * c_rarg1 - in address
3395 * c_rarg2 - offset
3396 * c_rarg3 - len
3397 * not Win64
3398 * c_rarg4 - k
3399 * Win64
3400 * rsp+40 - k
3401 */
3402 address StubGenerator::generate_mulAdd() {
3403 __ align(CodeEntryAlignment);
3404 StubGenStubId stub_id = StubGenStubId::mulAdd_id;
3405 StubCodeMark mark(this, stub_id);
3406 address start = __ pc();
3407
3408 if (SCCache::load_stub(this, vmIntrinsics::_mulAdd, "mulAdd", start)) {
3409 return start;
3410 }
3411
3412 // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3413 // Unix: rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
3414 const Register out = rdi;
3415 const Register in = rsi;
3416 const Register offset = r11;
3417 const Register len = rcx;
3418 const Register k = r8;
3419
3420 // Next registers will be saved on stack in mul_add().
3421 const Register tmp1 = r12;
3422 const Register tmp2 = r13;
3423 const Register tmp3 = r14;
3424 const Register tmp4 = r15;
3425 const Register tmp5 = rbx;
3426
3427 BLOCK_COMMENT("Entry:");
3428 __ enter(); // required for proper stackwalking of RuntimeStub frame
3429
3430 setup_arg_regs(4); // out => rdi, in => rsi, offset => rdx
3431 // len => rcx, k => r8
3432 // r9 and r10 may be used to save non-volatile registers
3433 #ifdef _WIN64
3434 // last argument is on stack on Win64
3435 __ movl(k, Address(rsp, 6 * wordSize));
3436 #endif
3437 __ movptr(r11, rdx); // move offset in rdx to offset(r11)
3438 __ mul_add(out, in, offset, len, k, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
3439
3440 restore_arg_regs();
3441
3442 __ leave(); // required for proper stackwalking of RuntimeStub frame
3443 __ ret(0);
3444
3445 SCCache::store_stub(this, vmIntrinsics::_mulAdd, "mulAdd", start);
3446 return start;
3447 }
3448
3449 address StubGenerator::generate_bigIntegerRightShift() {
3450 __ align(CodeEntryAlignment);
3451 StubGenStubId stub_id = StubGenStubId::bigIntegerRightShiftWorker_id;
3452 StubCodeMark mark(this, stub_id);
3453 address start = __ pc();
3454
3455 Label Shift512Loop, ShiftTwo, ShiftTwoLoop, ShiftOne, Exit;
3456 // For Unix, the arguments are as follows: rdi, rsi, rdx, rcx, r8.
3457 const Register newArr = rdi;
3458 const Register oldArr = rsi;
3459 const Register newIdx = rdx;
3460 const Register shiftCount = rcx; // It was intentional to have shiftCount in rcx since it is used implicitly for shift.
3461 const Register totalNumIter = r8;
3462
3463 // For windows, we use r9 and r10 as temps to save rdi and rsi. Thus we cannot allocate them for our temps.
3464 // For everything else, we prefer using r9 and r10 since we do not have to save them before use.
3465 const Register tmp1 = r11; // Caller save.
|