1 /*
  2  * Copyright (c) 2020, 2026, 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, Assembler::LMUL lmul);
 41 
 42   void string_compare_long_same_encoding(Register result, Register str1, Register str2,
 43                                   const bool isLL, Register cnt1, Register cnt2,
 44                                   Register tmp1, Register tmp2, Register tmp3,
 45                                   const int STUB_THRESHOLD, Label *STUB, Label *SHORT_STRING, Label *DONE);
 46   void string_compare_long_different_encoding(Register result, Register str1, Register str2,
 47                                   bool isLU, Register cnt1, Register cnt2,
 48                                   Register tmp1, Register tmp2, Register tmp3,
 49                                   const int STUB_THRESHOLD, Label *STUB, Label *DONE);
 50 
 51  public:
 52   void entry_barrier();
 53 
 54   // Code used by cmpFastLock and cmpFastUnlock mach instructions in .ad file.
 55   void fast_lock(Register object, Register box,
 56                  Register tmp1, Register tmp2, Register tmp3, Register tmp4);
 57   void fast_unlock(Register object, Register box,
 58                    Register tmp1, Register tmp2, Register tmp3);
 59 
 60   void string_compare(Register str1, Register str2,
 61                       Register cnt1, Register cnt2, Register result,
 62                       Register tmp1, Register tmp2, Register tmp3,
 63                       int ae);
 64 
 65   void string_indexof_char_short(Register str1, Register cnt1,
 66                                  Register ch, Register result,
 67                                  bool isL);
 68 
 69   void string_indexof_char(Register str1, Register cnt1,
 70                            Register ch, Register result,
 71                            Register tmp1, Register tmp2,
 72                            Register tmp3, Register tmp4,
 73                            bool isL);
 74 
 75   void string_indexof(Register str1, Register str2,
 76                       Register cnt1, Register cnt2,
 77                       Register tmp1, Register tmp2,
 78                       Register tmp3, Register tmp4,
 79                       Register tmp5, Register tmp6,
 80                       Register result, int ae);
 81 
 82   void string_indexof_linearscan(Register haystack, Register needle,
 83                                  Register haystack_len, Register needle_len,
 84                                  Register tmp1, Register tmp2,
 85                                  Register tmp3, Register tmp4,
 86                                  int needle_con_cnt, Register result, int ae);
 87 
 88   void arrays_equals(Register r1, Register r2,
 89                      Register tmp1, Register tmp2, Register tmp3,
 90                      Register result, int elem_size);
 91 
 92   void arrays_hashcode(Register ary, Register cnt, Register result,
 93                        Register tmp1, Register tmp2,
 94                        Register tmp3, Register tmp4,
 95                        Register tmp5, Register tmp6,
 96                        BasicType eltype);
 97   int arrays_hashcode_elsize(BasicType eltype);
 98   void arrays_hashcode_elload(Register dst, Address src, BasicType eltype);
 99 
100   void arrays_hashcode_v(Register ary, Register cnt, Register result,
101                          Register tmp1, Register tmp2, Register tmp3,
102                          BasicType eltype);
103   void arrays_hashcode_elload_v(VectorRegister vdst, VectorRegister vtmp,
104                                 Register src, BasicType eltype);
105 
106   void string_equals(Register r1, Register r2,
107                      Register result, Register cnt1);
108 
109   // refer to conditional_branches and float_conditional_branches
110   static const int bool_test_bits = 3;
111   static const int unsigned_branch_mask = 1 << bool_test_bits;
112   static const int double_branch_mask = 1 << bool_test_bits;
113 
114   // cmp
115   void cmp_branch(int cmpFlag,
116                   Register op1, Register op2,
117                   Label& label, bool is_far = false);
118 
119   void float_cmp_branch(int cmpFlag,
120                         FloatRegister op1, FloatRegister op2,
121                         Label& label, bool is_far = false);
122 
123   void enc_cmpUEqNeLeGt_imm0_branch(int cmpFlag, Register op,
124                                     Label& L, bool is_far = false);
125 
126   void enc_cmpEqNe_imm0_branch(int cmpFlag, Register op,
127                                Label& L, bool is_far = false);
128 
129   void enc_cmove(int cmpFlag,
130                  Register op1, Register op2,
131                  Register dst, Register src);
132 
133   void enc_cmove_cmp_fp(int cmpFlag,
134                         FloatRegister op1, FloatRegister op2,
135                         Register dst, Register src, bool is_single);
136 
137   void enc_cmove_fp_cmp(int cmpFlag, Register op1, Register op2,
138                         FloatRegister dst, FloatRegister src, bool is_single);
139 
140   void enc_cmove_fp_cmp_fp(int cmpFlag, FloatRegister op1, FloatRegister op2,
141                            FloatRegister dst, FloatRegister src,
142                            bool cmp_single, bool cmov_single);
143 
144   void spill(Register r, bool is64, int offset) {
145     is64 ? sd(r, Address(sp, offset))
146          : sw(r, Address(sp, offset));
147   }
148 
149   void spill(FloatRegister f, bool is64, int offset) {
150     is64 ? fsd(f, Address(sp, offset))
151          : fsw(f, Address(sp, offset));
152   }
153 
154   void spill(VectorRegister v, int offset) {
155     add(t0, sp, offset);
156     vs1r_v(v, t0);
157   }
158 
159   void unspill(Register r, bool is64, int offset) {
160     is64 ? ld(r, Address(sp, offset))
161          : lw(r, Address(sp, offset));
162   }
163 
164   void unspillu(Register r, bool is64, int offset) {
165     is64 ? ld(r, Address(sp, offset))
166          : lwu(r, Address(sp, offset));
167   }
168 
169   void unspill(FloatRegister f, bool is64, int offset) {
170     is64 ? fld(f, Address(sp, offset))
171          : flw(f, Address(sp, offset));
172   }
173 
174   void unspill(VectorRegister v, int offset) {
175     add(t0, sp, offset);
176     vl1r_v(v, t0);
177   }
178 
179   void spill_copy_vector_stack_to_stack(int src_offset, int dst_offset, uint vector_length_in_bytes) {
180     assert(vector_length_in_bytes % 16 == 0, "unexpected vector reg size");
181     for (int i = 0; i < (int)vector_length_in_bytes / 8; i++) {
182       unspill(t0, true, src_offset + (i * 8));
183       spill(t0, true, dst_offset + (i * 8));
184     }
185   }
186 
187   enum class FLOAT_TYPE {
188     half_precision,
189     single_precision,
190     double_precision
191   };
192 
193   void minmax_fp(FloatRegister dst,
194                  FloatRegister src1, FloatRegister src2,
195                  FLOAT_TYPE ft, bool is_min);
196 
197   void round_double_mode(FloatRegister dst, FloatRegister src, int round_mode,
198                          Register tmp1, Register tmp2, Register tmp3);
199 
200   void signum_fp(FloatRegister dst, FloatRegister one, bool is_double);
201 
202   void float16_to_float(FloatRegister dst, Register src, Register tmp);
203   void float_to_float16(Register dst, FloatRegister src, FloatRegister ftmp, Register xtmp);
204 
205   void signum_fp_v(VectorRegister dst, VectorRegister one, BasicType bt, int vlen);
206 
207 
208   // intrinsic methods implemented by rvv instructions
209 
210   void java_round_float_v(VectorRegister dst, VectorRegister src, FloatRegister ftmp, BasicType bt, uint vector_length);
211   void java_round_double_v(VectorRegister dst, VectorRegister src, FloatRegister ftmp, BasicType bt, uint vector_length);
212 
213   void float16_to_float_v(VectorRegister dst, VectorRegister src, uint vector_length);
214   void float_to_float16_v(VectorRegister dst, VectorRegister src, VectorRegister vtmp, Register tmp, uint vector_length);
215 
216   void string_equals_v(Register r1, Register r2,
217                        Register result, Register cnt1);
218 
219   void arrays_equals_v(Register r1, Register r2,
220                        Register result, Register cnt1,
221                        int elem_size);
222 
223   void string_compare_v(Register str1, Register str2,
224                         Register cnt1, Register cnt2,
225                         Register result,
226                         Register tmp1, Register tmp2,
227                         int encForm);
228 
229   void clear_array_v(Register base, Register cnt);
230 
231   void byte_array_inflate_v(Register src, Register dst,
232                             Register len, Register tmp);
233 
234   void char_array_compress_v(Register src, Register dst,
235                             Register len, Register result,
236                             Register tmp);
237 
238   void encode_iso_array_v(Register src, Register dst,
239                           Register len, Register result,
240                           Register tmp, bool ascii);
241 
242   void count_positives_v(Register ary, Register len,
243                         Register result, Register tmp);
244 
245   void string_indexof_char_v(Register str1, Register cnt1,
246                             Register ch, Register result,
247                             Register tmp1, Register tmp2,
248                             bool isL);
249 
250   void minmax_fp_v(VectorRegister dst,
251                   VectorRegister src1, VectorRegister src2,
252                   BasicType bt, bool is_min, uint vector_length);
253 
254   void minmax_fp_masked_v(VectorRegister dst, VectorRegister src1, VectorRegister src2,
255                           VectorRegister vmask, VectorRegister tmp1, VectorRegister tmp2,
256                           BasicType bt, bool is_min, uint vector_length);
257 
258   void reduce_minmax_fp_v(FloatRegister dst,
259                           FloatRegister src1, VectorRegister src2,
260                           VectorRegister tmp1, VectorRegister tmp2,
261                           bool is_double, bool is_min, uint vector_length,
262                           VectorMask vm = Assembler::unmasked);
263 
264   void reduce_integral_v(Register dst, Register src1,
265                         VectorRegister src2, VectorRegister tmp,
266                         int opc, BasicType bt, uint vector_length,
267                         VectorMask vm = Assembler::unmasked);
268 
269   void reduce_mul_integral_v(Register dst, Register src1, VectorRegister src2,
270                              VectorRegister vtmp1, VectorRegister vtmp2, BasicType bt,
271                              uint vector_length, VectorMask vm = Assembler::unmasked);
272 
273   void vsetvli_helper(BasicType bt, uint vector_length, LMUL vlmul = Assembler::m1, Register tmp = t0);
274 
275   void compare_integral_v(VectorRegister dst, VectorRegister src1, VectorRegister src2, int cond,
276                           BasicType bt, uint vector_length, VectorMask vm = Assembler::unmasked);
277 
278   void compare_fp_v(VectorRegister dst, VectorRegister src1, VectorRegister src2, int cond,
279                     BasicType bt, uint vector_length, VectorMask vm = Assembler::unmasked);
280 
281   void spill_vmask(VectorRegister v, int offset);
282 
283   void unspill_vmask(VectorRegister v, int offset);
284 
285   void spill_copy_vmask_stack_to_stack(int src_offset, int dst_offset, uint vector_length_in_bytes) {
286     assert(vector_length_in_bytes % 4 == 0, "unexpected vector mask reg size");
287     for (int i = 0; i < (int)vector_length_in_bytes / 4; i++) {
288       unspill(t0, false, src_offset + (i * 4));
289       spill(t0, false, dst_offset + (i * 4));
290     }
291   }
292 
293   void integer_extend_v(VectorRegister dst, BasicType dst_bt, uint vector_length,
294                         VectorRegister src, BasicType src_bt, bool is_signed);
295 
296   void integer_narrow_v(VectorRegister dst, BasicType dst_bt, uint vector_length,
297                         VectorRegister src, BasicType src_bt);
298 
299   void vfcvt_rtz_x_f_v_safe(VectorRegister dst, VectorRegister src);
300 
301   void extract_v(Register dst, VectorRegister src,
302                  BasicType bt, int idx, VectorRegister vtmp);
303 
304   void extract_fp_v(FloatRegister dst, VectorRegister src,
305                     BasicType bt, int idx, VectorRegister vtmp);
306 
307   void slidedown_v(VectorRegister dst, VectorRegister src,
308                    uint32_t offset, Register tmp = t0);
309 
310 #endif // CPU_RISCV_C2_MACROASSEMBLER_RISCV_HPP