Mercurial > hg > truffle
comparison src/cpu/x86/vm/stubGenerator_x86_64.cpp @ 11222:8f33568d693d
Merge
author | Christos Kotselidis <christos.kotselidis@oracle.com> |
---|---|
date | Tue, 06 Aug 2013 14:39:47 +0200 |
parents | 6b0fd0964b87 |
children | 2d4df4c43ae2 |
comparison
equal
deleted
inserted
replaced
11221:8d4bd13c6983 | 11222:8f33568d693d |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
79 | 79 |
80 class StubGenerator: public StubCodeGenerator { | 80 class StubGenerator: public StubCodeGenerator { |
81 private: | 81 private: |
82 | 82 |
83 #ifdef PRODUCT | 83 #ifdef PRODUCT |
84 #define inc_counter_np(counter) (0) | 84 #define inc_counter_np(counter) ((void)0) |
85 #else | 85 #else |
86 void inc_counter_np_(int& counter) { | 86 void inc_counter_np_(int& counter) { |
87 // This can destroy rscratch1 if counter is far from the code cache | 87 // This can destroy rscratch1 if counter is far from the code cache |
88 __ incrementl(ExternalAddress((address)&counter)); | 88 __ incrementl(ExternalAddress((address)&counter)); |
89 } | 89 } |
277 { | 277 { |
278 Label skip_ldmx; | 278 Label skip_ldmx; |
279 __ stmxcsr(mxcsr_save); | 279 __ stmxcsr(mxcsr_save); |
280 __ movl(rax, mxcsr_save); | 280 __ movl(rax, mxcsr_save); |
281 __ andl(rax, MXCSR_MASK); // Only check control and mask bits | 281 __ andl(rax, MXCSR_MASK); // Only check control and mask bits |
282 ExternalAddress mxcsr_std(StubRoutines::x86::mxcsr_std()); | 282 ExternalAddress mxcsr_std(StubRoutines::addr_mxcsr_std()); |
283 __ cmp32(rax, mxcsr_std); | 283 __ cmp32(rax, mxcsr_std); |
284 __ jcc(Assembler::equal, skip_ldmx); | 284 __ jcc(Assembler::equal, skip_ldmx); |
285 __ ldmxcsr(mxcsr_std); | 285 __ ldmxcsr(mxcsr_std); |
286 __ bind(skip_ldmx); | 286 __ bind(skip_ldmx); |
287 } | 287 } |
727 | 727 |
728 const Address mxcsr_save(rsp, 0); | 728 const Address mxcsr_save(rsp, 0); |
729 | 729 |
730 if (CheckJNICalls) { | 730 if (CheckJNICalls) { |
731 Label ok_ret; | 731 Label ok_ret; |
732 ExternalAddress mxcsr_std(StubRoutines::addr_mxcsr_std()); | |
732 __ push(rax); | 733 __ push(rax); |
733 __ subptr(rsp, wordSize); // allocate a temp location | 734 __ subptr(rsp, wordSize); // allocate a temp location |
734 __ stmxcsr(mxcsr_save); | 735 __ stmxcsr(mxcsr_save); |
735 __ movl(rax, mxcsr_save); | 736 __ movl(rax, mxcsr_save); |
736 __ andl(rax, MXCSR_MASK); // Only check control and mask bits | 737 __ andl(rax, MXCSR_MASK); // Only check control and mask bits |
737 __ cmpl(rax, *(int *)(StubRoutines::x86::mxcsr_std())); | 738 __ cmp32(rax, mxcsr_std); |
738 __ jcc(Assembler::equal, ok_ret); | 739 __ jcc(Assembler::equal, ok_ret); |
739 | 740 |
740 __ warn("MXCSR changed by native JNI code, use -XX:+RestoreMXCSROnJNICall"); | 741 __ warn("MXCSR changed by native JNI code, use -XX:+RestoreMXCSROnJNICall"); |
741 | 742 |
742 __ ldmxcsr(ExternalAddress(StubRoutines::x86::mxcsr_std())); | 743 __ ldmxcsr(mxcsr_std); |
743 | 744 |
744 __ bind(ok_ret); | 745 __ bind(ok_ret); |
745 __ addptr(rsp, wordSize); | 746 __ addptr(rsp, wordSize); |
746 __ pop(rax); | 747 __ pop(rax); |
747 } | 748 } |
3355 __ jmp(L_exit); | 3356 __ jmp(L_exit); |
3356 | 3357 |
3357 return start; | 3358 return start; |
3358 } | 3359 } |
3359 | 3360 |
3360 | 3361 // Safefetch stubs. |
3362 void generate_safefetch(const char* name, int size, address* entry, | |
3363 address* fault_pc, address* continuation_pc) { | |
3364 // safefetch signatures: | |
3365 // int SafeFetch32(int* adr, int errValue); | |
3366 // intptr_t SafeFetchN (intptr_t* adr, intptr_t errValue); | |
3367 // | |
3368 // arguments: | |
3369 // c_rarg0 = adr | |
3370 // c_rarg1 = errValue | |
3371 // | |
3372 // result: | |
3373 // PPC_RET = *adr or errValue | |
3374 | |
3375 StubCodeMark mark(this, "StubRoutines", name); | |
3376 | |
3377 // Entry point, pc or function descriptor. | |
3378 *entry = __ pc(); | |
3379 | |
3380 // Load *adr into c_rarg1, may fault. | |
3381 *fault_pc = __ pc(); | |
3382 switch (size) { | |
3383 case 4: | |
3384 // int32_t | |
3385 __ movl(c_rarg1, Address(c_rarg0, 0)); | |
3386 break; | |
3387 case 8: | |
3388 // int64_t | |
3389 __ movq(c_rarg1, Address(c_rarg0, 0)); | |
3390 break; | |
3391 default: | |
3392 ShouldNotReachHere(); | |
3393 } | |
3394 | |
3395 // return errValue or *adr | |
3396 *continuation_pc = __ pc(); | |
3397 __ movq(rax, c_rarg1); | |
3398 __ ret(0); | |
3399 } | |
3361 | 3400 |
3362 // This is a version of CBC/AES Decrypt which does 4 blocks in a loop at a time | 3401 // This is a version of CBC/AES Decrypt which does 4 blocks in a loop at a time |
3363 // to hide instruction latency | 3402 // to hide instruction latency |
3364 // | 3403 // |
3365 // Arguments: | 3404 // Arguments: |
3582 __ jmp(L_exit); | 3621 __ jmp(L_exit); |
3583 | 3622 |
3584 return start; | 3623 return start; |
3585 } | 3624 } |
3586 | 3625 |
3587 | 3626 /** |
3627 * Arguments: | |
3628 * | |
3629 * Inputs: | |
3630 * c_rarg0 - int crc | |
3631 * c_rarg1 - byte* buf | |
3632 * c_rarg2 - int length | |
3633 * | |
3634 * Ouput: | |
3635 * rax - int crc result | |
3636 */ | |
3637 address generate_updateBytesCRC32() { | |
3638 assert(UseCRC32Intrinsics, "need AVX and CLMUL instructions"); | |
3639 | |
3640 __ align(CodeEntryAlignment); | |
3641 StubCodeMark mark(this, "StubRoutines", "updateBytesCRC32"); | |
3642 | |
3643 address start = __ pc(); | |
3644 // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...) | |
3645 // Unix: rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...) | |
3646 // rscratch1: r10 | |
3647 const Register crc = c_rarg0; // crc | |
3648 const Register buf = c_rarg1; // source java byte array address | |
3649 const Register len = c_rarg2; // length | |
3650 const Register table = c_rarg3; // crc_table address (reuse register) | |
3651 const Register tmp = r11; | |
3652 assert_different_registers(crc, buf, len, table, tmp, rax); | |
3653 | |
3654 BLOCK_COMMENT("Entry:"); | |
3655 __ enter(); // required for proper stackwalking of RuntimeStub frame | |
3656 | |
3657 __ kernel_crc32(crc, buf, len, table, tmp); | |
3658 | |
3659 __ movl(rax, crc); | |
3660 __ leave(); // required for proper stackwalking of RuntimeStub frame | |
3661 __ ret(0); | |
3662 | |
3663 return start; | |
3664 } | |
3588 | 3665 |
3589 #undef __ | 3666 #undef __ |
3590 #define __ masm-> | 3667 #define __ masm-> |
3591 | 3668 |
3592 // Continuation point for throwing of implicit exceptions that are | 3669 // Continuation point for throwing of implicit exceptions that are |
3689 (framesize >> (LogBytesPerWord - LogBytesPerInt)), | 3766 (framesize >> (LogBytesPerWord - LogBytesPerInt)), |
3690 oop_maps, false); | 3767 oop_maps, false); |
3691 return stub->entry_point(); | 3768 return stub->entry_point(); |
3692 } | 3769 } |
3693 | 3770 |
3771 void create_control_words() { | |
3772 // Round to nearest, 53-bit mode, exceptions masked | |
3773 StubRoutines::_fpu_cntrl_wrd_std = 0x027F; | |
3774 // Round to zero, 53-bit mode, exception mased | |
3775 StubRoutines::_fpu_cntrl_wrd_trunc = 0x0D7F; | |
3776 // Round to nearest, 24-bit mode, exceptions masked | |
3777 StubRoutines::_fpu_cntrl_wrd_24 = 0x007F; | |
3778 // Round to nearest, 64-bit mode, exceptions masked | |
3779 StubRoutines::_fpu_cntrl_wrd_64 = 0x037F; | |
3780 // Round to nearest, 64-bit mode, exceptions masked | |
3781 StubRoutines::_mxcsr_std = 0x1F80; | |
3782 // Note: the following two constants are 80-bit values | |
3783 // layout is critical for correct loading by FPU. | |
3784 // Bias for strict fp multiply/divide | |
3785 StubRoutines::_fpu_subnormal_bias1[0]= 0x00000000; // 2^(-15360) == 0x03ff 8000 0000 0000 0000 | |
3786 StubRoutines::_fpu_subnormal_bias1[1]= 0x80000000; | |
3787 StubRoutines::_fpu_subnormal_bias1[2]= 0x03ff; | |
3788 // Un-Bias for strict fp multiply/divide | |
3789 StubRoutines::_fpu_subnormal_bias2[0]= 0x00000000; // 2^(+15360) == 0x7bff 8000 0000 0000 0000 | |
3790 StubRoutines::_fpu_subnormal_bias2[1]= 0x80000000; | |
3791 StubRoutines::_fpu_subnormal_bias2[2]= 0x7bff; | |
3792 } | |
3793 | |
3694 // Initialization | 3794 // Initialization |
3695 void generate_initial() { | 3795 void generate_initial() { |
3696 // Generates all stubs and initializes the entry points | 3796 // Generates all stubs and initializes the entry points |
3697 | 3797 |
3698 // This platform-specific stub is needed by generate_call_stub() | 3798 // This platform-specific settings are needed by generate_call_stub() |
3699 StubRoutines::x86::_mxcsr_std = generate_fp_mask("mxcsr_std", 0x0000000000001F80); | 3799 create_control_words(); |
3700 | 3800 |
3701 // entry points that exist in all platforms Note: This is code | 3801 // entry points that exist in all platforms Note: This is code |
3702 // that could be shared among different platforms - however the | 3802 // that could be shared among different platforms - however the |
3703 // benefit seems to be smaller than the disadvantage of having a | 3803 // benefit seems to be smaller than the disadvantage of having a |
3704 // much more complicated generator structure. See also comment in | 3804 // much more complicated generator structure. See also comment in |
3734 StubRoutines::_throw_StackOverflowError_entry = | 3834 StubRoutines::_throw_StackOverflowError_entry = |
3735 generate_throw_exception("StackOverflowError throw_exception", | 3835 generate_throw_exception("StackOverflowError throw_exception", |
3736 CAST_FROM_FN_PTR(address, | 3836 CAST_FROM_FN_PTR(address, |
3737 SharedRuntime:: | 3837 SharedRuntime:: |
3738 throw_StackOverflowError)); | 3838 throw_StackOverflowError)); |
3839 if (UseCRC32Intrinsics) { | |
3840 // set table address before stub generation which use it | |
3841 StubRoutines::_crc_table_adr = (address)StubRoutines::x86::_crc_table; | |
3842 StubRoutines::_updateBytesCRC32 = generate_updateBytesCRC32(); | |
3843 } | |
3739 } | 3844 } |
3740 | 3845 |
3741 void generate_all() { | 3846 void generate_all() { |
3742 // Generates all stubs and initializes the entry points | 3847 // Generates all stubs and initializes the entry points |
3743 | 3848 |
3794 StubRoutines::_aescrypt_encryptBlock = generate_aescrypt_encryptBlock(); | 3899 StubRoutines::_aescrypt_encryptBlock = generate_aescrypt_encryptBlock(); |
3795 StubRoutines::_aescrypt_decryptBlock = generate_aescrypt_decryptBlock(); | 3900 StubRoutines::_aescrypt_decryptBlock = generate_aescrypt_decryptBlock(); |
3796 StubRoutines::_cipherBlockChaining_encryptAESCrypt = generate_cipherBlockChaining_encryptAESCrypt(); | 3901 StubRoutines::_cipherBlockChaining_encryptAESCrypt = generate_cipherBlockChaining_encryptAESCrypt(); |
3797 StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt_Parallel(); | 3902 StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt_Parallel(); |
3798 } | 3903 } |
3904 | |
3905 // Safefetch stubs. | |
3906 generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry, | |
3907 &StubRoutines::_safefetch32_fault_pc, | |
3908 &StubRoutines::_safefetch32_continuation_pc); | |
3909 generate_safefetch("SafeFetchN", sizeof(intptr_t), &StubRoutines::_safefetchN_entry, | |
3910 &StubRoutines::_safefetchN_fault_pc, | |
3911 &StubRoutines::_safefetchN_continuation_pc); | |
3799 } | 3912 } |
3800 | 3913 |
3801 public: | 3914 public: |
3802 StubGenerator(CodeBuffer* code, bool all) : StubCodeGenerator(code) { | 3915 StubGenerator(CodeBuffer* code, bool all) : StubCodeGenerator(code) { |
3803 if (all) { | 3916 if (all) { |