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 // See full description in macroAssembler_riscv.cpp. 44 void fast_lock(Register object, Register box, Register tmp1, Register tmp2, Register tmp3); 45 void fast_unlock(Register object, Register box, Register tmp1, Register tmp2); 46 47 void string_compare(Register str1, Register str2, 48 Register cnt1, Register cnt2, Register result, 49 Register tmp1, Register tmp2, Register tmp3, 50 int ae); 51 52 void string_indexof_char_short(Register str1, Register cnt1, 53 Register ch, Register result, 54 bool isL); 55 56 void string_indexof_char(Register str1, Register cnt1, 57 Register ch, Register result, 58 Register tmp1, Register tmp2, 59 Register tmp3, Register tmp4, 60 bool isL); 61 62 void string_indexof(Register str1, Register str2, 63 Register cnt1, Register cnt2, 64 Register tmp1, Register tmp2, 65 Register tmp3, Register tmp4, 66 Register tmp5, Register tmp6, 67 Register result, int ae); 68 69 void string_indexof_linearscan(Register haystack, Register needle, 70 Register haystack_len, Register needle_len, 71 Register tmp1, Register tmp2, 72 Register tmp3, Register tmp4, 73 int needle_con_cnt, Register result, int ae); 74 75 void arrays_equals(Register r1, Register r2, 76 Register tmp3, Register tmp4, 77 Register tmp5, Register tmp6, 78 Register result, Register cnt1, 79 int elem_size); 80 81 void string_equals(Register r1, Register r2, 82 Register result, Register cnt1, 83 int elem_size); 84 85 // refer to conditional_branches and float_conditional_branches 86 static const int bool_test_bits = 3; 87 static const int neg_cond_bits = 2; 88 static const int unsigned_branch_mask = 1 << bool_test_bits; 89 static const int double_branch_mask = 1 << bool_test_bits; 90 91 // cmp 92 void cmp_branch(int cmpFlag, 93 Register op1, Register op2, 94 Label& label, bool is_far = false); 95 96 void float_cmp_branch(int cmpFlag, 97 FloatRegister op1, FloatRegister op2, 98 Label& label, bool is_far = false); 99 100 void enc_cmpUEqNeLeGt_imm0_branch(int cmpFlag, Register op, 101 Label& L, bool is_far = false); 102 103 void enc_cmpEqNe_imm0_branch(int cmpFlag, Register op, 104 Label& L, bool is_far = false); 105 106 void enc_cmove(int cmpFlag, 107 Register op1, Register op2, 108 Register dst, Register src); 109 110 void spill(Register r, bool is64, int offset) { 111 is64 ? sd(r, Address(sp, offset)) 112 : sw(r, Address(sp, offset)); 113 } 114 115 void spill(FloatRegister f, bool is64, int offset) { 116 is64 ? fsd(f, Address(sp, offset)) 117 : fsw(f, Address(sp, offset)); 118 } 119 120 void spill(VectorRegister v, int offset) { 121 add(t0, sp, offset); 122 vs1r_v(v, t0); 123 } 124 125 void unspill(Register r, bool is64, int offset) { 126 is64 ? ld(r, Address(sp, offset)) 127 : lw(r, Address(sp, offset)); 128 } 129 130 void unspillu(Register r, bool is64, int offset) { 131 is64 ? ld(r, Address(sp, offset)) 132 : lwu(r, Address(sp, offset)); 133 } 134 135 void unspill(FloatRegister f, bool is64, int offset) { 136 is64 ? fld(f, Address(sp, offset)) 137 : flw(f, Address(sp, offset)); 138 } 139 140 void unspill(VectorRegister v, int offset) { 141 add(t0, sp, offset); 142 vl1r_v(v, t0); 143 } 144 145 void spill_copy_vector_stack_to_stack(int src_offset, int dst_offset, int vector_length_in_bytes) { 146 assert(vector_length_in_bytes % 16 == 0, "unexpected vector reg size"); 147 for (int i = 0; i < vector_length_in_bytes / 8; i++) { 148 unspill(t0, true, src_offset + (i * 8)); 149 spill(t0, true, dst_offset + (i * 8)); 150 } 151 } 152 153 void minmax_fp(FloatRegister dst, 154 FloatRegister src1, FloatRegister src2, 155 bool is_double, bool is_min); 156 157 // intrinsic methods implemented by rvv instructions 158 void string_equals_v(Register r1, Register r2, 159 Register result, Register cnt1, 160 int elem_size); 161 162 void arrays_equals_v(Register r1, Register r2, 163 Register result, Register cnt1, 164 int elem_size); 165 166 void string_compare_v(Register str1, Register str2, 167 Register cnt1, Register cnt2, 168 Register result, 169 Register tmp1, Register tmp2, 170 int encForm); 171 172 void clear_array_v(Register base, Register cnt); 173 174 void byte_array_inflate_v(Register src, Register dst, 175 Register len, Register tmp); 176 177 void char_array_compress_v(Register src, Register dst, 178 Register len, Register result, 179 Register tmp); 180 181 void encode_iso_array_v(Register src, Register dst, 182 Register len, Register result, 183 Register tmp, bool ascii); 184 185 void count_positives_v(Register ary, Register len, 186 Register result, Register tmp); 187 188 void string_indexof_char_v(Register str1, Register cnt1, 189 Register ch, Register result, 190 Register tmp1, Register tmp2, 191 bool isL); 192 193 void minmax_fp_v(VectorRegister dst, 194 VectorRegister src1, VectorRegister src2, 195 bool is_double, bool is_min, int vector_length); 196 197 void minmax_fp_masked_v(VectorRegister dst, VectorRegister src1, VectorRegister src2, 198 VectorRegister vmask, VectorRegister tmp1, VectorRegister tmp2, 199 bool is_double, bool is_min, int vector_length); 200 201 void reduce_minmax_fp_v(FloatRegister dst, 202 FloatRegister src1, VectorRegister src2, 203 VectorRegister tmp1, VectorRegister tmp2, 204 bool is_double, bool is_min, int vector_length, 205 VectorMask vm = Assembler::unmasked); 206 207 void reduce_integral_v(Register dst, Register src1, 208 VectorRegister src2, VectorRegister tmp, 209 int opc, BasicType bt, int vector_length, 210 VectorMask vm = Assembler::unmasked); 211 212 void vsetvli_helper(BasicType bt, int vector_length, LMUL vlmul = Assembler::m1, Register tmp = t0); 213 214 void compare_integral_v(VectorRegister dst, VectorRegister src1, VectorRegister src2, int cond, 215 BasicType bt, int vector_length, VectorMask vm = Assembler::unmasked); 216 217 void compare_fp_v(VectorRegister dst, VectorRegister src1, VectorRegister src2, int cond, 218 BasicType bt, int vector_length, VectorMask vm = Assembler::unmasked); 219 220 // In Matcher::scalable_predicate_reg_slots, 221 // we assume each predicate register is one-eighth of the size of 222 // scalable vector register, one mask bit per vector byte. 223 void spill_vmask(VectorRegister v, int offset){ 224 vsetvli_helper(T_BYTE, MaxVectorSize >> 3); 225 add(t0, sp, offset); 226 vse8_v(v, t0); 227 } 228 229 void unspill_vmask(VectorRegister v, int offset){ 230 vsetvli_helper(T_BYTE, MaxVectorSize >> 3); 231 add(t0, sp, offset); 232 vle8_v(v, t0); 233 } 234 235 void spill_copy_vmask_stack_to_stack(int src_offset, int dst_offset, int vector_length_in_bytes) { 236 assert(vector_length_in_bytes % 4 == 0, "unexpected vector mask reg size"); 237 for (int i = 0; i < vector_length_in_bytes / 4; i++) { 238 unspill(t0, false, src_offset + (i * 4)); 239 spill(t0, false, dst_offset + (i * 4)); 240 } 241 } 242 243 void integer_extend_v(VectorRegister dst, BasicType dst_bt, int vector_length, 244 VectorRegister src, BasicType src_bt); 245 246 void integer_narrow_v(VectorRegister dst, BasicType dst_bt, int vector_length, 247 VectorRegister src, BasicType src_bt); 248 249 void vfcvt_rtz_x_f_v_safe(VectorRegister dst, VectorRegister src); 250 251 void extract_v(Register dst, VectorRegister src, BasicType bt, int idx, VectorRegister tmp); 252 void extract_fp_v(FloatRegister dst, VectorRegister src, BasicType bt, int idx, VectorRegister tmp); 253 254 #endif // CPU_RISCV_C2_MACROASSEMBLER_RISCV_HPP