2331 movcc(greater, false, xcc, 1, Rresult); |
2331 movcc(greater, false, xcc, 1, Rresult); |
2332 } |
2332 } |
2333 #endif |
2333 #endif |
2334 |
2334 |
2335 |
2335 |
|
2336 void MacroAssembler::load_sized_value(Address src, Register dst, |
|
2337 size_t size_in_bytes, bool is_signed) { |
|
2338 switch (size_in_bytes) { |
|
2339 case 8: ldx(src, dst); break; |
|
2340 case 4: ld( src, dst); break; |
|
2341 case 2: is_signed ? ldsh(src, dst) : lduh(src, dst); break; |
|
2342 case 1: is_signed ? ldsb(src, dst) : ldub(src, dst); break; |
|
2343 default: ShouldNotReachHere(); |
|
2344 } |
|
2345 } |
|
2346 |
|
2347 |
2336 void MacroAssembler::float_cmp( bool is_float, int unordered_result, |
2348 void MacroAssembler::float_cmp( bool is_float, int unordered_result, |
2337 FloatRegister Fa, FloatRegister Fb, |
2349 FloatRegister Fa, FloatRegister Fb, |
2338 Register Rresult) { |
2350 Register Rresult) { |
2339 |
2351 |
2340 fcmp(is_float ? FloatRegisterImpl::S : FloatRegisterImpl::D, fcc0, Fa, Fb); |
2352 fcmp(is_float ? FloatRegisterImpl::S : FloatRegisterImpl::D, fcc0, Fa, Fb); |
2623 |
2635 |
2624 return RegisterOrConstant(tmp); |
2636 return RegisterOrConstant(tmp); |
2625 } |
2637 } |
2626 |
2638 |
2627 |
2639 |
2628 void MacroAssembler::regcon_inc_ptr( RegisterOrConstant& dest, RegisterOrConstant src, Register temp ) { |
2640 RegisterOrConstant MacroAssembler::regcon_andn_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp) { |
2629 assert(dest.register_or_noreg() != G0, "lost side effect"); |
2641 assert(d.register_or_noreg() != G0, "lost side effect"); |
2630 if ((src.is_constant() && src.as_constant() == 0) || |
2642 if ((s2.is_constant() && s2.as_constant() == 0) || |
2631 (src.is_register() && src.as_register() == G0)) { |
2643 (s2.is_register() && s2.as_register() == G0)) { |
2632 // do nothing |
2644 // Do nothing, just move value. |
2633 } else if (dest.is_register()) { |
2645 if (s1.is_register()) { |
2634 add(dest.as_register(), ensure_simm13_or_reg(src, temp), dest.as_register()); |
2646 if (d.is_constant()) d = temp; |
2635 } else if (src.is_constant()) { |
2647 mov(s1.as_register(), d.as_register()); |
2636 intptr_t res = dest.as_constant() + src.as_constant(); |
2648 return d; |
2637 dest = RegisterOrConstant(res); // side effect seen by caller |
2649 } else { |
|
2650 return s1; |
|
2651 } |
|
2652 } |
|
2653 |
|
2654 if (s1.is_register()) { |
|
2655 assert_different_registers(s1.as_register(), temp); |
|
2656 if (d.is_constant()) d = temp; |
|
2657 andn(s1.as_register(), ensure_simm13_or_reg(s2, temp), d.as_register()); |
|
2658 return d; |
2638 } else { |
2659 } else { |
2639 assert(temp != noreg, "cannot handle constant += register"); |
2660 if (s2.is_register()) { |
2640 add(src.as_register(), ensure_simm13_or_reg(dest, temp), temp); |
2661 assert_different_registers(s2.as_register(), temp); |
2641 dest = RegisterOrConstant(temp); // side effect seen by caller |
2662 if (d.is_constant()) d = temp; |
2642 } |
2663 set(s1.as_constant(), temp); |
2643 } |
2664 andn(temp, s2.as_register(), d.as_register()); |
2644 |
2665 return d; |
2645 void MacroAssembler::regcon_sll_ptr( RegisterOrConstant& dest, RegisterOrConstant src, Register temp ) { |
2666 } else { |
2646 assert(dest.register_or_noreg() != G0, "lost side effect"); |
2667 intptr_t res = s1.as_constant() & ~s2.as_constant(); |
2647 if (!is_simm13(src.constant_or_zero())) |
2668 return res; |
2648 src = (src.as_constant() & 0xFF); |
2669 } |
2649 if ((src.is_constant() && src.as_constant() == 0) || |
2670 } |
2650 (src.is_register() && src.as_register() == G0)) { |
2671 } |
2651 // do nothing |
2672 |
2652 } else if (dest.is_register()) { |
2673 RegisterOrConstant MacroAssembler::regcon_inc_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp) { |
2653 sll_ptr(dest.as_register(), src, dest.as_register()); |
2674 assert(d.register_or_noreg() != G0, "lost side effect"); |
2654 } else if (src.is_constant()) { |
2675 if ((s2.is_constant() && s2.as_constant() == 0) || |
2655 intptr_t res = dest.as_constant() << src.as_constant(); |
2676 (s2.is_register() && s2.as_register() == G0)) { |
2656 dest = RegisterOrConstant(res); // side effect seen by caller |
2677 // Do nothing, just move value. |
|
2678 if (s1.is_register()) { |
|
2679 if (d.is_constant()) d = temp; |
|
2680 mov(s1.as_register(), d.as_register()); |
|
2681 return d; |
|
2682 } else { |
|
2683 return s1; |
|
2684 } |
|
2685 } |
|
2686 |
|
2687 if (s1.is_register()) { |
|
2688 assert_different_registers(s1.as_register(), temp); |
|
2689 if (d.is_constant()) d = temp; |
|
2690 add(s1.as_register(), ensure_simm13_or_reg(s2, temp), d.as_register()); |
|
2691 return d; |
2657 } else { |
2692 } else { |
2658 assert(temp != noreg, "cannot handle constant <<= register"); |
2693 if (s2.is_register()) { |
2659 set(dest.as_constant(), temp); |
2694 assert_different_registers(s2.as_register(), temp); |
2660 sll_ptr(temp, src, temp); |
2695 if (d.is_constant()) d = temp; |
2661 dest = RegisterOrConstant(temp); // side effect seen by caller |
2696 add(s2.as_register(), ensure_simm13_or_reg(s1, temp), d.as_register()); |
|
2697 return d; |
|
2698 } else { |
|
2699 intptr_t res = s1.as_constant() + s2.as_constant(); |
|
2700 return res; |
|
2701 } |
|
2702 } |
|
2703 } |
|
2704 |
|
2705 RegisterOrConstant MacroAssembler::regcon_sll_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp) { |
|
2706 assert(d.register_or_noreg() != G0, "lost side effect"); |
|
2707 if (!is_simm13(s2.constant_or_zero())) |
|
2708 s2 = (s2.as_constant() & 0xFF); |
|
2709 if ((s2.is_constant() && s2.as_constant() == 0) || |
|
2710 (s2.is_register() && s2.as_register() == G0)) { |
|
2711 // Do nothing, just move value. |
|
2712 if (s1.is_register()) { |
|
2713 if (d.is_constant()) d = temp; |
|
2714 mov(s1.as_register(), d.as_register()); |
|
2715 return d; |
|
2716 } else { |
|
2717 return s1; |
|
2718 } |
|
2719 } |
|
2720 |
|
2721 if (s1.is_register()) { |
|
2722 assert_different_registers(s1.as_register(), temp); |
|
2723 if (d.is_constant()) d = temp; |
|
2724 sll_ptr(s1.as_register(), ensure_simm13_or_reg(s2, temp), d.as_register()); |
|
2725 return d; |
|
2726 } else { |
|
2727 if (s2.is_register()) { |
|
2728 assert_different_registers(s2.as_register(), temp); |
|
2729 if (d.is_constant()) d = temp; |
|
2730 set(s1.as_constant(), temp); |
|
2731 sll_ptr(temp, s2.as_register(), d.as_register()); |
|
2732 return d; |
|
2733 } else { |
|
2734 intptr_t res = s1.as_constant() << s2.as_constant(); |
|
2735 return res; |
|
2736 } |
2662 } |
2737 } |
2663 } |
2738 } |
2664 |
2739 |
2665 |
2740 |
2666 // Look up the method for a megamorphic invokeinterface call. |
2741 // Look up the method for a megamorphic invokeinterface call. |
2706 } |
2781 } |
2707 add(recv_klass, scan_temp, scan_temp); |
2782 add(recv_klass, scan_temp, scan_temp); |
2708 |
2783 |
2709 // Adjust recv_klass by scaled itable_index, so we can free itable_index. |
2784 // Adjust recv_klass by scaled itable_index, so we can free itable_index. |
2710 RegisterOrConstant itable_offset = itable_index; |
2785 RegisterOrConstant itable_offset = itable_index; |
2711 regcon_sll_ptr(itable_offset, exact_log2(itableMethodEntry::size() * wordSize)); |
2786 itable_offset = regcon_sll_ptr(itable_index, exact_log2(itableMethodEntry::size() * wordSize), itable_offset); |
2712 regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes()); |
2787 itable_offset = regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes(), itable_offset); |
2713 add(recv_klass, ensure_simm13_or_reg(itable_offset, sethi_temp), recv_klass); |
2788 add(recv_klass, ensure_simm13_or_reg(itable_offset, sethi_temp), recv_klass); |
2714 |
2789 |
2715 // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { |
2790 // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { |
2716 // if (scan->interface() == intf) { |
2791 // if (scan->interface() == intf) { |
2717 // result = (klass + scan->offset() + itable_index); |
2792 // result = (klass + scan->offset() + itable_index); |
2853 // Check the supertype display: |
2928 // Check the supertype display: |
2854 if (must_load_sco) { |
2929 if (must_load_sco) { |
2855 // The super check offset is always positive... |
2930 // The super check offset is always positive... |
2856 lduw(super_klass, sco_offset, temp2_reg); |
2931 lduw(super_klass, sco_offset, temp2_reg); |
2857 super_check_offset = RegisterOrConstant(temp2_reg); |
2932 super_check_offset = RegisterOrConstant(temp2_reg); |
|
2933 // super_check_offset is register. |
|
2934 assert_different_registers(sub_klass, super_klass, temp_reg, super_check_offset.as_register()); |
2858 } |
2935 } |
2859 ld_ptr(sub_klass, super_check_offset, temp_reg); |
2936 ld_ptr(sub_klass, super_check_offset, temp_reg); |
2860 cmp(super_klass, temp_reg); |
2937 cmp(super_klass, temp_reg); |
2861 |
2938 |
2862 // This check has worked decisively for primary supers. |
2939 // This check has worked decisively for primary supers. |
3012 |
3089 |
3013 bind(L_fallthrough); |
3090 bind(L_fallthrough); |
3014 } |
3091 } |
3015 |
3092 |
3016 |
3093 |
3017 |
|
3018 |
|
3019 void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg, |
3094 void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg, |
3020 Register temp_reg, |
3095 Register temp_reg, |
3021 Label& wrong_method_type) { |
3096 Label& wrong_method_type) { |
|
3097 if (UseCompressedOops) unimplemented("coop"); // field accesses must decode |
3022 assert_different_registers(mtype_reg, mh_reg, temp_reg); |
3098 assert_different_registers(mtype_reg, mh_reg, temp_reg); |
3023 // compare method type against that of the receiver |
3099 // compare method type against that of the receiver |
3024 RegisterOrConstant mhtype_offset = delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg); |
3100 RegisterOrConstant mhtype_offset = delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg); |
3025 ld_ptr(mh_reg, mhtype_offset, temp_reg); |
3101 ld_ptr(mh_reg, mhtype_offset, temp_reg); |
3026 cmp(temp_reg, mtype_reg); |
3102 cmp(temp_reg, mtype_reg); |
3027 br(Assembler::notEqual, false, Assembler::pn, wrong_method_type); |
3103 br(Assembler::notEqual, false, Assembler::pn, wrong_method_type); |
3028 delayed()->nop(); |
3104 delayed()->nop(); |
3029 } |
3105 } |
3030 |
3106 |
3031 |
3107 |
3032 void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) { |
3108 // A method handle has a "vmslots" field which gives the size of its |
|
3109 // argument list in JVM stack slots. This field is either located directly |
|
3110 // in every method handle, or else is indirectly accessed through the |
|
3111 // method handle's MethodType. This macro hides the distinction. |
|
3112 void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register mh_reg, |
|
3113 Register temp_reg) { |
|
3114 assert_different_registers(vmslots_reg, mh_reg, temp_reg); |
|
3115 if (UseCompressedOops) unimplemented("coop"); // field accesses must decode |
|
3116 // load mh.type.form.vmslots |
|
3117 if (java_dyn_MethodHandle::vmslots_offset_in_bytes() != 0) { |
|
3118 // hoist vmslots into every mh to avoid dependent load chain |
|
3119 ld( Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); |
|
3120 } else { |
|
3121 Register temp2_reg = vmslots_reg; |
|
3122 ld_ptr(Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg)), temp2_reg); |
|
3123 ld_ptr(Address(temp2_reg, delayed_value(java_dyn_MethodType::form_offset_in_bytes, temp_reg)), temp2_reg); |
|
3124 ld( Address(temp2_reg, delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); |
|
3125 } |
|
3126 } |
|
3127 |
|
3128 |
|
3129 void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg, bool emit_delayed_nop) { |
3033 assert(mh_reg == G3_method_handle, "caller must put MH object in G3"); |
3130 assert(mh_reg == G3_method_handle, "caller must put MH object in G3"); |
3034 assert_different_registers(mh_reg, temp_reg); |
3131 assert_different_registers(mh_reg, temp_reg); |
|
3132 |
|
3133 if (UseCompressedOops) unimplemented("coop"); // field accesses must decode |
3035 |
3134 |
3036 // pick out the interpreted side of the handler |
3135 // pick out the interpreted side of the handler |
3037 ld_ptr(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg), temp_reg); |
3136 ld_ptr(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg), temp_reg); |
3038 |
3137 |
3039 // off we go... |
3138 // off we go... |
3041 jmp(temp_reg, 0); |
3140 jmp(temp_reg, 0); |
3042 |
3141 |
3043 // for the various stubs which take control at this point, |
3142 // for the various stubs which take control at this point, |
3044 // see MethodHandles::generate_method_handle_stub |
3143 // see MethodHandles::generate_method_handle_stub |
3045 |
3144 |
3046 // (Can any caller use this delay slot? If so, add an option for supression.) |
3145 // Some callers can fill the delay slot. |
3047 delayed()->nop(); |
3146 if (emit_delayed_nop) { |
3048 } |
3147 delayed()->nop(); |
|
3148 } |
|
3149 } |
|
3150 |
3049 |
3151 |
3050 RegisterOrConstant MacroAssembler::argument_offset(RegisterOrConstant arg_slot, |
3152 RegisterOrConstant MacroAssembler::argument_offset(RegisterOrConstant arg_slot, |
3051 int extra_slot_offset) { |
3153 int extra_slot_offset) { |
3052 // cf. TemplateTable::prepare_invoke(), if (load_receiver). |
3154 // cf. TemplateTable::prepare_invoke(), if (load_receiver). |
3053 int stackElementSize = Interpreter::stackElementWords() * wordSize; |
3155 int stackElementSize = Interpreter::stackElementSize; |
3054 int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0); |
3156 int offset = extra_slot_offset * stackElementSize; |
3055 int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1); |
|
3056 assert(offset1 - offset == stackElementSize, "correct arithmetic"); |
|
3057 if (arg_slot.is_constant()) { |
3157 if (arg_slot.is_constant()) { |
3058 offset += arg_slot.as_constant() * stackElementSize; |
3158 offset += arg_slot.as_constant() * stackElementSize; |
3059 return offset; |
3159 return offset; |
3060 } else { |
3160 } else { |
3061 Register temp = arg_slot.as_register(); |
3161 Register temp = arg_slot.as_register(); |