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"
3126
3127 /**
3128 * Arguments:
3129 *
3130 * Input:
3131 * c_rarg0 - x address
3132 * c_rarg1 - x length
3133 * c_rarg2 - y address
3134 * c_rarg3 - y length
3135 * not Win64
3136 * c_rarg4 - z address
3137 * Win64
3138 * rsp+40 - z address
3139 */
3140 address StubGenerator::generate_multiplyToLen() {
3141 __ align(CodeEntryAlignment);
3142 StubId stub_id = StubId::stubgen_multiplyToLen_id;
3143 StubCodeMark mark(this, stub_id);
3144 address start = __ pc();
3145
3146 // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3147 // Unix: rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
3148 const Register x = rdi;
3149 const Register xlen = rax;
3150 const Register y = rsi;
3151 const Register ylen = rcx;
3152 const Register z = r8;
3153
3154 // Next registers will be saved on stack in multiply_to_len().
3155 const Register tmp0 = r11;
3156 const Register tmp1 = r12;
3157 const Register tmp2 = r13;
3158 const Register tmp3 = r14;
3159 const Register tmp4 = r15;
3160 const Register tmp5 = rbx;
3161
3162 BLOCK_COMMENT("Entry:");
3163 __ enter(); // required for proper stackwalking of RuntimeStub frame
3164
3165 setup_arg_regs(4); // x => rdi, xlen => rsi, y => rdx
3166 // ylen => rcx, z => r8
3167 // r9 and r10 may be used to save non-volatile registers
3168 #ifdef _WIN64
3169 // last argument (#4) is on stack on Win64
3170 __ movptr(z, Address(rsp, 6 * wordSize));
3171 #endif
3172
3173 __ movptr(xlen, rsi);
3174 __ movptr(y, rdx);
3175 __ multiply_to_len(x, xlen, y, ylen, z, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
3176
3177 restore_arg_regs();
3178
3179 __ leave(); // required for proper stackwalking of RuntimeStub frame
3180 __ ret(0);
3181
3182 return start;
3183 }
3184
3185 /**
3186 * Arguments:
3187 *
3188 * Input:
3189 * c_rarg0 - obja address
3190 * c_rarg1 - objb address
3191 * c_rarg3 - length length
3192 * c_rarg4 - scale log2_array_indxscale
3193 *
3194 * Output:
3195 * rax - int >= mismatched index, < 0 bitwise complement of tail
3196 */
3197 address StubGenerator::generate_vectorizedMismatch() {
3198 __ align(CodeEntryAlignment);
3199 StubId stub_id = StubId::stubgen_vectorizedMismatch_id;
3200 StubCodeMark mark(this, stub_id);
3201 address start = __ pc();
3235 return start;
3236 }
3237
3238 /**
3239 * Arguments:
3240 *
3241 // Input:
3242 // c_rarg0 - x address
3243 // c_rarg1 - x length
3244 // c_rarg2 - z address
3245 // c_rarg3 - z length
3246 *
3247 */
3248 address StubGenerator::generate_squareToLen() {
3249
3250 __ align(CodeEntryAlignment);
3251 StubId stub_id = StubId::stubgen_squareToLen_id;
3252 StubCodeMark mark(this, stub_id);
3253 address start = __ pc();
3254
3255 // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3256 // Unix: rdi, rsi, rdx, rcx (c_rarg0, c_rarg1, ...)
3257 const Register x = rdi;
3258 const Register len = rsi;
3259 const Register z = r8;
3260 const Register zlen = rcx;
3261
3262 const Register tmp1 = r12;
3263 const Register tmp2 = r13;
3264 const Register tmp3 = r14;
3265 const Register tmp4 = r15;
3266 const Register tmp5 = rbx;
3267
3268 BLOCK_COMMENT("Entry:");
3269 __ enter(); // required for proper stackwalking of RuntimeStub frame
3270
3271 setup_arg_regs(4); // x => rdi, len => rsi, z => rdx
3272 // zlen => rcx
3273 // r9 and r10 may be used to save non-volatile registers
3274 __ movptr(r8, rdx);
3275 __ square_to_len(x, len, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
3276
3277 restore_arg_regs();
3278
3279 __ leave(); // required for proper stackwalking of RuntimeStub frame
3280 __ ret(0);
3281
3282 return start;
3283 }
3284
3285 address StubGenerator::generate_method_entry_barrier() {
3286 __ align(CodeEntryAlignment);
3287 StubId stub_id = StubId::stubgen_method_entry_barrier_id;
3288 StubCodeMark mark(this, stub_id);
3289 address start = __ pc();
3290
3291 Label deoptimize_label;
3292
3293 __ push(-1); // cookie, this is used for writing the new rsp when deoptimizing
3294
3295 BLOCK_COMMENT("Entry:");
3296 __ enter(); // save rbp
3297
3298 // save c_rarg0, because we want to use that value.
3299 // We could do without it but then we depend on the number of slots used by pusha
3300 __ push_ppx(c_rarg0);
3301
3361
3362 /**
3363 * Arguments:
3364 *
3365 * Input:
3366 * c_rarg0 - out address
3367 * c_rarg1 - in address
3368 * c_rarg2 - offset
3369 * c_rarg3 - len
3370 * not Win64
3371 * c_rarg4 - k
3372 * Win64
3373 * rsp+40 - k
3374 */
3375 address StubGenerator::generate_mulAdd() {
3376 __ align(CodeEntryAlignment);
3377 StubId stub_id = StubId::stubgen_mulAdd_id;
3378 StubCodeMark mark(this, stub_id);
3379 address start = __ pc();
3380
3381 // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3382 // Unix: rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
3383 const Register out = rdi;
3384 const Register in = rsi;
3385 const Register offset = r11;
3386 const Register len = rcx;
3387 const Register k = r8;
3388
3389 // Next registers will be saved on stack in mul_add().
3390 const Register tmp1 = r12;
3391 const Register tmp2 = r13;
3392 const Register tmp3 = r14;
3393 const Register tmp4 = r15;
3394 const Register tmp5 = rbx;
3395
3396 BLOCK_COMMENT("Entry:");
3397 __ enter(); // required for proper stackwalking of RuntimeStub frame
3398
3399 setup_arg_regs(4); // out => rdi, in => rsi, offset => rdx
3400 // len => rcx, k => r8
3401 // r9 and r10 may be used to save non-volatile registers
3402 #ifdef _WIN64
3403 // last argument is on stack on Win64
3404 __ movl(k, Address(rsp, 6 * wordSize));
3405 #endif
3406 __ movptr(r11, rdx); // move offset in rdx to offset(r11)
3407 __ mul_add(out, in, offset, len, k, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
3408
3409 restore_arg_regs();
3410
3411 __ leave(); // required for proper stackwalking of RuntimeStub frame
3412 __ ret(0);
3413
3414 return start;
3415 }
3416
3417 address StubGenerator::generate_bigIntegerRightShift() {
3418 __ align(CodeEntryAlignment);
3419 StubId stub_id = StubId::stubgen_bigIntegerRightShiftWorker_id;
3420 StubCodeMark mark(this, stub_id);
3421 address start = __ pc();
3422
3423 Label Shift512Loop, ShiftTwo, ShiftTwoLoop, ShiftOne, Exit;
3424 // For Unix, the arguments are as follows: rdi, rsi, rdx, rcx, r8.
3425 const Register newArr = rdi;
3426 const Register oldArr = rsi;
3427 const Register newIdx = rdx;
3428 const Register shiftCount = rcx; // It was intentional to have shiftCount in rcx since it is used implicitly for shift.
3429 const Register totalNumIter = r8;
3430
3431 // For windows, we use r9 and r10 as temps to save rdi and rsi. Thus we cannot allocate them for our temps.
3432 // For everything else, we prefer using r9 and r10 since we do not have to save them before use.
3433 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/aotCodeCache.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"
3127
3128 /**
3129 * Arguments:
3130 *
3131 * Input:
3132 * c_rarg0 - x address
3133 * c_rarg1 - x length
3134 * c_rarg2 - y address
3135 * c_rarg3 - y length
3136 * not Win64
3137 * c_rarg4 - z address
3138 * Win64
3139 * rsp+40 - z address
3140 */
3141 address StubGenerator::generate_multiplyToLen() {
3142 __ align(CodeEntryAlignment);
3143 StubId stub_id = StubId::stubgen_multiplyToLen_id;
3144 StubCodeMark mark(this, stub_id);
3145 address start = __ pc();
3146
3147 if (AOTCodeCache::load_stub(this, vmIntrinsics::_multiplyToLen, "multiplyToLen", start)) {
3148 return start;
3149 }
3150
3151 // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3152 // Unix: rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
3153 const Register x = rdi;
3154 const Register xlen = rax;
3155 const Register y = rsi;
3156 const Register ylen = rcx;
3157 const Register z = r8;
3158
3159 // Next registers will be saved on stack in multiply_to_len().
3160 const Register tmp0 = r11;
3161 const Register tmp1 = r12;
3162 const Register tmp2 = r13;
3163 const Register tmp3 = r14;
3164 const Register tmp4 = r15;
3165 const Register tmp5 = rbx;
3166
3167 BLOCK_COMMENT("Entry:");
3168 __ enter(); // required for proper stackwalking of RuntimeStub frame
3169
3170 setup_arg_regs(4); // x => rdi, xlen => rsi, y => rdx
3171 // ylen => rcx, z => r8
3172 // r9 and r10 may be used to save non-volatile registers
3173 #ifdef _WIN64
3174 // last argument (#4) is on stack on Win64
3175 __ movptr(z, Address(rsp, 6 * wordSize));
3176 #endif
3177
3178 __ movptr(xlen, rsi);
3179 __ movptr(y, rdx);
3180 __ multiply_to_len(x, xlen, y, ylen, z, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
3181
3182 restore_arg_regs();
3183
3184 __ leave(); // required for proper stackwalking of RuntimeStub frame
3185 __ ret(0);
3186
3187 AOTCodeCache::store_stub(this, vmIntrinsics::_multiplyToLen, "multiplyToLen", start);
3188 return start;
3189 }
3190
3191 /**
3192 * Arguments:
3193 *
3194 * Input:
3195 * c_rarg0 - obja address
3196 * c_rarg1 - objb address
3197 * c_rarg3 - length length
3198 * c_rarg4 - scale log2_array_indxscale
3199 *
3200 * Output:
3201 * rax - int >= mismatched index, < 0 bitwise complement of tail
3202 */
3203 address StubGenerator::generate_vectorizedMismatch() {
3204 __ align(CodeEntryAlignment);
3205 StubId stub_id = StubId::stubgen_vectorizedMismatch_id;
3206 StubCodeMark mark(this, stub_id);
3207 address start = __ pc();
3241 return start;
3242 }
3243
3244 /**
3245 * Arguments:
3246 *
3247 // Input:
3248 // c_rarg0 - x address
3249 // c_rarg1 - x length
3250 // c_rarg2 - z address
3251 // c_rarg3 - z length
3252 *
3253 */
3254 address StubGenerator::generate_squareToLen() {
3255
3256 __ align(CodeEntryAlignment);
3257 StubId stub_id = StubId::stubgen_squareToLen_id;
3258 StubCodeMark mark(this, stub_id);
3259 address start = __ pc();
3260
3261 if (AOTCodeCache::load_stub(this, vmIntrinsics::_squareToLen, "squareToLen", start)) {
3262 return start;
3263 }
3264
3265 // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3266 // Unix: rdi, rsi, rdx, rcx (c_rarg0, c_rarg1, ...)
3267 const Register x = rdi;
3268 const Register len = rsi;
3269 const Register z = r8;
3270 const Register zlen = rcx;
3271
3272 const Register tmp1 = r12;
3273 const Register tmp2 = r13;
3274 const Register tmp3 = r14;
3275 const Register tmp4 = r15;
3276 const Register tmp5 = rbx;
3277
3278 BLOCK_COMMENT("Entry:");
3279 __ enter(); // required for proper stackwalking of RuntimeStub frame
3280
3281 setup_arg_regs(4); // x => rdi, len => rsi, z => rdx
3282 // zlen => rcx
3283 // r9 and r10 may be used to save non-volatile registers
3284 __ movptr(r8, rdx);
3285 __ square_to_len(x, len, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
3286
3287 restore_arg_regs();
3288
3289 __ leave(); // required for proper stackwalking of RuntimeStub frame
3290 __ ret(0);
3291
3292 AOTCodeCache::store_stub(this, vmIntrinsics::_squareToLen, "squareToLen", start);
3293 return start;
3294 }
3295
3296 address StubGenerator::generate_method_entry_barrier() {
3297 __ align(CodeEntryAlignment);
3298 StubId stub_id = StubId::stubgen_method_entry_barrier_id;
3299 StubCodeMark mark(this, stub_id);
3300 address start = __ pc();
3301
3302 Label deoptimize_label;
3303
3304 __ push(-1); // cookie, this is used for writing the new rsp when deoptimizing
3305
3306 BLOCK_COMMENT("Entry:");
3307 __ enter(); // save rbp
3308
3309 // save c_rarg0, because we want to use that value.
3310 // We could do without it but then we depend on the number of slots used by pusha
3311 __ push_ppx(c_rarg0);
3312
3372
3373 /**
3374 * Arguments:
3375 *
3376 * Input:
3377 * c_rarg0 - out address
3378 * c_rarg1 - in address
3379 * c_rarg2 - offset
3380 * c_rarg3 - len
3381 * not Win64
3382 * c_rarg4 - k
3383 * Win64
3384 * rsp+40 - k
3385 */
3386 address StubGenerator::generate_mulAdd() {
3387 __ align(CodeEntryAlignment);
3388 StubId stub_id = StubId::stubgen_mulAdd_id;
3389 StubCodeMark mark(this, stub_id);
3390 address start = __ pc();
3391
3392 if (AOTCodeCache::load_stub(this, vmIntrinsics::_mulAdd, "mulAdd", start)) {
3393 return start;
3394 }
3395
3396 // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3397 // Unix: rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
3398 const Register out = rdi;
3399 const Register in = rsi;
3400 const Register offset = r11;
3401 const Register len = rcx;
3402 const Register k = r8;
3403
3404 // Next registers will be saved on stack in mul_add().
3405 const Register tmp1 = r12;
3406 const Register tmp2 = r13;
3407 const Register tmp3 = r14;
3408 const Register tmp4 = r15;
3409 const Register tmp5 = rbx;
3410
3411 BLOCK_COMMENT("Entry:");
3412 __ enter(); // required for proper stackwalking of RuntimeStub frame
3413
3414 setup_arg_regs(4); // out => rdi, in => rsi, offset => rdx
3415 // len => rcx, k => r8
3416 // r9 and r10 may be used to save non-volatile registers
3417 #ifdef _WIN64
3418 // last argument is on stack on Win64
3419 __ movl(k, Address(rsp, 6 * wordSize));
3420 #endif
3421 __ movptr(r11, rdx); // move offset in rdx to offset(r11)
3422 __ mul_add(out, in, offset, len, k, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
3423
3424 restore_arg_regs();
3425
3426 __ leave(); // required for proper stackwalking of RuntimeStub frame
3427 __ ret(0);
3428
3429 AOTCodeCache::store_stub(this, vmIntrinsics::_mulAdd, "mulAdd", start);
3430 return start;
3431 }
3432
3433 address StubGenerator::generate_bigIntegerRightShift() {
3434 __ align(CodeEntryAlignment);
3435 StubId stub_id = StubId::stubgen_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.
|