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