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