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