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"
3148
3149 /**
3150 * Arguments:
3151 *
3152 * Input:
3153 * c_rarg0 - x address
3154 * c_rarg1 - x length
3155 * c_rarg2 - y address
3156 * c_rarg3 - y length
3157 * not Win64
3158 * c_rarg4 - z address
3159 * Win64
3160 * rsp+40 - z address
3161 */
3162 address StubGenerator::generate_multiplyToLen() {
3163 __ align(CodeEntryAlignment);
3164 StubGenStubId stub_id = StubGenStubId::multiplyToLen_id;
3165 StubCodeMark mark(this, stub_id);
3166 address start = __ pc();
3167
3168 // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3169 // Unix: rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
3170 const Register x = rdi;
3171 const Register xlen = rax;
3172 const Register y = rsi;
3173 const Register ylen = rcx;
3174 const Register z = r8;
3175
3176 // Next registers will be saved on stack in multiply_to_len().
3177 const Register tmp0 = r11;
3178 const Register tmp1 = r12;
3179 const Register tmp2 = r13;
3180 const Register tmp3 = r14;
3181 const Register tmp4 = r15;
3182 const Register tmp5 = rbx;
3183
3184 BLOCK_COMMENT("Entry:");
3185 __ enter(); // required for proper stackwalking of RuntimeStub frame
3186
3187 setup_arg_regs(4); // x => rdi, xlen => rsi, y => rdx
3188 // ylen => rcx, z => r8
3189 // r9 and r10 may be used to save non-volatile registers
3190 #ifdef _WIN64
3191 // last argument (#4) is on stack on Win64
3192 __ movptr(z, Address(rsp, 6 * wordSize));
3193 #endif
3194
3195 __ movptr(xlen, rsi);
3196 __ movptr(y, rdx);
3197 __ multiply_to_len(x, xlen, y, ylen, z, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
3198
3199 restore_arg_regs();
3200
3201 __ leave(); // required for proper stackwalking of RuntimeStub frame
3202 __ ret(0);
3203
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 // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3278 // Unix: rdi, rsi, rdx, rcx (c_rarg0, c_rarg1, ...)
3279 const Register x = rdi;
3280 const Register len = rsi;
3281 const Register z = r8;
3282 const Register zlen = rcx;
3283
3284 const Register tmp1 = r12;
3285 const Register tmp2 = r13;
3286 const Register tmp3 = r14;
3287 const Register tmp4 = r15;
3288 const Register tmp5 = rbx;
3289
3290 BLOCK_COMMENT("Entry:");
3291 __ enter(); // required for proper stackwalking of RuntimeStub frame
3292
3293 setup_arg_regs(4); // x => rdi, len => rsi, z => rdx
3294 // zlen => rcx
3295 // r9 and r10 may be used to save non-volatile registers
3296 __ movptr(r8, rdx);
3297 __ square_to_len(x, len, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
3298
3299 restore_arg_regs();
3300
3301 __ leave(); // required for proper stackwalking of RuntimeStub frame
3302 __ ret(0);
3303
3304 return start;
3305 }
3306
3307 address StubGenerator::generate_method_entry_barrier() {
3308 __ align(CodeEntryAlignment);
3309 StubGenStubId stub_id = StubGenStubId::method_entry_barrier_id;
3310 StubCodeMark mark(this, stub_id);
3311 address start = __ pc();
3312
3313 Label deoptimize_label;
3314
3315 __ push(-1); // cookie, this is used for writing the new rsp when deoptimizing
3316
3317 BLOCK_COMMENT("Entry:");
3318 __ enter(); // save rbp
3319
3320 // save c_rarg0, because we want to use that value.
3321 // We could do without it but then we depend on the number of slots used by pusha
3322 __ push(c_rarg0);
3323
3383
3384 /**
3385 * Arguments:
3386 *
3387 * Input:
3388 * c_rarg0 - out address
3389 * c_rarg1 - in address
3390 * c_rarg2 - offset
3391 * c_rarg3 - len
3392 * not Win64
3393 * c_rarg4 - k
3394 * Win64
3395 * rsp+40 - k
3396 */
3397 address StubGenerator::generate_mulAdd() {
3398 __ align(CodeEntryAlignment);
3399 StubGenStubId stub_id = StubGenStubId::mulAdd_id;
3400 StubCodeMark mark(this, stub_id);
3401 address start = __ pc();
3402
3403 // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3404 // Unix: rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
3405 const Register out = rdi;
3406 const Register in = rsi;
3407 const Register offset = r11;
3408 const Register len = rcx;
3409 const Register k = r8;
3410
3411 // Next registers will be saved on stack in mul_add().
3412 const Register tmp1 = r12;
3413 const Register tmp2 = r13;
3414 const Register tmp3 = r14;
3415 const Register tmp4 = r15;
3416 const Register tmp5 = rbx;
3417
3418 BLOCK_COMMENT("Entry:");
3419 __ enter(); // required for proper stackwalking of RuntimeStub frame
3420
3421 setup_arg_regs(4); // out => rdi, in => rsi, offset => rdx
3422 // len => rcx, k => r8
3423 // r9 and r10 may be used to save non-volatile registers
3424 #ifdef _WIN64
3425 // last argument is on stack on Win64
3426 __ movl(k, Address(rsp, 6 * wordSize));
3427 #endif
3428 __ movptr(r11, rdx); // move offset in rdx to offset(r11)
3429 __ mul_add(out, in, offset, len, k, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
3430
3431 restore_arg_regs();
3432
3433 __ leave(); // required for proper stackwalking of RuntimeStub frame
3434 __ ret(0);
3435
3436 return start;
3437 }
3438
3439 address StubGenerator::generate_bigIntegerRightShift() {
3440 __ align(CodeEntryAlignment);
3441 StubGenStubId stub_id = StubGenStubId::bigIntegerRightShiftWorker_id;
3442 StubCodeMark mark(this, stub_id);
3443 address start = __ pc();
3444
3445 Label Shift512Loop, ShiftTwo, ShiftTwoLoop, ShiftOne, Exit;
3446 // For Unix, the arguments are as follows: rdi, rsi, rdx, rcx, r8.
3447 const Register newArr = rdi;
3448 const Register oldArr = rsi;
3449 const Register newIdx = rdx;
3450 const Register shiftCount = rcx; // It was intentional to have shiftCount in rcx since it is used implicitly for shift.
3451 const Register totalNumIter = r8;
3452
3453 // For windows, we use r9 and r10 as temps to save rdi and rsi. Thus we cannot allocate them for our temps.
3454 // For everything else, we prefer using r9 and r10 since we do not have to save them before use.
3455 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"
3149
3150 /**
3151 * Arguments:
3152 *
3153 * Input:
3154 * c_rarg0 - x address
3155 * c_rarg1 - x length
3156 * c_rarg2 - y address
3157 * c_rarg3 - y length
3158 * not Win64
3159 * c_rarg4 - z address
3160 * Win64
3161 * rsp+40 - z address
3162 */
3163 address StubGenerator::generate_multiplyToLen() {
3164 __ align(CodeEntryAlignment);
3165 StubGenStubId stub_id = StubGenStubId::multiplyToLen_id;
3166 StubCodeMark mark(this, stub_id);
3167 address start = __ pc();
3168
3169 if (SCCache::load_stub(this, vmIntrinsics::_multiplyToLen, "multiplyToLen", start)) {
3170 return start;
3171 }
3172
3173 // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3174 // Unix: rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
3175 const Register x = rdi;
3176 const Register xlen = rax;
3177 const Register y = rsi;
3178 const Register ylen = rcx;
3179 const Register z = r8;
3180
3181 // Next registers will be saved on stack in multiply_to_len().
3182 const Register tmp0 = r11;
3183 const Register tmp1 = r12;
3184 const Register tmp2 = r13;
3185 const Register tmp3 = r14;
3186 const Register tmp4 = r15;
3187 const Register tmp5 = rbx;
3188
3189 BLOCK_COMMENT("Entry:");
3190 __ enter(); // required for proper stackwalking of RuntimeStub frame
3191
3192 setup_arg_regs(4); // x => rdi, xlen => rsi, y => rdx
3193 // ylen => rcx, z => r8
3194 // r9 and r10 may be used to save non-volatile registers
3195 #ifdef _WIN64
3196 // last argument (#4) is on stack on Win64
3197 __ movptr(z, Address(rsp, 6 * wordSize));
3198 #endif
3199
3200 __ movptr(xlen, rsi);
3201 __ movptr(y, rdx);
3202 __ multiply_to_len(x, xlen, y, ylen, z, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
3203
3204 restore_arg_regs();
3205
3206 __ leave(); // required for proper stackwalking of RuntimeStub frame
3207 __ ret(0);
3208
3209 SCCache::store_stub(this, vmIntrinsics::_multiplyToLen, "multiplyToLen", start);
3210 return start;
3211 }
3212
3213 /**
3214 * Arguments:
3215 *
3216 * Input:
3217 * c_rarg0 - obja address
3218 * c_rarg1 - objb address
3219 * c_rarg3 - length length
3220 * c_rarg4 - scale log2_array_indxscale
3221 *
3222 * Output:
3223 * rax - int >= mismatched index, < 0 bitwise complement of tail
3224 */
3225 address StubGenerator::generate_vectorizedMismatch() {
3226 __ align(CodeEntryAlignment);
3227 StubGenStubId stub_id = StubGenStubId::vectorizedMismatch_id;
3228 StubCodeMark mark(this, stub_id);
3229 address start = __ pc();
3263 return start;
3264 }
3265
3266 /**
3267 * Arguments:
3268 *
3269 // Input:
3270 // c_rarg0 - x address
3271 // c_rarg1 - x length
3272 // c_rarg2 - z address
3273 // c_rarg3 - z length
3274 *
3275 */
3276 address StubGenerator::generate_squareToLen() {
3277
3278 __ align(CodeEntryAlignment);
3279 StubGenStubId stub_id = StubGenStubId::squareToLen_id;
3280 StubCodeMark mark(this, stub_id);
3281 address start = __ pc();
3282
3283 if (SCCache::load_stub(this, vmIntrinsics::_squareToLen, "squareToLen", start)) {
3284 return start;
3285 }
3286
3287 // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3288 // Unix: rdi, rsi, rdx, rcx (c_rarg0, c_rarg1, ...)
3289 const Register x = rdi;
3290 const Register len = rsi;
3291 const Register z = r8;
3292 const Register zlen = rcx;
3293
3294 const Register tmp1 = r12;
3295 const Register tmp2 = r13;
3296 const Register tmp3 = r14;
3297 const Register tmp4 = r15;
3298 const Register tmp5 = rbx;
3299
3300 BLOCK_COMMENT("Entry:");
3301 __ enter(); // required for proper stackwalking of RuntimeStub frame
3302
3303 setup_arg_regs(4); // x => rdi, len => rsi, z => rdx
3304 // zlen => rcx
3305 // r9 and r10 may be used to save non-volatile registers
3306 __ movptr(r8, rdx);
3307 __ square_to_len(x, len, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
3308
3309 restore_arg_regs();
3310
3311 __ leave(); // required for proper stackwalking of RuntimeStub frame
3312 __ ret(0);
3313
3314 SCCache::store_stub(this, vmIntrinsics::_squareToLen, "squareToLen", start);
3315 return start;
3316 }
3317
3318 address StubGenerator::generate_method_entry_barrier() {
3319 __ align(CodeEntryAlignment);
3320 StubGenStubId stub_id = StubGenStubId::method_entry_barrier_id;
3321 StubCodeMark mark(this, stub_id);
3322 address start = __ pc();
3323
3324 Label deoptimize_label;
3325
3326 __ push(-1); // cookie, this is used for writing the new rsp when deoptimizing
3327
3328 BLOCK_COMMENT("Entry:");
3329 __ enter(); // save rbp
3330
3331 // save c_rarg0, because we want to use that value.
3332 // We could do without it but then we depend on the number of slots used by pusha
3333 __ push(c_rarg0);
3334
3394
3395 /**
3396 * Arguments:
3397 *
3398 * Input:
3399 * c_rarg0 - out address
3400 * c_rarg1 - in address
3401 * c_rarg2 - offset
3402 * c_rarg3 - len
3403 * not Win64
3404 * c_rarg4 - k
3405 * Win64
3406 * rsp+40 - k
3407 */
3408 address StubGenerator::generate_mulAdd() {
3409 __ align(CodeEntryAlignment);
3410 StubGenStubId stub_id = StubGenStubId::mulAdd_id;
3411 StubCodeMark mark(this, stub_id);
3412 address start = __ pc();
3413
3414 if (SCCache::load_stub(this, vmIntrinsics::_mulAdd, "mulAdd", start)) {
3415 return start;
3416 }
3417
3418 // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3419 // Unix: rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
3420 const Register out = rdi;
3421 const Register in = rsi;
3422 const Register offset = r11;
3423 const Register len = rcx;
3424 const Register k = r8;
3425
3426 // Next registers will be saved on stack in mul_add().
3427 const Register tmp1 = r12;
3428 const Register tmp2 = r13;
3429 const Register tmp3 = r14;
3430 const Register tmp4 = r15;
3431 const Register tmp5 = rbx;
3432
3433 BLOCK_COMMENT("Entry:");
3434 __ enter(); // required for proper stackwalking of RuntimeStub frame
3435
3436 setup_arg_regs(4); // out => rdi, in => rsi, offset => rdx
3437 // len => rcx, k => r8
3438 // r9 and r10 may be used to save non-volatile registers
3439 #ifdef _WIN64
3440 // last argument is on stack on Win64
3441 __ movl(k, Address(rsp, 6 * wordSize));
3442 #endif
3443 __ movptr(r11, rdx); // move offset in rdx to offset(r11)
3444 __ mul_add(out, in, offset, len, k, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
3445
3446 restore_arg_regs();
3447
3448 __ leave(); // required for proper stackwalking of RuntimeStub frame
3449 __ ret(0);
3450
3451 SCCache::store_stub(this, vmIntrinsics::_mulAdd, "mulAdd", start);
3452 return start;
3453 }
3454
3455 address StubGenerator::generate_bigIntegerRightShift() {
3456 __ align(CodeEntryAlignment);
3457 StubGenStubId stub_id = StubGenStubId::bigIntegerRightShiftWorker_id;
3458 StubCodeMark mark(this, stub_id);
3459 address start = __ pc();
3460
3461 Label Shift512Loop, ShiftTwo, ShiftTwoLoop, ShiftOne, Exit;
3462 // For Unix, the arguments are as follows: rdi, rsi, rdx, rcx, r8.
3463 const Register newArr = rdi;
3464 const Register oldArr = rsi;
3465 const Register newIdx = rdx;
3466 const Register shiftCount = rcx; // It was intentional to have shiftCount in rcx since it is used implicitly for shift.
3467 const Register totalNumIter = r8;
3468
3469 // For windows, we use r9 and r10 as temps to save rdi and rsi. Thus we cannot allocate them for our temps.
3470 // For everything else, we prefer using r9 and r10 since we do not have to save them before use.
3471 const Register tmp1 = r11; // Caller save.
|