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