1 /* 2 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 #ifndef CPU_RISCV_C2_MACROASSEMBLER_RISCV_HPP 27 #define CPU_RISCV_C2_MACROASSEMBLER_RISCV_HPP 28 29 // C2_MacroAssembler contains high-level macros for C2 30 31 private: 32 // Return true if the phase output is in the scratch emit size mode. 33 virtual bool in_scratch_emit_size() override; 34 35 void element_compare(Register r1, Register r2, 36 Register result, Register cnt, 37 Register tmp1, Register tmp2, 38 VectorRegister vr1, VectorRegister vr2, 39 VectorRegister vrs, 40 bool is_latin, Label& DONE); 41 public: 42 // Code used by cmpFastLock and cmpFastUnlock mach instructions in .ad file. 43 void fast_lock(Register object, Register box, Register tmp1, Register tmp2, Register tmp3); 44 void fast_unlock(Register object, Register box, Register tmp1, Register tmp2); 45 // Code used by cmpFastLockLightweight and cmpFastUnlockLightweight mach instructions in .ad file. 46 void fast_lock_lightweight(Register object, Register tmp1, Register tmp2, Register tmp3); 47 void fast_unlock_lightweight(Register object, Register tmp1, Register tmp2, Register tmp3); 48 49 void string_compare(Register str1, Register str2, 50 Register cnt1, Register cnt2, Register result, 51 Register tmp1, Register tmp2, Register tmp3, 52 int ae); 53 54 void string_indexof_char_short(Register str1, Register cnt1, 55 Register ch, Register result, 56 bool isL); 57 58 void string_indexof_char(Register str1, Register cnt1, 59 Register ch, Register result, 60 Register tmp1, Register tmp2, 61 Register tmp3, Register tmp4, 62 bool isL); 63 64 void string_indexof(Register str1, Register str2, 65 Register cnt1, Register cnt2, 66 Register tmp1, Register tmp2, 67 Register tmp3, Register tmp4, 68 Register tmp5, Register tmp6, 69 Register result, int ae); 70 71 void string_indexof_linearscan(Register haystack, Register needle, 72 Register haystack_len, Register needle_len, 73 Register tmp1, Register tmp2, 74 Register tmp3, Register tmp4, 75 int needle_con_cnt, Register result, int ae); 76 77 void arrays_equals(Register r1, Register r2, 78 Register tmp3, Register tmp4, 79 Register tmp5, Register tmp6, 80 Register result, Register cnt1, 81 int elem_size); 82 83 void string_equals(Register r1, Register r2, 84 Register result, Register cnt1, 85 int elem_size); 86 87 // refer to conditional_branches and float_conditional_branches 88 static const int bool_test_bits = 3; 89 static const int neg_cond_bits = 2; 90 static const int unsigned_branch_mask = 1 << bool_test_bits; 91 static const int double_branch_mask = 1 << bool_test_bits; 92 93 // cmp 94 void cmp_branch(int cmpFlag, 95 Register op1, Register op2, 96 Label& label, bool is_far = false); 97 98 void float_cmp_branch(int cmpFlag, 99 FloatRegister op1, FloatRegister op2, 100 Label& label, bool is_far = false); 101 102 void enc_cmpUEqNeLeGt_imm0_branch(int cmpFlag, Register op, 103 Label& L, bool is_far = false); 104 105 void enc_cmpEqNe_imm0_branch(int cmpFlag, Register op, 106 Label& L, bool is_far = false); 107 108 void enc_cmove(int cmpFlag, 109 Register op1, Register op2, 110 Register dst, Register src); 111 112 void spill(Register r, bool is64, int offset) { 113 is64 ? sd(r, Address(sp, offset)) 114 : sw(r, Address(sp, offset)); 115 } 116 117 void spill(FloatRegister f, bool is64, int offset) { 118 is64 ? fsd(f, Address(sp, offset)) 119 : fsw(f, Address(sp, offset)); 120 } 121 122 void spill(VectorRegister v, int offset) { 123 add(t0, sp, offset); 124 vs1r_v(v, t0); 125 } 126 127 void unspill(Register r, bool is64, int offset) { 128 is64 ? ld(r, Address(sp, offset)) 129 : lw(r, Address(sp, offset)); 130 } 131 132 void unspillu(Register r, bool is64, int offset) { 133 is64 ? ld(r, Address(sp, offset)) 134 : lwu(r, Address(sp, offset)); 135 } 136 137 void unspill(FloatRegister f, bool is64, int offset) { 138 is64 ? fld(f, Address(sp, offset)) 139 : flw(f, Address(sp, offset)); 140 } 141 142 void unspill(VectorRegister v, int offset) { 143 add(t0, sp, offset); 144 vl1r_v(v, t0); 145 } 146 147 void spill_copy_vector_stack_to_stack(int src_offset, int dst_offset, int vector_length_in_bytes) { 148 assert(vector_length_in_bytes % 16 == 0, "unexpected vector reg size"); 149 for (int i = 0; i < vector_length_in_bytes / 8; i++) { 150 unspill(t0, true, src_offset + (i * 8)); 151 spill(t0, true, dst_offset + (i * 8)); 152 } 153 } 154 155 void minmax_fp(FloatRegister dst, 156 FloatRegister src1, FloatRegister src2, 157 bool is_double, bool is_min); 158 159 // intrinsic methods implemented by rvv instructions 160 void string_equals_v(Register r1, Register r2, 161 Register result, Register cnt1, 162 int elem_size); 163 164 void arrays_equals_v(Register r1, Register r2, 165 Register result, Register cnt1, 166 int elem_size); 167 168 void string_compare_v(Register str1, Register str2, 169 Register cnt1, Register cnt2, 170 Register result, 171 Register tmp1, Register tmp2, 172 int encForm); 173 174 void clear_array_v(Register base, Register cnt); 175 176 void byte_array_inflate_v(Register src, Register dst, 177 Register len, Register tmp); 178 179 void char_array_compress_v(Register src, Register dst, 180 Register len, Register result, 181 Register tmp); 182 183 void encode_iso_array_v(Register src, Register dst, 184 Register len, Register result, 185 Register tmp, bool ascii); 186 187 void count_positives_v(Register ary, Register len, 188 Register result, Register tmp); 189 190 void string_indexof_char_v(Register str1, Register cnt1, 191 Register ch, Register result, 192 Register tmp1, Register tmp2, 193 bool isL); 194 195 void minmax_fp_v(VectorRegister dst, 196 VectorRegister src1, VectorRegister src2, 197 bool is_double, bool is_min, int vector_length); 198 199 void minmax_fp_masked_v(VectorRegister dst, VectorRegister src1, VectorRegister src2, 200 VectorRegister vmask, VectorRegister tmp1, VectorRegister tmp2, 201 bool is_double, bool is_min, int vector_length); 202 203 void reduce_minmax_fp_v(FloatRegister dst, 204 FloatRegister src1, VectorRegister src2, 205 VectorRegister tmp1, VectorRegister tmp2, 206 bool is_double, bool is_min, int vector_length, 207 VectorMask vm = Assembler::unmasked); 208 209 void reduce_integral_v(Register dst, Register src1, 210 VectorRegister src2, VectorRegister tmp, 211 int opc, BasicType bt, int vector_length, 212 VectorMask vm = Assembler::unmasked); 213 214 void vsetvli_helper(BasicType bt, int vector_length, LMUL vlmul = Assembler::m1, Register tmp = t0); 215 216 void compare_integral_v(VectorRegister dst, VectorRegister src1, VectorRegister src2, int cond, 217 BasicType bt, int vector_length, VectorMask vm = Assembler::unmasked); 218 219 void compare_fp_v(VectorRegister dst, VectorRegister src1, VectorRegister src2, int cond, 220 BasicType bt, int vector_length, VectorMask vm = Assembler::unmasked); 221 222 // In Matcher::scalable_predicate_reg_slots, 223 // we assume each predicate register is one-eighth of the size of 224 // scalable vector register, one mask bit per vector byte. 225 void spill_vmask(VectorRegister v, int offset){ 226 vsetvli_helper(T_BYTE, MaxVectorSize >> 3); 227 add(t0, sp, offset); 228 vse8_v(v, t0); 229 } 230 231 void unspill_vmask(VectorRegister v, int offset){ 232 vsetvli_helper(T_BYTE, MaxVectorSize >> 3); 233 add(t0, sp, offset); 234 vle8_v(v, t0); 235 } 236 237 void spill_copy_vmask_stack_to_stack(int src_offset, int dst_offset, int vector_length_in_bytes) { 238 assert(vector_length_in_bytes % 4 == 0, "unexpected vector mask reg size"); 239 for (int i = 0; i < vector_length_in_bytes / 4; i++) { 240 unspill(t0, false, src_offset + (i * 4)); 241 spill(t0, false, dst_offset + (i * 4)); 242 } 243 } 244 245 void integer_extend_v(VectorRegister dst, BasicType dst_bt, int vector_length, 246 VectorRegister src, BasicType src_bt); 247 248 void integer_narrow_v(VectorRegister dst, BasicType dst_bt, int vector_length, 249 VectorRegister src, BasicType src_bt); 250 251 void vfcvt_rtz_x_f_v_safe(VectorRegister dst, VectorRegister src); 252 253 void extract_v(Register dst, VectorRegister src, BasicType bt, int idx, VectorRegister tmp); 254 void extract_fp_v(FloatRegister dst, VectorRegister src, BasicType bt, int idx, VectorRegister tmp); 255 256 #endif // CPU_RISCV_C2_MACROASSEMBLER_RISCV_HPP