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