3060 // Branch if not (cmp crx). |
3028 // Branch if not (cmp crx). |
3061 __ bc(cc_to_inverse_boint($cmp$$cmpcode), cc_to_biint($cmp$$cmpcode, $crx$$reg), done); |
3029 __ bc(cc_to_inverse_boint($cmp$$cmpcode), cc_to_biint($cmp$$cmpcode, $crx$$reg), done); |
3062 __ li($dst$$Register, $src$$constant); |
3030 __ li($dst$$Register, $src$$constant); |
3063 // TODO PPC port __ endgroup_if_needed(_size == 12); |
3031 // TODO PPC port __ endgroup_if_needed(_size == 12); |
3064 __ bind(done); |
3032 __ bind(done); |
3065 %} |
|
3066 |
|
3067 // New atomics. |
|
3068 enc_class enc_GetAndAddI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src) %{ |
|
3069 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
3070 |
|
3071 MacroAssembler _masm(&cbuf); |
|
3072 Register Rtmp = R0; |
|
3073 Register Rres = $res$$Register; |
|
3074 Register Rsrc = $src$$Register; |
|
3075 Register Rptr = $mem_ptr$$Register; |
|
3076 bool RegCollision = (Rres == Rsrc) || (Rres == Rptr); |
|
3077 Register Rold = RegCollision ? Rtmp : Rres; |
|
3078 |
|
3079 Label Lretry; |
|
3080 __ bind(Lretry); |
|
3081 __ lwarx(Rold, Rptr, MacroAssembler::cmpxchgx_hint_atomic_update()); |
|
3082 __ add(Rtmp, Rsrc, Rold); |
|
3083 __ stwcx_(Rtmp, Rptr); |
|
3084 if (UseStaticBranchPredictionInCompareAndSwapPPC64) { |
|
3085 __ bne_predict_not_taken(CCR0, Lretry); |
|
3086 } else { |
|
3087 __ bne( CCR0, Lretry); |
|
3088 } |
|
3089 if (RegCollision) __ subf(Rres, Rsrc, Rtmp); |
|
3090 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
3091 __ isync(); |
|
3092 } else { |
|
3093 __ sync(); |
|
3094 } |
|
3095 %} |
|
3096 |
|
3097 enc_class enc_GetAndAddL(iRegLdst res, iRegPdst mem_ptr, iRegLsrc src) %{ |
|
3098 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
3099 |
|
3100 MacroAssembler _masm(&cbuf); |
|
3101 Register Rtmp = R0; |
|
3102 Register Rres = $res$$Register; |
|
3103 Register Rsrc = $src$$Register; |
|
3104 Register Rptr = $mem_ptr$$Register; |
|
3105 bool RegCollision = (Rres == Rsrc) || (Rres == Rptr); |
|
3106 Register Rold = RegCollision ? Rtmp : Rres; |
|
3107 |
|
3108 Label Lretry; |
|
3109 __ bind(Lretry); |
|
3110 __ ldarx(Rold, Rptr, MacroAssembler::cmpxchgx_hint_atomic_update()); |
|
3111 __ add(Rtmp, Rsrc, Rold); |
|
3112 __ stdcx_(Rtmp, Rptr); |
|
3113 if (UseStaticBranchPredictionInCompareAndSwapPPC64) { |
|
3114 __ bne_predict_not_taken(CCR0, Lretry); |
|
3115 } else { |
|
3116 __ bne( CCR0, Lretry); |
|
3117 } |
|
3118 if (RegCollision) __ subf(Rres, Rsrc, Rtmp); |
|
3119 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
3120 __ isync(); |
|
3121 } else { |
|
3122 __ sync(); |
|
3123 } |
|
3124 %} |
|
3125 |
|
3126 enc_class enc_GetAndSetI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src) %{ |
|
3127 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
3128 |
|
3129 MacroAssembler _masm(&cbuf); |
|
3130 Register Rtmp = R0; |
|
3131 Register Rres = $res$$Register; |
|
3132 Register Rsrc = $src$$Register; |
|
3133 Register Rptr = $mem_ptr$$Register; |
|
3134 bool RegCollision = (Rres == Rsrc) || (Rres == Rptr); |
|
3135 Register Rold = RegCollision ? Rtmp : Rres; |
|
3136 |
|
3137 Label Lretry; |
|
3138 __ bind(Lretry); |
|
3139 __ lwarx(Rold, Rptr, MacroAssembler::cmpxchgx_hint_atomic_update()); |
|
3140 __ stwcx_(Rsrc, Rptr); |
|
3141 if (UseStaticBranchPredictionInCompareAndSwapPPC64) { |
|
3142 __ bne_predict_not_taken(CCR0, Lretry); |
|
3143 } else { |
|
3144 __ bne( CCR0, Lretry); |
|
3145 } |
|
3146 if (RegCollision) __ mr(Rres, Rtmp); |
|
3147 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
3148 __ isync(); |
|
3149 } else { |
|
3150 __ sync(); |
|
3151 } |
|
3152 %} |
|
3153 |
|
3154 enc_class enc_GetAndSetL(iRegLdst res, iRegPdst mem_ptr, iRegLsrc src) %{ |
|
3155 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
3156 |
|
3157 MacroAssembler _masm(&cbuf); |
|
3158 Register Rtmp = R0; |
|
3159 Register Rres = $res$$Register; |
|
3160 Register Rsrc = $src$$Register; |
|
3161 Register Rptr = $mem_ptr$$Register; |
|
3162 bool RegCollision = (Rres == Rsrc) || (Rres == Rptr); |
|
3163 Register Rold = RegCollision ? Rtmp : Rres; |
|
3164 |
|
3165 Label Lretry; |
|
3166 __ bind(Lretry); |
|
3167 __ ldarx(Rold, Rptr, MacroAssembler::cmpxchgx_hint_atomic_update()); |
|
3168 __ stdcx_(Rsrc, Rptr); |
|
3169 if (UseStaticBranchPredictionInCompareAndSwapPPC64) { |
|
3170 __ bne_predict_not_taken(CCR0, Lretry); |
|
3171 } else { |
|
3172 __ bne( CCR0, Lretry); |
|
3173 } |
|
3174 if (RegCollision) __ mr(Rres, Rtmp); |
|
3175 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
3176 __ isync(); |
|
3177 } else { |
|
3178 __ sync(); |
|
3179 } |
|
3180 %} |
3033 %} |
3181 |
3034 |
3182 // This enc_class is needed so that scheduler gets proper |
3035 // This enc_class is needed so that scheduler gets proper |
3183 // input mapping for latency computation. |
3036 // input mapping for latency computation. |
3184 enc_class enc_andc(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ |
3037 enc_class enc_andc(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ |
7573 // (CompareAndSwap ...)" or "If (CmpI (CompareAndSwap ..))" cannot be |
7426 // (CompareAndSwap ...)" or "If (CmpI (CompareAndSwap ..))" cannot be |
7574 // matched. |
7427 // matched. |
7575 |
7428 |
7576 // Strong versions: |
7429 // Strong versions: |
7577 |
7430 |
|
7431 instruct compareAndSwapB_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{ |
|
7432 match(Set res (CompareAndSwapB mem_ptr (Binary src1 src2))); |
|
7433 predicate(VM_Version::has_lqarx()); |
|
7434 effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump |
|
7435 format %{ "CMPXCHGB $res, $mem_ptr, $src1, $src2; as bool" %} |
|
7436 ins_encode %{ |
|
7437 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7438 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7439 __ cmpxchgb(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, |
|
7440 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), |
|
7441 $res$$Register, true); |
|
7442 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
7443 __ isync(); |
|
7444 } else { |
|
7445 __ sync(); |
|
7446 } |
|
7447 %} |
|
7448 ins_pipe(pipe_class_default); |
|
7449 %} |
|
7450 |
|
7451 instruct compareAndSwapB4_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, iRegIdst tmp2, flagsRegCR0 cr0) %{ |
|
7452 match(Set res (CompareAndSwapB mem_ptr (Binary src1 src2))); |
|
7453 predicate(!VM_Version::has_lqarx()); |
|
7454 effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); // TEMP_DEF to avoid jump |
|
7455 format %{ "CMPXCHGB $res, $mem_ptr, $src1, $src2; as bool" %} |
|
7456 ins_encode %{ |
|
7457 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7458 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7459 __ cmpxchgb(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, $tmp2$$Register, |
|
7460 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), |
|
7461 $res$$Register, true); |
|
7462 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
7463 __ isync(); |
|
7464 } else { |
|
7465 __ sync(); |
|
7466 } |
|
7467 %} |
|
7468 ins_pipe(pipe_class_default); |
|
7469 %} |
|
7470 |
|
7471 instruct compareAndSwapS_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{ |
|
7472 match(Set res (CompareAndSwapS mem_ptr (Binary src1 src2))); |
|
7473 predicate(VM_Version::has_lqarx()); |
|
7474 effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump |
|
7475 format %{ "CMPXCHGH $res, $mem_ptr, $src1, $src2; as bool" %} |
|
7476 ins_encode %{ |
|
7477 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7478 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7479 __ cmpxchgh(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, |
|
7480 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), |
|
7481 $res$$Register, true); |
|
7482 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
7483 __ isync(); |
|
7484 } else { |
|
7485 __ sync(); |
|
7486 } |
|
7487 %} |
|
7488 ins_pipe(pipe_class_default); |
|
7489 %} |
|
7490 |
|
7491 instruct compareAndSwapS4_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, iRegIdst tmp2, flagsRegCR0 cr0) %{ |
|
7492 match(Set res (CompareAndSwapS mem_ptr (Binary src1 src2))); |
|
7493 predicate(!VM_Version::has_lqarx()); |
|
7494 effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); // TEMP_DEF to avoid jump |
|
7495 format %{ "CMPXCHGH $res, $mem_ptr, $src1, $src2; as bool" %} |
|
7496 ins_encode %{ |
|
7497 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7498 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7499 __ cmpxchgh(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, $tmp2$$Register, |
|
7500 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), |
|
7501 $res$$Register, true); |
|
7502 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
7503 __ isync(); |
|
7504 } else { |
|
7505 __ sync(); |
|
7506 } |
|
7507 %} |
|
7508 ins_pipe(pipe_class_default); |
|
7509 %} |
|
7510 |
7578 instruct compareAndSwapI_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{ |
7511 instruct compareAndSwapI_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{ |
7579 match(Set res (CompareAndSwapI mem_ptr (Binary src1 src2))); |
7512 match(Set res (CompareAndSwapI mem_ptr (Binary src1 src2))); |
7580 effect(TEMP cr0); |
7513 effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump |
7581 format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as bool" %} |
7514 format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as bool" %} |
7582 // Variable size: instruction count smaller if regs are disjoint. |
|
7583 ins_encode %{ |
7515 ins_encode %{ |
7584 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
7516 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
7585 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
7517 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
7586 __ cmpxchgw(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, |
7518 __ cmpxchgw(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, |
7587 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), |
7519 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), |
7655 ins_pipe(pipe_class_default); |
7584 ins_pipe(pipe_class_default); |
7656 %} |
7585 %} |
7657 |
7586 |
7658 // Weak versions: |
7587 // Weak versions: |
7659 |
7588 |
|
7589 instruct weakCompareAndSwapB_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{ |
|
7590 match(Set res (WeakCompareAndSwapB mem_ptr (Binary src1 src2))); |
|
7591 predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst && VM_Version::has_lqarx()); |
|
7592 effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump |
|
7593 format %{ "weak CMPXCHGB $res, $mem_ptr, $src1, $src2; as bool" %} |
|
7594 ins_encode %{ |
|
7595 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7596 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7597 __ cmpxchgb(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, |
|
7598 MacroAssembler::MemBarNone, |
|
7599 MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, true, /*weak*/ true); |
|
7600 %} |
|
7601 ins_pipe(pipe_class_default); |
|
7602 %} |
|
7603 |
|
7604 instruct weakCompareAndSwapB4_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, iRegIdst tmp2, flagsRegCR0 cr0) %{ |
|
7605 match(Set res (WeakCompareAndSwapB mem_ptr (Binary src1 src2))); |
|
7606 predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst && !VM_Version::has_lqarx()); |
|
7607 effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); // TEMP_DEF to avoid jump |
|
7608 format %{ "weak CMPXCHGB $res, $mem_ptr, $src1, $src2; as bool" %} |
|
7609 ins_encode %{ |
|
7610 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7611 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7612 __ cmpxchgb(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, $tmp2$$Register, |
|
7613 MacroAssembler::MemBarNone, |
|
7614 MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, true, /*weak*/ true); |
|
7615 %} |
|
7616 ins_pipe(pipe_class_default); |
|
7617 %} |
|
7618 |
|
7619 instruct weakCompareAndSwapB_acq_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{ |
|
7620 match(Set res (WeakCompareAndSwapB mem_ptr (Binary src1 src2))); |
|
7621 predicate((((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst) && VM_Version::has_lqarx()); |
|
7622 effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump |
|
7623 format %{ "weak CMPXCHGB acq $res, $mem_ptr, $src1, $src2; as bool" %} |
|
7624 ins_encode %{ |
|
7625 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7626 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7627 __ cmpxchgb(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, |
|
7628 support_IRIW_for_not_multiple_copy_atomic_cpu ? MacroAssembler::MemBarAcq : MacroAssembler::MemBarFenceAfter, |
|
7629 MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, true, /*weak*/ true); |
|
7630 %} |
|
7631 ins_pipe(pipe_class_default); |
|
7632 %} |
|
7633 |
|
7634 instruct weakCompareAndSwapB4_acq_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, iRegIdst tmp2, flagsRegCR0 cr0) %{ |
|
7635 match(Set res (WeakCompareAndSwapB mem_ptr (Binary src1 src2))); |
|
7636 predicate((((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst) && !VM_Version::has_lqarx()); |
|
7637 effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); // TEMP_DEF to avoid jump |
|
7638 format %{ "weak CMPXCHGB acq $res, $mem_ptr, $src1, $src2; as bool" %} |
|
7639 ins_encode %{ |
|
7640 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7641 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7642 __ cmpxchgb(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, $tmp2$$Register, |
|
7643 support_IRIW_for_not_multiple_copy_atomic_cpu ? MacroAssembler::MemBarAcq : MacroAssembler::MemBarFenceAfter, |
|
7644 MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, true, /*weak*/ true); |
|
7645 %} |
|
7646 ins_pipe(pipe_class_default); |
|
7647 %} |
|
7648 |
|
7649 instruct weakCompareAndSwapS_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{ |
|
7650 match(Set res (WeakCompareAndSwapS mem_ptr (Binary src1 src2))); |
|
7651 predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst && VM_Version::has_lqarx()); |
|
7652 effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump |
|
7653 format %{ "weak CMPXCHGH $res, $mem_ptr, $src1, $src2; as bool" %} |
|
7654 ins_encode %{ |
|
7655 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7656 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7657 __ cmpxchgh(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, |
|
7658 MacroAssembler::MemBarNone, |
|
7659 MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, true, /*weak*/ true); |
|
7660 %} |
|
7661 ins_pipe(pipe_class_default); |
|
7662 %} |
|
7663 |
|
7664 instruct weakCompareAndSwapS4_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, iRegIdst tmp2, flagsRegCR0 cr0) %{ |
|
7665 match(Set res (WeakCompareAndSwapS mem_ptr (Binary src1 src2))); |
|
7666 predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst && !VM_Version::has_lqarx()); |
|
7667 effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); // TEMP_DEF to avoid jump |
|
7668 format %{ "weak CMPXCHGH $res, $mem_ptr, $src1, $src2; as bool" %} |
|
7669 ins_encode %{ |
|
7670 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7671 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7672 __ cmpxchgh(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, $tmp2$$Register, |
|
7673 MacroAssembler::MemBarNone, |
|
7674 MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, true, /*weak*/ true); |
|
7675 %} |
|
7676 ins_pipe(pipe_class_default); |
|
7677 %} |
|
7678 |
|
7679 instruct weakCompareAndSwapS_acq_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{ |
|
7680 match(Set res (WeakCompareAndSwapS mem_ptr (Binary src1 src2))); |
|
7681 predicate((((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst) && VM_Version::has_lqarx()); |
|
7682 effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump |
|
7683 format %{ "weak CMPXCHGH acq $res, $mem_ptr, $src1, $src2; as bool" %} |
|
7684 ins_encode %{ |
|
7685 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7686 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7687 __ cmpxchgh(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, |
|
7688 support_IRIW_for_not_multiple_copy_atomic_cpu ? MacroAssembler::MemBarAcq : MacroAssembler::MemBarFenceAfter, |
|
7689 MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, true, /*weak*/ true); |
|
7690 %} |
|
7691 ins_pipe(pipe_class_default); |
|
7692 %} |
|
7693 |
|
7694 instruct weakCompareAndSwapS4_acq_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, iRegIdst tmp2, flagsRegCR0 cr0) %{ |
|
7695 match(Set res (WeakCompareAndSwapS mem_ptr (Binary src1 src2))); |
|
7696 predicate((((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst) && !VM_Version::has_lqarx()); |
|
7697 effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); // TEMP_DEF to avoid jump |
|
7698 format %{ "weak CMPXCHGH acq $res, $mem_ptr, $src1, $src2; as bool" %} |
|
7699 ins_encode %{ |
|
7700 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7701 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7702 __ cmpxchgh(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, $tmp2$$Register, |
|
7703 support_IRIW_for_not_multiple_copy_atomic_cpu ? MacroAssembler::MemBarAcq : MacroAssembler::MemBarFenceAfter, |
|
7704 MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, true, /*weak*/ true); |
|
7705 %} |
|
7706 ins_pipe(pipe_class_default); |
|
7707 %} |
|
7708 |
7660 instruct weakCompareAndSwapI_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{ |
7709 instruct weakCompareAndSwapI_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{ |
7661 match(Set res (WeakCompareAndSwapI mem_ptr (Binary src1 src2))); |
7710 match(Set res (WeakCompareAndSwapI mem_ptr (Binary src1 src2))); |
7662 predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst); |
7711 predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst); |
7663 effect(TEMP cr0); |
7712 effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump |
7664 format %{ "weak CMPXCHGW $res, $mem_ptr, $src1, $src2; as bool" %} |
7713 format %{ "weak CMPXCHGW $res, $mem_ptr, $src1, $src2; as bool" %} |
7665 // Variable size: instruction count smaller if regs are disjoint. |
|
7666 ins_encode %{ |
7714 ins_encode %{ |
7667 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
7715 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
7668 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
7716 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
7669 __ cmpxchgw(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, |
7717 __ cmpxchgw(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, |
7670 MacroAssembler::MemBarNone, |
7718 MacroAssembler::MemBarNone, |
7794 ins_pipe(pipe_class_default); |
7835 ins_pipe(pipe_class_default); |
7795 %} |
7836 %} |
7796 |
7837 |
7797 // CompareAndExchange |
7838 // CompareAndExchange |
7798 |
7839 |
|
7840 instruct compareAndExchangeB_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{ |
|
7841 match(Set res (CompareAndExchangeB mem_ptr (Binary src1 src2))); |
|
7842 predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst && VM_Version::has_lqarx()); |
|
7843 effect(TEMP_DEF res, TEMP cr0); |
|
7844 format %{ "CMPXCHGB $res, $mem_ptr, $src1, $src2; as int" %} |
|
7845 ins_encode %{ |
|
7846 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7847 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7848 __ cmpxchgb(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, |
|
7849 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), |
|
7850 noreg, true); |
|
7851 %} |
|
7852 ins_pipe(pipe_class_default); |
|
7853 %} |
|
7854 |
|
7855 instruct compareAndExchangeB4_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, flagsRegCR0 cr0) %{ |
|
7856 match(Set res (CompareAndExchangeB mem_ptr (Binary src1 src2))); |
|
7857 predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst && !VM_Version::has_lqarx()); |
|
7858 effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP cr0); |
|
7859 format %{ "CMPXCHGB $res, $mem_ptr, $src1, $src2; as int" %} |
|
7860 ins_encode %{ |
|
7861 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7862 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7863 __ cmpxchgb(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, R0, |
|
7864 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), |
|
7865 noreg, true); |
|
7866 %} |
|
7867 ins_pipe(pipe_class_default); |
|
7868 %} |
|
7869 |
|
7870 instruct compareAndExchangeB_acq_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{ |
|
7871 match(Set res (CompareAndExchangeB mem_ptr (Binary src1 src2))); |
|
7872 predicate((((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst) && VM_Version::has_lqarx()); |
|
7873 effect(TEMP_DEF res, TEMP cr0); |
|
7874 format %{ "CMPXCHGB acq $res, $mem_ptr, $src1, $src2; as int" %} |
|
7875 ins_encode %{ |
|
7876 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7877 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7878 __ cmpxchgb(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, |
|
7879 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), |
|
7880 noreg, true); |
|
7881 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
7882 __ isync(); |
|
7883 } else { |
|
7884 // isync would be sufficient in case of CompareAndExchangeAcquire, but we currently don't optimize for that. |
|
7885 __ sync(); |
|
7886 } |
|
7887 %} |
|
7888 ins_pipe(pipe_class_default); |
|
7889 %} |
|
7890 |
|
7891 instruct compareAndExchangeB4_acq_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, flagsRegCR0 cr0) %{ |
|
7892 match(Set res (CompareAndExchangeB mem_ptr (Binary src1 src2))); |
|
7893 predicate((((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst) && !VM_Version::has_lqarx()); |
|
7894 effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP cr0); |
|
7895 format %{ "CMPXCHGB acq $res, $mem_ptr, $src1, $src2; as int" %} |
|
7896 ins_encode %{ |
|
7897 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7898 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7899 __ cmpxchgb(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, R0, |
|
7900 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), |
|
7901 noreg, true); |
|
7902 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
7903 __ isync(); |
|
7904 } else { |
|
7905 // isync would be sufficient in case of CompareAndExchangeAcquire, but we currently don't optimize for that. |
|
7906 __ sync(); |
|
7907 } |
|
7908 %} |
|
7909 ins_pipe(pipe_class_default); |
|
7910 %} |
|
7911 |
|
7912 instruct compareAndExchangeS_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{ |
|
7913 match(Set res (CompareAndExchangeS mem_ptr (Binary src1 src2))); |
|
7914 predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst && VM_Version::has_lqarx()); |
|
7915 effect(TEMP_DEF res, TEMP cr0); |
|
7916 format %{ "CMPXCHGH $res, $mem_ptr, $src1, $src2; as int" %} |
|
7917 ins_encode %{ |
|
7918 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7919 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7920 __ cmpxchgh(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, |
|
7921 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), |
|
7922 noreg, true); |
|
7923 %} |
|
7924 ins_pipe(pipe_class_default); |
|
7925 %} |
|
7926 |
|
7927 instruct compareAndExchangeS4_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, flagsRegCR0 cr0) %{ |
|
7928 match(Set res (CompareAndExchangeS mem_ptr (Binary src1 src2))); |
|
7929 predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst && !VM_Version::has_lqarx()); |
|
7930 effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP cr0); |
|
7931 format %{ "CMPXCHGH $res, $mem_ptr, $src1, $src2; as int" %} |
|
7932 ins_encode %{ |
|
7933 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7934 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7935 __ cmpxchgh(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, R0, |
|
7936 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), |
|
7937 noreg, true); |
|
7938 %} |
|
7939 ins_pipe(pipe_class_default); |
|
7940 %} |
|
7941 |
|
7942 instruct compareAndExchangeS_acq_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{ |
|
7943 match(Set res (CompareAndExchangeS mem_ptr (Binary src1 src2))); |
|
7944 predicate((((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst) && VM_Version::has_lqarx()); |
|
7945 effect(TEMP_DEF res, TEMP cr0); |
|
7946 format %{ "CMPXCHGH acq $res, $mem_ptr, $src1, $src2; as int" %} |
|
7947 ins_encode %{ |
|
7948 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7949 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7950 __ cmpxchgh(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, |
|
7951 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), |
|
7952 noreg, true); |
|
7953 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
7954 __ isync(); |
|
7955 } else { |
|
7956 // isync would be sufficient in case of CompareAndExchangeAcquire, but we currently don't optimize for that. |
|
7957 __ sync(); |
|
7958 } |
|
7959 %} |
|
7960 ins_pipe(pipe_class_default); |
|
7961 %} |
|
7962 |
|
7963 instruct compareAndExchangeS4_acq_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, flagsRegCR0 cr0) %{ |
|
7964 match(Set res (CompareAndExchangeS mem_ptr (Binary src1 src2))); |
|
7965 predicate((((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst) && !VM_Version::has_lqarx()); |
|
7966 effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP cr0); |
|
7967 format %{ "CMPXCHGH acq $res, $mem_ptr, $src1, $src2; as int" %} |
|
7968 ins_encode %{ |
|
7969 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
7970 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
|
7971 __ cmpxchgh(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, R0, |
|
7972 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), |
|
7973 noreg, true); |
|
7974 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
7975 __ isync(); |
|
7976 } else { |
|
7977 // isync would be sufficient in case of CompareAndExchangeAcquire, but we currently don't optimize for that. |
|
7978 __ sync(); |
|
7979 } |
|
7980 %} |
|
7981 ins_pipe(pipe_class_default); |
|
7982 %} |
|
7983 |
7799 instruct compareAndExchangeI_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{ |
7984 instruct compareAndExchangeI_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{ |
7800 match(Set res (CompareAndExchangeI mem_ptr (Binary src1 src2))); |
7985 match(Set res (CompareAndExchangeI mem_ptr (Binary src1 src2))); |
7801 predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst); |
7986 predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst); |
7802 effect(TEMP_DEF res, TEMP cr0); |
7987 effect(TEMP_DEF res, TEMP cr0); |
7803 format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as int" %} |
7988 format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as int" %} |
7804 // Variable size: instruction count smaller if regs are disjoint. |
|
7805 ins_encode %{ |
7989 ins_encode %{ |
7806 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
7990 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
7807 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
7991 // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. |
7808 __ cmpxchgw(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, |
7992 __ cmpxchgw(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, |
7809 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), |
7993 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), |
7948 ins_pipe(pipe_class_default); |
8125 ins_pipe(pipe_class_default); |
7949 %} |
8126 %} |
7950 |
8127 |
7951 // Special RMW |
8128 // Special RMW |
7952 |
8129 |
|
8130 instruct getAndAddB(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src, flagsRegCR0 cr0) %{ |
|
8131 match(Set res (GetAndAddB mem_ptr src)); |
|
8132 predicate(VM_Version::has_lqarx()); |
|
8133 effect(TEMP_DEF res, TEMP cr0); |
|
8134 format %{ "GetAndAddB $res, $mem_ptr, $src" %} |
|
8135 ins_encode %{ |
|
8136 __ getandaddb($res$$Register, $src$$Register, $mem_ptr$$Register, |
|
8137 R0, noreg, noreg, MacroAssembler::cmpxchgx_hint_atomic_update()); |
|
8138 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
8139 __ isync(); |
|
8140 } else { |
|
8141 __ sync(); |
|
8142 } |
|
8143 %} |
|
8144 ins_pipe(pipe_class_default); |
|
8145 %} |
|
8146 |
|
8147 instruct getAndAddB4(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src, iRegIsrc tmp1, iRegIsrc tmp2, flagsRegCR0 cr0) %{ |
|
8148 match(Set res (GetAndAddB mem_ptr src)); |
|
8149 predicate(!VM_Version::has_lqarx()); |
|
8150 effect(TEMP_DEF res, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); |
|
8151 format %{ "GetAndAddB $res, $mem_ptr, $src" %} |
|
8152 ins_encode %{ |
|
8153 __ getandaddb($res$$Register, $src$$Register, $mem_ptr$$Register, |
|
8154 R0, $tmp1$$Register, $tmp2$$Register, MacroAssembler::cmpxchgx_hint_atomic_update()); |
|
8155 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
8156 __ isync(); |
|
8157 } else { |
|
8158 __ sync(); |
|
8159 } |
|
8160 %} |
|
8161 ins_pipe(pipe_class_default); |
|
8162 %} |
|
8163 |
|
8164 instruct getAndAddS(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src, flagsRegCR0 cr0) %{ |
|
8165 match(Set res (GetAndAddS mem_ptr src)); |
|
8166 predicate(VM_Version::has_lqarx()); |
|
8167 effect(TEMP_DEF res, TEMP cr0); |
|
8168 format %{ "GetAndAddS $res, $mem_ptr, $src" %} |
|
8169 ins_encode %{ |
|
8170 __ getandaddh($res$$Register, $src$$Register, $mem_ptr$$Register, |
|
8171 R0, noreg, noreg, MacroAssembler::cmpxchgx_hint_atomic_update()); |
|
8172 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
8173 __ isync(); |
|
8174 } else { |
|
8175 __ sync(); |
|
8176 } |
|
8177 %} |
|
8178 ins_pipe(pipe_class_default); |
|
8179 %} |
|
8180 |
|
8181 instruct getAndAddS4(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src, iRegIsrc tmp1, iRegIsrc tmp2, flagsRegCR0 cr0) %{ |
|
8182 match(Set res (GetAndAddS mem_ptr src)); |
|
8183 predicate(!VM_Version::has_lqarx()); |
|
8184 effect(TEMP_DEF res, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); |
|
8185 format %{ "GetAndAddS $res, $mem_ptr, $src" %} |
|
8186 ins_encode %{ |
|
8187 __ getandaddh($res$$Register, $src$$Register, $mem_ptr$$Register, |
|
8188 R0, $tmp1$$Register, $tmp2$$Register, MacroAssembler::cmpxchgx_hint_atomic_update()); |
|
8189 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
8190 __ isync(); |
|
8191 } else { |
|
8192 __ sync(); |
|
8193 } |
|
8194 %} |
|
8195 ins_pipe(pipe_class_default); |
|
8196 %} |
|
8197 |
7953 instruct getAndAddI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src, flagsRegCR0 cr0) %{ |
8198 instruct getAndAddI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src, flagsRegCR0 cr0) %{ |
7954 match(Set res (GetAndAddI mem_ptr src)); |
8199 match(Set res (GetAndAddI mem_ptr src)); |
7955 effect(TEMP cr0); |
8200 effect(TEMP_DEF res, TEMP cr0); |
7956 format %{ "GetAndAddI $res, $mem_ptr, $src" %} |
8201 format %{ "GetAndAddI $res, $mem_ptr, $src" %} |
7957 // Variable size: instruction count smaller if regs are disjoint. |
8202 ins_encode %{ |
7958 ins_encode( enc_GetAndAddI(res, mem_ptr, src) ); |
8203 __ getandaddw($res$$Register, $src$$Register, $mem_ptr$$Register, |
|
8204 R0, MacroAssembler::cmpxchgx_hint_atomic_update()); |
|
8205 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
8206 __ isync(); |
|
8207 } else { |
|
8208 __ sync(); |
|
8209 } |
|
8210 %} |
7959 ins_pipe(pipe_class_default); |
8211 ins_pipe(pipe_class_default); |
7960 %} |
8212 %} |
7961 |
8213 |
7962 instruct getAndAddL(iRegLdst res, iRegPdst mem_ptr, iRegLsrc src, flagsRegCR0 cr0) %{ |
8214 instruct getAndAddL(iRegLdst res, iRegPdst mem_ptr, iRegLsrc src, flagsRegCR0 cr0) %{ |
7963 match(Set res (GetAndAddL mem_ptr src)); |
8215 match(Set res (GetAndAddL mem_ptr src)); |
7964 effect(TEMP cr0); |
8216 effect(TEMP_DEF res, TEMP cr0); |
7965 format %{ "GetAndAddL $res, $mem_ptr, $src" %} |
8217 format %{ "GetAndAddL $res, $mem_ptr, $src" %} |
7966 // Variable size: instruction count smaller if regs are disjoint. |
8218 ins_encode %{ |
7967 ins_encode( enc_GetAndAddL(res, mem_ptr, src) ); |
8219 __ getandaddd($res$$Register, $src$$Register, $mem_ptr$$Register, |
|
8220 R0, MacroAssembler::cmpxchgx_hint_atomic_update()); |
|
8221 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
8222 __ isync(); |
|
8223 } else { |
|
8224 __ sync(); |
|
8225 } |
|
8226 %} |
|
8227 ins_pipe(pipe_class_default); |
|
8228 %} |
|
8229 |
|
8230 instruct getAndSetB(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src, flagsRegCR0 cr0) %{ |
|
8231 match(Set res (GetAndSetB mem_ptr src)); |
|
8232 predicate(VM_Version::has_lqarx()); |
|
8233 effect(TEMP_DEF res, TEMP cr0); |
|
8234 format %{ "GetAndSetB $res, $mem_ptr, $src" %} |
|
8235 ins_encode %{ |
|
8236 __ getandsetb($res$$Register, $src$$Register, $mem_ptr$$Register, |
|
8237 noreg, noreg, noreg, MacroAssembler::cmpxchgx_hint_atomic_update()); |
|
8238 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
8239 __ isync(); |
|
8240 } else { |
|
8241 __ sync(); |
|
8242 } |
|
8243 %} |
|
8244 ins_pipe(pipe_class_default); |
|
8245 %} |
|
8246 |
|
8247 instruct getAndSetB4(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src, iRegIsrc tmp1, iRegIsrc tmp2, flagsRegCR0 cr0) %{ |
|
8248 match(Set res (GetAndSetB mem_ptr src)); |
|
8249 predicate(!VM_Version::has_lqarx()); |
|
8250 effect(TEMP_DEF res, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); |
|
8251 format %{ "GetAndSetB $res, $mem_ptr, $src" %} |
|
8252 ins_encode %{ |
|
8253 __ getandsetb($res$$Register, $src$$Register, $mem_ptr$$Register, |
|
8254 R0, $tmp1$$Register, $tmp2$$Register, MacroAssembler::cmpxchgx_hint_atomic_update()); |
|
8255 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
8256 __ isync(); |
|
8257 } else { |
|
8258 __ sync(); |
|
8259 } |
|
8260 %} |
|
8261 ins_pipe(pipe_class_default); |
|
8262 %} |
|
8263 |
|
8264 instruct getAndSetS(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src, flagsRegCR0 cr0) %{ |
|
8265 match(Set res (GetAndSetS mem_ptr src)); |
|
8266 predicate(VM_Version::has_lqarx()); |
|
8267 effect(TEMP_DEF res, TEMP cr0); |
|
8268 format %{ "GetAndSetS $res, $mem_ptr, $src" %} |
|
8269 ins_encode %{ |
|
8270 __ getandseth($res$$Register, $src$$Register, $mem_ptr$$Register, |
|
8271 noreg, noreg, noreg, MacroAssembler::cmpxchgx_hint_atomic_update()); |
|
8272 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
8273 __ isync(); |
|
8274 } else { |
|
8275 __ sync(); |
|
8276 } |
|
8277 %} |
|
8278 ins_pipe(pipe_class_default); |
|
8279 %} |
|
8280 |
|
8281 instruct getAndSetS4(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src, iRegIsrc tmp1, iRegIsrc tmp2, flagsRegCR0 cr0) %{ |
|
8282 match(Set res (GetAndSetS mem_ptr src)); |
|
8283 predicate(!VM_Version::has_lqarx()); |
|
8284 effect(TEMP_DEF res, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); |
|
8285 format %{ "GetAndSetS $res, $mem_ptr, $src" %} |
|
8286 ins_encode %{ |
|
8287 __ getandseth($res$$Register, $src$$Register, $mem_ptr$$Register, |
|
8288 R0, $tmp1$$Register, $tmp2$$Register, MacroAssembler::cmpxchgx_hint_atomic_update()); |
|
8289 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
8290 __ isync(); |
|
8291 } else { |
|
8292 __ sync(); |
|
8293 } |
|
8294 %} |
7968 ins_pipe(pipe_class_default); |
8295 ins_pipe(pipe_class_default); |
7969 %} |
8296 %} |
7970 |
8297 |
7971 instruct getAndSetI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src, flagsRegCR0 cr0) %{ |
8298 instruct getAndSetI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src, flagsRegCR0 cr0) %{ |
7972 match(Set res (GetAndSetI mem_ptr src)); |
8299 match(Set res (GetAndSetI mem_ptr src)); |
7973 effect(TEMP cr0); |
8300 effect(TEMP_DEF res, TEMP cr0); |
7974 format %{ "GetAndSetI $res, $mem_ptr, $src" %} |
8301 format %{ "GetAndSetI $res, $mem_ptr, $src" %} |
7975 // Variable size: instruction count smaller if regs are disjoint. |
8302 ins_encode %{ |
7976 ins_encode( enc_GetAndSetI(res, mem_ptr, src) ); |
8303 __ getandsetw($res$$Register, $src$$Register, $mem_ptr$$Register, |
|
8304 MacroAssembler::cmpxchgx_hint_atomic_update()); |
|
8305 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
8306 __ isync(); |
|
8307 } else { |
|
8308 __ sync(); |
|
8309 } |
|
8310 %} |
7977 ins_pipe(pipe_class_default); |
8311 ins_pipe(pipe_class_default); |
7978 %} |
8312 %} |
7979 |
8313 |
7980 instruct getAndSetL(iRegLdst res, iRegPdst mem_ptr, iRegLsrc src, flagsRegCR0 cr0) %{ |
8314 instruct getAndSetL(iRegLdst res, iRegPdst mem_ptr, iRegLsrc src, flagsRegCR0 cr0) %{ |
7981 match(Set res (GetAndSetL mem_ptr src)); |
8315 match(Set res (GetAndSetL mem_ptr src)); |
7982 effect(TEMP cr0); |
8316 effect(TEMP_DEF res, TEMP cr0); |
7983 format %{ "GetAndSetL $res, $mem_ptr, $src" %} |
8317 format %{ "GetAndSetL $res, $mem_ptr, $src" %} |
7984 // Variable size: instruction count smaller if regs are disjoint. |
8318 ins_encode %{ |
7985 ins_encode( enc_GetAndSetL(res, mem_ptr, src) ); |
8319 __ getandsetd($res$$Register, $src$$Register, $mem_ptr$$Register, |
|
8320 MacroAssembler::cmpxchgx_hint_atomic_update()); |
|
8321 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
8322 __ isync(); |
|
8323 } else { |
|
8324 __ sync(); |
|
8325 } |
|
8326 %} |
7986 ins_pipe(pipe_class_default); |
8327 ins_pipe(pipe_class_default); |
7987 %} |
8328 %} |
7988 |
8329 |
7989 instruct getAndSetP(iRegPdst res, iRegPdst mem_ptr, iRegPsrc src, flagsRegCR0 cr0) %{ |
8330 instruct getAndSetP(iRegPdst res, iRegPdst mem_ptr, iRegPsrc src, flagsRegCR0 cr0) %{ |
7990 match(Set res (GetAndSetP mem_ptr src)); |
8331 match(Set res (GetAndSetP mem_ptr src)); |
7991 effect(TEMP cr0); |
8332 effect(TEMP_DEF res, TEMP cr0); |
7992 format %{ "GetAndSetP $res, $mem_ptr, $src" %} |
8333 format %{ "GetAndSetP $res, $mem_ptr, $src" %} |
7993 // Variable size: instruction count smaller if regs are disjoint. |
8334 ins_encode %{ |
7994 ins_encode( enc_GetAndSetL(res, mem_ptr, src) ); |
8335 __ getandsetd($res$$Register, $src$$Register, $mem_ptr$$Register, |
|
8336 MacroAssembler::cmpxchgx_hint_atomic_update()); |
|
8337 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
8338 __ isync(); |
|
8339 } else { |
|
8340 __ sync(); |
|
8341 } |
|
8342 %} |
7995 ins_pipe(pipe_class_default); |
8343 ins_pipe(pipe_class_default); |
7996 %} |
8344 %} |
7997 |
8345 |
7998 instruct getAndSetN(iRegNdst res, iRegPdst mem_ptr, iRegNsrc src, flagsRegCR0 cr0) %{ |
8346 instruct getAndSetN(iRegNdst res, iRegPdst mem_ptr, iRegNsrc src, flagsRegCR0 cr0) %{ |
7999 match(Set res (GetAndSetN mem_ptr src)); |
8347 match(Set res (GetAndSetN mem_ptr src)); |
8000 effect(TEMP cr0); |
8348 effect(TEMP_DEF res, TEMP cr0); |
8001 format %{ "GetAndSetN $res, $mem_ptr, $src" %} |
8349 format %{ "GetAndSetN $res, $mem_ptr, $src" %} |
8002 // Variable size: instruction count smaller if regs are disjoint. |
8350 ins_encode %{ |
8003 ins_encode( enc_GetAndSetI(res, mem_ptr, src) ); |
8351 __ getandsetw($res$$Register, $src$$Register, $mem_ptr$$Register, |
|
8352 MacroAssembler::cmpxchgx_hint_atomic_update()); |
|
8353 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
|
8354 __ isync(); |
|
8355 } else { |
|
8356 __ sync(); |
|
8357 } |
|
8358 %} |
8004 ins_pipe(pipe_class_default); |
8359 ins_pipe(pipe_class_default); |
8005 %} |
8360 %} |
8006 |
8361 |
8007 //----------Arithmetic Instructions-------------------------------------------- |
8362 //----------Arithmetic Instructions-------------------------------------------- |
8008 // Addition Instructions |
8363 // Addition Instructions |
11945 __ subf($result$$Register, $result$$Register, $len$$Register); |
12299 __ subf($result$$Register, $result$$Register, $len$$Register); |
11946 %} |
12300 %} |
11947 ins_pipe(pipe_class_default); |
12301 ins_pipe(pipe_class_default); |
11948 %} |
12302 %} |
11949 |
12303 |
11950 |
|
11951 // String_IndexOf for needle of length 1. |
|
11952 // |
|
11953 // Match needle into immediate operands: no loadConP node needed. Saves one |
|
11954 // register and two instructions over string_indexOf_imm1Node. |
|
11955 // |
|
11956 // Assumes register result differs from all input registers. |
|
11957 // |
|
11958 // Preserves registers haystack, haycnt |
|
11959 // Kills registers tmp1, tmp2 |
|
11960 // Defines registers result |
|
11961 // |
|
11962 // Use dst register classes if register gets killed, as it is the case for tmp registers! |
|
11963 // |
|
11964 // Unfortunately this does not match too often. In many situations the AddP is used |
|
11965 // by several nodes, even several StrIndexOf nodes, breaking the match tree. |
|
11966 instruct string_indexOf_imm1_char(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt, |
|
11967 immP needleImm, immL offsetImm, immI_1 needlecntImm, |
|
11968 iRegIdst tmp1, iRegIdst tmp2, |
|
11969 flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{ |
|
11970 predicate(SpecialStringIndexOf && !CompactStrings); // type check implicit by parameter type, See Matcher::match_rule_supported |
|
11971 match(Set result (StrIndexOf (Binary haystack haycnt) (Binary (AddP needleImm offsetImm) needlecntImm))); |
|
11972 |
|
11973 effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr); |
|
11974 |
|
11975 ins_cost(150); |
|
11976 format %{ "String IndexOf CSCL1 $haystack[0..$haycnt], $needleImm+$offsetImm[0..$needlecntImm]" |
|
11977 "-> $result \t// KILL $haycnt, $tmp1, $tmp2, $cr0, $cr1" %} |
|
11978 |
|
11979 ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted |
|
11980 ins_encode %{ |
|
11981 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
11982 immPOper *needleOper = (immPOper *)$needleImm; |
|
11983 const TypeOopPtr *t = needleOper->type()->isa_oopptr(); |
|
11984 ciTypeArray* needle_values = t->const_oop()->as_type_array(); // Pointer to live char * |
|
11985 jchar chr; |
|
11986 if (java_lang_String::has_coder_field()) { |
|
11987 // New compact strings byte array strings |
|
11988 #ifdef VM_LITTLE_ENDIAN |
|
11989 chr = (((jchar)(unsigned char)needle_values->element_value(1).as_byte()) << 8) | |
|
11990 ((jchar)(unsigned char)needle_values->element_value(0).as_byte()); |
|
11991 #else |
|
11992 chr = (((jchar)(unsigned char)needle_values->element_value(0).as_byte()) << 8) | |
|
11993 ((jchar)(unsigned char)needle_values->element_value(1).as_byte()); |
|
11994 #endif |
|
11995 } else { |
|
11996 // Old char array strings |
|
11997 chr = needle_values->char_at(0); |
|
11998 } |
|
11999 __ string_indexof_1($result$$Register, |
|
12000 $haystack$$Register, $haycnt$$Register, |
|
12001 R0, chr, |
|
12002 $tmp1$$Register, $tmp2$$Register); |
|
12003 %} |
|
12004 ins_pipe(pipe_class_compare); |
|
12005 %} |
|
12006 |
|
12007 // String_IndexOf for needle of length 1. |
|
12008 // |
|
12009 // Special case requires less registers and emits less instructions. |
|
12010 // |
|
12011 // Assumes register result differs from all input registers. |
|
12012 // |
|
12013 // Preserves registers haystack, haycnt |
|
12014 // Kills registers tmp1, tmp2, needle |
|
12015 // Defines registers result |
|
12016 // |
|
12017 // Use dst register classes if register gets killed, as it is the case for tmp registers! |
|
12018 instruct string_indexOf_imm1(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt, |
|
12019 rscratch2RegP needle, immI_1 needlecntImm, |
|
12020 iRegIdst tmp1, iRegIdst tmp2, |
|
12021 flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{ |
|
12022 match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm))); |
|
12023 effect(USE_KILL needle, /* TDEF needle, */ TEMP_DEF result, |
|
12024 TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr); |
|
12025 // Required for EA: check if it is still a type_array. |
|
12026 predicate(SpecialStringIndexOf && !CompactStrings && |
|
12027 n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() && |
|
12028 n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array()); |
|
12029 ins_cost(180); |
|
12030 |
|
12031 ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted. |
|
12032 |
|
12033 format %{ "String IndexOf SCL1 $haystack[0..$haycnt], $needle[0..$needlecntImm]" |
|
12034 " -> $result \t// KILL $haycnt, $needle, $tmp1, $tmp2, $cr0, $cr1" %} |
|
12035 ins_encode %{ |
|
12036 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
12037 Node *ndl = in(operand_index($needle)); // The node that defines needle. |
|
12038 ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array(); |
|
12039 guarantee(needle_values, "sanity"); |
|
12040 jchar chr; |
|
12041 if (java_lang_String::has_coder_field()) { |
|
12042 // New compact strings byte array strings |
|
12043 #ifdef VM_LITTLE_ENDIAN |
|
12044 chr = (((jchar)(unsigned char)needle_values->element_value(1).as_byte()) << 8) | |
|
12045 ((jchar)(unsigned char)needle_values->element_value(0).as_byte()); |
|
12046 #else |
|
12047 chr = (((jchar)(unsigned char)needle_values->element_value(0).as_byte()) << 8) | |
|
12048 ((jchar)(unsigned char)needle_values->element_value(1).as_byte()); |
|
12049 #endif |
|
12050 } else { |
|
12051 // Old char array strings |
|
12052 chr = needle_values->char_at(0); |
|
12053 } |
|
12054 __ string_indexof_1($result$$Register, |
|
12055 $haystack$$Register, $haycnt$$Register, |
|
12056 R0, chr, |
|
12057 $tmp1$$Register, $tmp2$$Register); |
|
12058 %} |
|
12059 ins_pipe(pipe_class_compare); |
|
12060 %} |
|
12061 |
|
12062 // String_IndexOfChar |
|
12063 // |
|
12064 // Assumes register result differs from all input registers. |
|
12065 // |
|
12066 // Preserves registers haystack, haycnt |
|
12067 // Kills registers tmp1, tmp2 |
|
12068 // Defines registers result |
|
12069 // |
|
12070 // Use dst register classes if register gets killed, as it is the case for tmp registers! |
|
12071 instruct string_indexOfChar(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt, |
|
12072 iRegIsrc ch, iRegIdst tmp1, iRegIdst tmp2, |
|
12073 flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{ |
|
12074 match(Set result (StrIndexOfChar (Binary haystack haycnt) ch)); |
|
12075 effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr); |
|
12076 predicate(SpecialStringIndexOf && !CompactStrings); |
|
12077 ins_cost(180); |
|
12078 |
|
12079 ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted. |
|
12080 |
|
12081 format %{ "String IndexOfChar $haystack[0..$haycnt], $ch" |
|
12082 " -> $result \t// KILL $haycnt, $tmp1, $tmp2, $cr0, $cr1" %} |
|
12083 ins_encode %{ |
|
12084 __ string_indexof_1($result$$Register, |
|
12085 $haystack$$Register, $haycnt$$Register, |
|
12086 $ch$$Register, 0 /* this is not used if the character is already in a register */, |
|
12087 $tmp1$$Register, $tmp2$$Register); |
|
12088 %} |
|
12089 ins_pipe(pipe_class_compare); |
|
12090 %} |
|
12091 |
|
12092 // String_IndexOf. |
|
12093 // |
|
12094 // Length of needle as immediate. This saves instruction loading constant needle |
|
12095 // length. |
|
12096 // @@@ TODO Specify rules for length < 8 or so, and roll out comparison of needle |
|
12097 // completely or do it in vector instruction. This should save registers for |
|
12098 // needlecnt and needle. |
|
12099 // |
|
12100 // Assumes register result differs from all input registers. |
|
12101 // Overwrites haycnt, needlecnt. |
|
12102 // Use dst register classes if register gets killed, as it is the case for tmp registers! |
|
12103 instruct string_indexOf_imm(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, |
|
12104 iRegPsrc needle, uimmI15 needlecntImm, |
|
12105 iRegIdst tmp1, iRegIdst tmp2, iRegIdst tmp3, iRegIdst tmp4, iRegIdst tmp5, |
|
12106 flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{ |
|
12107 match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm))); |
|
12108 effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP_DEF result, |
|
12109 TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, KILL cr0, KILL cr1, KILL cr6, KILL ctr); |
|
12110 // Required for EA: check if it is still a type_array. |
|
12111 predicate(SpecialStringIndexOf && !CompactStrings && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() && |
|
12112 n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array()); |
|
12113 ins_cost(250); |
|
12114 |
|
12115 ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted. |
|
12116 |
|
12117 format %{ "String IndexOf SCL $haystack[0..$haycnt], $needle[0..$needlecntImm]" |
|
12118 " -> $result \t// KILL $haycnt, $tmp1, $tmp2, $tmp3, $tmp4, $tmp5, $cr0, $cr1" %} |
|
12119 ins_encode %{ |
|
12120 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
12121 Node *ndl = in(operand_index($needle)); // The node that defines needle. |
|
12122 ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array(); |
|
12123 |
|
12124 __ string_indexof($result$$Register, |
|
12125 $haystack$$Register, $haycnt$$Register, |
|
12126 $needle$$Register, needle_values, $tmp5$$Register, $needlecntImm$$constant, |
|
12127 $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register); |
|
12128 %} |
|
12129 ins_pipe(pipe_class_compare); |
|
12130 %} |
|
12131 |
|
12132 // StrIndexOf node. |
|
12133 // |
|
12134 // Assumes register result differs from all input registers. |
|
12135 // Overwrites haycnt, needlecnt. |
|
12136 // Use dst register classes if register gets killed, as it is the case for tmp registers! |
|
12137 instruct string_indexOf(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, iRegPsrc needle, rscratch2RegI needlecnt, |
|
12138 iRegLdst tmp1, iRegLdst tmp2, iRegLdst tmp3, iRegLdst tmp4, |
|
12139 flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{ |
|
12140 match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecnt))); |
|
12141 effect(USE_KILL haycnt, USE_KILL needlecnt, /*better: TDEF haycnt, TDEF needlecnt,*/ |
|
12142 TEMP_DEF result, |
|
12143 TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr0, KILL cr1, KILL cr6, KILL ctr); |
|
12144 predicate(SpecialStringIndexOf && !CompactStrings); // See Matcher::match_rule_supported. |
|
12145 ins_cost(300); |
|
12146 |
|
12147 ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted. |
|
12148 |
|
12149 format %{ "String IndexOf $haystack[0..$haycnt], $needle[0..$needlecnt]" |
|
12150 " -> $result \t// KILL $haycnt, $needlecnt, $tmp1, $tmp2, $tmp3, $tmp4, $cr0, $cr1" %} |
|
12151 ins_encode %{ |
|
12152 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
12153 __ string_indexof($result$$Register, |
|
12154 $haystack$$Register, $haycnt$$Register, |
|
12155 $needle$$Register, NULL, $needlecnt$$Register, 0, // needlecnt not constant. |
|
12156 $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register); |
|
12157 %} |
|
12158 ins_pipe(pipe_class_compare); |
|
12159 %} |
|
12160 |
|
12161 // String equals with immediate. |
|
12162 instruct string_equals_imm(iRegPsrc str1, iRegPsrc str2, uimmI15 cntImm, iRegIdst result, |
|
12163 iRegPdst tmp1, iRegPdst tmp2, |
|
12164 flagsRegCR0 cr0, flagsRegCR6 cr6, regCTR ctr) %{ |
|
12165 match(Set result (StrEquals (Binary str1 str2) cntImm)); |
|
12166 effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, |
|
12167 KILL cr0, KILL cr6, KILL ctr); |
|
12168 predicate(SpecialStringEquals && !CompactStrings); // See Matcher::match_rule_supported. |
|
12169 ins_cost(250); |
|
12170 |
|
12171 ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted. |
|
12172 |
|
12173 format %{ "String Equals SCL [0..$cntImm]($str1),[0..$cntImm]($str2)" |
|
12174 " -> $result \t// KILL $cr0, $cr6, $ctr, TEMP $result, $tmp1, $tmp2" %} |
|
12175 ins_encode %{ |
|
12176 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
12177 __ char_arrays_equalsImm($str1$$Register, $str2$$Register, $cntImm$$constant, |
|
12178 $result$$Register, $tmp1$$Register, $tmp2$$Register); |
|
12179 %} |
|
12180 ins_pipe(pipe_class_compare); |
|
12181 %} |
|
12182 |
|
12183 // String equals. |
|
12184 // Use dst register classes if register gets killed, as it is the case for TEMP operands! |
|
12185 instruct string_equals(iRegPsrc str1, iRegPsrc str2, iRegIsrc cnt, iRegIdst result, |
|
12186 iRegPdst tmp1, iRegPdst tmp2, iRegPdst tmp3, iRegPdst tmp4, iRegPdst tmp5, |
|
12187 flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{ |
|
12188 match(Set result (StrEquals (Binary str1 str2) cnt)); |
|
12189 effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, |
|
12190 KILL cr0, KILL cr1, KILL cr6, KILL ctr); |
|
12191 predicate(SpecialStringEquals && !CompactStrings); // See Matcher::match_rule_supported. |
|
12192 ins_cost(300); |
|
12193 |
|
12194 ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted. |
|
12195 |
|
12196 format %{ "String Equals [0..$cnt]($str1),[0..$cnt]($str2) -> $result" |
|
12197 " \t// KILL $cr0, $cr1, $cr6, $ctr, TEMP $result, $tmp1, $tmp2, $tmp3, $tmp4, $tmp5" %} |
|
12198 ins_encode %{ |
|
12199 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
12200 __ char_arrays_equals($str1$$Register, $str2$$Register, $cnt$$Register, $result$$Register, |
|
12201 $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, $tmp5$$Register); |
|
12202 %} |
|
12203 ins_pipe(pipe_class_compare); |
|
12204 %} |
|
12205 |
|
12206 // String compare. |
|
12207 // Char[] pointers are passed in. |
|
12208 // Use dst register classes if register gets killed, as it is the case for TEMP operands! |
|
12209 instruct string_compare(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4RegI cnt2, iRegIdst result, |
|
12210 iRegPdst tmp, flagsRegCR0 cr0, regCTR ctr) %{ |
|
12211 predicate(!CompactStrings); |
|
12212 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); |
|
12213 effect(USE_KILL cnt1, USE_KILL cnt2, USE_KILL str1, USE_KILL str2, TEMP_DEF result, TEMP tmp, KILL cr0, KILL ctr); |
|
12214 ins_cost(300); |
|
12215 |
|
12216 ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted. |
|
12217 |
|
12218 format %{ "String Compare $str1[0..$cnt1], $str2[0..$cnt2] -> $result" |
|
12219 " \t// TEMP $tmp, $result KILLs $str1, $cnt1, $str2, $cnt2, $cr0, $ctr" %} |
|
12220 ins_encode %{ |
|
12221 // TODO: PPC port $archOpcode(ppc64Opcode_compound); |
|
12222 __ string_compare($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, |
|
12223 $result$$Register, $tmp$$Register); |
|
12224 %} |
|
12225 ins_pipe(pipe_class_compare); |
|
12226 %} |
|
12227 |
12304 |
12228 //---------- Min/Max Instructions --------------------------------------------- |
12305 //---------- Min/Max Instructions --------------------------------------------- |
12229 |
12306 |
12230 instruct minI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ |
12307 instruct minI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ |
12231 match(Set dst (MinI src1 src2)); |
12308 match(Set dst (MinI src1 src2)); |