Mercurial > hg > truffle
comparison src/cpu/x86/vm/x86_64.ad @ 2404:b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
Summary: Materialize the pointer to the polling page in a register instead of using rip-relative addressing when the distance from the code cache is larger than disp32.
Reviewed-by: never, kvn
author | iveresov |
---|---|
date | Sun, 27 Mar 2011 13:17:37 -0700 |
parents | 7e88bdae86ec |
children | 9340a27154cb |
comparison
equal
deleted
inserted
replaced
2403:1927db75dd85 | 2404:b40d4fa697bf |
---|---|
572 } | 572 } |
573 | 573 |
574 // In os_cpu .ad file | 574 // In os_cpu .ad file |
575 // int MachCallRuntimeNode::ret_addr_offset() | 575 // int MachCallRuntimeNode::ret_addr_offset() |
576 | 576 |
577 // Indicate if the safepoint node needs the polling page as an input. | 577 // Indicate if the safepoint node needs the polling page as an input, |
578 // Since amd64 does not have absolute addressing but RIP-relative | 578 // it does if the polling page is more than disp32 away. |
579 // addressing and the polling page is within 2G, it doesn't. | |
580 bool SafePointNode::needs_polling_address_input() | 579 bool SafePointNode::needs_polling_address_input() |
581 { | 580 { |
582 return false; | 581 return Assembler::is_polling_page_far(); |
583 } | 582 } |
584 | 583 |
585 // | 584 // |
586 // Compute padding required for nodes which need alignment | 585 // Compute padding required for nodes which need alignment |
587 // | 586 // |
990 // Remove word for return adr already pushed | 989 // Remove word for return adr already pushed |
991 // and RBP | 990 // and RBP |
992 framesize -= 2*wordSize; | 991 framesize -= 2*wordSize; |
993 | 992 |
994 if (framesize) { | 993 if (framesize) { |
995 st->print_cr("addq\trsp, %d\t# Destroy frame", framesize); | 994 st->print_cr("addq rsp, %d\t# Destroy frame", framesize); |
996 st->print("\t"); | 995 st->print("\t"); |
997 } | 996 } |
998 | 997 |
999 st->print_cr("popq\trbp"); | 998 st->print_cr("popq rbp"); |
1000 if (do_polling() && C->is_method_compilation()) { | 999 if (do_polling() && C->is_method_compilation()) { |
1001 st->print_cr("\ttestl\trax, [rip + #offset_to_poll_page]\t" | |
1002 "# Safepoint: poll for GC"); | |
1003 st->print("\t"); | 1000 st->print("\t"); |
1001 if (Assembler::is_polling_page_far()) { | |
1002 st->print_cr("movq rscratch1, #polling_page_address\n\t" | |
1003 "testl rax, [rscratch1]\t" | |
1004 "# Safepoint: poll for GC"); | |
1005 } else { | |
1006 st->print_cr("testl rax, [rip + #offset_to_poll_page]\t" | |
1007 "# Safepoint: poll for GC"); | |
1008 } | |
1004 } | 1009 } |
1005 } | 1010 } |
1006 #endif | 1011 #endif |
1007 | 1012 |
1008 void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const | 1013 void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const |
1031 | 1036 |
1032 // popq rbp | 1037 // popq rbp |
1033 emit_opcode(cbuf, 0x58 | RBP_enc); | 1038 emit_opcode(cbuf, 0x58 | RBP_enc); |
1034 | 1039 |
1035 if (do_polling() && C->is_method_compilation()) { | 1040 if (do_polling() && C->is_method_compilation()) { |
1036 // testl %rax, off(%rip) // Opcode + ModRM + Disp32 == 6 bytes | 1041 MacroAssembler _masm(&cbuf); |
1037 // XXX reg_mem doesn't support RIP-relative addressing yet | 1042 AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_return_type); |
1038 cbuf.set_insts_mark(); | 1043 if (Assembler::is_polling_page_far()) { |
1039 cbuf.relocate(cbuf.insts_mark(), relocInfo::poll_return_type, 0); // XXX | 1044 __ lea(rscratch1, polling_page); |
1040 emit_opcode(cbuf, 0x85); // testl | 1045 __ relocate(relocInfo::poll_return_type); |
1041 emit_rm(cbuf, 0x0, RAX_enc, 0x5); // 00 rax 101 == 0x5 | 1046 __ testl(rax, Address(rscratch1, 0)); |
1042 // cbuf.insts_mark() is beginning of instruction | 1047 } else { |
1043 emit_d32_reloc(cbuf, os::get_polling_page()); | 1048 __ testl(rax, polling_page); |
1044 // relocInfo::poll_return_type, | 1049 } |
1045 } | 1050 } |
1046 } | 1051 } |
1047 | 1052 |
1048 uint MachEpilogNode::size(PhaseRegAlloc* ra_) const | 1053 uint MachEpilogNode::size(PhaseRegAlloc* ra_) const |
1049 { | 1054 { |
1050 Compile* C = ra_->C; | 1055 return MachNode::size(ra_); // too many variables; just compute it |
1051 int framesize = C->frame_slots() << LogBytesPerInt; | 1056 // the hard way |
1052 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); | |
1053 // Remove word for return adr already pushed | |
1054 // and RBP | |
1055 framesize -= 2*wordSize; | |
1056 | |
1057 uint size = 0; | |
1058 | |
1059 if (do_polling() && C->is_method_compilation()) { | |
1060 size += 6; | |
1061 } | |
1062 | |
1063 // count popq rbp | |
1064 size++; | |
1065 | |
1066 if (framesize) { | |
1067 if (framesize < 0x80) { | |
1068 size += 4; | |
1069 } else if (framesize) { | |
1070 size += 7; | |
1071 } | |
1072 } | |
1073 | |
1074 return size; | |
1075 } | 1057 } |
1076 | 1058 |
1077 int MachEpilogNode::reloc() const | 1059 int MachEpilogNode::reloc() const |
1078 { | 1060 { |
1079 return 2; // a large enough number | 1061 return 2; // a large enough number |
3408 if (_counters != NULL) { | 3390 if (_counters != NULL) { |
3409 masm.atomic_incl(ExternalAddress((address) _counters->total_entry_count_addr())); | 3391 masm.atomic_incl(ExternalAddress((address) _counters->total_entry_count_addr())); |
3410 } | 3392 } |
3411 if (EmitSync & 1) { | 3393 if (EmitSync & 1) { |
3412 // Without cast to int32_t a movptr will destroy r10 which is typically obj | 3394 // Without cast to int32_t a movptr will destroy r10 which is typically obj |
3413 masm.movptr (Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ; | 3395 masm.movptr (Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ; |
3414 masm.cmpptr(rsp, (int32_t)NULL_WORD) ; | 3396 masm.cmpptr(rsp, (int32_t)NULL_WORD) ; |
3415 } else | 3397 } else |
3416 if (EmitSync & 2) { | 3398 if (EmitSync & 2) { |
3417 Label DONE_LABEL; | 3399 Label DONE_LABEL; |
3418 if (UseBiasedLocking) { | 3400 if (UseBiasedLocking) { |
3419 // Note: tmpReg maps to the swap_reg argument and scrReg to the tmp_reg argument. | 3401 // Note: tmpReg maps to the swap_reg argument and scrReg to the tmp_reg argument. |
3437 masm.bind(DONE_LABEL); | 3419 masm.bind(DONE_LABEL); |
3438 masm.nop(); // avoid branch to branch | 3420 masm.nop(); // avoid branch to branch |
3439 } else { | 3421 } else { |
3440 Label DONE_LABEL, IsInflated, Egress; | 3422 Label DONE_LABEL, IsInflated, Egress; |
3441 | 3423 |
3442 masm.movptr(tmpReg, Address(objReg, 0)) ; | 3424 masm.movptr(tmpReg, Address(objReg, 0)) ; |
3443 masm.testl (tmpReg, 0x02) ; // inflated vs stack-locked|neutral|biased | 3425 masm.testl (tmpReg, 0x02) ; // inflated vs stack-locked|neutral|biased |
3444 masm.jcc (Assembler::notZero, IsInflated) ; | 3426 masm.jcc (Assembler::notZero, IsInflated) ; |
3445 | 3427 |
3446 // it's stack-locked, biased or neutral | 3428 // it's stack-locked, biased or neutral |
3447 // TODO: optimize markword triage order to reduce the number of | 3429 // TODO: optimize markword triage order to reduce the number of |
3448 // conditional branches in the most common cases. | 3430 // conditional branches in the most common cases. |
3449 // Beware -- there's a subtle invariant that fetch of the markword | 3431 // Beware -- there's a subtle invariant that fetch of the markword |
3450 // at [FETCH], below, will never observe a biased encoding (*101b). | 3432 // at [FETCH], below, will never observe a biased encoding (*101b). |
3454 masm.biased_locking_enter(boxReg, objReg, tmpReg, scrReg, true, DONE_LABEL, NULL, _counters); | 3436 masm.biased_locking_enter(boxReg, objReg, tmpReg, scrReg, true, DONE_LABEL, NULL, _counters); |
3455 masm.movptr(tmpReg, Address(objReg, 0)) ; // [FETCH] | 3437 masm.movptr(tmpReg, Address(objReg, 0)) ; // [FETCH] |
3456 } | 3438 } |
3457 | 3439 |
3458 // was q will it destroy high? | 3440 // was q will it destroy high? |
3459 masm.orl (tmpReg, 1) ; | 3441 masm.orl (tmpReg, 1) ; |
3460 masm.movptr(Address(boxReg, 0), tmpReg) ; | 3442 masm.movptr(Address(boxReg, 0), tmpReg) ; |
3461 if (os::is_MP()) { masm.lock(); } | 3443 if (os::is_MP()) { masm.lock(); } |
3462 masm.cmpxchgptr(boxReg, Address(objReg, 0)); // Updates tmpReg | 3444 masm.cmpxchgptr(boxReg, Address(objReg, 0)); // Updates tmpReg |
3463 if (_counters != NULL) { | 3445 if (_counters != NULL) { |
3464 masm.cond_inc32(Assembler::equal, | 3446 masm.cond_inc32(Assembler::equal, |
3465 ExternalAddress((address) _counters->fast_path_entry_count_addr())); | 3447 ExternalAddress((address) _counters->fast_path_entry_count_addr())); |
3466 } | 3448 } |
3483 // relocating (deferring) the following ST. | 3465 // relocating (deferring) the following ST. |
3484 // We should also think about trying a CAS without having | 3466 // We should also think about trying a CAS without having |
3485 // fetched _owner. If the CAS is successful we may | 3467 // fetched _owner. If the CAS is successful we may |
3486 // avoid an RTO->RTS upgrade on the $line. | 3468 // avoid an RTO->RTS upgrade on the $line. |
3487 // Without cast to int32_t a movptr will destroy r10 which is typically obj | 3469 // Without cast to int32_t a movptr will destroy r10 which is typically obj |
3488 masm.movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ; | 3470 masm.movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ; |
3489 | 3471 |
3490 masm.mov (boxReg, tmpReg) ; | 3472 masm.mov (boxReg, tmpReg) ; |
3491 masm.movptr (tmpReg, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; | 3473 masm.movptr (tmpReg, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; |
3492 masm.testptr(tmpReg, tmpReg) ; | 3474 masm.testptr(tmpReg, tmpReg) ; |
3493 masm.jcc (Assembler::notZero, DONE_LABEL) ; | 3475 masm.jcc (Assembler::notZero, DONE_LABEL) ; |
3494 | 3476 |
3495 // It's inflated and appears unlocked | 3477 // It's inflated and appears unlocked |
3496 if (os::is_MP()) { masm.lock(); } | 3478 if (os::is_MP()) { masm.lock(); } |
3497 masm.cmpxchgptr(r15_thread, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; | 3479 masm.cmpxchgptr(r15_thread, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; |
3498 // Intentional fall-through into DONE_LABEL ... | 3480 // Intentional fall-through into DONE_LABEL ... |
3499 | 3481 |
3500 masm.bind (DONE_LABEL) ; | 3482 masm.bind (DONE_LABEL) ; |
3501 masm.nop () ; // avoid jmp to jmp | 3483 masm.nop () ; // avoid jmp to jmp |
3502 } | 3484 } |
3511 Register objReg = as_Register($obj$$reg); | 3493 Register objReg = as_Register($obj$$reg); |
3512 Register boxReg = as_Register($box$$reg); | 3494 Register boxReg = as_Register($box$$reg); |
3513 Register tmpReg = as_Register($tmp$$reg); | 3495 Register tmpReg = as_Register($tmp$$reg); |
3514 MacroAssembler masm(&cbuf); | 3496 MacroAssembler masm(&cbuf); |
3515 | 3497 |
3516 if (EmitSync & 4) { | 3498 if (EmitSync & 4) { |
3517 masm.cmpptr(rsp, 0) ; | 3499 masm.cmpptr(rsp, 0) ; |
3518 } else | 3500 } else |
3519 if (EmitSync & 8) { | 3501 if (EmitSync & 8) { |
3520 Label DONE_LABEL; | 3502 Label DONE_LABEL; |
3521 if (UseBiasedLocking) { | 3503 if (UseBiasedLocking) { |
3522 masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL); | 3504 masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL); |
3539 Label DONE_LABEL, Stacked, CheckSucc ; | 3521 Label DONE_LABEL, Stacked, CheckSucc ; |
3540 | 3522 |
3541 if (UseBiasedLocking && !UseOptoBiasInlining) { | 3523 if (UseBiasedLocking && !UseOptoBiasInlining) { |
3542 masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL); | 3524 masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL); |
3543 } | 3525 } |
3544 | 3526 |
3545 masm.movptr(tmpReg, Address(objReg, 0)) ; | 3527 masm.movptr(tmpReg, Address(objReg, 0)) ; |
3546 masm.cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD) ; | 3528 masm.cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD) ; |
3547 masm.jcc (Assembler::zero, DONE_LABEL) ; | 3529 masm.jcc (Assembler::zero, DONE_LABEL) ; |
3548 masm.testl (tmpReg, 0x02) ; | 3530 masm.testl (tmpReg, 0x02) ; |
3549 masm.jcc (Assembler::zero, Stacked) ; | 3531 masm.jcc (Assembler::zero, Stacked) ; |
3550 | 3532 |
3551 // It's inflated | 3533 // It's inflated |
3552 masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; | 3534 masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; |
3553 masm.xorptr(boxReg, r15_thread) ; | 3535 masm.xorptr(boxReg, r15_thread) ; |
3554 masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)) ; | 3536 masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)) ; |
3555 masm.jcc (Assembler::notZero, DONE_LABEL) ; | 3537 masm.jcc (Assembler::notZero, DONE_LABEL) ; |
3556 masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ; | 3538 masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ; |
3557 masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ; | 3539 masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ; |
3558 masm.jcc (Assembler::notZero, CheckSucc) ; | 3540 masm.jcc (Assembler::notZero, CheckSucc) ; |
3559 masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD) ; | 3541 masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD) ; |
3560 masm.jmp (DONE_LABEL) ; | 3542 masm.jmp (DONE_LABEL) ; |
3561 | 3543 |
3562 if ((EmitSync & 65536) == 0) { | 3544 if ((EmitSync & 65536) == 0) { |
3563 Label LSuccess, LGoSlowPath ; | 3545 Label LSuccess, LGoSlowPath ; |
3564 masm.bind (CheckSucc) ; | 3546 masm.bind (CheckSucc) ; |
3565 masm.cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int32_t)NULL_WORD) ; | 3547 masm.cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int32_t)NULL_WORD) ; |
3566 masm.jcc (Assembler::zero, LGoSlowPath) ; | 3548 masm.jcc (Assembler::zero, LGoSlowPath) ; |
3567 | 3549 |
3589 masm.bind (LSuccess) ; | 3571 masm.bind (LSuccess) ; |
3590 masm.testl (boxReg, 0) ; // set ICC.ZF=1 to indicate success | 3572 masm.testl (boxReg, 0) ; // set ICC.ZF=1 to indicate success |
3591 masm.jmp (DONE_LABEL) ; | 3573 masm.jmp (DONE_LABEL) ; |
3592 } | 3574 } |
3593 | 3575 |
3594 masm.bind (Stacked) ; | 3576 masm.bind (Stacked) ; |
3595 masm.movptr(tmpReg, Address (boxReg, 0)) ; // re-fetch | 3577 masm.movptr(tmpReg, Address (boxReg, 0)) ; // re-fetch |
3596 if (os::is_MP()) { masm.lock(); } | 3578 if (os::is_MP()) { masm.lock(); } |
3597 masm.cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses RAX which is box | 3579 masm.cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses RAX which is box |
3598 | 3580 |
3599 if (EmitSync & 65536) { | 3581 if (EmitSync & 65536) { |
3600 masm.bind (CheckSucc) ; | 3582 masm.bind (CheckSucc) ; |
3601 } | 3583 } |
3911 emit_opcode(cbuf, Assembler::REX_B); | 3893 emit_opcode(cbuf, Assembler::REX_B); |
3912 } | 3894 } |
3913 emit_opcode(cbuf, 0x58 | (dstenc & 7)); | 3895 emit_opcode(cbuf, 0x58 | (dstenc & 7)); |
3914 | 3896 |
3915 // done: | 3897 // done: |
3916 %} | |
3917 | |
3918 // Safepoint Poll. This polls the safepoint page, and causes an | |
3919 // exception if it is not readable. Unfortunately, it kills | |
3920 // RFLAGS in the process. | |
3921 enc_class enc_safepoint_poll | |
3922 %{ | |
3923 // testl %rax, off(%rip) // Opcode + ModRM + Disp32 == 6 bytes | |
3924 // XXX reg_mem doesn't support RIP-relative addressing yet | |
3925 cbuf.set_insts_mark(); | |
3926 cbuf.relocate(cbuf.insts_mark(), relocInfo::poll_type, 0); // XXX | |
3927 emit_opcode(cbuf, 0x85); // testl | |
3928 emit_rm(cbuf, 0x0, RAX_enc, 0x5); // 00 rax 101 == 0x5 | |
3929 // cbuf.insts_mark() is beginning of instruction | |
3930 emit_d32_reloc(cbuf, os::get_polling_page()); | |
3931 // relocInfo::poll_type, | |
3932 %} | 3898 %} |
3933 %} | 3899 %} |
3934 | 3900 |
3935 | 3901 |
3936 | 3902 |
4231 op_cost(5); | 4197 op_cost(5); |
4232 format %{ %} | 4198 format %{ %} |
4233 interface(CONST_INTER); | 4199 interface(CONST_INTER); |
4234 %} | 4200 %} |
4235 | 4201 |
4202 operand immP_poll() %{ | |
4203 predicate(n->get_ptr() != 0 && n->get_ptr() == (intptr_t)os::get_polling_page()); | |
4204 match(ConP); | |
4205 | |
4206 // formats are generated automatically for constants and base registers | |
4207 format %{ %} | |
4208 interface(CONST_INTER); | |
4209 %} | |
4210 | |
4236 // Pointer Immediate | 4211 // Pointer Immediate |
4237 operand immN() %{ | 4212 operand immN() %{ |
4238 match(ConN); | 4213 match(ConN); |
4239 | 4214 |
4240 op_cost(10); | 4215 op_cost(10); |
4838 format %{ %} | 4813 format %{ %} |
4839 interface(REG_INTER); | 4814 interface(REG_INTER); |
4840 %} | 4815 %} |
4841 | 4816 |
4842 // Double register operands | 4817 // Double register operands |
4843 operand regD() | 4818 operand regD() |
4844 %{ | 4819 %{ |
4845 constraint(ALLOC_IN_RC(double_reg)); | 4820 constraint(ALLOC_IN_RC(double_reg)); |
4846 match(RegD); | 4821 match(RegD); |
4847 | 4822 |
4848 format %{ %} | 4823 format %{ %} |
6566 opcode(0x33); /* + rd */ | 6541 opcode(0x33); /* + rd */ |
6567 ins_encode(REX_reg_reg(dst, dst), OpcP, reg_reg(dst, dst)); | 6542 ins_encode(REX_reg_reg(dst, dst), OpcP, reg_reg(dst, dst)); |
6568 ins_pipe(ialu_reg); | 6543 ins_pipe(ialu_reg); |
6569 %} | 6544 %} |
6570 | 6545 |
6546 instruct loadConP_poll(rRegP dst, immP_poll src) %{ | |
6547 match(Set dst src); | |
6548 format %{ "movq $dst, $src\t!ptr" %} | |
6549 ins_encode %{ | |
6550 AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_type); | |
6551 __ lea($dst$$Register, polling_page); | |
6552 %} | |
6553 ins_pipe(ialu_reg_fat); | |
6554 %} | |
6555 | |
6571 instruct loadConP31(rRegP dst, immP31 src, rFlagsReg cr) | 6556 instruct loadConP31(rRegP dst, immP31 src, rFlagsReg cr) |
6572 %{ | 6557 %{ |
6573 match(Set dst src); | 6558 match(Set dst src); |
6574 effect(KILL cr); | 6559 effect(KILL cr); |
6575 | 6560 |
7239 %} | 7224 %} |
7240 | 7225 |
7241 instruct bytes_reverse_unsigned_short(rRegI dst) %{ | 7226 instruct bytes_reverse_unsigned_short(rRegI dst) %{ |
7242 match(Set dst (ReverseBytesUS dst)); | 7227 match(Set dst (ReverseBytesUS dst)); |
7243 | 7228 |
7244 format %{ "bswapl $dst\n\t" | 7229 format %{ "bswapl $dst\n\t" |
7245 "shrl $dst,16\n\t" %} | 7230 "shrl $dst,16\n\t" %} |
7246 ins_encode %{ | 7231 ins_encode %{ |
7247 __ bswapl($dst$$Register); | 7232 __ bswapl($dst$$Register); |
7248 __ shrl($dst$$Register, 16); | 7233 __ shrl($dst$$Register, 16); |
7249 %} | 7234 %} |
7250 ins_pipe( ialu_reg ); | 7235 ins_pipe( ialu_reg ); |
7251 %} | 7236 %} |
7252 | 7237 |
7253 instruct bytes_reverse_short(rRegI dst) %{ | 7238 instruct bytes_reverse_short(rRegI dst) %{ |
7254 match(Set dst (ReverseBytesS dst)); | 7239 match(Set dst (ReverseBytesS dst)); |
7255 | 7240 |
7256 format %{ "bswapl $dst\n\t" | 7241 format %{ "bswapl $dst\n\t" |
7257 "sar $dst,16\n\t" %} | 7242 "sar $dst,16\n\t" %} |
7258 ins_encode %{ | 7243 ins_encode %{ |
7259 __ bswapl($dst$$Register); | 7244 __ bswapl($dst$$Register); |
7260 __ sarl($dst$$Register, 16); | 7245 __ sarl($dst$$Register, 16); |
7261 %} | 7246 %} |
7262 ins_pipe( ialu_reg ); | 7247 ins_pipe( ialu_reg ); |
7263 %} | 7248 %} |
7264 | 7249 |
7265 //---------- Zeros Count Instructions ------------------------------------------ | 7250 //---------- Zeros Count Instructions ------------------------------------------ |
7478 instruct membar_volatile(rFlagsReg cr) %{ | 7463 instruct membar_volatile(rFlagsReg cr) %{ |
7479 match(MemBarVolatile); | 7464 match(MemBarVolatile); |
7480 effect(KILL cr); | 7465 effect(KILL cr); |
7481 ins_cost(400); | 7466 ins_cost(400); |
7482 | 7467 |
7483 format %{ | 7468 format %{ |
7484 $$template | 7469 $$template |
7485 if (os::is_MP()) { | 7470 if (os::is_MP()) { |
7486 $$emit$$"lock addl [rsp + #0], 0\t! membar_volatile" | 7471 $$emit$$"lock addl [rsp + #0], 0\t! membar_volatile" |
7487 } else { | 7472 } else { |
7488 $$emit$$"MEMBAR-volatile ! (empty encoding)" | 7473 $$emit$$"MEMBAR-volatile ! (empty encoding)" |
8289 instruct storePConditional(memory heap_top_ptr, | 8274 instruct storePConditional(memory heap_top_ptr, |
8290 rax_RegP oldval, rRegP newval, | 8275 rax_RegP oldval, rRegP newval, |
8291 rFlagsReg cr) | 8276 rFlagsReg cr) |
8292 %{ | 8277 %{ |
8293 match(Set cr (StorePConditional heap_top_ptr (Binary oldval newval))); | 8278 match(Set cr (StorePConditional heap_top_ptr (Binary oldval newval))); |
8294 | 8279 |
8295 format %{ "cmpxchgq $heap_top_ptr, $newval\t# (ptr) " | 8280 format %{ "cmpxchgq $heap_top_ptr, $newval\t# (ptr) " |
8296 "If rax == $heap_top_ptr then store $newval into $heap_top_ptr" %} | 8281 "If rax == $heap_top_ptr then store $newval into $heap_top_ptr" %} |
8297 opcode(0x0F, 0xB1); | 8282 opcode(0x0F, 0xB1); |
8298 ins_encode(lock_prefix, | 8283 ins_encode(lock_prefix, |
8299 REX_reg_mem_wide(newval, heap_top_ptr), | 8284 REX_reg_mem_wide(newval, heap_top_ptr), |
9852 ins_pipe(ialu_reg_reg); | 9837 ins_pipe(ialu_reg_reg); |
9853 %} | 9838 %} |
9854 | 9839 |
9855 // Xor Register with Immediate -1 | 9840 // Xor Register with Immediate -1 |
9856 instruct xorI_rReg_im1(rRegI dst, immI_M1 imm) %{ | 9841 instruct xorI_rReg_im1(rRegI dst, immI_M1 imm) %{ |
9857 match(Set dst (XorI dst imm)); | 9842 match(Set dst (XorI dst imm)); |
9858 | 9843 |
9859 format %{ "not $dst" %} | 9844 format %{ "not $dst" %} |
9860 ins_encode %{ | 9845 ins_encode %{ |
9861 __ notl($dst$$Register); | 9846 __ notl($dst$$Register); |
9862 %} | 9847 %} |
9863 ins_pipe(ialu_reg); | 9848 ins_pipe(ialu_reg); |
9864 %} | 9849 %} |
10095 ins_pipe(ialu_reg_reg); | 10080 ins_pipe(ialu_reg_reg); |
10096 %} | 10081 %} |
10097 | 10082 |
10098 // Xor Register with Immediate -1 | 10083 // Xor Register with Immediate -1 |
10099 instruct xorL_rReg_im1(rRegL dst, immL_M1 imm) %{ | 10084 instruct xorL_rReg_im1(rRegL dst, immL_M1 imm) %{ |
10100 match(Set dst (XorL dst imm)); | 10085 match(Set dst (XorL dst imm)); |
10101 | 10086 |
10102 format %{ "notq $dst" %} | 10087 format %{ "notq $dst" %} |
10103 ins_encode %{ | 10088 ins_encode %{ |
10104 __ notq($dst$$Register); | 10089 __ notq($dst$$Register); |
10105 %} | 10090 %} |
10106 ins_pipe(ialu_reg); | 10091 ins_pipe(ialu_reg); |
10107 %} | 10092 %} |
12471 | 12456 |
12472 // ============================================================================ | 12457 // ============================================================================ |
12473 // Safepoint Instructions | 12458 // Safepoint Instructions |
12474 instruct safePoint_poll(rFlagsReg cr) | 12459 instruct safePoint_poll(rFlagsReg cr) |
12475 %{ | 12460 %{ |
12461 predicate(!Assembler::is_polling_page_far()); | |
12476 match(SafePoint); | 12462 match(SafePoint); |
12477 effect(KILL cr); | 12463 effect(KILL cr); |
12478 | 12464 |
12479 format %{ "testl rax, [rip + #offset_to_poll_page]\t" | 12465 format %{ "testl rax, [rip + #offset_to_poll_page]\t" |
12480 "# Safepoint: poll for GC" %} | 12466 "# Safepoint: poll for GC" %} |
12481 size(6); // Opcode + ModRM + Disp32 == 6 bytes | |
12482 ins_cost(125); | 12467 ins_cost(125); |
12483 ins_encode(enc_safepoint_poll); | 12468 ins_encode %{ |
12469 AddressLiteral addr(os::get_polling_page(), relocInfo::poll_type); | |
12470 __ testl(rax, addr); | |
12471 %} | |
12472 ins_pipe(ialu_reg_mem); | |
12473 %} | |
12474 | |
12475 instruct safePoint_poll_far(rFlagsReg cr, rRegP poll) | |
12476 %{ | |
12477 predicate(Assembler::is_polling_page_far()); | |
12478 match(SafePoint poll); | |
12479 effect(KILL cr, USE poll); | |
12480 | |
12481 format %{ "testl rax, [$poll]\t" | |
12482 "# Safepoint: poll for GC" %} | |
12483 ins_cost(125); | |
12484 ins_encode %{ | |
12485 __ relocate(relocInfo::poll_type); | |
12486 __ testl(rax, Address($poll$$Register, 0)); | |
12487 %} | |
12484 ins_pipe(ialu_reg_mem); | 12488 ins_pipe(ialu_reg_mem); |
12485 %} | 12489 %} |
12486 | 12490 |
12487 // ============================================================================ | 12491 // ============================================================================ |
12488 // Procedure Call/Return Instructions | 12492 // Procedure Call/Return Instructions |