1 //
  2 // Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
  3 // Copyright (c) 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 // RISCV Bit-Manipulation Extension Architecture Description File
 27 
 28 instruct rorI_imm_rvb(iRegINoSp dst, iRegI src, immI shift) %{
 29   predicate(UseRVB);
 30   match(Set dst (RotateRight src shift));
 31 
 32   format %{ "roriw  $dst, $src, ($shift & 0x1f)\t#@rorI_imm_rvb" %}
 33 
 34   ins_cost(ALU_COST);
 35   ins_encode %{
 36     __ roriw(as_Register($dst$$reg), as_Register($src$$reg), $shift$$constant & 0x1f);
 37   %}
 38 
 39   ins_pipe(ialu_reg_shift);
 40 %}
 41 
 42 instruct rorL_imm_rvb(iRegLNoSp dst, iRegL src, immI shift) %{
 43   predicate(UseRVB);
 44   match(Set dst (RotateRight src shift));
 45 
 46   format %{ "rori  $dst, $src, ($shift & 0x3f)\t#@rorL_imm_rvb" %}
 47 
 48   ins_cost(ALU_COST);
 49   ins_encode %{
 50     __ rori(as_Register($dst$$reg), as_Register($src$$reg), $shift$$constant & 0x3f);
 51   %}
 52 
 53   ins_pipe(ialu_reg_shift);
 54 %}
 55 
 56 instruct rorI_reg_rvb(iRegINoSp dst, iRegI src, iRegI shift) %{
 57   predicate(UseRVB);
 58   match(Set dst (RotateRight src shift));
 59 
 60   format %{ "rorw  $dst, $src, $shift\t#@rorI_reg_rvb" %}
 61   ins_cost(ALU_COST);
 62   ins_encode %{
 63     __ rorw(as_Register($dst$$reg), as_Register($src$$reg), as_Register($shift$$reg));
 64   %}
 65   ins_pipe(ialu_reg_reg);
 66 %}
 67 
 68 instruct rorL_reg_rvb(iRegLNoSp dst, iRegL src, iRegI shift) %{
 69   predicate(UseRVB);
 70   match(Set dst (RotateRight src shift));
 71 
 72   format %{ "ror  $dst, $src, $shift\t#@rorL_reg_rvb" %}
 73   ins_cost(ALU_COST);
 74   ins_encode %{
 75     __ ror(as_Register($dst$$reg), as_Register($src$$reg), as_Register($shift$$reg));
 76   %}
 77   ins_pipe(ialu_reg_reg);
 78 %}
 79 
 80 instruct rolI_reg_rvb(iRegINoSp dst, iRegI src, iRegI shift) %{
 81   predicate(UseRVB);
 82   match(Set dst (RotateLeft src shift));
 83 
 84   format %{ "rolw  $dst, $src, $shift\t#@rolI_reg_rvb" %}
 85   ins_cost(ALU_COST);
 86   ins_encode %{
 87     __ rolw(as_Register($dst$$reg), as_Register($src$$reg), as_Register($shift$$reg));
 88   %}
 89   ins_pipe(ialu_reg_reg);
 90 %}
 91 
 92 instruct rolL_reg_rvb(iRegLNoSp dst, iRegL src, iRegI shift) %{
 93   predicate(UseRVB);
 94   match(Set dst (RotateLeft src shift));
 95 
 96   format %{ "rol  $dst, $src, $shift\t#@rolL_reg_rvb" %}
 97   ins_cost(ALU_COST);
 98   ins_encode %{
 99     __ rol(as_Register($dst$$reg), as_Register($src$$reg), as_Register($shift$$reg));
100   %}
101   ins_pipe(ialu_reg_reg);
102 %}
103 
104 // Convert oop into int for vectors alignment masking
105 instruct convP2I_rvb(iRegINoSp dst, iRegP src) %{
106   predicate(UseRVB);
107   match(Set dst (ConvL2I (CastP2X src)));
108 
109   format %{ "zext.w  $dst, $src\t# ptr -> int @convP2I_rvb" %}
110 
111   ins_cost(ALU_COST);
112   ins_encode %{
113     __ zext_w(as_Register($dst$$reg), as_Register($src$$reg));
114   %}
115 
116   ins_pipe(ialu_reg);
117 %}
118 
119 // byte to int
120 instruct convB2I_reg_reg_rvb(iRegINoSp dst, iRegIorL2I src, immI_24 lshift, immI_24 rshift) %{
121   predicate(UseRVB);
122   match(Set dst (RShiftI (LShiftI src lshift) rshift));
123 
124   format %{ "sext.b  $dst, $src\t# b2i, #@convB2I_reg_reg_rvb" %}
125 
126   ins_cost(ALU_COST);
127   ins_encode %{
128     __ sext_b(as_Register($dst$$reg), as_Register($src$$reg));
129   %}
130 
131   ins_pipe(ialu_reg);
132 %}
133 
134 // int to short
135 instruct convI2S_reg_reg_rvb(iRegINoSp dst, iRegIorL2I src, immI_16 lshift, immI_16 rshift) %{
136   predicate(UseRVB);
137   match(Set dst (RShiftI (LShiftI src lshift) rshift));
138 
139   format %{ "sext.h  $dst, $src\t# i2s, #@convI2S_reg_reg_rvb" %}
140 
141   ins_cost(ALU_COST);
142   ins_encode %{
143     __ sext_h(as_Register($dst$$reg), as_Register($src$$reg));
144   %}
145 
146   ins_pipe(ialu_reg);
147 %}
148 
149 // short to unsigned int
150 instruct convS2UI_reg_reg_rvb(iRegINoSp dst, iRegIorL2I src, immI_16bits mask) %{
151   predicate(UseRVB);
152   match(Set dst (AndI src mask));
153 
154   format %{ "zext.h  $dst, $src\t# s2ui, #@convS2UI_reg_reg_rvb" %}
155 
156   ins_cost(ALU_COST);
157   ins_encode %{
158     __ zext_h(as_Register($dst$$reg), as_Register($src$$reg));
159   %}
160 
161   ins_pipe(ialu_reg);
162 %}
163 
164 // int to unsigned long (zero extend)
165 instruct convI2UL_reg_reg_rvb(iRegLNoSp dst, iRegIorL2I src, immL_32bits mask) %{
166   predicate(UseRVB);
167   match(Set dst (AndL (ConvI2L src) mask));
168 
169   format %{ "zext.w  $dst, $src\t# i2ul, #@convI2UL_reg_reg_rvb" %}
170 
171   ins_cost(ALU_COST);
172   ins_encode %{
173     __ zext_w(as_Register($dst$$reg), as_Register($src$$reg));
174   %}
175 
176   ins_pipe(ialu_reg_shift);
177 %}
178 
179 // BSWAP instructions
180 instruct bytes_reverse_int_rvb(iRegINoSp dst, iRegIorL2I src) %{
181   predicate(UseRVB);
182   match(Set dst (ReverseBytesI src));
183 
184   ins_cost(ALU_COST * 2);
185   format %{ "revb_w_w  $dst, $src\t#@bytes_reverse_int_rvb" %}
186 
187   ins_encode %{
188     __ revb_w_w(as_Register($dst$$reg), as_Register($src$$reg));
189   %}
190 
191   ins_pipe(ialu_reg);
192 %}
193 
194 instruct bytes_reverse_long_rvb(iRegLNoSp dst, iRegL src) %{
195   predicate(UseRVB);
196   match(Set dst (ReverseBytesL src));
197 
198   ins_cost(ALU_COST);
199   format %{ "rev8  $dst, $src\t#@bytes_reverse_long_rvb" %}
200 
201   ins_encode %{
202     __ rev8(as_Register($dst$$reg), as_Register($src$$reg));
203   %}
204 
205   ins_pipe(ialu_reg);
206 %}
207 
208 instruct bytes_reverse_unsigned_short_rvb(iRegINoSp dst, iRegIorL2I src) %{
209   predicate(UseRVB);
210   match(Set dst (ReverseBytesUS src));
211 
212   ins_cost(ALU_COST * 2);
213   format %{ "revb_h_h_u  $dst, $src\t#@bytes_reverse_unsigned_short_rvb" %}
214 
215   ins_encode %{
216     __ revb_h_h_u(as_Register($dst$$reg), as_Register($src$$reg));
217   %}
218 
219   ins_pipe(ialu_reg);
220 %}
221 
222 instruct bytes_reverse_short_rvb(iRegINoSp dst, iRegIorL2I src) %{
223   predicate(UseRVB);
224   match(Set dst (ReverseBytesS src));
225 
226   ins_cost(ALU_COST * 2);
227   format %{ "revb_h_h  $dst, $src\t#@bytes_reverse_short_rvb" %}
228 
229   ins_encode %{
230     __ revb_h_h(as_Register($dst$$reg), as_Register($src$$reg));
231   %}
232 
233   ins_pipe(ialu_reg);
234 %}
235 
236 // Shift Add Pointer
237 instruct shaddP_reg_reg_rvb(iRegPNoSp dst, iRegP src1, iRegL src2, immIScale imm) %{
238   predicate(UseRVB);
239   match(Set dst (AddP src1 (LShiftL src2 imm)));
240 
241   ins_cost(ALU_COST);
242   format %{ "shadd  $dst, $src2, $src1, $imm\t# ptr, #@shaddP_reg_reg_rvb" %}
243 
244   ins_encode %{
245     __ shadd(as_Register($dst$$reg),
246              as_Register($src2$$reg),
247              as_Register($src1$$reg),
248              t0,
249              $imm$$constant);
250   %}
251 
252   ins_pipe(ialu_reg_reg);
253 %}
254 
255 instruct shaddP_reg_reg_ext_rvb(iRegPNoSp dst, iRegP src1, iRegI src2, immIScale imm) %{
256   predicate(UseRVB);
257   match(Set dst (AddP src1 (LShiftL (ConvI2L src2) imm)));
258 
259   ins_cost(ALU_COST);
260   format %{ "shadd  $dst, $src2, $src1, $imm\t# ptr, #@shaddP_reg_reg_ext_rvb" %}
261 
262   ins_encode %{
263     __ shadd(as_Register($dst$$reg),
264              as_Register($src2$$reg),
265              as_Register($src1$$reg),
266              t0,
267              $imm$$constant);
268   %}
269 
270   ins_pipe(ialu_reg_reg);
271 %}
272 
273 // Shift Add Long
274 instruct shaddL_reg_reg_rvb(iRegLNoSp dst, iRegL src1, iRegL src2, immIScale imm) %{
275   predicate(UseRVB);
276   match(Set dst (AddL src1 (LShiftL src2 imm)));
277 
278   ins_cost(ALU_COST);
279   format %{ "shadd  $dst, $src2, $src1, $imm\t#@shaddL_reg_reg_rvb" %}
280 
281   ins_encode %{
282     __ shadd(as_Register($dst$$reg),
283              as_Register($src2$$reg),
284              as_Register($src1$$reg),
285              t0,
286              $imm$$constant);
287   %}
288 
289   ins_pipe(ialu_reg_reg);
290 %}
291 
292 instruct shaddL_reg_reg_ext_rvb(iRegLNoSp dst, iRegL src1, iRegI src2, immIScale imm) %{
293   predicate(UseRVB);
294   match(Set dst (AddL src1 (LShiftL (ConvI2L src2) imm)));
295 
296   ins_cost(ALU_COST);
297   format %{ "shadd  $dst, $src2, $src1, $imm\t#@shaddL_reg_reg_ext_rvb" %}
298 
299   ins_encode %{
300     __ shadd(as_Register($dst$$reg),
301              as_Register($src2$$reg),
302              as_Register($src1$$reg),
303              t0,
304              $imm$$constant);
305   %}
306 
307   ins_pipe(ialu_reg_reg);
308 %}
309 
310 // Zeros Count instructions
311 instruct countLeadingZerosI_rvb(iRegINoSp dst, iRegIorL2I src) %{
312   predicate(UseRVB);
313   match(Set dst (CountLeadingZerosI src));
314 
315   ins_cost(ALU_COST);
316   format %{ "clzw  $dst, $src\t#@countLeadingZerosI_rvb" %}
317 
318   ins_encode %{
319     __ clzw(as_Register($dst$$reg), as_Register($src$$reg));
320   %}
321 
322   ins_pipe(ialu_reg);
323 %}
324 
325 instruct countLeadingZerosL_rvb(iRegINoSp dst, iRegL src) %{
326   predicate(UseRVB);
327   match(Set dst (CountLeadingZerosL src));
328 
329   ins_cost(ALU_COST);
330   format %{ "clz  $dst, $src\t#@countLeadingZerosL_rvb" %}
331 
332   ins_encode %{
333     __ clz(as_Register($dst$$reg), as_Register($src$$reg));
334   %}
335 
336   ins_pipe(ialu_reg);
337 %}
338 
339 instruct countTrailingZerosI_rvb(iRegINoSp dst, iRegIorL2I src) %{
340   predicate(UseRVB);
341   match(Set dst (CountTrailingZerosI src));
342 
343   ins_cost(ALU_COST);
344   format %{ "ctzw  $dst, $src\t#@countTrailingZerosI_rvb" %}
345 
346   ins_encode %{
347     __ ctzw(as_Register($dst$$reg), as_Register($src$$reg));
348   %}
349 
350   ins_pipe(ialu_reg);
351 %}
352 
353 instruct countTrailingZerosL_rvb(iRegINoSp dst, iRegL src) %{
354   predicate(UseRVB);
355   match(Set dst (CountTrailingZerosL src));
356 
357   ins_cost(ALU_COST);
358   format %{ "ctz  $dst, $src\t#@countTrailingZerosL_rvb" %}
359 
360   ins_encode %{
361     __ ctz(as_Register($dst$$reg), as_Register($src$$reg));
362   %}
363 
364   ins_pipe(ialu_reg);
365 %}
366 
367 // Population Count instructions
368 instruct popCountI_rvb(iRegINoSp dst, iRegIorL2I src) %{
369   predicate(UsePopCountInstruction);
370   match(Set dst (PopCountI src));
371 
372   ins_cost(ALU_COST);
373   format %{ "cpopw  $dst, $src\t#@popCountI_rvb" %}
374 
375   ins_encode %{
376     __ cpopw(as_Register($dst$$reg), as_Register($src$$reg));
377   %}
378 
379   ins_pipe(ialu_reg);
380 %}
381 
382 // Note: Long/bitCount(long) returns an int.
383 instruct popCountL_rvb(iRegINoSp dst, iRegL src) %{
384   predicate(UsePopCountInstruction);
385   match(Set dst (PopCountL src));
386 
387   ins_cost(ALU_COST);
388   format %{ "cpop  $dst, $src\t#@popCountL_rvb" %}
389 
390   ins_encode %{
391     __ cpop(as_Register($dst$$reg), as_Register($src$$reg));
392   %}
393 
394   ins_pipe(ialu_reg);
395 %}
396 
397 // Max and Min
398 instruct minI_reg_rvb(iRegINoSp dst, iRegI src1, iRegI src2) %{
399   predicate(UseRVB);
400   match(Set dst (MinI src1 src2));
401 
402   ins_cost(ALU_COST);
403   format %{ "min  $dst, $src1, $src2\t#@minI_reg_rvb" %}
404 
405   ins_encode %{
406     __ min(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg));
407   %}
408 
409   ins_pipe(ialu_reg_reg);
410 %}
411 
412 instruct maxI_reg_rvb(iRegINoSp dst, iRegI src1, iRegI src2) %{
413   predicate(UseRVB);
414   match(Set dst (MaxI src1 src2));
415 
416   ins_cost(ALU_COST);
417   format %{ "max  $dst, $src1, $src2\t#@maxI_reg_rvb" %}
418 
419   ins_encode %{
420     __ max(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg));
421   %}
422 
423   ins_pipe(ialu_reg_reg);
424 %}
425 
426 // Abs
427 instruct absI_reg_rvb(iRegINoSp dst, iRegI src) %{
428   predicate(UseRVB);
429   match(Set dst (AbsI src));
430 
431   ins_cost(ALU_COST * 2);
432   format %{
433     "negw  t0, $src\n\t"
434     "max  $dst, $src, t0\t#@absI_reg_rvb"
435   %}
436 
437   ins_encode %{
438     __ negw(t0, as_Register($src$$reg));
439     __ max(as_Register($dst$$reg), as_Register($src$$reg), t0);
440   %}
441 
442   ins_pipe(ialu_reg_reg);
443 %}
444 
445 instruct absL_reg_rvb(iRegLNoSp dst, iRegL src) %{
446   predicate(UseRVB);
447   match(Set dst (AbsL src));
448 
449   ins_cost(ALU_COST * 2);
450   format %{
451     "neg  t0, $src\n\t"
452     "max $dst, $src, t0\t#@absL_reg_rvb"
453   %}
454 
455   ins_encode %{
456     __ neg(t0, as_Register($src$$reg));
457     __ max(as_Register($dst$$reg), as_Register($src$$reg), t0);
458   %}
459 
460   ins_pipe(ialu_reg);
461 %}
462 
463 // And Not
464 instruct andnI_reg_reg_rvb(iRegINoSp dst, iRegI src1, iRegI src2, immI_M1 m1) %{
465   predicate(UseRVB);
466   match(Set dst (AndI src1 (XorI src2 m1)));
467 
468   ins_cost(ALU_COST);
469   format %{ "andn  $dst, $src1, $src2\t#@andnI_reg_reg_rvb" %}
470 
471   ins_encode %{
472     __ andn(as_Register($dst$$reg),
473             as_Register($src1$$reg),
474             as_Register($src2$$reg));
475   %}
476 
477   ins_pipe(ialu_reg_reg);
478 %}
479 
480 instruct andnL_reg_reg_rvb(iRegLNoSp dst, iRegL src1, iRegL src2, immL_M1 m1) %{
481   predicate(UseRVB);
482   match(Set dst (AndL src1 (XorL src2 m1)));
483 
484   ins_cost(ALU_COST);
485   format %{ "andn  $dst, $src1, $src2\t#@andnL_reg_reg_rvb" %}
486 
487   ins_encode %{
488     __ andn(as_Register($dst$$reg),
489             as_Register($src1$$reg),
490             as_Register($src2$$reg));
491   %}
492 
493   ins_pipe(ialu_reg_reg);
494 %}
495 
496 // Or Not
497 instruct ornI_reg_reg_rvb(iRegINoSp dst, iRegI src1, iRegI src2, immI_M1 m1) %{
498   predicate(UseRVB);
499   match(Set dst (OrI src1 (XorI src2 m1)));
500 
501   ins_cost(ALU_COST);
502   format %{ "orn  $dst, $src1, $src2\t#@ornI_reg_reg_rvb" %}
503 
504   ins_encode %{
505     __ orn(as_Register($dst$$reg),
506            as_Register($src1$$reg),
507            as_Register($src2$$reg));
508   %}
509 
510   ins_pipe(ialu_reg_reg);
511 %}
512 
513 instruct ornL_reg_reg_rvb(iRegLNoSp dst, iRegL src1, iRegL src2, immL_M1 m1) %{
514   predicate(UseRVB);
515   match(Set dst (OrL src1 (XorL src2 m1)));
516 
517   ins_cost(ALU_COST);
518   format %{ "orn  $dst, $src1, $src2\t#@ornL_reg_reg_rvb" %}
519 
520   ins_encode %{
521     __ orn(as_Register($dst$$reg),
522            as_Register($src1$$reg),
523            as_Register($src2$$reg));
524   %}
525 
526   ins_pipe(ialu_reg_reg);
527 %}