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