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_b(iRegINoSp dst, iRegI src, immI shift) %{ 29 predicate(UseZbb); 30 match(Set dst (RotateRight src shift)); 31 32 format %{ "roriw $dst, $src, ($shift & 0x1f)\t#@rorI_imm_b" %} 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_b(iRegLNoSp dst, iRegL src, immI shift) %{ 43 predicate(UseZbb); 44 match(Set dst (RotateRight src shift)); 45 46 format %{ "rori $dst, $src, ($shift & 0x3f)\t#@rorL_imm_b" %} 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_b(iRegINoSp dst, iRegI src, iRegI shift) %{ 57 predicate(UseZbb); 58 match(Set dst (RotateRight src shift)); 59 60 format %{ "rorw $dst, $src, $shift\t#@rorI_reg_b" %} 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_b(iRegLNoSp dst, iRegL src, iRegI shift) %{ 69 predicate(UseZbb); 70 match(Set dst (RotateRight src shift)); 71 72 format %{ "ror $dst, $src, $shift\t#@rorL_reg_b" %} 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_b(iRegINoSp dst, iRegI src, iRegI shift) %{ 81 predicate(UseZbb); 82 match(Set dst (RotateLeft src shift)); 83 84 format %{ "rolw $dst, $src, $shift\t#@rolI_reg_b" %} 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_b(iRegLNoSp dst, iRegL src, iRegI shift) %{ 93 predicate(UseZbb); 94 match(Set dst (RotateLeft src shift)); 95 96 format %{ "rol $dst, $src, $shift\t#@rolL_reg_b" %} 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_b(iRegINoSp dst, iRegP src) %{ 106 predicate(UseZba); 107 match(Set dst (ConvL2I (CastP2X src))); 108 109 format %{ "zext.w $dst, $src\t# ptr -> int @convP2I_b" %} 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_b(iRegINoSp dst, iRegIorL2I src, immI_24 lshift, immI_24 rshift) %{ 121 predicate(UseZbb); 122 match(Set dst (RShiftI (LShiftI src lshift) rshift)); 123 124 format %{ "sext.b $dst, $src\t# b2i, #@convB2I_reg_reg_b" %} 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_b(iRegINoSp dst, iRegIorL2I src, immI_16 lshift, immI_16 rshift) %{ 136 predicate(UseZbb); 137 match(Set dst (RShiftI (LShiftI src lshift) rshift)); 138 139 format %{ "sext.h $dst, $src\t# i2s, #@convI2S_reg_reg_b" %} 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_b(iRegINoSp dst, iRegIorL2I src, immI_16bits mask) %{ 151 predicate(UseZbb); 152 match(Set dst (AndI src mask)); 153 154 format %{ "zext.h $dst, $src\t# s2ui, #@convS2UI_reg_reg_b" %} 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_b(iRegLNoSp dst, iRegIorL2I src, immL_32bits mask) %{ 166 predicate(UseZba); 167 match(Set dst (AndL (ConvI2L src) mask)); 168 169 format %{ "zext.w $dst, $src\t# i2ul, #@convI2UL_reg_reg_b" %} 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_b(iRegINoSp dst, iRegIorL2I src) %{ 181 predicate(UseZbb); 182 match(Set dst (ReverseBytesI src)); 183 184 ins_cost(ALU_COST * 2); 185 format %{ "revb_w_w $dst, $src\t#@bytes_reverse_int_b" %} 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_b(iRegLNoSp dst, iRegL src) %{ 195 predicate(UseZbb); 196 match(Set dst (ReverseBytesL src)); 197 198 ins_cost(ALU_COST); 199 format %{ "rev8 $dst, $src\t#@bytes_reverse_long_b" %} 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_b(iRegINoSp dst, iRegIorL2I src) %{ 209 predicate(UseZbb); 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_b" %} 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_b(iRegINoSp dst, iRegIorL2I src) %{ 223 predicate(UseZbb); 224 match(Set dst (ReverseBytesS src)); 225 226 ins_cost(ALU_COST * 2); 227 format %{ "revb_h_h $dst, $src\t#@bytes_reverse_short_b" %} 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_b(iRegPNoSp dst, iRegP src1, iRegL src2, immIScale imm) %{ 238 predicate(UseZba); 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_b" %} 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_b(iRegPNoSp dst, iRegP src1, iRegI src2, immIScale imm) %{ 256 predicate(UseZba); 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_b" %} 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_b(iRegLNoSp dst, iRegL src1, iRegL src2, immIScale imm) %{ 275 predicate(UseZba); 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_b" %} 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_b(iRegLNoSp dst, iRegL src1, iRegI src2, immIScale imm) %{ 293 predicate(UseZba); 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_b" %} 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_b(iRegINoSp dst, iRegIorL2I src) %{ 312 predicate(UseZbb); 313 match(Set dst (CountLeadingZerosI src)); 314 315 ins_cost(ALU_COST); 316 format %{ "clzw $dst, $src\t#@countLeadingZerosI_b" %} 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_b(iRegINoSp dst, iRegL src) %{ 326 predicate(UseZbb); 327 match(Set dst (CountLeadingZerosL src)); 328 329 ins_cost(ALU_COST); 330 format %{ "clz $dst, $src\t#@countLeadingZerosL_b" %} 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_b(iRegINoSp dst, iRegIorL2I src) %{ 340 predicate(UseZbb); 341 match(Set dst (CountTrailingZerosI src)); 342 343 ins_cost(ALU_COST); 344 format %{ "ctzw $dst, $src\t#@countTrailingZerosI_b" %} 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_b(iRegINoSp dst, iRegL src) %{ 354 predicate(UseZbb); 355 match(Set dst (CountTrailingZerosL src)); 356 357 ins_cost(ALU_COST); 358 format %{ "ctz $dst, $src\t#@countTrailingZerosL_b" %} 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_b(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_b" %} 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_b(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_b" %} 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_b(iRegINoSp dst, iRegI src1, iRegI src2) %{ 399 predicate(UseZbb); 400 match(Set dst (MinI src1 src2)); 401 402 ins_cost(ALU_COST); 403 format %{ "min $dst, $src1, $src2\t#@minI_reg_b" %} 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_b(iRegINoSp dst, iRegI src1, iRegI src2) %{ 413 predicate(UseZbb); 414 match(Set dst (MaxI src1 src2)); 415 416 ins_cost(ALU_COST); 417 format %{ "max $dst, $src1, $src2\t#@maxI_reg_b" %} 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_b(iRegINoSp dst, iRegI src) %{ 428 predicate(UseZbb); 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_b" 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_b(iRegLNoSp dst, iRegL src) %{ 446 predicate(UseZbb); 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_b" 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_b(iRegINoSp dst, iRegI src1, iRegI src2, immI_M1 m1) %{ 465 predicate(UseZbb); 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_b" %} 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_b(iRegLNoSp dst, iRegL src1, iRegL src2, immL_M1 m1) %{ 481 predicate(UseZbb); 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_b" %} 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_b(iRegINoSp dst, iRegI src1, iRegI src2, immI_M1 m1) %{ 498 predicate(UseZbb); 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_b" %} 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_b(iRegLNoSp dst, iRegL src1, iRegL src2, immL_M1 m1) %{ 514 predicate(UseZbb); 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_b" %} 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 %}